Skip to content

Commit 8c0f02c

Browse files
committed
Merge bitcoin/bitcoin#24265: Drop StripRedundantLastElementsOfPath() function
ebda2b8 util: Drop no longer needed StripRedundantLastElementsOfPath() function (Hennadii Stepanov) ecd094e Use ArgsManager::GetPathArg() for "-walletdir" option (Hennadii Stepanov) 06fed4c Use ArgsManager::GetPathArg() for "-blocksdir" option (Hennadii Stepanov) 15b632b Use ArgsManager::GetPathArg() for "-datadir" option (Hennadii Stepanov) 540ca51 util: Add ArgsManager::GetPathArg() function (Hennadii Stepanov) Pull request description: [Switching](bitcoin/bitcoin#20744) to `std::filesystems` makes possible to leverage [`std::filesystem::path::lexically_normal`](https://en.cppreference.com/w/cpp/filesystem/path/lexically_normal) and get rid of ugly `StripRedundantLastElementsOfPath()` crutch. To make its usage simple and error-proof, a new `ArgsManager::GetPathArg()` member function introduced which guarantees to return a normalized with no trailing slashes paths provided via `-datadir`, `-blocksdir` or `-walletdir` command-line arguments or configure options. ACKs for top commit: ryanofsky: Code review ACK ebda2b8. Only change since last review is rebase which simplified the last commit Tree-SHA512: ed86959b6038b7152b5a1d473478667b72caab1716cc9149e1a75833d50511f22157e4e5e55a9465d1fa76b90bce5e5286f4e4f0d1ae65ebd9c012fae19d835f
2 parents 5e8e0b3 + ebda2b8 commit 8c0f02c

File tree

7 files changed

+121
-26
lines changed

7 files changed

+121
-26
lines changed

src/init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
11501150
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
11511151

11521152
// Warn about relative -datadir path.
1153-
if (args.IsArgSet("-datadir") && !fs::PathFromString(args.GetArg("-datadir", "")).is_absolute()) {
1153+
if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) {
11541154
LogPrintf("Warning: relative datadir option '%s' specified, which will be interpreted relative to the " /* Continued */
11551155
"current working directory '%s'. This is fragile, because if bitcoin is started in the future "
11561156
"from a different location, it will be unable to locate the current data files. There could "

src/test/getarg_tests.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,98 @@ BOOST_AUTO_TEST_CASE(intarg)
159159
BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-bar", 11), 0);
160160
}
161161

162+
BOOST_AUTO_TEST_CASE(patharg)
163+
{
164+
const auto dir = std::make_pair("-dir", ArgsManager::ALLOW_ANY);
165+
SetupArgs({dir});
166+
ResetArgs("");
167+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), fs::path{});
168+
169+
const fs::path root_path{"/"};
170+
ResetArgs("-dir=/");
171+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
172+
173+
ResetArgs("-dir=/.");
174+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
175+
176+
ResetArgs("-dir=/./");
177+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
178+
179+
ResetArgs("-dir=/.//");
180+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
181+
182+
#ifdef WIN32
183+
const fs::path win_root_path{"C:\\"};
184+
ResetArgs("-dir=C:\\");
185+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
186+
187+
ResetArgs("-dir=C:/");
188+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
189+
190+
ResetArgs("-dir=C:\\\\");
191+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
192+
193+
ResetArgs("-dir=C:\\.");
194+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
195+
196+
ResetArgs("-dir=C:\\.\\");
197+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
198+
199+
ResetArgs("-dir=C:\\.\\\\");
200+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
201+
#endif
202+
203+
const fs::path absolute_path{"/home/user/.bitcoin"};
204+
ResetArgs("-dir=/home/user/.bitcoin");
205+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
206+
207+
ResetArgs("-dir=/root/../home/user/.bitcoin");
208+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
209+
210+
ResetArgs("-dir=/home/./user/.bitcoin");
211+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
212+
213+
ResetArgs("-dir=/home/user/.bitcoin/");
214+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
215+
216+
ResetArgs("-dir=/home/user/.bitcoin//");
217+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
218+
219+
ResetArgs("-dir=/home/user/.bitcoin/.");
220+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
221+
222+
ResetArgs("-dir=/home/user/.bitcoin/./");
223+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
224+
225+
ResetArgs("-dir=/home/user/.bitcoin/.//");
226+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
227+
228+
const fs::path relative_path{"user/.bitcoin"};
229+
ResetArgs("-dir=user/.bitcoin");
230+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
231+
232+
ResetArgs("-dir=somewhere/../user/.bitcoin");
233+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
234+
235+
ResetArgs("-dir=user/./.bitcoin");
236+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
237+
238+
ResetArgs("-dir=user/.bitcoin/");
239+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
240+
241+
ResetArgs("-dir=user/.bitcoin//");
242+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
243+
244+
ResetArgs("-dir=user/.bitcoin/.");
245+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
246+
247+
ResetArgs("-dir=user/.bitcoin/./");
248+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
249+
250+
ResetArgs("-dir=user/.bitcoin/.//");
251+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
252+
}
253+
162254
BOOST_AUTO_TEST_CASE(doubledash)
163255
{
164256
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);

src/util/system.cpp

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -245,19 +245,6 @@ static std::optional<util::SettingsValue> InterpretValue(const KeyInfo& key, con
245245
return value;
246246
}
247247

