* Store the size of a store path in the database (to be precise, the
size of the NAR serialisation of the path, i.e., `nix-store --dump PATH'). This is useful for Hydra.
This commit is contained in:
		
							parent
							
								
									fb9368b5a0
								
							
						
					
					
						commit
						a3883cbd28
					
				
					 16 changed files with 144 additions and 91 deletions
				
			
		
							
								
								
									
										2
									
								
								externals/Makefile.am
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								externals/Makefile.am
									
										
									
									
										vendored
									
									
								
							|  | @ -47,7 +47,7 @@ build-sqlite: | ||||||
| else | else | ||||||
| build-sqlite: $(SQLITE) | build-sqlite: $(SQLITE) | ||||||
| 	(cd $(SQLITE) && \ | 	(cd $(SQLITE) && \ | ||||||
| 	CC="$(CC)" ./configure --disable-static --prefix=$(pkglibdir)/dummy --libdir=${pkglibdir} $(SUB_CONFIGURE_FLAGS) && \ | 	CC="$(CC)" CFLAGS="-DSQLITE_ENABLE_COLUMN_METADATA=1" ./configure --disable-static --prefix=$(pkglibdir)/dummy --libdir=${pkglibdir} $(SUB_CONFIGURE_FLAGS) && \ | ||||||
| 	$(MAKE) ) | 	$(MAKE) ) | ||||||
| 	touch build-sqlite | 	touch build-sqlite | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1547,7 +1547,7 @@ void DerivationGoal::startBuilder() | ||||||
| 
 | 
 | ||||||
|         /* Write closure info to `fileName'. */ |         /* Write closure info to `fileName'. */ | ||||||
|         writeFile(tmpDir + "/" + fileName, |         writeFile(tmpDir + "/" + fileName, | ||||||
|             makeValidityRegistration(paths, false, false)); |             worker.store.makeValidityRegistration(paths, false, false)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|      |      | ||||||
|  | @ -1870,7 +1870,7 @@ PathSet parseReferenceSpecifiers(const Derivation & drv, string attr) | ||||||
| void DerivationGoal::computeClosure() | void DerivationGoal::computeClosure() | ||||||
| { | { | ||||||
|     map<Path, PathSet> allReferences; |     map<Path, PathSet> allReferences; | ||||||
|     map<Path, Hash> contentHashes; |     map<Path, HashResult> contentHashes; | ||||||
| 
 | 
 | ||||||
|     /* When using a build hook, the build hook can register the output
 |     /* When using a build hook, the build hook can register the output
 | ||||||
|        as valid (by doing `nix-store --import').  If so we don't have |        as valid (by doing `nix-store --import').  If so we don't have | ||||||
|  | @ -1927,7 +1927,7 @@ void DerivationGoal::computeClosure() | ||||||
|             if (ht == htUnknown) |             if (ht == htUnknown) | ||||||
|                 throw BuildError(format("unknown hash algorithm `%1%'") % algo); |                 throw BuildError(format("unknown hash algorithm `%1%'") % algo); | ||||||
|             Hash h = parseHash(ht, i->second.hash); |             Hash h = parseHash(ht, i->second.hash); | ||||||
|             Hash h2 = recursive ? hashPath(ht, path) : hashFile(ht, path); |             Hash h2 = recursive ? hashPath(ht, path).first : hashFile(ht, path); | ||||||
|             if (h != h2) |             if (h != h2) | ||||||
|                 throw BuildError( |                 throw BuildError( | ||||||
|                     format("output path `%1%' should have %2% hash `%3%', instead has `%4%'") |                     format("output path `%1%' should have %2% hash `%3%', instead has `%4%'") | ||||||
|  | @ -1941,7 +1941,7 @@ void DerivationGoal::computeClosure() | ||||||
| 	   contained in it.  Compute the SHA-256 NAR hash at the same | 	   contained in it.  Compute the SHA-256 NAR hash at the same | ||||||
| 	   time.  The hash is stored in the database so that we can | 	   time.  The hash is stored in the database so that we can | ||||||
| 	   verify later on whether nobody has messed with the store. */ | 	   verify later on whether nobody has messed with the store. */ | ||||||
|         Hash hash; |         HashResult hash; | ||||||
|         PathSet references = scanForReferences(path, allPaths, hash); |         PathSet references = scanForReferences(path, allPaths, hash); | ||||||
|         contentHashes[path] = hash; |         contentHashes[path] = hash; | ||||||
| 
 | 
 | ||||||
|  | @ -1970,14 +1970,18 @@ void DerivationGoal::computeClosure() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Register each output path as valid, and register the sets of
 |     /* Register each output path as valid, and register the sets of
 | ||||||
|        paths referenced by each of them.  !!! this should be |        paths referenced by each of them. */ | ||||||
|        atomic so that either all paths are registered as valid, or |     ValidPathInfos infos; | ||||||
|        none are. */ |     foreach (DerivationOutputs::iterator, i, drv.outputs) { | ||||||
|     foreach (DerivationOutputs::iterator, i, drv.outputs) |         ValidPathInfo info; | ||||||
|         worker.store.registerValidPath(i->second.path, |         info.path = i->second.path; | ||||||
|             contentHashes[i->second.path], |         info.hash = contentHashes[i->second.path].first; | ||||||
|             allReferences[i->second.path], |         info.narSize = contentHashes[i->second.path].second; | ||||||
|             drvPath); |         info.references = allReferences[i->second.path]; | ||||||
|  |         info.deriver = drvPath; | ||||||
|  |         infos.push_back(info); | ||||||
|  |     } | ||||||
|  |     worker.store.registerValidPaths(infos); | ||||||
| 
 | 
 | ||||||
|     /* It is now safe to delete the lock files, since all future
 |     /* It is now safe to delete the lock files, since all future
 | ||||||
|        lockers will see that the output paths are valid; they will not |        lockers will see that the output paths are valid; they will not | ||||||
|  | @ -2385,10 +2389,15 @@ void SubstitutionGoal::finished() | ||||||
| 
 | 
 | ||||||
|     canonicalisePathMetaData(storePath); |     canonicalisePathMetaData(storePath); | ||||||
| 
 | 
 | ||||||
|     Hash contentHash = hashPath(htSHA256, storePath); |     HashResult hash = hashPath(htSHA256, storePath); | ||||||
|      |      | ||||||
|     worker.store.registerValidPath(storePath, contentHash, |     ValidPathInfo info2; | ||||||
|         info.references, info.deriver); |     info2.path = storePath; | ||||||
|  |     info2.hash = hash.first; | ||||||
|  |     info2.narSize = hash.second; | ||||||
|  |     info2.references = info.references; | ||||||
|  |     info2.deriver = info.deriver; | ||||||
|  |     worker.store.registerValidPath(info2); | ||||||
| 
 | 
 | ||||||
|     outputLock->setDeletion(true); |     outputLock->setDeletion(true); | ||||||
|      |      | ||||||
|  |  | ||||||
|  | @ -327,9 +327,16 @@ void LocalStore::openDB(bool create) | ||||||
|             throw SQLiteError(db, "initialising database schema"); |             throw SQLiteError(db, "initialising database schema"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /* Backwards compatibility with old (pre-release) databases.  Can
 | ||||||
|  |        remove this eventually. */ | ||||||
|  |     if (sqlite3_table_column_metadata(db, 0, "ValidPaths", "narSize", 0, 0, 0, 0, 0) != SQLITE_OK) { | ||||||
|  |         if (sqlite3_exec(db, "alter table ValidPaths add column narSize integer" , 0, 0, 0) != SQLITE_OK) | ||||||
|  |             throw SQLiteError(db, "adding column narSize"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /* Prepare SQL statements. */ |     /* Prepare SQL statements. */ | ||||||
|     stmtRegisterValidPath.create(db, |     stmtRegisterValidPath.create(db, | ||||||
|         "insert into ValidPaths (path, hash, registrationTime, deriver) values (?, ?, ?, ?);"); |         "insert into ValidPaths (path, hash, registrationTime, deriver, narSize) values (?, ?, ?, ?, ?);"); | ||||||
|     stmtAddReference.create(db, |     stmtAddReference.create(db, | ||||||
|         "insert or replace into Refs (referrer, reference) values (?, ?);"); |         "insert or replace into Refs (referrer, reference) values (?, ?);"); | ||||||
|     stmtQueryPathInfo.create(db, |     stmtQueryPathInfo.create(db, | ||||||
|  | @ -431,19 +438,6 @@ void canonicalisePathMetaData(const Path & path) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void LocalStore::registerValidPath(const Path & path, |  | ||||||
|     const Hash & hash, const PathSet & references, |  | ||||||
|     const Path & deriver) |  | ||||||
| { |  | ||||||
|     ValidPathInfo info; |  | ||||||
|     info.path = path; |  | ||||||
|     info.hash = hash; |  | ||||||
|     info.references = references; |  | ||||||
|     info.deriver = deriver; |  | ||||||
|     registerValidPath(info); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| unsigned long long LocalStore::addValidPath(const ValidPathInfo & info) | unsigned long long LocalStore::addValidPath(const ValidPathInfo & info) | ||||||
| { | { | ||||||
|     SQLiteStmtUse use(stmtRegisterValidPath); |     SQLiteStmtUse use(stmtRegisterValidPath); | ||||||
|  | @ -454,6 +448,10 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info) | ||||||
|         stmtRegisterValidPath.bind(info.deriver); |         stmtRegisterValidPath.bind(info.deriver); | ||||||
|     else |     else | ||||||
|         stmtRegisterValidPath.bind(); // null
 |         stmtRegisterValidPath.bind(); // null
 | ||||||
|  |     if (info.narSize != 0) | ||||||
|  |         stmtRegisterValidPath.bind(info.narSize); | ||||||
|  |     else | ||||||
|  |         stmtRegisterValidPath.bind(); // null
 | ||||||
|     if (sqlite3_step(stmtRegisterValidPath) != SQLITE_DONE) |     if (sqlite3_step(stmtRegisterValidPath) != SQLITE_DONE) | ||||||
|         throw SQLiteError(db, format("registering valid path `%1%' in database") % info.path); |         throw SQLiteError(db, format("registering valid path `%1%' in database") % info.path); | ||||||
|     unsigned long long id = sqlite3_last_insert_rowid(db); |     unsigned long long id = sqlite3_last_insert_rowid(db); | ||||||
|  | @ -920,10 +918,18 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name, | ||||||
|                the path in the database.  We may just have computed it |                the path in the database.  We may just have computed it | ||||||
|                above (if called with recursive == true and hashAlgo == |                above (if called with recursive == true and hashAlgo == | ||||||
|                sha256); otherwise, compute it here. */ |                sha256); otherwise, compute it here. */ | ||||||
|             registerValidPath(dstPath, |             HashResult hash; | ||||||
|                 (recursive && hashAlgo == htSHA256) ? h : |             if (recursive) { | ||||||
|                 (recursive ? hashString(htSHA256, dump) : hashPath(htSHA256, dstPath)), |                 hash.first = hashAlgo == htSHA256 ? h : hashString(htSHA256, dump); | ||||||
|                 PathSet(), ""); |                 hash.second = dump.size(); | ||||||
|  |             } else | ||||||
|  |                 hash = hashPath(htSHA256, dstPath); | ||||||
|  |              | ||||||
|  |             ValidPathInfo info; | ||||||
|  |             info.path = dstPath; | ||||||
|  |             info.hash = hash.first; | ||||||
|  |             info.narSize = hash.second; | ||||||
|  |             registerValidPath(info); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         outputLock.setDeletion(true); |         outputLock.setDeletion(true); | ||||||
|  | @ -971,8 +977,14 @@ Path LocalStore::addTextToStore(const string & name, const string & s, | ||||||
| 
 | 
 | ||||||
|             canonicalisePathMetaData(dstPath); |             canonicalisePathMetaData(dstPath); | ||||||
| 
 | 
 | ||||||
|             registerValidPath(dstPath, |             HashResult hash = hashPath(htSHA256, dstPath); | ||||||
|                 hashPath(htSHA256, dstPath), references, ""); |              | ||||||
|  |             ValidPathInfo info; | ||||||
|  |             info.path = dstPath; | ||||||
|  |             info.hash = hash.first; | ||||||
|  |             info.narSize = hash.second; | ||||||
|  |             info.references = references; | ||||||
|  |             registerValidPath(info); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         outputLock.setDeletion(true); |         outputLock.setDeletion(true); | ||||||
|  | @ -998,7 +1010,7 @@ struct HashAndWriteSink : Sink | ||||||
|     Hash currentHash() |     Hash currentHash() | ||||||
|     { |     { | ||||||
|         HashSink hashSinkClone(hashSink); |         HashSink hashSinkClone(hashSink); | ||||||
|         return hashSinkClone.finish(); |         return hashSinkClone.finish().first; | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -1136,7 +1148,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source) | ||||||
|     Path deriver = readString(hashAndReadSource); |     Path deriver = readString(hashAndReadSource); | ||||||
|     if (deriver != "") assertStorePath(deriver); |     if (deriver != "") assertStorePath(deriver); | ||||||
| 
 | 
 | ||||||
|     Hash hash = hashAndReadSource.hashSink.finish(); |     Hash hash = hashAndReadSource.hashSink.finish().first; | ||||||
|     hashAndReadSource.hashing = false; |     hashAndReadSource.hashing = false; | ||||||
| 
 | 
 | ||||||
|     bool haveSignature = readInt(hashAndReadSource) == 1; |     bool haveSignature = readInt(hashAndReadSource) == 1; | ||||||
|  | @ -1200,9 +1212,15 @@ Path LocalStore::importPath(bool requireSignature, Source & source) | ||||||
|              |              | ||||||
|             /* !!! if we were clever, we could prevent the hashPath()
 |             /* !!! if we were clever, we could prevent the hashPath()
 | ||||||
|                here. */ |                here. */ | ||||||
|             if (deriver != "" && !isValidPath(deriver)) deriver = ""; |             HashResult hash = hashPath(htSHA256, dstPath); | ||||||
|             registerValidPath(dstPath, |              | ||||||
|                 hashPath(htSHA256, dstPath), references, deriver); |             ValidPathInfo info; | ||||||
|  |             info.path = dstPath; | ||||||
|  |             info.hash = hash.first; | ||||||
|  |             info.narSize = hash.second; | ||||||
|  |             info.references = references; | ||||||
|  |             info.deriver = deriver != "" && isValidPath(deriver) ? deriver : ""; | ||||||
|  |             registerValidPath(info); | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         outputLock.setDeletion(true); |         outputLock.setDeletion(true); | ||||||
|  | @ -1263,12 +1281,14 @@ void LocalStore::verifyStore(bool checkContents) | ||||||
| 
 | 
 | ||||||
|             /* Check the content hash (optionally - slow). */ |             /* Check the content hash (optionally - slow). */ | ||||||
|             printMsg(lvlTalkative, format("checking contents of `%1%'") % *i); |             printMsg(lvlTalkative, format("checking contents of `%1%'") % *i); | ||||||
|             Hash current = hashPath(info.hash.type, *i); |             Hash current = hashPath(info.hash.type, *i).first; | ||||||
|             if (current != info.hash) { |             if (current != info.hash) { | ||||||
|                 printMsg(lvlError, format("path `%1%' was modified! " |                 printMsg(lvlError, format("path `%1%' was modified! " | ||||||
|                         "expected hash `%2%', got `%3%'") |                         "expected hash `%2%', got `%3%'") | ||||||
|                     % *i % printHash(info.hash) % printHash(current)); |                     % *i % printHash(info.hash) % printHash(current)); | ||||||
|             } |             } | ||||||
|  |              | ||||||
|  |             /* !!! Check info.narSize */ | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -97,6 +97,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     PathSet queryValidPaths(); |     PathSet queryValidPaths(); | ||||||
|      |      | ||||||
|  |     ValidPathInfo queryPathInfo(const Path & path); | ||||||
|  | 
 | ||||||
|     Hash queryPathHash(const Path & path); |     Hash queryPathHash(const Path & path); | ||||||
| 
 | 
 | ||||||
|     void queryReferences(const Path & path, PathSet & references); |     void queryReferences(const Path & path, PathSet & references); | ||||||
|  | @ -173,8 +175,7 @@ public: | ||||||
|        execution of the derivation (or something equivalent).  Also |        execution of the derivation (or something equivalent).  Also | ||||||
|        register the hash of the file system contents of the path.  The |        register the hash of the file system contents of the path.  The | ||||||
|        hash must be a SHA-256 hash. */ |        hash must be a SHA-256 hash. */ | ||||||
|     void registerValidPath(const Path & path, |     void registerValidPath(const ValidPathInfo & info); | ||||||
|         const Hash & hash, const PathSet & references, const Path & deriver); |  | ||||||
| 
 | 
 | ||||||
|     void registerValidPaths(const ValidPathInfos & infos); |     void registerValidPaths(const ValidPathInfos & infos); | ||||||
| 
 | 
 | ||||||
|  | @ -224,10 +225,6 @@ private: | ||||||
|          |          | ||||||
|     void addReference(unsigned long long referrer, unsigned long long reference); |     void addReference(unsigned long long referrer, unsigned long long reference); | ||||||
|      |      | ||||||
|     void registerValidPath(const ValidPathInfo & info); |  | ||||||
| 
 |  | ||||||
|     ValidPathInfo queryPathInfo(const Path & path); |  | ||||||
| 
 |  | ||||||
|     void appendReferrer(const Path & from, const Path & to, bool lock); |     void appendReferrer(const Path & from, const Path & to, bool lock); | ||||||
|      |      | ||||||
|     void rewriteReferrers(const Path & path, bool purge, PathSet referrers); |     void rewriteReferrers(const Path & path, bool purge, PathSet referrers); | ||||||
|  |  | ||||||
|  | @ -68,7 +68,7 @@ static void hashAndLink(bool dryRun, HashToPath & hashToPath, | ||||||
|            the contents of the symlink (i.e. the result of |            the contents of the symlink (i.e. the result of | ||||||
|            readlink()), not the contents of the target (which may not |            readlink()), not the contents of the target (which may not | ||||||
|            even exist). */ |            even exist). */ | ||||||
|         Hash hash = hashPath(htSHA256, path); |         Hash hash = hashPath(htSHA256, path).first; | ||||||
|         stats.totalFiles++; |         stats.totalFiles++; | ||||||
|         printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash)); |         printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -81,7 +81,7 @@ void RefScanSink::operator () (const unsigned char * data, unsigned int len) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| PathSet scanForReferences(const string & path, | PathSet scanForReferences(const string & path, | ||||||
|     const PathSet & refs, Hash & hash) |     const PathSet & refs, HashResult & hash) | ||||||
| { | { | ||||||
|     RefScanSink sink; |     RefScanSink sink; | ||||||
|     std::map<string, Path> backMap; |     std::map<string, Path> backMap; | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| namespace nix { | namespace nix { | ||||||
| 
 | 
 | ||||||
| PathSet scanForReferences(const Path & path, const PathSet & refs, | PathSet scanForReferences(const Path & path, const PathSet & refs, | ||||||
|     Hash & hash); |     HashResult & hash); | ||||||
|      |      | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -247,6 +247,12 @@ bool RemoteStore::querySubstitutablePathInfo(const Path & path, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | ValidPathInfo RemoteStore::queryPathInfo(const Path & path) | ||||||
|  | { | ||||||
|  |     throw Error("not implemented"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| Hash RemoteStore::queryPathHash(const Path & path) | Hash RemoteStore::queryPathHash(const Path & path) | ||||||
| { | { | ||||||
|     openConnection(); |     openConnection(); | ||||||
|  |  | ||||||
|  | @ -29,6 +29,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     PathSet queryValidPaths(); |     PathSet queryValidPaths(); | ||||||
|      |      | ||||||
|  |     ValidPathInfo queryPathInfo(const Path & path); | ||||||
|  | 
 | ||||||
|     Hash queryPathHash(const Path & path); |     Hash queryPathHash(const Path & path); | ||||||
| 
 | 
 | ||||||
|     void queryReferences(const Path & path, PathSet & references); |     void queryReferences(const Path & path, PathSet & references); | ||||||
|  |  | ||||||
|  | @ -3,7 +3,8 @@ create table if not exists ValidPaths ( | ||||||
|     path             text unique not null, |     path             text unique not null, | ||||||
|     hash             text not null, |     hash             text not null, | ||||||
|     registrationTime integer not null, |     registrationTime integer not null, | ||||||
|     deriver          text |     deriver          text, | ||||||
|  |     narSize          integer | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| create table if not exists Refs ( | create table if not exists Refs ( | ||||||
|  |  | ||||||
|  | @ -190,7 +190,7 @@ std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath, | ||||||
|     bool recursive, HashType hashAlgo, PathFilter & filter) |     bool recursive, HashType hashAlgo, PathFilter & filter) | ||||||
| { | { | ||||||
|     HashType ht(hashAlgo); |     HashType ht(hashAlgo); | ||||||
|     Hash h = recursive ? hashPath(ht, srcPath, filter) : hashFile(ht, srcPath); |     Hash h = recursive ? hashPath(ht, srcPath, filter).first : hashFile(ht, srcPath); | ||||||
|     string name = baseNameOf(srcPath); |     string name = baseNameOf(srcPath); | ||||||
|     Path dstPath = makeFixedOutputPath(recursive, hashAlgo, h, name); |     Path dstPath = makeFixedOutputPath(recursive, hashAlgo, h, name); | ||||||
|     return std::pair<Path, Hash>(dstPath, h); |     return std::pair<Path, Hash>(dstPath, h); | ||||||
|  | @ -216,7 +216,7 @@ Path computeStorePathForText(const string & name, const string & s, | ||||||
| /* Return a string accepted by decodeValidPathInfo() that
 | /* Return a string accepted by decodeValidPathInfo() that
 | ||||||
|    registers the specified paths as valid.  Note: it's the |    registers the specified paths as valid.  Note: it's the | ||||||
|    responsibility of the caller to provide a closure. */ |    responsibility of the caller to provide a closure. */ | ||||||
| string makeValidityRegistration(const PathSet & paths, | string StoreAPI::makeValidityRegistration(const PathSet & paths, | ||||||
|     bool showDerivers, bool showHash) |     bool showDerivers, bool showHash) | ||||||
| { | { | ||||||
|     string s = ""; |     string s = ""; | ||||||
|  | @ -224,18 +224,19 @@ string makeValidityRegistration(const PathSet & paths, | ||||||
|     foreach (PathSet::iterator, i, paths) { |     foreach (PathSet::iterator, i, paths) { | ||||||
|         s += *i + "\n"; |         s += *i + "\n"; | ||||||
| 
 | 
 | ||||||
|         if (showHash) |         ValidPathInfo info = queryPathInfo(*i); | ||||||
|             s += printHash(store->queryPathHash(*i)) + "\n"; |  | ||||||
| 
 | 
 | ||||||
|         Path deriver = showDerivers ? store->queryDeriver(*i) : ""; |         if (showHash) { | ||||||
|  |             s += printHash(info.hash) + "\n"; | ||||||
|  |             s += (format("%1%\n") % info.narSize).str(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Path deriver = showDerivers ? info.deriver : ""; | ||||||
|         s += deriver + "\n"; |         s += deriver + "\n"; | ||||||
| 
 | 
 | ||||||
|         PathSet references; |         s += (format("%1%\n") % info.references.size()).str(); | ||||||
|         store->queryReferences(*i, references); |  | ||||||
| 
 | 
 | ||||||
|         s += (format("%1%\n") % references.size()).str(); |         foreach (PathSet::iterator, j, info.references) | ||||||
|              |  | ||||||
|         foreach (PathSet::iterator, j, references) |  | ||||||
|             s += *j + "\n"; |             s += *j + "\n"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -252,6 +253,8 @@ ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven) | ||||||
|         string s; |         string s; | ||||||
|         getline(str, s); |         getline(str, s); | ||||||
|         info.hash = parseHash(htSHA256, s); |         info.hash = parseHash(htSHA256, s); | ||||||
|  |         getline(str, s); | ||||||
|  |         if (!string2Int(s, info.narSize)) throw Error("number expected"); | ||||||
|     } |     } | ||||||
|     getline(str, info.deriver); |     getline(str, info.deriver); | ||||||
|     string s; int n; |     string s; int n; | ||||||
|  |  | ||||||
|  | @ -90,6 +90,21 @@ struct SubstitutablePathInfo | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | struct ValidPathInfo  | ||||||
|  | { | ||||||
|  |     Path path; | ||||||
|  |     Path deriver; | ||||||
|  |     Hash hash; | ||||||
|  |     PathSet references; | ||||||
|  |     time_t registrationTime; | ||||||
|  |     unsigned long long narSize; // 0 = unknown
 | ||||||
|  |     unsigned long long id; // internal use only
 | ||||||
|  |     ValidPathInfo() : registrationTime(0), narSize(0) { } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef list<ValidPathInfo> ValidPathInfos; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class StoreAPI  | class StoreAPI  | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  | @ -102,6 +117,9 @@ public: | ||||||
|     /* Query the set of valid paths. */ |     /* Query the set of valid paths. */ | ||||||
|     virtual PathSet queryValidPaths() = 0; |     virtual PathSet queryValidPaths() = 0; | ||||||
| 
 | 
 | ||||||
|  |     /* Query information about a valid path. */ | ||||||
|  |     virtual ValidPathInfo queryPathInfo(const Path & path) = 0; | ||||||
|  | 
 | ||||||
|     /* Queries the hash of a valid path. */  |     /* Queries the hash of a valid path. */  | ||||||
|     virtual Hash queryPathHash(const Path & path) = 0; |     virtual Hash queryPathHash(const Path & path) = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -214,6 +232,12 @@ public: | ||||||
|     /* Clear the "failed" status of the given paths.  The special
 |     /* Clear the "failed" status of the given paths.  The special
 | ||||||
|        value `*' causes all failed paths to be cleared. */ |        value `*' causes all failed paths to be cleared. */ | ||||||
|     virtual void clearFailedPaths(const PathSet & paths) = 0; |     virtual void clearFailedPaths(const PathSet & paths) = 0; | ||||||
|  | 
 | ||||||
|  |     /* Return a string representing information about the path that
 | ||||||
|  |        can be loaded into the database using `nix-store --load-db' or | ||||||
|  |        `nix-store --register-validity'. */ | ||||||
|  |     string makeValidityRegistration(const PathSet & paths, | ||||||
|  |         bool showDerivers, bool showHash); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -307,22 +331,6 @@ boost::shared_ptr<StoreAPI> openStore(); | ||||||
| string showPaths(const PathSet & paths); | string showPaths(const PathSet & paths); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| string makeValidityRegistration(const PathSet & paths, |  | ||||||
|     bool showDerivers, bool showHash); |  | ||||||
|      |  | ||||||
| struct ValidPathInfo  |  | ||||||
| { |  | ||||||
|     Path path; |  | ||||||
|     Path deriver; |  | ||||||
|     Hash hash; |  | ||||||
|     PathSet references; |  | ||||||
|     time_t registrationTime; |  | ||||||
|     unsigned long long id; // internal use only
 |  | ||||||
|     ValidPathInfo() : registrationTime(0) { } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef list<ValidPathInfo> ValidPathInfos; |  | ||||||
| 
 |  | ||||||
| ValidPathInfo decodeValidPathInfo(std::istream & str, | ValidPathInfo decodeValidPathInfo(std::istream & str, | ||||||
|     bool hashGiven = false); |     bool hashGiven = false); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -286,12 +286,14 @@ Hash hashFile(HashType ht, const Path & path) | ||||||
| HashSink::HashSink(HashType ht) : ht(ht) | HashSink::HashSink(HashType ht) : ht(ht) | ||||||
| { | { | ||||||
|     ctx = new Ctx; |     ctx = new Ctx; | ||||||
|  |     bytes = 0; | ||||||
|     start(ht, *ctx); |     start(ht, *ctx); | ||||||
| } | } | ||||||
|      |      | ||||||
| HashSink::HashSink(const HashSink & h) | HashSink::HashSink(const HashSink & h) | ||||||
| { | { | ||||||
|     ht = h.ht; |     ht = h.ht; | ||||||
|  |     bytes = h.bytes; | ||||||
|     ctx = new Ctx; |     ctx = new Ctx; | ||||||
|     *ctx = *h.ctx; |     *ctx = *h.ctx; | ||||||
| } | } | ||||||
|  | @ -304,18 +306,20 @@ HashSink::~HashSink() | ||||||
| void HashSink::operator () | void HashSink::operator () | ||||||
|     (const unsigned char * data, unsigned int len) |     (const unsigned char * data, unsigned int len) | ||||||
| { | { | ||||||
|  |     bytes += len; | ||||||
|     update(ht, *ctx, data, len); |     update(ht, *ctx, data, len); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Hash HashSink::finish() | HashResult HashSink::finish() | ||||||
| { | { | ||||||
|     Hash hash(ht); |     Hash hash(ht); | ||||||
|     nix::finish(ht, *ctx, hash.hash); |     nix::finish(ht, *ctx, hash.hash); | ||||||
|     return hash; |     return HashResult(hash, bytes); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Hash hashPath(HashType ht, const Path & path, PathFilter & filter) | HashResult hashPath( | ||||||
|  |     HashType ht, const Path & path, PathFilter & filter) | ||||||
| { | { | ||||||
|     HashSink sink(ht); |     HashSink sink(ht); | ||||||
|     dumpPath(path, sink, filter); |     dumpPath(path, sink, filter); | ||||||
|  |  | ||||||
|  | @ -40,7 +40,6 @@ struct Hash | ||||||
| 
 | 
 | ||||||
|     /* For sorting. */ |     /* For sorting. */ | ||||||
|     bool operator < (const Hash & h) const; |     bool operator < (const Hash & h) const; | ||||||
| 
 |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -72,7 +71,8 @@ Hash hashFile(HashType ht, const Path & path); | ||||||
|    (essentially) hashString(ht, dumpPath(path)). */ |    (essentially) hashString(ht, dumpPath(path)). */ | ||||||
| struct PathFilter; | struct PathFilter; | ||||||
| extern PathFilter defaultPathFilter; | extern PathFilter defaultPathFilter; | ||||||
| Hash hashPath(HashType ht, const Path & path, | typedef std::pair<Hash, unsigned long long> HashResult; | ||||||
|  | HashResult hashPath(HashType ht, const Path & path, | ||||||
|     PathFilter & filter = defaultPathFilter); |     PathFilter & filter = defaultPathFilter); | ||||||
| 
 | 
 | ||||||
| /* Compress a hash to the specified number of bytes by cyclically
 | /* Compress a hash to the specified number of bytes by cyclically
 | ||||||
|  | @ -93,13 +93,14 @@ class HashSink : public Sink | ||||||
| private: | private: | ||||||
|     HashType ht; |     HashType ht; | ||||||
|     Ctx * ctx; |     Ctx * ctx; | ||||||
|  |     unsigned long long bytes; | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     HashSink(HashType ht); |     HashSink(HashType ht); | ||||||
|     HashSink(const HashSink & h); |     HashSink(const HashSink & h); | ||||||
|     ~HashSink(); |     ~HashSink(); | ||||||
|     virtual void operator () (const unsigned char * data, unsigned int len); |     virtual void operator () (const unsigned char * data, unsigned int len); | ||||||
|     Hash finish(); |     HashResult finish(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ void run(Strings args) | ||||||
| 
 | 
 | ||||||
|     if (op == opHash) { |     if (op == opHash) { | ||||||
|         for (Strings::iterator i = ss.begin(); i != ss.end(); ++i) { |         for (Strings::iterator i = ss.begin(); i != ss.end(); ++i) { | ||||||
|             Hash h = flat ? hashFile(ht, *i) : hashPath(ht, *i); |             Hash h = flat ? hashFile(ht, *i) : hashPath(ht, *i).first; | ||||||
|             if (truncate && h.hashSize > 20) h = compressHash(h, 20); |             if (truncate && h.hashSize > 20) h = compressHash(h, 20); | ||||||
|             std::cout << format("%1%\n") % |             std::cout << format("%1%\n") % | ||||||
|                 (base32 ? printHash32(h) : printHash(h)); |                 (base32 ? printHash32(h) : printHash(h)); | ||||||
|  |  | ||||||
|  | @ -393,9 +393,8 @@ static void opDumpDB(Strings opFlags, Strings opArgs) | ||||||
|     if (!opArgs.empty()) |     if (!opArgs.empty()) | ||||||
|         throw UsageError("no arguments expected"); |         throw UsageError("no arguments expected"); | ||||||
|     PathSet validPaths = store->queryValidPaths(); |     PathSet validPaths = store->queryValidPaths(); | ||||||
|     foreach (PathSet::iterator, i, validPaths) { |     foreach (PathSet::iterator, i, validPaths) | ||||||
|         cout << makeValidityRegistration(singleton<PathSet>(*i), true, true); |         cout << store->makeValidityRegistration(singleton<PathSet>(*i), true, true); | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -410,8 +409,11 @@ static void registerValidity(bool reregister, bool hashGiven, bool canonicalise) | ||||||
|             /* !!! races */ |             /* !!! races */ | ||||||
|             if (canonicalise) |             if (canonicalise) | ||||||
|                 canonicalisePathMetaData(info.path); |                 canonicalisePathMetaData(info.path); | ||||||
|             if (!hashGiven) |             if (!hashGiven) { | ||||||
|                 info.hash = hashPath(htSHA256, info.path); |                 HashResult hash = hashPath(htSHA256, info.path); | ||||||
|  |                 info.hash = hash.first; | ||||||
|  |                 info.narSize = hash.second; | ||||||
|  |             } | ||||||
|             infos.push_back(info); |             infos.push_back(info); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue