1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2024-10-18 00:16:11 -04:00

Compare commits

...

7 commits

Author SHA1 Message Date
Eelco Dolstra f8a0cc1b40
Merge 79b1708451 into ab0f9f9089 2024-10-13 11:10:36 +00:00
Robert Hensing ab0f9f9089
Merge pull request #11680 from Mic92/git-utils
git-utils: fix x86_64-w64-mingw32 build
2024-10-13 13:09:00 +02:00
Valentin Gagarin de0a34a362
doc: note that nix eval is eager (#11670)
doc: note that `nix eval` is eager

---------

Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2024-10-13 12:31:01 +02:00
Robert Hensing 3c59df412a nix/meson.build: Rename name_suffix -> executable_suffix 2024-10-13 12:29:48 +02:00
Jörg Thalheim bd1961b7cc meson: fix executable extensions for windows build 2024-10-11 21:50:50 +02:00
Jörg Thalheim 30655dd146 git-utils: fix x86_64-w64-mingw32 build 2024-10-11 21:04:52 +02:00
Eelco Dolstra 79b1708451 Support fine-grained database schema migrations
Backward-compatible schema changes (e.g. those that add tables or
nullable columns) now no longer need a change to the global schema
file (/nix/var/nix/db/schema). Thus, old Nix versions can continue to
access the database.

This is especially useful for schema changes required by experimental
features. In particular, it replaces the ad-hoc handling of the schema
changes for CA derivations (i.e. the file /nix/var/nix/db/ca-schema).

Schema versions 8 and 10 could have been handled by this mechanism in
a backward-compatible way as well.
2024-10-10 17:08:27 +02:00
5 changed files with 69 additions and 62 deletions

View file

@ -208,7 +208,7 @@ static git_packbuilder_progress PACKBUILDER_PROGRESS_CHECK_INTERRUPT = &packBuil
static void initRepoAtomically(std::filesystem::path &path, bool bare) {
if (pathExists(path.string())) return;
Path tmpDir = createTempDir(std::filesystem::path(path).parent_path());
Path tmpDir = createTempDir(os_string_to_string(PathViewNG { std::filesystem::path(path).parent_path() }));
AutoDelete delTmpDir(tmpDir, true);
Repository tmpRepo;

View file

@ -95,51 +95,6 @@ struct LocalStore::State::Stmts {
SQLiteStmt AddRealisationReference;
};
static int getSchema(Path schemaPath)
{
int curSchema = 0;
if (pathExists(schemaPath)) {
auto s = readFile(schemaPath);
auto n = string2Int<int>(s);
if (!n)
throw Error("'%1%' is corrupt", schemaPath);
curSchema = *n;
}
return curSchema;
}
void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd)
{
const int nixCASchemaVersion = 4;
int curCASchema = getSchema(schemaPath);
if (curCASchema != nixCASchemaVersion) {
if (curCASchema > nixCASchemaVersion) {
throw Error("current Nix store ca-schema is version %1%, but I only support %2%",
curCASchema, nixCASchemaVersion);
}
if (!lockFile(lockFd.get(), ltWrite, false)) {
printInfo("waiting for exclusive access to the Nix store for ca drvs...");
lockFile(lockFd.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks
lockFile(lockFd.get(), ltWrite, true);
}
if (curCASchema == 0) {
static const char schema[] =
#include "ca-specific-schema.sql.gen.hh"
;
db.exec(schema);
curCASchema = nixCASchemaVersion;
}
if (curCASchema < 4)
throw Error("experimental CA schema version %d is no longer supported", curCASchema);
writeFile(schemaPath, fmt("%d", nixCASchemaVersion), 0666, true);
lockFile(lockFd.get(), ltRead, true);
}
}
LocalStore::LocalStore(
std::string_view scheme,
PathView path,
@ -316,6 +271,10 @@ LocalStore::LocalStore(
openDB(*state, false);
/* Legacy database schema migrations. Don't bump 'schema' for
new migrations; instead, add a migration to
upgradeDBSchema(). */
if (curSchema < 8) {
SQLiteTxn txn(state->db);
state->db.exec("alter table ValidPaths add column ultimate integer");
@ -342,13 +301,7 @@ LocalStore::LocalStore(
else openDB(*state, false);
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
if (!readOnly) {
migrateCASchema(state->db, dbDir + "/ca-schema", globalLock);
} else {
throw Error("need to migrate to content-addressed schema, but this cannot be done in read-only mode");
}
}
upgradeDBSchema(*state);
/* Prepare SQL statements. */
state->stmts->RegisterValidPath.create(state->db,
@ -483,7 +436,17 @@ std::string LocalStore::getUri()
int LocalStore::getSchema()
{ return nix::getSchema(schemaPath); }
{
int curSchema = 0;
if (pathExists(schemaPath)) {
auto s = readFile(schemaPath);
auto n = string2Int<int>(s);
if (!n)
throw Error("'%1%' is corrupt", schemaPath);
curSchema = *n;
}
return curSchema;
}
void LocalStore::openDB(State & state, bool create)
{
@ -566,6 +529,42 @@ void LocalStore::openDB(State & state, bool create)
}
void LocalStore::upgradeDBSchema(State & state)
{
state.db.exec("create table if not exists SchemaMigrations (migration text primary key not null);");
std::set<std::string> schemaMigrations;
{
SQLiteStmt querySchemaMigrations;
querySchemaMigrations.create(state.db, "select migration from SchemaMigrations;");
auto useQuerySchemaMigrations(querySchemaMigrations.use());
while (useQuerySchemaMigrations.next())
schemaMigrations.insert(useQuerySchemaMigrations.getStr(0));
}
auto doUpgrade = [&](const std::string & migrationName, const std::string & stmt)
{
if (schemaMigrations.contains(migrationName))
return;
warn("executing Nix database schema migration '%s'...", migrationName);
SQLiteTxn txn(state.db);
state.db.exec(stmt + fmt("\ninsert into SchemaMigrations values('%s')", migrationName));
txn.commit();
schemaMigrations.insert(migrationName);
};
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations))
doUpgrade(
"20220326-ca-derivations",
#include "ca-specific-schema.sql.gen.hh"
);
}
/* To improve purity, users may want to make the Nix store a read-only
bind mount. So make the Nix store writable for this process. */
void LocalStore::makeStoreWritable()

View file

@ -356,6 +356,8 @@ private:
void openDB(State & state, bool create);
void upgradeDBSchema(State & state);
void makeStoreWritable();
uint64_t queryValidPathId(State & state, const StorePath & path);

View file

@ -50,8 +50,9 @@ R""(
# Description
This command evaluates the given Nix expression and prints the
result on standard output.
This command evaluates the given Nix expression, and prints the result on standard output.
It also evaluates any nested attribute values and list items.
# Output format

View file

@ -212,18 +212,23 @@ nix_symlinks = [
'nix-store',
]
executable_suffix = ''
if host_machine.system() == 'windows'
executable_suffix = '.exe'
endif
foreach linkname : nix_symlinks
install_symlink(
linkname,
linkname + executable_suffix,
# TODO(Qyriad): should these continue to be relative symlinks?
pointing_to : 'nix',
pointing_to : fs.name(this_exe),
install_dir : get_option('bindir'),
# The 'runtime' tag is what executables default to, which we want to emulate here.
install_tag : 'runtime'
)
t = custom_target(
command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'],
output: linkname,
output: linkname + executable_suffix,
# TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working)
build_by_default: true
)
@ -233,15 +238,15 @@ endforeach
install_symlink(
'build-remote',
pointing_to : '..' / '..'/ get_option('bindir') / 'nix',
install_dir : get_option('libexecdir') / 'nix',
pointing_to : '..' / '..'/ get_option('bindir') / fs.name(this_exe),
install_dir : get_option('libexecdir') / fs.name(this_exe),
# The 'runtime' tag is what executables default to, which we want to emulate here.
install_tag : 'runtime'
)
custom_target(
command: ['ln', '-sf', fs.name(this_exe), '@OUTPUT@'],
output: 'build-remote',
output: 'build-remote' + executable_suffix,
# TODO(Ericson2314): Don't do this once we have the `meson.override_find_program` working)
build_by_default: true
)