Remove static initializers for RegisterLegacyCommand

This moves the "legacy"/"nix2" commands under a new `src/legacy/`
directory, instead of being scattered around in a bunch of different
directories.

A new `liblegacy` build target is defined, and the `nix` binary is
linked against it.

Then, `RegisterLegacyCommand` is replaced with `LegacyCommand::add`
calls in functions like `registerNixCollectGarbage()`. These
registration functions are called explicitly in `src/nix/main.cc`.

See: #359

Change-Id: Id450ffc3f793374907599cfcc121863b792aac1a
This commit is contained in:
Rebecca Turner 2024-09-10 13:13:19 -07:00
parent 7752927660
commit b63d4a0c62
Signed by: rbt
SSH key fingerprint: SHA256:SiNaEWabvotTldoNb5jIKqjJ3RnpS4aRXA4KLAdW5vs
40 changed files with 253 additions and 83 deletions

View file

@ -19,8 +19,9 @@
#include "legacy.hh" #include "legacy.hh"
#include "experimental-features.hh" #include "experimental-features.hh"
#include "hash.hh" #include "hash.hh"
#include "build-remote.hh"
using namespace nix; namespace nix {
static void handleAlarm(int sig) { static void handleAlarm(int sig) {
} }
@ -388,4 +389,8 @@ connected:
} }
} }
static RegisterLegacyCommand r_build_remote("build-remote", main_build_remote); void registerBuildRemote() {
LegacyCommands::add("build-remote", main_build_remote);
}
}

View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerBuildRemote();
}

35
src/legacy/meson.build Normal file
View file

@ -0,0 +1,35 @@
legacy_include_directories = include_directories('.')
legacy_sources = files(
# `build-remote` is not really legacy (it powers all remote builds), but it's
# not a `nix3` command.
'build-remote.cc',
'dotgraph.cc',
'graphml.cc',
'nix-build.cc',
'nix-channel.cc',
'nix-collect-garbage.cc',
'nix-copy-closure.cc',
'nix-env.cc',
'nix-env.hh',
'nix-instantiate.cc',
'nix-store.cc',
'user-env.cc',
)
legacy_headers = files(
'build-remote.hh',
'nix-build.hh',
'nix-channel.hh',
'nix-collect-garbage.hh',
'nix-copy-closure.hh',
'nix-instantiate.hh',
'nix-store.hh',
)
legacy_generated_headers = [
gen_header.process('buildenv.nix', preserve_path_from: meson.current_source_dir()),
gen_header.process('unpack-channel.nix', preserve_path_from: meson.current_source_dir()),
]
fs.copyfile('unpack-channel.nix')

View file

@ -24,12 +24,14 @@
#include "attr-path.hh" #include "attr-path.hh"
#include "legacy.hh" #include "legacy.hh"
#include "shlex.hh" #include "shlex.hh"
#include "nix-build.hh"
extern char * * environ __attribute__((weak)); // Man what even is this
namespace nix {
using namespace nix;
using namespace std::string_literals; using namespace std::string_literals;
extern char * * environ __attribute__((weak));
static void main_nix_build(int argc, char * * argv) static void main_nix_build(int argc, char * * argv)
{ {
auto dryRun = false; auto dryRun = false;
@ -613,5 +615,9 @@ static void main_nix_build(int argc, char * * argv)
} }
} }
static RegisterLegacyCommand r_nix_build("nix-build", main_nix_build); void registerNixBuildAndNixShell() {
static RegisterLegacyCommand r_nix_shell("nix-shell", main_nix_build); LegacyCommands::add("nix-build", main_nix_build);
LegacyCommands::add("nix-shell", main_nix_build);
}
}

8
src/legacy/nix-build.hh Normal file
View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixBuildAndNixShell();
}

View file

