Repository: bitcoin/bitcoin
File: src/wallet/wallet.cpp (C++)

Code before:
        // First change to using SQLite
        if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};

        // Do the migration of keys and scripts for non-empty wallets, and cleanup if it fails
        if (HasLegacyRecords(*local_wallet)) {
            success = DoMigration(*local_wallet, context, error, res);
            // No scripts mean empty wallet after migration
            empty_local_wallet = local_wallet->GetAllScriptPubKeyMans().empty();
        } else {
            // Make sure that descriptors flag is actually set
            local_wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
            success = true;
        }
    }

    // In case of reloading failure, we need to remember the wallet dirs to remove
    // Set is used as it may be populated with the same wallet directory paths multiple times,
    // both before and after reloading. This ensures the set is complete even if one of the wallets
    // fails to reload.
    std::set<fs::path> wallet_dirs;
    if (success) {
        Assume(!res.wallet); // We will set it here.
        // Check if the local wallet is empty after migration
        if (empty_local_wallet) {
            // This wallet has no records. We can safely remove it.
            std::vector<fs::path> paths_to_remove = local_wallet->GetDatabase().Files();
            local_wallet.reset();
            for (const auto& path_to_remove : paths_to_remove) fs::remove_all(path_to_remove);
        }

        // Migration successful, unload all wallets locally, then reload them.
        // Note: We use a pointer to the shared_ptr to avoid increasing its reference count,
        // as 'reload_wallet' expects to be the sole owner (use_count == 1).
        for (std::shared_ptr<CWallet>* wallet_ptr : {&local_wallet, &res.watchonly_wallet, &res.solvables_wallet}) {
            if (success && *wallet_ptr) {
                std::shared_ptr<CWallet>& wallet = *wallet_ptr;
                // Save db path and reload wallet
                wallet_dirs.insert(fs::PathFromString(wallet->GetDatabase().Filename()).parent_path());
                success = reload_wallet(wallet);

                // When no wallet is set, set the main wallet.
                if (!res.wallet) {
                    res.wallet_name = wallet->GetName();
                    res.wallet = std::move(wallet);
                }
            }
        }
    }
    if (!success) {
        // Migration failed, cleanup
        // Before deleting the wallet's directory, copy the backup file to the top-level wallets dir

Review comment (suggestion):
In 2b8b658308c8fbfd9d41d8eb7b9491b615c43872:
Based on the commit description, this change seems more like you reasoning about the code flow than something that benefits the reader? I'm not sure it's adding much value.


Code after:
            local_wallet.reset();
            for (const auto& path_to_remove : paths_to_remove) fs::remove_all(path_to_remove);
        }

        // Migration successful, load all the migrated wallets.
        for (std::shared_ptr<CWallet>* wallet_ptr : {&local_wallet, &res.watchonly_wallet, &res.solvables_wallet}) {
            if (success && *wallet_ptr) {
                std::shared_ptr<CWallet>& wallet = *wallet_ptr;
                // Save db path and load wallet
                wallet_dirs.insert(fs::PathFromString(wallet->GetDatabase().Filename()).parent_path());
                assert(wallet.use_count() == 1);
                std::string wallet_name = wallet->GetName();
                wallet.reset();
                wallet = LoadWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
                success = (wallet != nullptr);

                // When no wallet is set, set the main wallet.
                if (!res.wallet) {
                    res.wallet_name = wallet->GetName();
                    res.wallet = std::move(wallet);
                }
            }
        }
    }
    if (!success) {
        // Migration failed, cleanup
        // Before deleting the wallet's directory, copy the backup file to the top-level wallets dir
        fs::path temp_backup_location = fsbridge::AbsPathJoin(GetWalletDir(), backup_filename);
        fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);

        // Make list of wallets to cleanup
        std::vector<std::shared_ptr<CWallet>> created_wallets;
        if (local_wallet) created_wallets.push_back(std::move(local_wallet));
        if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));
        if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));

        // Get the directories to remove after unloading
        for (std::shared_ptr<CWallet>& w : created_wallets) {
            wallet_dirs.emplace(fs::PathFromString(w->GetDatabase().Filename()).parent_path());
        }

        // Unload the wallets
        for (std::shared_ptr<CWallet>& w : created_wallets) {
            if (w->HaveChain()) {
                // Unloading for wallets that were loaded for normal use
                if (!RemoveWallet(context, w, /*load_on_start=*/false)) {
                    error += _("\nUnable to cleanup failed migration");
                    return util::Error{error};
                }
                WaitForDeleteWallet(std::move(w));
            } else {