* Get `nix-push' working again. It now uses Nix/Fix to create Nix

archives (using the package in corepkgs/nar).
* queryPathByHash -> expandHash, and it takes an argument specifying
  the target path (which may be empty).
* Install the core Fix packages in $prefix/share/fix.  TODO: bootstrap
  Nix and install Nix as a Fix package.
This commit is contained in:
Eelco Dolstra 2003-07-10 13:41:28 +00:00
parent 5d4b90b689
commit d072485d28
16 changed files with 154 additions and 54 deletions

View file

@ -1 +1 @@
SUBDIRS = src scripts SUBDIRS = src scripts corepkgs

View file

@ -13,9 +13,10 @@ AC_PROG_RANLIB
# Unix shell scripting should die a slow and painful death. # Unix shell scripting should die a slow and painful death.
AC_DEFINE_UNQUOTED(NIX_STORE_DIR, "$(eval echo $prefix/store)", Nix store directory.) AC_DEFINE_UNQUOTED(NIX_STORE_DIR, "$(eval echo $prefix/store)", Nix store directory.)
AC_DEFINE_UNQUOTED(NIX_DATA_DIR, "$(eval echo $datadir)", Nix data directory.)
AC_DEFINE_UNQUOTED(NIX_STATE_DIR, "$(eval echo $localstatedir/nix)", Nix state directory.) AC_DEFINE_UNQUOTED(NIX_STATE_DIR, "$(eval echo $localstatedir/nix)", Nix state directory.)
AC_DEFINE_UNQUOTED(NIX_LOG_DIR, "$(eval echo $localstatedir/log/nix)", Nix log file directory.) AC_DEFINE_UNQUOTED(NIX_LOG_DIR, "$(eval echo $localstatedir/log/nix)", Nix log file directory.)
AM_CONFIG_HEADER([config.h]) AM_CONFIG_HEADER([config.h])
AC_CONFIG_FILES([Makefile src/Makefile scripts/Makefile]) AC_CONFIG_FILES([Makefile src/Makefile scripts/Makefile corepkgs/Makefile])
AC_OUTPUT AC_OUTPUT

8
corepkgs/Makefile.am Normal file
View file

@ -0,0 +1,8 @@
install-data-local:
$(INSTALL) -d $(datadir)/fix
$(INSTALL) -d $(datadir)/fix/fetchurl
$(INSTALL_DATA) fetchurl/fetchurl.fix $(datadir)/fix/fetchurl
$(INSTALL_DATA) fetchurl/fetchurl.sh $(datadir)/fix/fetchurl
$(INSTALL) -d $(datadir)/fix/nar
$(INSTALL_DATA) nar/nar.fix $(datadir)/fix/nar
$(INSTALL_DATA) nar/nar.sh $(datadir)/fix/nar

8
corepkgs/nar/nar.fix Normal file
View file

@ -0,0 +1,8 @@
Function(["path", "name"],
Package(
[ ("name", Var("name"))
, ("build", Relative("nar/nar.sh"))
, ("path", Var("path"))
]
)
)

3
corepkgs/nar/nar.sh Normal file
View file

@ -0,0 +1,3 @@
#! /bin/sh
/tmp/nix/bin/nix --dump --file "$path" > $out || exit 1

View file

@ -1,5 +1,5 @@
bin_SCRIPTS = nix-switch nix-collect-garbage \ bin_SCRIPTS = nix-switch nix-collect-garbage \
nix-pull-prebuilts nix-push-prebuilts nix-pull nix-push
install-exec-local: install-exec-local:
$(INSTALL) -d $(sysconfdir)/profile.d $(INSTALL) -d $(sysconfdir)/profile.d

2
scripts/nix-pull Normal file
View file

@ -0,0 +1,2 @@
#! /usr/bin/perl -w

60
scripts/nix-push Normal file
View file

@ -0,0 +1,60 @@
#! /usr/bin/perl -w
my @pushlist;
foreach my $hash (@ARGV) {
die unless $hash =~ /^([0-9a-z]{32})$/;
# Get all paths referenced by the normalisation of the given
# fstate expression.
my @paths;
open PATHS, "nix -qrh $hash 2> /dev/null |" or die "nix -qrh";
while (<PATHS>) {
chomp;
next unless /^\//;
push @paths, $_;
}
close PATHS;
# For each path, create a Fix expression that turns the path into
# a Nix archive.
foreach my $path (@paths) {
# Hash the path.
my $phash = `nix-hash $path`;
$? and die "nix-hash";
chomp $phash;
die unless $phash =~ /^([0-9a-z]{32})$/;
# Construct a Fix expression that creates a Nar archive.
my $fixexpr =
"App(IncludeFix(\"nar/nar.fix\"), " .
"[ (\"path\", Path(\"$path\", Hash(\"$phash\"), [Include(\"$hash\")]))" .
", (\"name\", \"$phash.nar\")" .
"])";
my $fixfile = "/tmp/nix-push-tmp.fix";
open FIX, ">$fixfile";
print FIX $fixexpr;
close FIX;
# Instantiate a Nix expression from the Fix expression.
my $nhash = `fix $fixfile`;
$? and die "instantiating Nix archive expression";
chomp $nhash;
die unless $nhash =~ /^([0-9a-z]{32})$/;
# Realise the Nix expression.
my $npath = `nix -qph $nhash 2> /dev/null`;
$? and die "creating Nix archive";
chomp $npath;
push @pushlist, $npath;
print "$path -> $npath\n";
}
}
# Push the prebuilts to the server. !!! FIXME
system "rsync -av -e ssh @pushlist eelco\@losser.st-lab.cs.uu.nl:/home/eelco/public_html/nix-dist/";

View file

@ -15,6 +15,8 @@ static Strings searchDirs;
static string searchPath(string relPath) static string searchPath(string relPath)
{ {
if (string(relPath, 0, 1) == "/") return relPath;
for (Strings::iterator i = searchDirs.begin(); for (Strings::iterator i = searchDirs.begin();
i != searchDirs.end(); i++) i != searchDirs.end(); i++)
{ {
@ -218,7 +220,10 @@ static Expr evalExpr(Expr e)
static Expr evalFile(string relPath) static Expr evalFile(string relPath)
{ {
Expr e = ATreadFromNamedFile(searchPath(relPath).c_str()); string path = searchPath(relPath);
Expr e = ATreadFromNamedFile(path.c_str());
if (!e)
throw Error(format("unable to read a term from `%1%'") % path);
return evalExpr(e); return evalExpr(e);
} }
@ -228,6 +233,7 @@ void run(Strings args)
Strings files; Strings files;
searchDirs.push_back("."); searchDirs.push_back(".");
searchDirs.push_back(nixDataDir + "/fix");
for (Strings::iterator it = args.begin(); for (Strings::iterator it = args.begin();
it != args.end(); ) it != args.end(); )

View file

@ -149,7 +149,7 @@ Hash hashTerm(ATerm t)
ATerm termFromHash(const Hash & hash, string * p) ATerm termFromHash(const Hash & hash, string * p)
{ {
string path = queryPathByHash(hash); string path = expandHash(hash);
if (p) *p = path; if (p) *p = path;
ATerm t = ATreadFromNamedFile(path.c_str()); ATerm t = ATreadFromNamedFile(path.c_str());
if (!t) throw Error(format("cannot read aterm %1%") % path); if (!t) throw Error(format("cannot read aterm %1%") % path);
@ -253,26 +253,6 @@ static FState realise(FState fs, StringSet & paths)
/* Expand the hash into the target path. */ /* Expand the hash into the target path. */
expandHash(hash, path); expandHash(hash, path);
#if 0
/* Perhaps the path already exists and has the right hash? */
if (pathExists(path)) {
if (hash != hashPath(path))
throw Error(format("path %1% exists, but does not have hash %2%")
% path % (string) hash);
debug(format("path %1% already has hash %2%")
% path % (string) hash);
} else {
/* Do we know a path with that hash? If so, copy it. */
string path2 = queryPathByHash(hash);
copyPath(path2, path);
}
#endif
return nf; return nf;
} }

View file

@ -4,8 +4,11 @@
string dbHash2Paths = "hash2paths"; string dbHash2Paths = "hash2paths";
string dbSuccessors = "successors"; string dbSuccessors = "successors";
string dbSubstitutes = "substitutes";
string nixStore = "/UNINIT"; string nixStore = "/UNINIT";
string nixDataDir = "/UNINIT";
string nixLogDir = "/UNINIT"; string nixLogDir = "/UNINIT";
string nixDB = "/UNINIT"; string nixDB = "/UNINIT";
@ -14,4 +17,5 @@ void initDB()
{ {
createDB(nixDB, dbHash2Paths); createDB(nixDB, dbHash2Paths);
createDB(nixDB, dbSuccessors); createDB(nixDB, dbSuccessors);
createDB(nixDB, dbSubstitutes);
} }