@ -7,12 +7,13 @@
#include "fetchers.hh" #include "fetchers.hh"
#include "eval-settings.hh" // for defexpr #include "eval-settings.hh" // for defexpr
#include "users.hh" #include "users.hh"
#include "nix-channel.hh"
#include <fcntl.h> #include <fcntl.h>
#include <regex> #include <regex>
#include <pwd.h> #include <pwd.h>
using namespace nix; namespace nix {
typedef std::map<std::string, std::string> Channels; typedef std::map<std::string, std::string> Channels;
@ -264,4 +265,8 @@ static int main_nix_channel(int argc, char ** argv)
} }
} }
static RegisterLegacyCommand r_nix_channel("nix-channel", main_nix_channel); void registerNixChannel() {
LegacyCommands::add("nix-channel", main_nix_channel);
}
}

View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixChannel();
}

View file

@ -7,11 +7,12 @@
#include "globals.hh" #include "globals.hh"
#include "legacy.hh" #include "legacy.hh"
#include "signals.hh" #include "signals.hh"
#include "nix-collect-garbage.hh"
#include <iostream> #include <iostream>
#include <cerrno> #include <cerrno>
using namespace nix; namespace nix {
std::string deleteOlderThan; std::string deleteOlderThan;
bool dryRun = false; bool dryRun = false;
@ -110,4 +111,8 @@ static int main_nix_collect_garbage(int argc, char * * argv)
} }
} }
static RegisterLegacyCommand r_nix_collect_garbage("nix-collect-garbage", main_nix_collect_garbage); void registerNixCollectGarbage() {
LegacyCommands::add("nix-collect-garbage", main_nix_collect_garbage);
}
}

View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixCollectGarbage();
}

View file

@ -1,8 +1,9 @@
#include "shared.hh" #include "shared.hh"
#include "store-api.hh" #include "store-api.hh"
#include "legacy.hh" #include "legacy.hh"
#include "nix-copy-closure.hh"
using namespace nix; namespace nix {
static int main_nix_copy_closure(int argc, char ** argv) static int main_nix_copy_closure(int argc, char ** argv)
{ {
@ -60,4 +61,8 @@ static int main_nix_copy_closure(int argc, char ** argv)
} }
} }
static RegisterLegacyCommand r_nix_copy_closure("nix-copy-closure", main_nix_copy_closure); void registerNixCopyClosure() {
LegacyCommands::add("nix-copy-closure", main_nix_copy_closure);
}
}

View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixCopyClosure();
}

View file

@ -17,6 +17,7 @@
#include "xml-writer.hh" #include "xml-writer.hh"
#include "legacy.hh" #include "legacy.hh"
#include "eval-settings.hh" // for defexpr #include "eval-settings.hh" // for defexpr
#include "nix-env.hh"
#include <ctime> #include <ctime>
#include <algorithm> #include <algorithm>
@ -28,9 +29,10 @@
#include <unistd.h> #include <unistd.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using namespace nix;
using std::cout; using std::cout;
namespace nix {
typedef enum { typedef enum {
srcNixExprDrvs, srcNixExprDrvs,
@ -1544,4 +1546,8 @@ static int main_nix_env(int argc, char * * argv)
} }
} }
static RegisterLegacyCommand r_nix_env("nix-env", main_nix_env); void registerNixEnv() {
LegacyCommands::add("nix-env", main_nix_env);
}
}

8
src/legacy/nix-env.hh Normal file
View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixEnv();
}

View file

@ -11,12 +11,13 @@
#include "local-fs-store.hh" #include "local-fs-store.hh"
#include "common-eval-args.hh" #include "common-eval-args.hh"
#include "legacy.hh" #include "legacy.hh"
#include "nix-instantiate.hh"
#include <map> #include <map>
#include <iostream> #include <iostream>
using namespace nix; namespace nix {
static Path gcRoot; static Path gcRoot;
@ -195,4 +196,8 @@ static int main_nix_instantiate(int argc, char * * argv)
} }
} }
static RegisterLegacyCommand r_nix_instantiate("nix-instantiate", main_nix_instantiate); void registerNixInstantiate() {
LegacyCommands::add("nix-instantiate", main_nix_instantiate);
}
}

