Add 'guix-register'.
* nix/guix-register/guix-register.cc, tests/guix-register.sh: New files. * Makefile.am (SH_TESTS)[BUILD_DAEMON]: Add tests/guix-register.sh. * daemon.am (sbin_PROGRAMS, guix_register_SOURCES, guix_register_CPPFLAGS, guix_register_LDADD): New variables. * test-env.in: Export 'storedir', 'prefix', 'datarootdir', 'datadir', and 'localstatedir'.
This commit is contained in:
parent
996ed6acd5
commit
a7a4e6a4f7
|
@ -76,3 +76,4 @@ stamp-h[0-9]
|
||||||
/nix/scripts/substitute-binary
|
/nix/scripts/substitute-binary
|
||||||
/doc/images/bootstrap-graph.png
|
/doc/images/bootstrap-graph.png
|
||||||
/doc/images/bootstrap-graph.eps
|
/doc/images/bootstrap-graph.eps
|
||||||
|
/guix-register
|
||||||
|
|
|
@ -117,6 +117,13 @@ SH_TESTS = \
|
||||||
tests/guix-hash.sh \
|
tests/guix-hash.sh \
|
||||||
tests/guix-package.sh
|
tests/guix-package.sh
|
||||||
|
|
||||||
|
if BUILD_DAEMON
|
||||||
|
|
||||||
|
SH_TESTS += tests/guix-register.sh
|
||||||
|
|
||||||
|
endif BUILD_DAEMON
|
||||||
|
|
||||||
|
|
||||||
TESTS = $(SCM_TESTS) $(SH_TESTS)
|
TESTS = $(SCM_TESTS) $(SH_TESTS)
|
||||||
|
|
||||||
TEST_EXTENSIONS = .scm .sh
|
TEST_EXTENSIONS = .scm .sh
|
||||||
|
|
16
daemon.am
16
daemon.am
|
@ -121,6 +121,7 @@ libstore_a_CXXFLAGS = \
|
||||||
$(SQLITE3_CFLAGS) $(LIBGCRYPT_CFLAGS)
|
$(SQLITE3_CFLAGS) $(LIBGCRYPT_CFLAGS)
|
||||||
|
|
||||||
bin_PROGRAMS = guix-daemon
|
bin_PROGRAMS = guix-daemon
|
||||||
|
sbin_PROGRAMS = guix-register
|
||||||
|
|
||||||
guix_daemon_SOURCES = \
|
guix_daemon_SOURCES = \
|
||||||
nix/nix-daemon/nix-daemon.cc \
|
nix/nix-daemon/nix-daemon.cc \
|
||||||
|
@ -137,6 +138,21 @@ guix_daemon_LDADD = \
|
||||||
guix_daemon_headers = \
|
guix_daemon_headers = \
|
||||||
nix/nix-daemon/shared.hh
|
nix/nix-daemon/shared.hh
|
||||||
|
|
||||||
|
|
||||||
|
guix_register_SOURCES = \
|
||||||
|
nix/guix-register/guix-register.cc
|
||||||
|
|
||||||
|
guix_register_CPPFLAGS = \
|
||||||
|
$(libutil_a_CPPFLAGS) \
|
||||||
|
$(libstore_a_CPPFLAGS) \
|
||||||
|
-I$(top_srcdir)/nix/libstore
|
||||||
|
|
||||||
|
# XXX: Should we start using shared libs?
|
||||||
|
guix_register_LDADD = \
|
||||||
|
libstore.a libutil.a libformat.a -lbz2 \
|
||||||
|
$(SQLITE3_LIBS) $(LIBGCRYPT_LIBS)
|
||||||
|
|
||||||
|
|
||||||
libexec_PROGRAMS = nix-setuid-helper
|
libexec_PROGRAMS = nix-setuid-helper
|
||||||
nix_setuid_helper_SOURCES = \
|
nix_setuid_helper_SOURCES = \
|
||||||
nix/nix-setuid-helper/nix-setuid-helper.cc
|
nix/nix-setuid-helper/nix-setuid-helper.cc
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
/* GNU Guix --- Functional package management for GNU
|
||||||
|
Copyright (C) 2013 Ludovic Courtès <ludo@gnu.org>
|
||||||
|
Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012,
|
||||||
|
2013 Eelco Dolstra <eelco.dolstra@logicblox.com>
|
||||||
|
|
||||||
|
This file is part of GNU Guix.
|
||||||
|
|
||||||
|
GNU Guix is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or (at
|
||||||
|
your option) any later version.
|
||||||
|
|
||||||
|
GNU Guix is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* This file derives from the implementation of 'nix-store
|
||||||
|
--register-validity', by Eelco Dolstra, as found in the Nix package
|
||||||
|
manager's src/nix-store/nix-store.cc. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <globals.hh>
|
||||||
|
#include <local-store.hh>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include <argp.h>
|
||||||
|
|
||||||
|
using namespace nix;
|
||||||
|
|
||||||
|
/* Input stream where we read closure descriptions. */
|
||||||
|
static std::istream *input = &std::cin;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Command-line options. */
|
||||||
|
|
||||||
|
const char *argp_program_version =
|
||||||
|
"guix-register (" PACKAGE_NAME ") " PACKAGE_VERSION;
|
||||||
|
const char *argp_program_bug_address = PACKAGE_BUGREPORT;
|
||||||
|
|
||||||
|
static char doc[] =
|
||||||
|
"guix-register -- register a closure as valid in a store\
|
||||||
|
\v\
|
||||||
|
This program is used internally when populating a store with data \
|
||||||
|
from an existing store. It updates the new store's database with \
|
||||||
|
information about which store files are valid, and what their \
|
||||||
|
references are.";
|
||||||
|
|
||||||
|
static const struct argp_option options[] =
|
||||||
|
{
|
||||||
|
{ "prefix", 'p', "DIRECTORY", 0,
|
||||||
|
"Open the store that lies under DIRECTORY" },
|
||||||
|
{ 0, 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Parse a single option. */
|
||||||
|
static error_t
|
||||||
|
parse_opt (int key, char *arg, struct argp_state *state)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case 'p':
|
||||||
|
{
|
||||||
|
string prefix = canonPath (arg);
|
||||||
|
settings.nixStore = prefix + NIX_STORE_DIR;
|
||||||
|
settings.nixDataDir = prefix + NIX_DATA_DIR;
|
||||||
|
settings.nixLogDir = prefix + NIX_LOG_DIR;
|
||||||
|
settings.nixStateDir = prefix + NIX_STATE_DIR;
|
||||||
|
settings.nixDBPath = settings.nixStateDir + "/db";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ARGP_KEY_ARG:
|
||||||
|
{
|
||||||
|
std::ifstream *file;
|
||||||
|
|
||||||
|
if (state->arg_num >= 2)
|
||||||
|
/* Too many arguments. */
|
||||||
|
argp_usage (state);
|
||||||
|
|
||||||
|
file = new std::ifstream ();
|
||||||
|
file->open (arg);
|
||||||
|
|
||||||
|
input = file;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (error_t) ARGP_ERR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (error_t) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Argument parsing. */
|
||||||
|
static struct argp argp = { options, parse_opt, 0, doc };
|
||||||
|
|
||||||
|
|
||||||
|
/* Read from INPUT the description of a closure, and register it as valid in
|
||||||
|
STORE. The expected format on INPUT is that used by #:references-graphs:
|
||||||
|
|
||||||
|
FILE
|
||||||
|
DERIVER
|
||||||
|
NUMBER-OF-REFERENCES
|
||||||
|
REF1
|
||||||
|
...
|
||||||
|
REFN
|
||||||
|
|
||||||
|
This is really meant as an internal format. */
|
||||||
|
static void
|
||||||
|
register_validity (LocalStore *store, std::istream &input,
|
||||||
|
bool reregister = true, bool hashGiven = false,
|
||||||
|
bool canonicalise = true)
|
||||||
|
{
|
||||||
|
ValidPathInfos infos;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ValidPathInfo info = decodeValidPathInfo (input, hashGiven);
|
||||||
|
if (info.path == "")
|
||||||
|
break;
|
||||||
|
if (!store->isValidPath (info.path) || reregister)
|
||||||
|
{
|
||||||
|
/* !!! races */
|
||||||
|
if (canonicalise)
|
||||||
|
canonicalisePathMetaData (info.path, -1);
|
||||||
|
|
||||||
|
if (!hashGiven)
|
||||||
|
{
|
||||||
|
HashResult hash = hashPath (htSHA256, info.path);
|
||||||
|
info.hash = hash.first;
|
||||||
|
info.narSize = hash.second;
|
||||||
|
}
|
||||||
|
infos.push_back (info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
store->registerValidPaths (infos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
argp_parse (&argp, argc, argv, 0, 0, 0);
|
||||||
|
|
||||||
|
LocalStore store;
|
||||||
|
register_validity (&store, *input);
|
||||||
|
}
|
||||||
|
catch (std::exception &e)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "error: %s\n", e.what ());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -69,5 +69,12 @@ then
|
||||||
trap "kill $daemon_pid ; rm -rf $NIX_STATE_DIR" EXIT
|
trap "kill $daemon_pid ; rm -rf $NIX_STATE_DIR" EXIT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
storedir="@storedir@"
|
||||||
|
prefix="@prefix@"
|
||||||
|
datarootdir="@datarootdir@"
|
||||||
|
datadir="@datadir@"
|
||||||
|
localstatedir="@localstatedir@"
|
||||||
|
export storedir prefix datarootdir datadir localstatedir
|
||||||
|
|
||||||
"@abs_top_builddir@/pre-inst-env" "$@"
|
"@abs_top_builddir@/pre-inst-env" "$@"
|
||||||
exit $?
|
exit $?
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
# GNU Guix --- Functional package management for GNU
|
||||||
|
# Copyright © 2013 Ludovic Courtès <ludo@gnu.org>
|
||||||
|
#
|
||||||
|
# This file is part of GNU Guix.
|
||||||
|
#
|
||||||
|
# GNU Guix is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or (at
|
||||||
|
# your option) any later version.
|
||||||
|
#
|
||||||
|
# GNU Guix is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test the 'guix-register' command-line utility.
|
||||||
|
#
|
||||||
|
|
||||||
|
guix-register --version
|
||||||
|
|
||||||
|
new_store="t-register-$$"
|
||||||
|
closure="t-register-closure-$$"
|
||||||
|
rm -rf "$new_store"
|
||||||
|
|
||||||
|
exit_hook=":"
|
||||||
|
trap "chmod -R +w $new_store ; rm -rf $new_store $closure ; \$exit_hook" EXIT
|
||||||
|
|
||||||
|
mkdir -p "$new_store/$storedir"
|
||||||
|
new_store_dir="`cd "$new_store/$storedir" ; pwd`"
|
||||||
|
new_store="`cd "$new_store" ; pwd`"
|
||||||
|
|
||||||
|
to_copy="`guix build guile-bootstrap`"
|
||||||
|
cp -r "$to_copy" "$new_store_dir"
|
||||||
|
copied="$new_store_dir/`basename $to_copy`"
|
||||||
|
|
||||||
|
# Create a file representing a closure with zero references, and with an empty
|
||||||
|
# "deriver" field.
|
||||||
|
cat >> "$closure" <<EOF
|
||||||
|
$copied
|
||||||
|
|
||||||
|
0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Register it.
|
||||||
|
guix-register -p "$new_store" < "$closure"
|
||||||
|
|
||||||
|
# Doing it a second time shouldn't hurt.
|
||||||
|
guix-register -p "$new_store" "$closure"
|
||||||
|
|
||||||
|
# Now make sure this is recognized as valid.
|
||||||
|
|
||||||
|
NIX_IGNORE_SYMLINK_STORE=1
|
||||||
|
NIX_STORE_DIR="$new_store_dir"
|
||||||
|
NIX_LOCALSTATE_DIR="$new_store$localstatedir"
|
||||||
|
NIX_LOG_DIR="$new_store$localstatedir/log/nix"
|
||||||
|
NIX_DB_DIR="$new_store$localstatedir/nix/db"
|
||||||
|
|
||||||
|
export NIX_IGNORE_SYMLINK_STORE NIX_STORE_DIR NIX_LOCALSTATE_DIR \
|
||||||
|
NIX_LOG_DIR NIX_DB_DIR
|
||||||
|
|
||||||
|
guix-daemon --disable-chroot &
|
||||||
|
subdaemon_pid=$!
|
||||||
|
exit_hook="kill $subdaemon_pid"
|
||||||
|
|
||||||
|
# At this point the copy in $new_store must be valid, and unreferenced.
|
||||||
|
guile -c "
|
||||||
|
(use-modules (guix store))
|
||||||
|
(define s (open-connection))
|
||||||
|
(exit (and (valid-path? s \"$copied\")
|
||||||
|
(equal? (list \"$copied\") (dead-paths s))))"
|
Loading…
Reference in New Issue