View file

@ -52,6 +52,8 @@ extern string dbSubstitutes;
derived files. */ derived files. */
extern string nixStore; extern string nixStore;
extern string nixDataDir; /* !!! fix */
/* nixLogDir is the directory where we log various operations. */ /* nixLogDir is the directory where we log various operations. */
extern string nixLogDir; extern string nixLogDir;

View file

@ -37,7 +37,7 @@ static ArgType argType = atpUnknown;
Source selection for --install, --dump: Source selection for --install, --dump:
--file / -f: by file name --file / -f: by file name !!! -> path
--hash / -h: by hash --hash / -h: by hash
Query flags: Query flags:
@ -87,6 +87,12 @@ static Hash argToHash(const string & arg)
} }
static FState hash2fstate(Hash hash)
{
return ATmake("Include(<str>)", ((string) hash).c_str());
}
/* Realise (or install) paths from the given Nix fstate /* Realise (or install) paths from the given Nix fstate
expressions. */ expressions. */
static void opInstall(Strings opFlags, Strings opArgs) static void opInstall(Strings opFlags, Strings opArgs)
@ -98,7 +104,7 @@ static void opInstall(Strings opFlags, Strings opArgs)
it != opArgs.end(); it++) it != opArgs.end(); it++)
{ {
StringSet paths; StringSet paths;
realiseFState(termFromHash(argToHash(*it)), paths); realiseFState(hash2fstate(argToHash(*it)), paths);
} }
} }
@ -157,14 +163,16 @@ static void opQuery(Strings opFlags, Strings opArgs)
switch (query) { switch (query) {
case qPath: case qPath: {
StringSet refs;
cout << format("%s\n") % cout << format("%s\n") %
(string) fstatePath(termFromHash(hash)); (string) fstatePath(realiseFState(termFromHash(hash), refs));
break; break;
}
case qRefs: { case qRefs: {
StringSet refs; StringSet refs;
FState fs = ATmake("Include(<str>)", ((string) hash).c_str()); FState fs = hash2fstate(hash);
fstateRefs(realiseFState(fs, refs), refs); fstateRefs(realiseFState(fs, refs), refs);
for (StringSet::iterator j = refs.begin(); for (StringSet::iterator j = refs.begin();
j != refs.end(); j++) j != refs.end(); j++)
@ -203,10 +211,8 @@ static void opDump(Strings opFlags, Strings opArgs)
string arg = *opArgs.begin(); string arg = *opArgs.begin();
string path; string path;
if (argType == atpHash) if (argType == atpHash) path = expandHash(parseHash(arg));
path = queryPathByHash(parseHash(arg)); else if (argType == atpPath) path = arg;
else if (argType == atpPath)
path = arg;
dumpPath(path, sink); dumpPath(path, sink);
} }

View file

@ -16,6 +16,7 @@ static void initAndRun(int argc, char * * argv)
{ {
/* Setup Nix paths. */ /* Setup Nix paths. */
nixStore = NIX_STORE_DIR; nixStore = NIX_STORE_DIR;
nixDataDir = NIX_DATA_DIR;
nixLogDir = NIX_LOG_DIR; nixLogDir = NIX_LOG_DIR;
nixDB = (string) NIX_STATE_DIR + "/nixstate.db"; nixDB = (string) NIX_STATE_DIR + "/nixstate.db";

View file

@ -131,25 +131,53 @@ bool isInPrefix(const string & path, const string & _prefix)
} }
static string queryPathByHashPrefix(Hash hash, const string & prefix) string expandHash(const Hash & hash, const string & target,
const string & prefix)
{ {
Strings paths; Strings paths;
if (!target.empty() && !isInPrefix(target, prefix))
abort();
if (!queryListDB(nixDB, dbHash2Paths, hash, paths)) if (!queryListDB(nixDB, dbHash2Paths, hash, paths))
throw Error(format("no paths known with hash `%1%'") % (string) hash); throw Error(format("no paths known with hash `%1%'") % (string) hash);
/* Arbitrarily pick the first one that exists and still hash the /* !!! we shouldn't check for staleness by default --- too slow */
right hash. */
/* Pick one equal to `target'. */
if (!target.empty()) {
for (Strings::iterator i = paths.begin();
i != paths.end(); i++)
{
string path = *i;
try {
if (path == target && hashPath(path) == hash)
return path;
} catch (Error & e) {
debug(format("stale path: %1%") % e.msg());
/* try next one */
}
}
}
/* Arbitrarily pick the first one that exists and isn't stale. */
for (Strings::iterator it = paths.begin(); for (Strings::iterator it = paths.begin();
it != paths.end(); it++) it != paths.end(); it++)
{ {
string path = *it; string path = *it;
try { try {
if (isInPrefix(path, prefix) && hashPath(path) == hash) if (isInPrefix(path, prefix) && hashPath(path) == hash) {
if (target.empty())
return path; return path;
else {
copyPath(path, target);
return target;
}
}
} catch (Error & e) { } catch (Error & e) {
debug(format("checking hash: %1%") % e.msg()); debug(format("stale path: %1%") % e.msg());
/* try next one */ /* try next one */
} }
} }
@ -158,15 +186,6 @@ static string queryPathByHashPrefix(Hash hash, const string & prefix)
} }
string expandHash(const Hash & hash, const string & outPath = "")
{
string queryPathByHash(Hash hash)
{
return queryPathByHashPrefix(hash, "/");
}
void addToStore(string srcPath, string & dstPath, Hash & hash) void addToStore(string srcPath, string & dstPath, Hash & hash)
{ {
srcPath = absPath(srcPath); srcPath = absPath(srcPath);
@ -174,7 +193,7 @@ void addToStore(string srcPath, string & dstPath, Hash & hash)
hash = hashPath(srcPath); hash = hashPath(srcPath);
try { try {
dstPath = queryPathByHashPrefix(hash, nixStore); dstPath = expandHash(hash, "", nixStore);
return; return;
} catch (...) { } catch (...) {
} }

View file

@ -13,15 +13,15 @@ void copyPath(string src, string dst);
/* Register a path keyed on its hash. */ /* Register a path keyed on its hash. */
Hash registerPath(const string & path, Hash hash = Hash()); Hash registerPath(const string & path, Hash hash = Hash());
/* Return a path whose contents have the given hash. If outPath is /* Return a path whose contents have the given hash. If target is
not empty, ensure that such a path is realised in outPath (if not empty, ensure that such a path is realised in target (if
necessary by copying from another location). If prefix is not necessary by copying from another location). If prefix is not
empty, only return a path that is an descendent of prefix. empty, only return a path that is an descendent of prefix.
If no path with the given hash is known to exist in the file If no path with the given hash is known to exist in the file
system, ... system,
*/ */
string expandHash(const Hash & hash, const string & outPath = "", string expandHash(const Hash & hash, const string & target = "",
const string & prefix = "/"); const string & prefix = "/");
/* Copy a file to the nixStore directory and register it in dbRefs. /* Copy a file to the nixStore directory and register it in dbRefs.