* Refactoring: hash class.

This commit is contained in:
Eelco Dolstra 2003-06-15 13:41:32 +00:00
parent f66055fa1e
commit 21fe717ce2
8 changed files with 266 additions and 184 deletions

View file

@ -1,13 +1,16 @@
bin_PROGRAMS = nix fix bin_PROGRAMS = nix fix
noinst_PROGRAMS = test
AM_CXXFLAGS = -DSYSTEM=\"@host@\" -Wall AM_CXXFLAGS = -DSYSTEM=\"@host@\" -Wall
nix_SOURCES = nix.cc db.cc util.cc md5.c nix_SOURCES = nix.cc db.cc util.cc hash.cc md5.c
nix_LDADD = -ldb_cxx-4 -lATerm nix_LDADD = -ldb_cxx-4 -lATerm
fix_SOURCES = fix.cc util.cc md5.c fix_SOURCES = fix.cc util.cc hash.cc md5.c
fix_LDADD = -lATerm fix_LDADD = -lATerm
test_SOURCES = test.cc util.cc hash.cc md5.c
install-data-local: install-data-local:
$(INSTALL) -d $(localstatedir)/nix $(INSTALL) -d $(localstatedir)/nix
$(INSTALL) -d $(localstatedir)/nix/descriptors $(INSTALL) -d $(localstatedir)/nix/descriptors

View file