View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixInstantiate();
}

View file

@ -15,6 +15,7 @@
#include "graphml.hh" #include "graphml.hh"
#include "legacy.hh" #include "legacy.hh"
#include "path-with-outputs.hh" #include "path-with-outputs.hh"
#include "nix-store.hh"
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
@ -24,10 +25,9 @@
#include <fcntl.h> #include <fcntl.h>
namespace nix_store { namespace nix {
using namespace nix;
using std::cin; using std::cin;
using std::cout; using std::cout;
@ -1176,6 +1176,8 @@ static int main_nix_store(int argc, char * * argv)
} }
} }
static RegisterLegacyCommand r_nix_store("nix-store", main_nix_store); void registerNixStore() {
LegacyCommands::add("nix-store", main_nix_store);
}
} }

8
src/legacy/nix-store.hh Normal file
View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixStore();
}

View file

@ -2,6 +2,6 @@
namespace nix { namespace nix {
RegisterLegacyCommand::Commands * RegisterLegacyCommand::commands = 0; LegacyCommands::Commands * LegacyCommands::commands = 0;
} }

View file

@ -9,12 +9,12 @@ namespace nix {
typedef std::function<void(int, char * *)> MainFunction; typedef std::function<void(int, char * *)> MainFunction;
struct RegisterLegacyCommand struct LegacyCommands
{ {
typedef std::map<std::string, MainFunction> Commands; typedef std::map<std::string, MainFunction> Commands;
static Commands * commands; static Commands * commands;
RegisterLegacyCommand(const std::string & name, MainFunction fun) static void add(const std::string & name, MainFunction fun)
{ {
if (!commands) commands = new Commands; if (!commands) commands = new Commands;
(*commands)[name] = fun; (*commands)[name] = fun;

View file

@ -26,54 +26,9 @@ libasanoptions = declare_dependency(
link_whole: asanoptions link_whole: asanoptions
) )
build_remote_sources = files( # Legacy commands.
'build-remote/build-remote.cc', subdir('legacy')
)
nix_build_sources = files(
'nix-build/nix-build.cc',
)
nix_channel_sources = files(
'nix-channel/nix-channel.cc',
)
unpack_channel_gen = gen_header.process('nix-channel/unpack-channel.nix')
nix_collect_garbage_sources = files(
'nix-collect-garbage/nix-collect-garbage.cc',
)
nix_copy_closure_sources = files(
'nix-copy-closure/nix-copy-closure.cc',
)
nix_env_buildenv_gen = gen_header.process('nix-env/buildenv.nix')
nix_env_sources = files(
'nix-env/nix-env.cc',
'nix-env/user-env.cc',
)
nix_instantiate_sources = files(
'nix-instantiate/nix-instantiate.cc',
)
nix_store_sources = files(
'nix-store/dotgraph.cc',
'nix-store/graphml.cc',
'nix-store/nix-store.cc',
)
# Hurray for Meson list flattening!
nix2_commands_sources = [
build_remote_sources,
nix_build_sources,
nix_channel_sources,
unpack_channel_gen,
nix_collect_garbage_sources,
nix_copy_closure_sources,
nix_env_buildenv_gen,
nix_env_sources,
nix_instantiate_sources,
nix_store_sources,
]
# Finally, the nix command itself, which all of the other commands are implmented in terms of # Finally, the nix command itself, which all of the other commands are implmented in terms of
# as a multicall binary. # as a multicall binary.
subdir('nix') subdir('nix')
# Just copies nix-channel/unpack-channel.nix to the build directory.
# Done as a subdir to get Meson to respect the path hierarchy.
subdir('nix-channel')

View file

@ -1 +0,0 @@
fs.copyfile('unpack-channel.nix')

View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixDaemon();
}

View file

@ -14,6 +14,7 @@
#include "signals.hh" #include "signals.hh"
#include "daemon.hh" #include "daemon.hh"
#include "unix-domain-socket.hh" #include "unix-domain-socket.hh"
#include "daemon-command.hh"
#include <algorithm> #include <algorithm>
#include <climits> #include <climits>
@ -36,7 +37,8 @@
#include <sys/ucred.h> #include <sys/ucred.h>
#endif #endif
using namespace nix; namespace nix {
using namespace nix::daemon; using namespace nix::daemon;
/** /**
@ -496,7 +498,9 @@ static int main_nix_daemon(int argc, char * * argv)
} }
} }
static RegisterLegacyCommand r_nix_daemon("nix-daemon", main_nix_daemon); void registerNixDaemon() {
LegacyCommands::add("nix-daemon", main_nix_daemon);
}
struct CmdDaemon : StoreCommand struct CmdDaemon : StoreCommand
{ {
@ -560,3 +564,5 @@ struct CmdDaemon : StoreCommand
}; };
static auto rCmdDaemon = registerCommand2<CmdDaemon>({"daemon"}); static auto rCmdDaemon = registerCommand2<CmdDaemon>({"daemon"});
}

8
src/nix/hash-command.hh Normal file
View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixHash();
}

View file

@ -5,8 +5,9 @@
#include "shared.hh" #include "shared.hh"
#include "references.hh" #include "references.hh"
#include "archive.hh" #include "archive.hh"
#include "hash-command.hh"
using namespace nix; namespace nix {
struct CmdHashBase : Command struct CmdHashBase : Command
{ {
@ -221,4 +222,8 @@ static int compatNixHash(int argc, char * * argv)
return 0; return 0;
} }
static RegisterLegacyCommand r_nix_hash("nix-hash", compatNixHash); void registerNixHash() {
LegacyCommands::add("nix-hash", compatNixHash);
}
}

View file

@ -15,6 +15,17 @@
#include "markdown.hh" #include "markdown.hh"
#include "experimental-features-json.hh" #include "experimental-features-json.hh"
#include "deprecated-features-json.hh" #include "deprecated-features-json.hh"
#include "build-remote.hh"
#include "daemon-command.hh"
#include "hash-command.hh"
#include "nix-build.hh"
#include "nix-channel.hh"
#include "nix-collect-garbage.hh"
#include "nix-copy-closure.hh"
#include "nix-env.hh"
#include "nix-instantiate.hh"
#include "nix-store.hh"
#include "prefetch-command.hh"
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -30,6 +41,21 @@ void chrootHelper(int argc, char * * argv);
namespace nix { namespace nix {
void registerLegacyCommands()
{
registerNixEnv();
registerNixBuildAndNixShell();
registerNixInstantiate();
registerNixCopyClosure();
registerNixCollectGarbage();
registerNixChannel();
registerNixStore();
registerBuildRemote();
registerNixDaemon();
registerNixPrefetchUrl();
registerNixHash();
}
static bool haveProxyEnvironmentVariables() static bool haveProxyEnvironmentVariables()
{ {
static const std::vector<std::string> proxyVariables = { static const std::vector<std::string> proxyVariables = {
@ -356,8 +382,10 @@ void mainWrapped(int argc, char * * argv)
// Clean up the progress bar if shown using --log-format in a legacy command too. // Clean up the progress bar if shown using --log-format in a legacy command too.
// Otherwise, this is a harmless no-op. // Otherwise, this is a harmless no-op.
Finally f([] { logger->pause(); }); Finally f([] { logger->pause(); });
{ {
auto legacy = (*RegisterLegacyCommand::commands)[programName]; registerLegacyCommands();
auto legacy = (*LegacyCommands::commands)[programName];
if (legacy) return legacy(argc, argv); if (legacy) return legacy(argc, argv);
} }

View file

@ -71,11 +71,21 @@ nix_sources = files(
'why-depends.cc', 'why-depends.cc',
) )
nix_headers = files(
'daemon-command.hh',
'hash-command.hh',
'prefetch-command.hh',
)
nix = executable( nix = executable(
'nix', 'nix',
nix_sources, nix_sources,
legacy_sources,
nix_generated_headers, nix_generated_headers,
nix2_commands_sources, nix_headers,
legacy_headers,
legacy_generated_headers,
include_directories : legacy_include_directories,
dependencies : [ dependencies : [
libasanoptions, libasanoptions,
liblixcmd, liblixcmd,

View file

@ -0,0 +1,8 @@
#pragma once
/// @file
namespace nix {
void registerNixPrefetchUrl();
}

View file

@ -9,10 +9,11 @@
#include "eval-inline.hh" // IWYU pragma: keep #include "eval-inline.hh" // IWYU pragma: keep
#include "legacy.hh" #include "legacy.hh"
#include "terminal.hh" #include "terminal.hh"
#include "prefetch-command.hh"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using namespace nix; namespace nix {
/* If url starts with mirror://, then resolve it using the list of /* If url starts with mirror://, then resolve it using the list of
mirrors defined in Nixpkgs. */ mirrors defined in Nixpkgs. */
@ -248,7 +249,9 @@ static int main_nix_prefetch_url(int argc, char * * argv)
} }
} }
static RegisterLegacyCommand r_nix_prefetch_url("nix-prefetch-url", main_nix_prefetch_url); void registerNixPrefetchUrl() {
LegacyCommands::add("nix-prefetch-url", main_nix_prefetch_url);
}
struct CmdStorePrefetchFile : StoreCommand, MixJSON struct CmdStorePrefetchFile : StoreCommand, MixJSON
{ {
@ -328,3 +331,5 @@ struct CmdStorePrefetchFile : StoreCommand, MixJSON
}; };
static auto rCmdStorePrefetchFile = registerCommand2<CmdStorePrefetchFile>({"store", "prefetch-file"}); static auto rCmdStorePrefetchFile = registerCommand2<CmdStorePrefetchFile>({"store", "prefetch-file"});
}

