Skip to content

Commit 5855150

Browse files
committed
Make GUI and CLI tools use the same datadir
Currently if a you choose a non-default datadir in the GUI intro screen, the datadir is ignored by CLI tools. This means `bitcoin-cli` and `bitcoin-wallet` will try to use the wrong datadir and show errors if they are called without a -datadir arguments, and `bitcoind` will appear to work but use a different datadir, not loading the same wallets and settings, and downloading blocks into the wrong place. There are also more subtle inconsistencies between GUI and CLI selection of datadirs such as #27273 where GUI might ignore a datadir= line in a bitcoin.conf that CLI tools would apply. This PR gets rid of inconsistencies between GUI and CLI tools and makes them use the same datadir setting by default. It is followup to bitcoin-core/gui#602 which made GUI and CLI tools use the same `-dbcache`, `-par`, `-spendzeroconfchange`, `-signer`, `-upnp`, `-natpmp`, `-listen`, `-server`, `-prune`, `-proxy`, `-onion`, and `-lang` settings as long as they loaded the same datadir. The reason for GUI and CLI tools using inconsistent datadirs, is that GUI stores the datadir path in a `strDataDir` field in `.config/Bitcoin/Bitcoin-Qt.conf`[^1] which CLI tools ignore. This PR changes the GUI to instead store the datadir path at the default datadir location `~/.bitcoin`[^2] as a symlink that CLI tools will already follow, or as a text file if the filesystem does not support creating symlinks. If upgrading from a previous version of the GUI and there is only a GUI datadir, the `strDataDir` setting will be automatically migrated to a symlink so CLI tools will start using it as well. If CLI and GUI tools are currently using different default datadirs, the GUI will show a prompt allowing either of the datadirs to be loaded and optionally set as the common default going forward.
1 parent b091d9b commit 5855150

File tree

8 files changed

+367
-91
lines changed

8 files changed

+367
-91
lines changed

src/common/init.cpp

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
#include <optional>
1515

1616
namespace common {
17-
std::optional<ConfigError> InitConfig(ArgsManager& args, SettingsAbortFn settings_abort_fn)
17+
std::optional<ConfigError> InitConfig(ArgsManager& args, InitialDataDirFn initial_datadir_fn,
18+
SettingsAbortFn settings_abort_fn)
1819
{
1920
try {
2021
if (!CheckDataDirOption(args)) {
@@ -33,7 +34,9 @@ std::optional<ConfigError> InitConfig(ArgsManager& args, SettingsAbortFn setting
3334
std::string error;
3435
fs::path orig_config_path;
3536
fs::path orig_datadir_path;
36-
if (!args.ReadConfigFiles(error, true, &orig_config_path, &orig_datadir_path)) {
37+
bool aborted{false};
38+
if (!args.ReadConfigFiles(error, true, initial_datadir_fn, &orig_config_path, &orig_datadir_path, &aborted)) {
39+
if (aborted) return ConfigError{ConfigStatus::ABORTED, Untranslated(error)};
3740
return ConfigError{ConfigStatus::FAILED, strprintf(_("Error reading configuration file: %s"), error)};
3841
}
3942

@@ -42,23 +45,9 @@ std::optional<ConfigError> InitConfig(ArgsManager& args, SettingsAbortFn setting
4245

4346
// Create datadir if it does not exist.
4447
const auto base_path{args.GetDataDirBase()};
45-
if (!fs::exists(base_path)) {
46-
// When creating a *new* datadir, also create a "wallets" subdirectory,
47-
// whether or not the wallet is enabled now, so if the wallet is enabled
48-
// in the future, it will use the "wallets" subdirectory for creating
49-
// and listing wallets, rather than the top-level directory where
50-
// wallets could be mixed up with other files. For backwards
51-
// compatibility, wallet code will use the "wallets" subdirectory only
52-
// if it already exists, but never create it itself. There is discussion
53-
// in https://github.com/bitcoin/bitcoin/issues/16220 about ways to
54-
// change wallet code so it would no longer be necessary to create
55-
// "wallets" subdirectories here.
56-
fs::create_directories(base_path / "wallets");
57-
}
5848
const auto net_path{args.GetDataDirNet()};
59-
if (!fs::exists(net_path)) {
60-
fs::create_directories(net_path / "wallets");
61-
}
49+
if (!CreateDataDir(base_path, error)) return ConfigError{ConfigStatus::FAILED, Untranslated(error)};
50+
if (!CreateDataDir(net_path, error)) return ConfigError{ConfigStatus::FAILED, Untranslated(error)};
6251

6352
// Show an error or warning if there is a bitcoin.conf file in the
6453
// datadir that is being ignored.

src/common/init.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef BITCOIN_COMMON_INIT_H
66
#define BITCOIN_COMMON_INIT_H
77

8+
#include <util/fs.h>
9+
#include <util/system.h>
810
#include <util/translation.h>
911

1012
#include <functional>
@@ -33,7 +35,8 @@ struct ConfigError {
3335
using SettingsAbortFn = std::function<bool(const bilingual_str& message, const std::vector<std::string>& details)>;
3436

3537
/* Read config files, and create datadir and settings.json if they don't exist. */
36-
std::optional<ConfigError> InitConfig(ArgsManager& args, SettingsAbortFn settings_abort_fn = nullptr);
38+
std::optional<ConfigError> InitConfig(ArgsManager& args, InitialDataDirFn initial_datadir_fn = nullptr,
39+
SettingsAbortFn settings_abort_fn = nullptr);
3740
} // namespace common
3841

3942
#endif // BITCOIN_COMMON_INIT_H

src/qt/bitcoin.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -568,16 +568,22 @@ int GuiMain(int argc, char* argv[])
568568
// User language is set up: pick a data directory
569569
bool did_show_intro = false;
570570
int64_t prune_MiB = 0; // Intro dialog prune configuration
571-
// Gracefully exit if the user cancels
572-
if (!Intro::showIfNeeded(did_show_intro, prune_MiB)) return EXIT_SUCCESS;
571+
auto initial_datadir_fn = [&](fs::path& datadir, std::string& error, bool* aborted) -> bool {
572+
if (!Intro::showIfNeeded(did_show_intro, datadir, prune_MiB)) {
573+
error = "Quitting, could not determine datadir.";
574+
if (aborted) *aborted = true;
575+
return false;
576+
}
577+
return true;
578+
};
573579

574580
/// 6-7. Parse bitcoin.conf, determine network, switch to network specific
575581
/// options, and create datadir and settings.json.
576582
// - Do not call gArgs.GetDataDirNet() before this step finishes
577583
// - Do not call Params() before this step
578584
// - QSettings() will use the new application name after this, resulting in network-specific settings
579585
// - Needs to be done before createOptionsModel
580-
if (auto error = common::InitConfig(gArgs, ErrorSettingsRead)) {
586+
if (auto error = common::InitConfig(gArgs, initial_datadir_fn, ErrorSettingsRead)) {
581587
InitError(error->message, error->details);
582588
if (error->status == common::ConfigStatus::FAILED_WRITE) {
583589
// Show a custom error message to provide more information in the

0 commit comments

Comments
 (0)