aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstore/build.cc5
-rw-r--r--src/libstore/references.cc68
-rw-r--r--src/libstore/references.hh2
-rw-r--r--src/libutil/hash.cc6
-rw-r--r--src/libutil/hash.hh2
5 files changed, 52 insertions, 31 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index e4ff1efd3..193974bf8 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1390,10 +1390,7 @@ void DerivationGoal::computeClosure()
in it. */
PathSet references;
if (!pathExists(path + "/nix-support/no-scan")) {
- Paths references2;
- references2 = filterReferences(path,
- Paths(allPaths.begin(), allPaths.end()));
- references = PathSet(references2.begin(), references2.end());
+ references = scanForReferences(path, allPaths);
/* For debugging, print out the referenced and
unreferenced paths. */
diff --git a/src/libstore/references.cc b/src/libstore/references.cc
index 843aed97f..75a6efead 100644
--- a/src/libstore/references.cc
+++ b/src/libstore/references.cc
@@ -11,26 +11,45 @@
#include "hash.hh"
+static unsigned int refLength = 32; /* characters */
+
+
static void search(const string & s,
- Strings & ids, Strings & seen)
+ StringSet & ids, StringSet & seen)
{
- for (Strings::iterator i = ids.begin();
- i != ids.end(); )
- {
- checkInterrupt();
- if (s.find(*i) == string::npos)
- i++;
- else {
- debug(format("found reference to `%1%'") % *i);
- seen.push_back(*i);
- i = ids.erase(i);
+ static bool initialised = false;
+ static bool isBase32[256];
+ if (!initialised) {
+ for (unsigned int i = 0; i < 256; ++i) isBase32[i] = false;
+ for (unsigned int i = 0; i < base32Chars.size(); ++i)
+ isBase32[(unsigned char) base32Chars[i]] = true;
+ initialised = true;
+ }
+
+ for (unsigned int i = 0; i + refLength <= s.size(); ) {
+ int j;
+ bool match = true;
+ for (j = refLength - 1; j >= 0; --j)
+ if (!isBase32[(unsigned char) s[i + j]]) {
+ i += j + 1;
+ match = false;
+ break;
+ }
+ if (!match) continue;
+ string ref(s, i, refLength);
+ if (ids.find(ref) != ids.end()) {
+ debug(format("found reference to `%1%' at offset `%2%'")
+ % ref % i);
+ seen.insert(ref);
+ ids.erase(ref);
}
+ ++i;
}
}
void checkPath(const string & path,
- Strings & ids, Strings & seen)
+ StringSet & ids, StringSet & seen)
{
checkInterrupt();
@@ -69,36 +88,35 @@ void checkPath(const string & path,
}
-Strings filterReferences(const string & path, const Strings & paths)
+PathSet scanForReferences(const string & path, const PathSet & paths)
{
- map<string, string> backMap;
- Strings ids;
- Strings seen;
+ map<string, Path> backMap;
+ StringSet ids;
+ StringSet seen;
/* For efficiency (and a higher hit rate), just search for the
hash part of the file name. (This assumes that all references
have the form `HASH-bla'). */
- for (Strings::const_iterator i = paths.begin();
- i != paths.end(); i++)
- {
+ for (PathSet::const_iterator i = paths.begin(); i != paths.end(); i++) {
string baseName = baseNameOf(*i);
unsigned int pos = baseName.find('-');
if (pos == string::npos)
throw Error(format("bad reference `%1%'") % *i);
string s = string(baseName, 0, pos);
+ assert(s.size() == refLength);
+ assert(backMap.find(s) == backMap.end());
// parseHash(htSHA256, s);
- ids.push_back(s);
+ ids.insert(s);
backMap[s] = *i;
}
checkPath(path, ids, seen);
- Strings found;
- for (Strings::iterator i = seen.begin(); i != seen.end(); i++)
- {
- map<string, string>::iterator j;
+ PathSet found;
+ for (StringSet::iterator i = seen.begin(); i != seen.end(); i++) {
+ map<string, Path>::iterator j;
if ((j = backMap.find(*i)) == backMap.end()) abort();
- found.push_back(j->second);
+ found.insert(j->second);
}
return found;
diff --git a/src/libstore/references.hh b/src/libstore/references.hh
index ada23a883..4b1299e7a 100644
--- a/src/libstore/references.hh
+++ b/src/libstore/references.hh
@@ -4,7 +4,7 @@
#include "util.hh"
-Strings filterReferences(const Path & path, const Strings & refs);
+PathSet scanForReferences(const Path & path, const PathSet & refs);
#endif /* !__REFERENCES_H */
diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc
index 271e63665..71d4ba67e 100644
--- a/src/libutil/hash.cc
+++ b/src/libutil/hash.cc
@@ -109,13 +109,15 @@ static unsigned char divMod(unsigned char * bytes, unsigned char y)
// omitted: E O U T
-char chars[] = "0123456789abcdfghijklmnpqrsvwxyz";
+const string base32Chars = "0123456789abcdfghijklmnpqrsvwxyz";
string printHash32(const Hash & hash)
{
Hash hash2(hash);
unsigned int len = (hash.hashSize * 8 - 1) / 5 + 1;
+
+ const char * chars = base32Chars.c_str();
string s(len, '0');
@@ -165,6 +167,8 @@ Hash parseHash32(HashType ht, const string & s)
{
Hash hash(ht);
+ const char * chars = base32Chars.c_str();
+
for (unsigned int i = 0; i < s.length(); ++i) {
char c = s[i];
unsigned char digit;
diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh
index 398b17421..0a0dfed7e 100644
--- a/src/libutil/hash.hh
+++ b/src/libutil/hash.hh
@@ -15,6 +15,8 @@ const int md5HashSize = 16;
const int sha1HashSize = 20;
const int sha256HashSize = 32;
+extern const string base32Chars;
+
struct Hash
{