@ -10,6 +10,7 @@ extern "C" {
} }
#include "util.hh" #include "util.hh"
#include "hash.hh"
static string nixDescriptorDir; static string nixDescriptorDir;
@ -20,7 +21,7 @@ static bool verbose = false;
/* Mapping of Fix file names to the hashes of the resulting Nix /* Mapping of Fix file names to the hashes of the resulting Nix
descriptors. */ descriptors. */
typedef map<string, string> DescriptorMap; typedef map<string, Hash> DescriptorMap;
void registerFile(string filename) void registerFile(string filename)
@ -32,12 +33,13 @@ void registerFile(string filename)
} }
void registerURL(string hash, string url) void registerURL(Hash hash, string url)
{ {
int res = system(("nix regurl " + hash + " " + url).c_str()); int res = system(("nix regurl " + (string) hash + " " + url).c_str());
/* !!! escape */ /* !!! escape */
if (WEXITSTATUS(res) != 0) if (WEXITSTATUS(res) != 0)
throw Error("cannot register " + hash + " -> " + url + " with Nix"); throw Error("cannot register " +
(string) hash + " -> " + url + " with Nix");
} }
@ -61,7 +63,7 @@ struct EvalContext
ATerm evaluate(ATerm e, EvalContext ctx); ATerm evaluate(ATerm e, EvalContext ctx);
string instantiateDescriptor(string filename, EvalContext ctx); Hash instantiateDescriptor(string filename, EvalContext ctx);
string evaluateStr(ATerm e, EvalContext ctx) string evaluateStr(ATerm e, EvalContext ctx)
@ -101,7 +103,7 @@ ATerm evaluate(ATerm e, EvalContext ctx)
ATmatch(e, "Pkg(<str>)", &s) || ATmatch(e, "Pkg(<str>)", &s) ||
ATmatch(e, "File(<str>)", &s)) ATmatch(e, "File(<str>)", &s))
{ {
checkHash(s); parseHash(s);
return e; return e;
} }
@ -131,7 +133,7 @@ ATerm evaluate(ATerm e, EvalContext ctx)
else if (ATmatch(e, "Fix(<term>)", &e2)) { else if (ATmatch(e, "Fix(<term>)", &e2)) {
string filename = absPath(evaluateStr(e2, ctx), ctx.dir); /* !!! */ string filename = absPath(evaluateStr(e2, ctx), ctx.dir); /* !!! */
return ATmake("Pkg(<str>)", return ATmake("Pkg(<str>)",
instantiateDescriptor(filename, ctx).c_str()); ((string) instantiateDescriptor(filename, ctx)).c_str());
} }
#if 0 #if 0
@ -160,19 +162,18 @@ ATerm evaluate(ATerm e, EvalContext ctx)
hash. */ hash. */
else if (ATmatch(e, "Local(<term>)", &e2)) { else if (ATmatch(e, "Local(<term>)", &e2)) {
string filename = absPath(evaluateStr(e2, ctx), ctx.dir); /* !!! */ string filename = absPath(evaluateStr(e2, ctx), ctx.dir); /* !!! */
string hash = hashFile(filename); Hash hash = hashFile(filename);
registerFile(filename); /* !!! */ registerFile(filename); /* !!! */
return ATmake("File(<str>)", hash.c_str()); return ATmake("File(<str>)", ((string) hash).c_str());
} }
/* `Url' registers a mapping from a hash to an url with Nix, and /* `Url' registers a mapping from a hash to an url with Nix, and
returns the hash. */ returns the hash. */
else if (ATmatch(e, "Url(<term>, <term>)", &e2, &e3)) { else if (ATmatch(e, "Url(<term>, <term>)", &e2, &e3)) {
string hash = evaluateStr(e2, ctx); Hash hash = parseHash(evaluateStr(e2, ctx));
checkHash(hash);
string url = evaluateStr(e3, ctx); string url = evaluateStr(e3, ctx);
registerURL(hash, url); registerURL(hash, url);
return ATmake("File(<str>)", hash.c_str()); return ATmake("File(<str>)", ((string) hash).c_str());
} }
/* `If' provides conditional evaluation. */ /* `If' provides conditional evaluation. */
@ -199,7 +200,7 @@ string getStringFromMap(BindingsMap & bindingsMap,
/* Instantiate a Fix descriptors into a Nix descriptor, recursively /* Instantiate a Fix descriptors into a Nix descriptor, recursively
instantiating referenced descriptors as well. */ instantiating referenced descriptors as well. */
string instantiateDescriptor(string filename, EvalContext ctx) Hash instantiateDescriptor(string filename, EvalContext ctx)
{ {
/* Already done? */ /* Already done? */
DescriptorMap::iterator isInMap = ctx.done->find(filename); DescriptorMap::iterator isInMap = ctx.done->find(filename);
@ -256,8 +257,9 @@ string instantiateDescriptor(string filename, EvalContext ctx)
if (!ATwriteToNamedTextFile(outTerm, tmpFilename.c_str())) if (!ATwriteToNamedTextFile(outTerm, tmpFilename.c_str()))
throw Error("cannot write aterm to " + tmpFilename); throw Error("cannot write aterm to " + tmpFilename);
string outHash = hashFile(tmpFilename); Hash outHash = hashFile(tmpFilename);
string outFilename = nixDescriptorDir + "/" + id + "-" + outHash + ".nix"; string outFilename = nixDescriptorDir + "/" +
id + "-" + (string) outHash + ".nix";
if (rename(tmpFilename.c_str(), outFilename.c_str())) if (rename(tmpFilename.c_str(), outFilename.c_str()))
throw Error("cannot rename " + tmpFilename + " to " + outFilename); throw Error("cannot rename " + tmpFilename + " to " + outFilename);
@ -265,7 +267,8 @@ string instantiateDescriptor(string filename, EvalContext ctx)
registerFile(outFilename); registerFile(outFilename);
if (verbose) if (verbose)
cerr << "instantiated " << outHash << " from " << filename << endl; cerr << "instantiated " << (string) outHash
<< " from " << filename << endl;
(*ctx.done)[filename] = outHash; (*ctx.done)[filename] = outHash;
return outHash; return outHash;
@ -284,7 +287,7 @@ void instantiateDescriptors(Strings filenames)
it != filenames.end(); it++) it != filenames.end(); it++)
{ {
string filename = absPath(*it); string filename = absPath(*it);
cout << instantiateDescriptor(filename, ctx) << endl; cout << (string) instantiateDescriptor(filename, ctx) << endl;
} }
} }
@ -293,7 +296,7 @@ void instantiateDescriptors(Strings filenames)
void printUsage() void printUsage()
{ {
cerr << cerr <<
"Usage: fix ... "Usage: fix ...\n\
"; ";
} }