View file

@ -8,7 +8,7 @@
#include "archive.hh" #include "archive.hh"
#include "builtins/buildenv.hh" #include "builtins/buildenv.hh"
#include "flake/flakeref.hh" #include "flake/flakeref.hh"
#include "../nix-env/user-env.hh" #include "user-env.hh"
#include "profiles.hh" #include "profiles.hh"
#include "names.hh" #include "names.hh"

View file

@ -11,8 +11,8 @@ nix-instantiate --restrict-eval ./simple.nix -I src1=simple.nix -I src2=config.n
(! nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix') (! nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix')
nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix' -I src=../.. nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix' -I src=../..
(! nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../../src/nix-channel') (! nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../../src/legacy')
nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../../src/nix-channel' -I src=../../src nix-instantiate --restrict-eval --eval -E 'builtins.readDir ../../src/legacy' -I src=../../src
(! nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in <foo>') (! nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in <foo>')
nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in <foo>' -I src=. nix-instantiate --restrict-eval --eval -E 'let __nixPath = [ { prefix = "foo"; path = ./.; } ]; in <foo>' -I src=.

View file

@ -255,7 +255,7 @@ test(
env : default_test_env + { env : default_test_env + {
# No special meaning here, it's just a file laying around that is unlikely to go anywhere # No special meaning here, it's just a file laying around that is unlikely to go anywhere
# any time soon. # any time soon.
'_NIX_TEST_UNIT_DATA': meson.project_source_root() / 'src/nix-env/buildenv.nix', '_NIX_TEST_UNIT_DATA': meson.project_source_root() / 'src/legacy/buildenv.nix',
# Use a temporary home directory for the unit tests. # Use a temporary home directory for the unit tests.
# Otherwise, /homeless-shelter is created in the single-user sandbox, and functional tests will fail. # Otherwise, /homeless-shelter is created in the single-user sandbox, and functional tests will fail.
# TODO(alois31): handle TMPDIR properly (meson can't, and setting HOME in the test is too late)… # TODO(alois31): handle TMPDIR properly (meson can't, and setting HOME in the test is too late)…