248-
namespace {
249-
fs::path StripRedundantLastElementsOfPath(const fs::path& path)
250-
{
251-
auto result = path;
252-
while (result.filename().empty() || fs::PathToString(result.filename()) == ".") {
253-
result = result.parent_path();
254-
}
255-
256-
assert(fs::equivalent(result, path.lexically_normal()));
257-
return result;
258-
}
259-
} // namespace
260-
261248
// Define default constructor and destructor that are not inline, so code instantiating this class doesn't need to
262249
// #include class definitions for all members.
263250
// For example, m_settings has an internal dependency on univalue.
@@ -399,6 +386,13 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co
399386
return std::nullopt;
400387
}
401388

389+
fs::path ArgsManager::GetPathArg(std::string pathlike_arg) const
390+
{
391+
auto result = fs::PathFromString(GetArg(pathlike_arg, "")).lexically_normal();
392+
// Remove trailing slash, if present.
393+
return result.has_filename() ? result : result.parent_path();
394+
}
395+
402396
const fs::path& ArgsManager::GetBlocksDirPath() const
403397
{
404398
LOCK(cs_args);
@@ -409,7 +403,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
409403
if (!path.empty()) return path;
410404

411405
if (IsArgSet("-blocksdir")) {
412-
path = fs::absolute(fs::PathFromString(GetArg("-blocksdir", "")));
406+
path = fs::absolute(GetPathArg("-blocksdir"));
413407
if (!fs::is_directory(path)) {
414408
path = "";
415409
return path;
@@ -433,9 +427,9 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const
433427
// this function
434428
if (!path.empty()) return path;
435429

436-
std::string datadir = GetArg("-datadir", "");
430+
const fs::path datadir{GetPathArg("-datadir")};
437431
if (!datadir.empty()) {
438-
path = fs::absolute(StripRedundantLastElementsOfPath(fs::PathFromString(datadir)));
432+
path = fs::absolute(datadir);
439433
if (!fs::is_directory(path)) {
440434
path = "";
441435
return path;
@@ -455,7 +449,6 @@ const fs::path& ArgsManager::GetDataDir(bool net_specific) const
455449
}
456450
}
457451

458-
path = StripRedundantLastElementsOfPath(path);
459452
return path;
460453
}
461454

@@ -816,8 +809,8 @@ fs::path GetDefaultDataDir()
816809

817810
bool CheckDataDirOption()
818811
{
819-
std::string datadir = gArgs.GetArg("-datadir", "");
820-
return datadir.empty() || fs::is_directory(fs::absolute(fs::PathFromString(datadir)));
812+
const fs::path datadir{gArgs.GetPathArg("-datadir")};
813+
return datadir.empty() || fs::is_directory(fs::absolute(datadir));
821814
}
822815

823816
fs::path GetConfigFile(const std::string& confPath)

src/util/system.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,16 @@ class ArgsManager
264264
*/
265265
std::optional<const Command> GetCommand() const;
266266

267+
/**
268+
* Get a normalized path from a specified pathlike argument
269+
*
270+
* It is guaranteed that the returned path has no trailing slashes.
271+
*
272+
* @param pathlike_arg Pathlike argument to get a path from (e.g., "-datadir", "-blocksdir" or "-walletdir")
273+
* @return Normalized path which is get from a specified pathlike argument
274+
*/
275+
fs::path GetPathArg(std::string pathlike_arg) const;
276+
267277
/**
268278
* Get blocks directory path
269279
*

src/wallet/load.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ bool VerifyWallets(WalletContext& context)
2828
ArgsManager& args = *Assert(context.args);
2929

3030
if (args.IsArgSet("-walletdir")) {
31-
fs::path wallet_dir = fs::PathFromString(args.GetArg("-walletdir", ""));
31+
const fs::path wallet_dir{args.GetPathArg("-walletdir")};
3232
std::error_code error;
3333
// The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
3434
// It also lets the fs::exists and fs::is_directory checks below pass on windows, since they return false

src/wallet/test/init_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default)
1818
SetWalletDir(m_walletdir_path_cases["default"]);
1919
bool result = m_wallet_loader->verify();
2020
BOOST_CHECK(result == true);
21-
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
21+
fs::path walletdir = gArgs.GetPathArg("-walletdir");
2222
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
2323
BOOST_CHECK_EQUAL(walletdir, expected_path);
2424
}
@@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom)
2828
SetWalletDir(m_walletdir_path_cases["custom"]);
2929
bool result = m_wallet_loader->verify();
3030
BOOST_CHECK(result == true);
31-
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
31+
fs::path walletdir = gArgs.GetPathArg("-walletdir");
3232
fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]);
3333
BOOST_CHECK_EQUAL(walletdir, expected_path);
3434
}
@@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
6868
SetWalletDir(m_walletdir_path_cases["trailing"]);
6969
bool result = m_wallet_loader->verify();
7070
BOOST_CHECK(result == true);
71-
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
71+
fs::path walletdir = gArgs.GetPathArg("-walletdir");
7272
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
7373
BOOST_CHECK_EQUAL(walletdir, expected_path);
7474
}
@@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
7878
SetWalletDir(m_walletdir_path_cases["trailing2"]);
7979
bool result = m_wallet_loader->verify();
8080
BOOST_CHECK(result == true);
81-
fs::path walletdir = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
81+
fs::path walletdir = gArgs.GetPathArg("-walletdir");
8282
fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
8383
BOOST_CHECK_EQUAL(walletdir, expected_path);
8484
}

src/wallet/walletutil.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fs::path GetWalletDir()
1313
fs::path path;
1414

1515
if (gArgs.IsArgSet("-walletdir")) {
16-
path = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
16+
path = gArgs.GetPathArg("-walletdir");
1717
if (!fs::is_directory(path)) {
1818
// If the path specified doesn't exist, we return the deliberately
1919
// invalid empty string.

0 commit comments

Comments
 (0)