87
src/hash.cc Normal file
View file

@ -0,0 +1,87 @@
extern "C" {
#include "md5.h"
}
#include "hash.hh"
#include <iostream>
/* Create a zeroed hash object. */
Hash::Hash()
{
memset(hash, 0, sizeof(hash));
}
/* Check whether two hash are equal. */
bool Hash::operator == (Hash & h2)
{
for (unsigned int i = 0; i < hashSize; i++)
if (hash[i] != h2.hash[i]) return false;
return true;
}
/* Check whether two hash are not equal. */
bool Hash::operator != (Hash & h2)
{
return !(*this == h2);
}
/* Convert a hash code into a hexadecimal representation. */
Hash::operator string() const
{
ostringstream str;
for (unsigned int i = 0; i < hashSize; i++) {
str.fill('0');
str.width(2);
str << hex << (int) hash[i];
}
return str.str();
}
/* Parse a hexadecimal representation of a hash code. */
Hash parseHash(const string & s)
{
Hash hash;
for (unsigned int i = 0; i < Hash::hashSize; i++) {
string s2(s, i * 2, 2);
if (!isxdigit(s2[0]) || !isxdigit(s2[1]))
throw BadRefError("invalid hash: " + s);
istringstream str(s2);
int n;
str >> hex >> n;
hash.hash[i] = n;
}
return hash;
}
/* Verify that a reference is valid (that is, is a MD5 hash code). */
bool isHash(const string & s)
{
if (s.length() != 32) return false;
for (int i = 0; i < 32; i++) {
char c = s[i];
if (!((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f')))
return false;
}
return true;
}
/* Compute the MD5 hash of a file. */
Hash hashFile(const string & fileName)
{
Hash hash;
FILE * file = fopen(fileName.c_str(), "rb");
if (!file)
throw Error("file `" + fileName + "' does not exist");
int err = md5_stream(file, hash.hash);
fclose(file);
if (err) throw Error("cannot hash file");
return hash;
}

34
src/hash.hh Normal file
View file

@ -0,0 +1,34 @@
#ifndef __HASH_H
#define __HASH_H
#include <string>
#include "util.hh"
using namespace std;
struct Hash
{
static const unsigned int hashSize = 16;
unsigned char hash[hashSize];
Hash();
bool operator == (Hash & h2);
bool operator != (Hash & h2);
operator string() const;
};
class BadRefError : public Error
{
public:
BadRefError(string _err) : Error(_err) { };
};
Hash parseHash(const string & s);
bool isHash(const string & s);
Hash hashFile(const string & fileName);
#endif /* !__HASH_H */

View file

@ -16,6 +16,7 @@ extern "C" {
} }
#include "util.hh" #include "util.hh"
#include "hash.hh"
#include "db.hh" #include "db.hh"
using namespace std; using namespace std;
@ -58,7 +59,7 @@ string fetchURL(string url)
database), we use that. Otherwise, we attempt to fetch it from the database), we use that. Otherwise, we attempt to fetch it from the
network (using dbNetSources). We verify that the file has the network (using dbNetSources). We verify that the file has the
right hash. */ right hash. */
string getFile(string hash) string getFile(Hash hash)
{ {
bool checkedNet = false; bool checkedNet = false;
@ -77,10 +78,10 @@ string getFile(string hash)
if (checkedNet) if (checkedNet)
throw Error("consistency problem: file fetched from " + url + throw Error("consistency problem: file fetched from " + url +
" should have hash " + hash + ", but it doesn't"); " should have hash " + (string) hash + ", but it doesn't");
if (!queryDB(nixDB, dbNetSources, hash, url)) if (!queryDB(nixDB, dbNetSources, hash, url))
throw Error("a file with hash " + hash + " is requested, " throw Error("a file with hash " + (string) hash + " is requested, "
"but it is not known to exist locally or on the network"); "but it is not known to exist locally or on the network");
checkedNet = true; checkedNet = true;
@ -95,7 +96,7 @@ string getFile(string hash)
typedef map<string, string> Params; typedef map<string, string> Params;
void readPkgDescr(const string & hash, void readPkgDescr(Hash hash,
Params & pkgImports, Params & fileImports, Params & arguments) Params & pkgImports, Params & fileImports, Params & arguments)
{ {
string pkgfile; string pkgfile;
@ -117,10 +118,10 @@ void readPkgDescr(const string & hash,
string name(cname); string name(cname);
char * arg; char * arg;
if (ATmatch(value, "Pkg(<str>)", &arg)) { if (ATmatch(value, "Pkg(<str>)", &arg)) {
checkHash(arg); parseHash(arg);
pkgImports[name] = arg; pkgImports[name] = arg;
} else if (ATmatch(value, "File(<str>)", &arg)) { } else if (ATmatch(value, "File(<str>)", &arg)) {
checkHash(arg); parseHash(arg);
fileImports[name] = arg; fileImports[name] = arg;
} else if (ATmatch(value, "Str(<str>)", &arg)) } else if (ATmatch(value, "Str(<str>)", &arg))
arguments[name] = arg; arguments[name] = arg;
@ -136,13 +137,13 @@ void readPkgDescr(const string & hash,
} }
string getPkg(string hash); string getPkg(Hash hash);
typedef map<string, string> Environment; typedef map<string, string> Environment;
void fetchDeps(string hash, Environment & env) void fetchDeps(Hash hash, Environment & env)
{ {
/* Read the package description file. */ /* Read the package description file. */
Params pkgImports, fileImports, arguments; Params pkgImports, fileImports, arguments;
@ -156,7 +157,7 @@ void fetchDeps(string hash, Environment & env)
cerr << "fetching package dependency " cerr << "fetching package dependency "
<< it->first << " <- " << it->second << it->first << " <- " << it->second
<< endl; << endl;
env[it->first] = getPkg(it->second); env[it->first] = getPkg(parseHash(it->second));
} }
for (Params::iterator it = fileImports.begin(); for (Params::iterator it = fileImports.begin();
@ -168,7 +169,7 @@ void fetchDeps(string hash, Environment & env)
string file; string file;
file = getFile(it->second); file = getFile(parseHash(it->second));
env[it->first] = file; env[it->first] = file;
} }
@ -198,7 +199,7 @@ string getFromEnv(const Environment & env, const string & key)
} }
string queryPkgId(const string & hash) string queryPkgId(Hash hash)
{ {
Params pkgImports, fileImports, arguments; Params pkgImports, fileImports, arguments;
readPkgDescr(hash, pkgImports, fileImports, arguments); readPkgDescr(hash, pkgImports, fileImports, arguments);
@ -206,7 +207,7 @@ string queryPkgId(const string & hash)
} }
void installPkg(string hash) void installPkg(Hash hash)
{ {
string pkgfile; string pkgfile;
string src; string src;
@ -223,14 +224,15 @@ void installPkg(string hash)
string id = getFromEnv(env, "id"); string id = getFromEnv(env, "id");
/* Construct a path for the installed package. */ /* Construct a path for the installed package. */
path = nixHomeDir + "/pkg/" + id + "-" + hash; path = nixHomeDir + "/pkg/" + id + "-" + (string) hash;
/* Create the path. */ /* Create the path. */
if (mkdir(path.c_str(), 0777)) if (mkdir(path.c_str(), 0777))
throw Error("unable to create directory " + path); throw Error("unable to create directory " + path);
/* Create a log file. */ /* Create a log file. */
string logFileName = nixLogDir + "/" + id + "-" + hash + ".log"; string logFileName =
nixLogDir + "/" + id + "-" + (string) hash + ".log";
/* !!! auto-pclose on exit */ /* !!! auto-pclose on exit */
FILE * logFile = popen(("tee " + logFileName + " >&2").c_str(), "w"); /* !!! escaping */ FILE * logFile = popen(("tee " + logFileName + " >&2").c_str(), "w"); /* !!! escaping */
if (!logFile) if (!logFile)
@ -256,11 +258,11 @@ void installPkg(string hash)
} }
/* Try to use a prebuilt. */ /* Try to use a prebuilt. */
string prebuiltHash, prebuiltFile; string prebuiltHashS, prebuiltFile;
if (queryDB(nixDB, dbPrebuilts, hash, prebuiltHash)) { if (queryDB(nixDB, dbPrebuilts, hash, prebuiltHashS)) {
try { try {
prebuiltFile = getFile(prebuiltHash); prebuiltFile = getFile(parseHash(prebuiltHashS));
} catch (Error e) { } catch (Error e) {
cerr << "cannot obtain prebuilt (ignoring): " << e.what() << endl; cerr << "cannot obtain prebuilt (ignoring): " << e.what() << endl;
goto build; goto build;
@ -339,17 +341,16 @@ void installPkg(string hash)
} }
string getPkg(string hash) string getPkg(Hash hash)
{ {
string path; string path;
checkHash(hash);
while (!queryDB(nixDB, dbInstPkgs, hash, path)) while (!queryDB(nixDB, dbInstPkgs, hash, path))
installPkg(hash); installPkg(hash);
return path; return path;
} }
void runPkg(string hash, void runPkg(Hash hash,
Strings::iterator firstArg, Strings::iterator firstArg,
Strings::iterator lastArg) Strings::iterator lastArg)
{ {
@ -389,7 +390,7 @@ void runPkg(string hash,
} }
void ensurePkg(string hash) void ensurePkg(Hash hash)
{ {
Params pkgImports, fileImports, arguments; Params pkgImports, fileImports, arguments;
readPkgDescr(hash, pkgImports, fileImports, arguments); readPkgDescr(hash, pkgImports, fileImports, arguments);
@ -403,10 +404,9 @@ void ensurePkg(string hash)
} }
void delPkg(string hash) void delPkg(Hash hash)
{ {
string path; string path;
checkHash(hash);
if (queryDB(nixDB, dbInstPkgs, hash, path)) { if (queryDB(nixDB, dbInstPkgs, hash, path)) {
int res = system(("chmod -R +w " + path + " && rm -rf " + path).c_str()); // !!! escaping int res = system(("chmod -R +w " + path + " && rm -rf " + path).c_str()); // !!! escaping
delDB(nixDB, dbInstPkgs, hash); // not a bug ??? delDB(nixDB, dbInstPkgs, hash); // not a bug ???
@ -423,7 +423,7 @@ void exportPkgs(string outDir,
outDir = absPath(outDir); outDir = absPath(outDir);
for (Strings::iterator it = firstHash; it != lastHash; it++) { for (Strings::iterator it = firstHash; it != lastHash; it++) {
string hash = *it; Hash hash = parseHash(*it);
string pkgDir = getPkg(hash); string pkgDir = getPkg(hash);
string tmpFile = outDir + "/export_tmp"; string tmpFile = outDir + "/export_tmp";
@ -435,42 +435,38 @@ void exportPkgs(string outDir,
string prebuiltHash = hashFile(tmpFile); string prebuiltHash = hashFile(tmpFile);
string pkgId = queryPkgId(hash); string pkgId = queryPkgId(hash);
string prebuiltFile = outDir + "/" + string prebuiltFile = outDir + "/" +
pkgId + "-" + hash + "-" + prebuiltHash + ".tar.bz2"; pkgId + "-" + (string) hash + "-" + prebuiltHash + ".tar.bz2";
rename(tmpFile.c_str(), prebuiltFile.c_str()); rename(tmpFile.c_str(), prebuiltFile.c_str());
} }
} }
void registerPrebuilt(string pkgHash, string prebuiltHash) void registerPrebuilt(Hash pkgHash, Hash prebuiltHash)
{ {
checkHash(pkgHash);
checkHash(prebuiltHash);
setDB(nixDB, dbPrebuilts, pkgHash, prebuiltHash); setDB(nixDB, dbPrebuilts, pkgHash, prebuiltHash);
} }
string registerFile(string filename) Hash registerFile(string filename)
{ {
filename = absPath(filename); filename = absPath(filename);
string hash = hashFile(filename); Hash hash = hashFile(filename);
setDB(nixDB, dbRefs, hash, filename); setDB(nixDB, dbRefs, hash, filename);
return hash; return hash;
} }
void registerURL(string hash, string url) void registerURL(Hash hash, string url)
{ {
checkHash(hash);
setDB(nixDB, dbNetSources, hash, url); setDB(nixDB, dbNetSources, hash, url);
/* !!! currently we allow only one network source per hash */ /* !!! currently we allow only one network source per hash */
} }
/* This is primarily used for bootstrapping. */ /* This is primarily used for bootstrapping. */
void registerInstalledPkg(string hash, string path) void registerInstalledPkg(Hash hash, string path)
{ {
checkHash(hash);
if (path == "") if (path == "")
delDB(nixDB, dbInstPkgs, hash); delDB(nixDB, dbInstPkgs, hash);
else else
@ -498,12 +494,13 @@ void verifyDB()
it != fileRefs.end(); it++) it != fileRefs.end(); it++)
{ {
try { try {
if (hashFile(it->second) != it->first) { Hash hash = parseHash(it->first);
if (hashFile(it->second) != hash) {
cerr << "file " << it->second << " has changed\n"; cerr << "file " << it->second << " has changed\n";
delDB(nixDB, dbRefs, it->first); delDB(nixDB, dbRefs, it->first);
} }
} catch (BadRefError e) { /* !!! better error check */ } catch (Error e) { /* !!! better error check */
cerr << "file " << it->second << " has disappeared\n"; cerr << "error: " << e.what() << endl;
delDB(nixDB, dbRefs, it->first); delDB(nixDB, dbRefs, it->first);
} }
} }
@ -544,7 +541,7 @@ void printInfo(Strings::iterator first, Strings::iterator last)
{ {
for (Strings::iterator it = first; it != last; it++) { for (Strings::iterator it = first; it != last; it++) {
try { try {
cout << *it << " " << queryPkgId(*it) << endl; cout << *it << " " << queryPkgId(parseHash(*it)) << endl;
} catch (Error & e) { // !!! more specific } catch (Error & e) { // !!! more specific
cout << *it << " (descriptor missing)\n"; cout << *it << " (descriptor missing)\n";
} }
@ -559,7 +556,7 @@ void computeClosure(Strings::iterator first, Strings::iterator last,
set<string> doneSet; set<string> doneSet;
while (!workList.empty()) { while (!workList.empty()) {
string hash = workList.front(); Hash hash = parseHash(workList.front());
workList.pop_front(); workList.pop_front();
if (doneSet.find(hash) == doneSet.end()) { if (doneSet.find(hash) == doneSet.end()) {
@ -605,7 +602,7 @@ void printGraph(Strings::iterator first, Strings::iterator last)
it != allHashes.end(); it++) it != allHashes.end(); it++)
{ {
Params pkgImports, fileImports, arguments; Params pkgImports, fileImports, arguments;
readPkgDescr(*it, pkgImports, fileImports, arguments); readPkgDescr(parseHash(*it), pkgImports, fileImports, arguments);
cout << dotQuote(*it) << "[label = \"" cout << dotQuote(*it) << "[label = \""
<< getFromEnv(arguments, "id") << getFromEnv(arguments, "id")
@ -633,8 +630,8 @@ void fetch(string id)
} }
/* Register it by hash. */ /* Register it by hash. */
string hash = registerFile(fn); Hash hash = registerFile(fn);
cout << hash << endl; cout << (string) hash << endl;
} }
@ -648,60 +645,60 @@ void fetch(Strings::iterator first, Strings::iterator last)
void printUsage() void printUsage()
{ {
cerr << cerr <<
"Usage: nix SUBCOMMAND OPTIONS... "Usage: nix SUBCOMMAND OPTIONS...\n\
\n\
Subcommands: Subcommands:\n\
\n\
init init\n\
Initialize the database. Initialize the database.\n\
\n\
verify verify\n\
Remove stale entries from the database. Remove stale entries from the database.\n\
\n\
regfile FILENAME... regfile FILENAME...\n\
Register each FILENAME keyed by its hash. Register each FILENAME keyed by its hash.\n\
\n\
reginst HASH PATH reginst HASH PATH\n\
Register an installed package. Register an installed package.\n\
\n\
getpkg HASH... getpkg HASH...\n\
For each HASH, ensure that the package referenced by HASH is For each HASH, ensure that the package referenced by HASH is\n\
installed. Print out the path of the installation on stdout. installed. Print out the path of the installation on stdout.\n\
\n\
delpkg HASH... delpkg HASH...\n\
Uninstall the package referenced by each HASH, disregarding any Uninstall the package referenced by each HASH, disregarding any\n\
dependencies that other packages may have on HASH. dependencies that other packages may have on HASH.\n\
\n\
listinst listinst\n\
Prints a list of installed packages. Prints a list of installed packages.\n\
\n\
run HASH ARGS... run HASH ARGS...\n\
Run the descriptor referenced by HASH with the given arguments. Run the descriptor referenced by HASH with the given arguments.\n\
\n\
ensure HASH... ensure HASH...\n\
Like getpkg, but if HASH refers to a run descriptor, fetch only Like getpkg, but if HASH refers to a run descriptor, fetch only\n\
the dependencies. the dependencies.\n\
\n\
export DIR HASH... export DIR HASH...\n\
Export installed packages to DIR. Export installed packages to DIR.\n\
\n\
regprebuilt HASH1 HASH2 regprebuilt HASH1 HASH2\n\
Inform Nix that an export HASH2 can be used to fast-build HASH1. Inform Nix that an export HASH2 can be used to fast-build HASH1.\n\
\n\
info HASH... info HASH...\n\
Print information about the specified descriptors. Print information about the specified descriptors.\n\
\n\
closure HASH... closure HASH...\n\
Determine the closure of the set of descriptors under the import Determine the closure of the set of descriptors under the import\n\
relation, starting at the given roots. relation, starting at the given roots.\n\
\n\
graph HASH... graph HASH...\n\
Like closure, but print a dot graph specification. Like closure, but print a dot graph specification.\n\
\n\
fetch ID... fetch ID...\n\
Fetch the objects identified by ID and place them in the Nix Fetch the objects identified by ID and place them in the Nix\n\
sources directory. ID can be a hash or URL. Print out the hash sources directory. ID can be a hash or URL. Print out the hash\n\
of the object. of the object.\n\
"; ";
} }
@ -743,29 +740,31 @@ void run(Strings::iterator argCur, Strings::iterator argEnd)
verifyDB(); verifyDB();
} else if (cmd == "getpkg") { } else if (cmd == "getpkg") {
for (Strings::iterator it = argCur; it != argEnd; it++) { for (Strings::iterator it = argCur; it != argEnd; it++) {
string path = getPkg(*it); string path = getPkg(parseHash(*it));
cout << path << endl; cout << path << endl;
} }
} else if (cmd == "delpkg") { } else if (cmd == "delpkg") {
for_each(argCur, argEnd, delPkg); for (Strings::iterator it = argCur; it != argEnd; it++)
delPkg(parseHash(*it));
} else if (cmd == "run") { } else if (cmd == "run") {
if (argc < 1) throw argcError; if (argc < 1) throw argcError;
runPkg(*argCur, argCur + 1, argEnd); runPkg(parseHash(*argCur), argCur + 1, argEnd);
} else if (cmd == "ensure") { } else if (cmd == "ensure") {
for_each(argCur, argEnd, ensurePkg); for (Strings::iterator it = argCur; it != argEnd; it++)
ensurePkg(parseHash(*it));
} else if (cmd == "export") { } else if (cmd == "export") {
if (argc < 1) throw argcError; if (argc < 1) throw argcError;
exportPkgs(*argCur, argCur + 1, argEnd); exportPkgs(*argCur, argCur + 1, argEnd);
} else if (cmd == "regprebuilt") { } else if (cmd == "regprebuilt") {
if (argc != 2) throw argcError; if (argc != 2) throw argcError;
registerPrebuilt(*argCur, argCur[1]); registerPrebuilt(parseHash(argCur[0]), parseHash(argCur[1]));
} else if (cmd == "regfile") { } else if (cmd == "regfile") {
for_each(argCur, argEnd, registerFile); for_each(argCur, argEnd, registerFile);
} else if (cmd == "regurl") { } else if (cmd == "regurl") {
registerURL(argCur[0], argCur[1]); registerURL(parseHash(argCur[0]), argCur[1]);
} else if (cmd == "reginst") { } else if (cmd == "reginst") {
if (argc != 2) throw argcError; if (argc != 2) throw argcError;
registerInstalledPkg(*argCur, argCur[1]); registerInstalledPkg(parseHash(argCur[0]), argCur[1]);
} else if (cmd == "listinst") { } else if (cmd == "listinst") {
if (argc != 0) throw argcError; if (argc != 0) throw argcError;
listInstalledPkgs(); listInstalledPkgs();

16
src/test.cc Normal file
View file

@ -0,0 +1,16 @@
#include <iostream>
#include "hash.hh"
int main(int argc, char * * argv)
{
Hash h = hashFile("/etc/passwd");
cout << (string) h << endl;
h = parseHash("0b0ffd0538622bfe20b92c4aa57254d9");
cout << (string) h << endl;
return 0;
}

View file

@ -27,53 +27,6 @@ string absPath(string filename, string dir)
} }
static string printHash(unsigned char * buf)
{
ostringstream str;
for (int i = 0; i < 16; i++) {
str.fill('0');
str.width(2);
str << hex << (int) buf[i];
}
return str.str();
}
/* Verify that a reference is valid (that is, is a MD5 hash code). */
bool isHash(const string & s)
{
if (s.length() != 32) return false;
for (int i = 0; i < 32; i++) {
char c = s[i];
if (!((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f')))
return false;
}
return true;
}
void checkHash(const string & s)
{
if (!isHash(s)) throw BadRefError("invalid reference: " + s);
}
/* Compute the MD5 hash of a file. */
string hashFile(string filename)
{
unsigned char hash[16];
FILE * file = fopen(filename.c_str(), "rb");
if (!file)
throw BadRefError("file `" + filename + "' does not exist");
int err = md5_stream(file, hash);
fclose(file);
if (err) throw BadRefError("cannot hash file");
return printHash(hash);
}
/* Return the directory part of the given path, i.e., everything /* Return the directory part of the given path, i.e., everything
before the final `/'. */ before the final `/'. */
string dirOf(string s) string dirOf(string s)

View file

@ -7,10 +7,6 @@
#include <unistd.h> #include <unistd.h>
extern "C" {
#include "md5.h"
}
using namespace std; using namespace std;
@ -29,12 +25,6 @@ public:
UsageError(string _err) : Error(_err) { }; UsageError(string _err) : Error(_err) { };
}; };
class BadRefError : public Error
{
public:
BadRefError(string _err) : Error(_err) { };
};
typedef vector<string> Strings; typedef vector<string> Strings;
@ -50,9 +40,6 @@ extern string nixHomeDirEnvVar;
string absPath(string filename, string dir = ""); string absPath(string filename, string dir = "");
bool isHash(const string & s);
void checkHash(const string & s);
string hashFile(string filename);
string dirOf(string s); string dirOf(string s);
string baseNameOf(string s); string baseNameOf(string s);