2016-03-24 10:41:00 +00:00
# include "crypto.hh"
2020-06-17 03:56:48 +00:00
# include "fs-accessor.hh"
2006-11-30 17:43:04 +00:00
# include "globals.hh"
2016-03-24 10:41:00 +00:00
# include "store-api.hh"
2006-11-30 18:35:36 +00:00
# include "util.hh"
2016-04-20 12:12:38 +00:00
# include "nar-info-disk-cache.hh"
2016-07-18 22:50:27 +00:00
# include "thread-pool.hh"
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
# include "json.hh"
2020-03-30 14:04:18 +00:00
# include "url.hh"
2020-07-10 11:21:37 +00:00
# include "archive.hh"
2020-09-21 16:40:11 +00:00
# include "callback.hh"
2019-07-10 17:46:15 +00:00
2020-12-05 14:33:16 +00:00
# include <regex>
2006-11-30 17:43:04 +00:00
namespace nix {
2016-06-01 12:49:12 +00:00
bool Store : : isInStore ( const Path & path ) const
2006-11-30 17:43:04 +00:00
{
2016-06-01 12:49:12 +00:00
return isInDir ( path , storeDir ) ;
2006-11-30 17:43:04 +00:00
}
2020-07-13 14:19:37 +00:00
std : : pair < StorePath , Path > Store : : toStorePath ( const Path & path ) const
2006-11-30 17:43:04 +00:00
{
if ( ! isInStore ( path ) )
2020-04-21 23:07:07 +00:00
throw Error ( " path '%1%' is not in the Nix store " , path ) ;
2016-06-01 12:49:12 +00:00
Path : : size_type slash = path . find ( ' / ' , storeDir . size ( ) + 1 ) ;
2006-11-30 17:43:04 +00:00
if ( slash = = Path : : npos )
2020-07-13 14:19:37 +00:00
return { parseStorePath ( path ) , " " } ;
2006-11-30 17:43:04 +00:00
else
2020-07-13 14:19:37 +00:00
return { parseStorePath ( std : : string_view ( path ) . substr ( 0 , slash ) ) , path . substr ( slash ) } ;
2006-11-30 17:43:04 +00:00
}
2019-12-16 18:11:47 +00:00
Path Store : : followLinksToStore ( std : : string_view _path ) const
2007-11-29 16:18:24 +00:00
{
2019-12-16 18:11:47 +00:00
Path path = absPath ( std : : string ( _path ) ) ;
2007-11-29 16:18:24 +00:00
while ( ! isInStore ( path ) ) {
if ( ! isLink ( path ) ) break ;
string target = readLink ( path ) ;
path = absPath ( target , dirOf ( path ) ) ;
}
if ( ! isInStore ( path ) )
2020-07-13 14:19:37 +00:00
throw BadStorePath ( " path '%1%' is not in the Nix store " , path ) ;
2007-11-29 16:18:24 +00:00
return path ;
}
2019-12-16 18:11:47 +00:00
StorePath Store : : followLinksToStorePath ( std : : string_view path ) const
2007-11-29 16:18:24 +00:00
{
2020-07-13 14:19:37 +00:00
return toStorePath ( followLinksToStore ( path ) ) . first ;
2016-02-15 11:49:01 +00:00
}
2019-12-16 18:11:47 +00:00
StorePathWithOutputs Store : : followLinksToStorePathWithOutputs ( std : : string_view path ) const
{
auto [ path2 , outputs ] = nix : : parsePathWithOutputs ( path ) ;
2020-06-16 20:20:18 +00:00
return StorePathWithOutputs { followLinksToStorePath ( path2 ) , std : : move ( outputs ) } ;
2011-07-20 18:10:47 +00:00
}
2008-12-03 15:06:30 +00:00
/* Store paths have the following form:
2020-06-03 20:08:32 +00:00
< realized - path > = < store > / < h > - < name >
2008-12-03 15:06:30 +00:00
where
< store > = the location of the Nix store , usually / nix / store
2015-07-17 17:24:28 +00:00
2008-12-03 15:06:30 +00:00
< name > = a human readable name for the path , typically obtained
from the name attribute of the derivation , or the name of the
2011-07-20 18:10:47 +00:00
source file from which the store path is created . For derivation
outputs other than the default " out " output , the string " -<id> "
is suffixed to < name > .
2015-07-17 17:24:28 +00:00
2008-12-03 15:06:30 +00:00
< h > = base - 32 representation of the first 160 bits of a SHA - 256
hash of < s > ; the hash part of the store name
2015-07-17 17:24:28 +00:00
2008-12-03 15:06:30 +00:00
< s > = the string " <type>:sha256:<h2>:<store>:<name> " ;
note that it includes the location of the store as well as the
name to make sure that changes to either of those are reflected
in the hash ( e . g . you won ' t get / nix / store / < h > - name1 and
/ nix / store / < h > - name2 with equal hash parts ) .
2015-07-17 17:24:28 +00:00
2008-12-03 15:06:30 +00:00
< type > = one of :
" text:<r1>:<r2>:...<rN> "
for plain text files written to the store using
2020-06-03 20:08:32 +00:00
addTextToStore ( ) ; < r1 > . . . < rN > are the store paths referenced
by this path , in the form described by < realized - path >
" source:<r1>:<r2>:...:<rN>:self "
2008-12-03 15:06:30 +00:00
for paths copied to the store using addToStore ( ) when recursive
2020-06-03 20:08:32 +00:00
= true and hashAlgo = " sha256 " . Just like in the text case , we
can have the store paths referenced by the path .
Additionally , we can have an optional : self label to denote self
reference .
2011-07-20 18:10:47 +00:00
" output:<id> "
2008-12-03 15:06:30 +00:00
for either the outputs created by derivations , OR paths copied
to the store using addToStore ( ) with recursive ! = true or
hashAlgo ! = " sha256 " ( in that case " source " is used ; it ' s
2011-07-20 18:10:47 +00:00
silly , but it ' s done that way for compatibility ) . < id > is the
name of the output ( usually , " out " ) .
2008-12-03 15:06:30 +00:00
< h2 > = base - 16 representation of a SHA - 256 hash of :
if < type > = " text:... " :
the string written to the resulting store path
if < type > = " source " :
the serialisation of the path from which this store path is
copied , as returned by hashPath ( )
2016-03-24 10:27:58 +00:00
if < type > = " output:<id> " :
2008-12-03 15:06:30 +00:00
for non - fixed derivation outputs :
the derivation ( see hashDerivationModulo ( ) in
primops . cc )
for paths copied by addToStore ( ) or produced by fixed - output
derivations :
the string " fixed:out:<rec><algo>:<hash>: " , where
2016-03-24 10:27:58 +00:00
< rec > = " r: " for recursive ( path ) hashes , or " " for flat
2008-12-03 15:06:30 +00:00
( file ) hashes
< algo > = " md5 " , " sha1 " or " sha256 "
< hash > = base - 16 representation of the path or flat hash of
the contents of the path ( or expected contents of the
path for fixed - output derivations )
2020-06-03 20:08:32 +00:00
Note that since an output derivation has always type output , while
something added by addToStore can have type output or source depending
on the hash , this means that the same input can be hashed differently
if added to the store via addToStore or via a derivation , in the sha256
recursive case .
2008-12-03 15:06:30 +00:00
It would have been nicer to handle fixed - output derivations under
" source " , e . g . have something like " source:<rec><algo> " , but we ' re
stuck with this for now . . .
The main reason for this way of computing names is to prevent name
collisions ( for security ) . For instance , it shouldn ' t be feasible
to come up with a derivation whose output path collides with the
path for a copied source . The former would have a < s > starting with
2017-05-11 12:02:03 +00:00
" output:out: " , while the latter would have a < s > starting with
2008-12-03 15:06:30 +00:00
" source: " .
*/
2020-08-07 19:09:26 +00:00
StorePath Store : : makeStorePath ( std : : string_view type ,
std : : string_view hash , std : : string_view name ) const
2006-11-30 17:43:04 +00:00
{
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
2020-08-07 19:09:26 +00:00
string s = std : : string { type } + " : " + std : : string { hash }
+ " : " + storeDir + " : " + std : : string { name } ;
2019-12-05 18:11:09 +00:00
auto h = compressHash ( hashString ( htSHA256 , s ) , 20 ) ;
2020-06-16 12:16:39 +00:00
return StorePath ( h , name ) ;
2006-11-30 17:43:04 +00:00
}
2020-08-07 19:09:26 +00:00
StorePath Store : : makeStorePath ( std : : string_view type ,
const Hash & hash , std : : string_view name ) const
{
return makeStorePath ( type , hash . to_string ( Base16 , true ) , name ) ;
}
StorePath Store : : makeOutputPath ( std : : string_view id ,
2019-12-05 18:11:09 +00:00
const Hash & hash , std : : string_view name ) const
2011-07-20 18:10:47 +00:00
{
2020-08-07 19:09:26 +00:00
return makeStorePath ( " output: " + std : : string { id } , hash , outputPathName ( name , id ) ) ;
2011-07-20 18:10:47 +00:00
}
2019-12-05 18:11:09 +00:00
static std : : string makeType (
const Store & store ,
string & & type ,
const StorePathSet & references ,
bool hasSelfReference = false )
2018-03-29 22:56:13 +00:00
{
for ( auto & i : references ) {
type + = " : " ;
2019-12-05 18:11:09 +00:00
type + = store . printStorePath ( i ) ;
2018-03-29 22:56:13 +00:00
}
2019-12-05 18:11:09 +00:00
if ( hasSelfReference ) type + = " :self " ;
2019-11-26 20:07:44 +00:00
return std : : move ( type ) ;
2018-03-29 22:56:13 +00:00
}
2019-12-05 18:11:09 +00:00
StorePath Store : : makeFixedOutputPath (
2020-03-23 03:43:07 +00:00
FileIngestionMethod method ,
2019-12-05 18:11:09 +00:00
const Hash & hash ,
std : : string_view name ,
const StorePathSet & references ,
bool hasSelfReference ) const
2006-11-30 17:43:04 +00:00
{
2020-03-23 03:43:07 +00:00
if ( hash . type = = htSHA256 & & method = = FileIngestionMethod : : Recursive ) {
2019-12-05 18:11:09 +00:00
return makeStorePath ( makeType ( * this , " source " , references , hasSelfReference ) , hash , name ) ;
2018-03-29 22:56:13 +00:00
} else {
assert ( references . empty ( ) ) ;
2020-03-30 22:31:51 +00:00
return makeStorePath ( " output:out " ,
hashString ( htSHA256 ,
" fixed:out: "
2020-06-17 04:55:47 +00:00
+ makeFileIngestionPrefix ( method )
2020-06-03 10:38:23 +00:00
+ hash . to_string ( Base16 , true ) + " : " ) ,
2020-03-30 22:31:51 +00:00
name ) ;
2018-03-29 22:56:13 +00:00
}
2006-11-30 17:43:04 +00:00
}
2020-06-22 17:08:11 +00:00
StorePath Store : : makeFixedOutputPathFromCA ( std : : string_view name , ContentAddress ca ,
2020-06-12 21:36:35 +00:00
const StorePathSet & references , bool hasSelfReference ) const
{
2020-06-22 17:08:11 +00:00
// New template
return std : : visit ( overloaded {
[ & ] ( TextHash th ) {
return makeTextPath ( name , th . hash , references ) ;
} ,
[ & ] ( FixedOutputHash fsh ) {
return makeFixedOutputPath ( fsh . method , fsh . hash , name , references , hasSelfReference ) ;
}
} , ca ) ;
2020-06-12 21:36:35 +00:00
}
2006-12-01 18:00:01 +00:00
2019-12-05 18:11:09 +00:00
StorePath Store : : makeTextPath ( std : : string_view name , const Hash & hash ,
const StorePathSet & references ) const
2016-08-03 11:17:11 +00:00
{
assert ( hash . type = = htSHA256 ) ;
/* Stuff the references (if any) into the type. This is a bit
hacky , but we can ' t put them in ` s ' since that would be
ambiguous . */
2019-12-05 18:11:09 +00:00
return makeStorePath ( makeType ( * this , " text " , references ) , hash , name ) ;
2016-08-03 11:17:11 +00:00
}
2019-12-05 18:11:09 +00:00
std : : pair < StorePath , Hash > Store : : computeStorePathForPath ( std : : string_view name ,
2020-05-27 18:04:20 +00:00
const Path & srcPath , FileIngestionMethod method , HashType hashAlgo , PathFilter & filter ) const
2006-12-01 18:00:01 +00:00
{
2020-05-27 18:04:20 +00:00
Hash h = method = = FileIngestionMethod : : Recursive
2020-03-30 22:31:51 +00:00
? hashPath ( hashAlgo , srcPath , filter ) . first
: hashFile ( hashAlgo , srcPath ) ;
2020-05-27 18:04:20 +00:00
return std : : make_pair ( makeFixedOutputPath ( method , h , name ) , h ) ;
2006-12-01 18:00:01 +00:00
}
2019-12-05 18:11:09 +00:00
StorePath Store : : computeStorePathForText ( const string & name , const string & s ,
const StorePathSet & references ) const
2006-12-01 18:00:01 +00:00
{
2016-08-03 11:17:11 +00:00
return makeTextPath ( name , hashString ( htSHA256 , s ) , references ) ;
2006-12-01 18:00:01 +00:00
}
2020-08-03 04:13:45 +00:00
StorePath Store : : addToStore ( const string & name , const Path & _srcPath ,
FileIngestionMethod method , HashType hashAlgo , PathFilter & filter , RepairFlag repair )
{
Path srcPath ( absPath ( _srcPath ) ) ;
auto source = sinkToSource ( [ & ] ( Sink & sink ) {
if ( method = = FileIngestionMethod : : Recursive )
dumpPath ( srcPath , sink , filter ) ;
else
readFile ( srcPath , sink ) ;
} ) ;
return addToStoreFromDump ( * source , name , method , hashAlgo , repair ) ;
}
2020-07-21 00:18:12 +00:00
/*
The aim of this function is to compute in one pass the correct ValidPathInfo for
the files that we are trying to add to the store . To accomplish that in one
pass , given the different kind of inputs that we can take ( normal nar archives ,
nar archives with non SHA - 256 hashes , and flat files ) , we set up a net of sinks
and aliases . Also , since the dataflow is obfuscated by this , we include here a
graphviz diagram :
digraph graphname {
node [ shape = box ]
fileSource - > narSink
narSink [ style = dashed ]
narSink - > unsualHashTee [ style = dashed , label = " Recursive && !SHA-256 " ]
narSink - > narHashSink [ style = dashed , label = " else " ]
unsualHashTee - > narHashSink
unsualHashTee - > caHashSink
fileSource - > parseSink
parseSink [ style = dashed ]
parseSink - > fileSink [ style = dashed , label = " Flat " ]
parseSink - > blank [ style = dashed , label = " Recursive " ]
fileSink - > caHashSink
}
*/
2020-07-10 11:21:37 +00:00
ValidPathInfo Store : : addToStoreSlow ( std : : string_view name , const Path & srcPath ,
FileIngestionMethod method , HashType hashAlgo ,
std : : optional < Hash > expectedCAHash )
{
2020-07-16 05:09:41 +00:00
HashSink narHashSink { htSHA256 } ;
HashSink caHashSink { hashAlgo } ;
2020-07-10 11:21:37 +00:00
2020-07-21 00:18:12 +00:00
/* Note that fileSink and unusualHashTee must be mutually exclusive, since
they both write to caHashSink . Note that that requisite is currently true
because the former is only used in the flat case . */
RetrieveRegularNARSink fileSink { caHashSink } ;
TeeSink unusualHashTee { narHashSink , caHashSink } ;
2020-07-10 13:56:24 +00:00
2020-07-21 00:18:12 +00:00
auto & narSink = method = = FileIngestionMethod : : Recursive & & hashAlgo ! = htSHA256
? static_cast < Sink & > ( unusualHashTee )
2020-07-16 05:09:41 +00:00
: narHashSink ;
2020-07-21 00:18:12 +00:00
/* Functionally, this means that fileSource will yield the content of
srcPath . The fact that we use scratchpadSink as a temporary buffer here
is an implementation detail . */
auto fileSource = sinkToSource ( [ & ] ( Sink & scratchpadSink ) {
dumpPath ( srcPath , scratchpadSink ) ;
2020-07-16 05:09:41 +00:00
} ) ;
2020-07-10 11:21:37 +00:00
2020-07-21 00:18:12 +00:00
/* tapped provides the same data as fileSource, but we also write all the
information to narSink . */
TeeSource tapped { * fileSource , narSink } ;
2020-07-10 13:56:24 +00:00
2020-07-16 05:09:41 +00:00
ParseSink blank ;
auto & parseSink = method = = FileIngestionMethod : : Flat
? fileSink
: blank ;
2020-07-21 00:18:12 +00:00
/* The information that flows from tapped (besides being replicated in
narSink ) , is now put in parseSink . */
parseDump ( parseSink , tapped ) ;
2020-07-16 05:09:41 +00:00
2020-07-21 00:18:12 +00:00
/* We extract the result of the computation from the sink by calling
finish . */
2020-07-16 05:09:41 +00:00
auto [ narHash , narSize ] = narHashSink . finish ( ) ;
auto hash = method = = FileIngestionMethod : : Recursive & & hashAlgo = = htSHA256
? narHash
: caHashSink . finish ( ) . first ;
2020-07-10 11:21:37 +00:00
if ( expectedCAHash & & expectedCAHash ! = hash )
throw Error ( " hash mismatch for '%s' " , srcPath ) ;
2020-08-06 18:31:48 +00:00
ValidPathInfo info {
makeFixedOutputPath ( method , hash , name ) ,
narHash ,
} ;
2020-07-10 11:21:37 +00:00
info . narSize = narSize ;
info . ca = FixedOutputHash { . method = method , . hash = hash } ;
if ( ! isValidPath ( info . path ) ) {
2020-07-21 00:18:12 +00:00
auto source = sinkToSource ( [ & ] ( Sink & scratchpadSink ) {
dumpPath ( srcPath , scratchpadSink ) ;
2020-07-10 11:21:37 +00:00
} ) ;
addToStore ( info , * source ) ;
}
return info ;
}
2016-06-01 12:49:12 +00:00
Store : : Store ( const Params & params )
2020-09-10 08:55:51 +00:00
: StoreConfig ( params )
2017-04-13 13:55:38 +00:00
, state ( { ( size_t ) pathInfoCacheSize } )
2016-06-01 12:49:12 +00:00
{
}
2016-04-20 12:12:38 +00:00
std : : string Store : : getUri ( )
{
return " " ;
}
2020-03-11 19:04:47 +00:00
bool Store : : PathInfoCacheValue : : isKnownNow ( )
{
std : : chrono : : duration ttl = didExist ( )
? std : : chrono : : seconds ( settings . ttlPositiveNarInfoCache )
: std : : chrono : : seconds ( settings . ttlNegativeNarInfoCache ) ;
return std : : chrono : : steady_clock : : now ( ) < time_point + ttl ;
}
2016-04-20 12:12:38 +00:00
2020-12-17 10:35:24 +00:00
std : : map < std : : string , std : : optional < StorePath > > Store : : queryDerivationOutputMapNoResolve ( const StorePath & path )
{
std : : map < std : : string , std : : optional < StorePath > > outputs ;
auto drv = readInvalidDerivation ( path ) ;
for ( auto & [ outputName , output ] : drv . outputsAndOptPaths ( * this ) ) {
outputs . emplace ( outputName , output . second ) ;
}
return outputs ;
}
std : : map < std : : string , std : : optional < StorePath > > Store : : queryPartialDerivationOutputMap ( const StorePath & path )
{
if ( settings . isExperimentalFeatureEnabled ( " ca-derivations " ) ) {
auto resolvedDrv = Derivation : : tryResolve ( * this , path ) ;
if ( resolvedDrv ) {
auto resolvedDrvPath = writeDerivation ( * this , * resolvedDrv , NoRepair , true ) ;
if ( isValidPath ( resolvedDrvPath ) )
return queryDerivationOutputMapNoResolve ( resolvedDrvPath ) ;
}
}
return queryDerivationOutputMapNoResolve ( path ) ;
}
2020-08-20 14:12:51 +00:00
OutputPathMap Store : : queryDerivationOutputMap ( const StorePath & path ) {
auto resp = queryPartialDerivationOutputMap ( path ) ;
2020-08-04 22:28:10 +00:00
OutputPathMap result ;
for ( auto & [ outName , optOutPath ] : resp ) {
if ( ! optOutPath )
throw Error ( " output '%s' has no store path mapped to it " , outName ) ;
result . insert_or_assign ( outName , * optOutPath ) ;
}
return result ;
2020-07-24 21:02:51 +00:00
}
2020-06-10 09:20:52 +00:00
StorePathSet Store : : queryDerivationOutputs ( const StorePath & path )
{
auto outputMap = this - > queryDerivationOutputMap ( path ) ;
StorePathSet outputPaths ;
for ( auto & i : outputMap ) {
outputPaths . emplace ( std : : move ( i . second ) ) ;
}
return outputPaths ;
}
2019-12-05 18:11:09 +00:00
bool Store : : isValidPath ( const StorePath & storePath )
2016-02-15 13:48:38 +00:00
{
2020-06-16 12:16:39 +00:00
std : : string hashPart ( storePath . hashPart ( ) ) ;
2016-04-21 15:53:47 +00:00
2016-04-19 16:50:15 +00:00
{
auto state_ ( state . lock ( ) ) ;
2016-04-21 15:53:47 +00:00
auto res = state_ - > pathInfoCache . get ( hashPart ) ;
2020-03-11 19:04:47 +00:00
if ( res & & res - > isKnownNow ( ) ) {
2016-04-19 16:50:15 +00:00
stats . narInfoReadAverted + + ;
2020-03-11 19:04:47 +00:00
return res - > didExist ( ) ;
2016-04-19 16:50:15 +00:00
}
}
2016-04-20 12:12:38 +00:00
if ( diskCache ) {
2016-04-21 15:53:47 +00:00
auto res = diskCache - > lookupNarInfo ( getUri ( ) , hashPart ) ;
2016-04-20 12:12:38 +00:00
if ( res . first ! = NarInfoDiskCache : : oUnknown ) {
2016-04-21 15:53:47 +00:00
stats . narInfoReadAverted + + ;
2016-04-20 12:12:38 +00:00
auto state_ ( state . lock ( ) ) ;
2016-04-21 15:53:47 +00:00
state_ - > pathInfoCache . upsert ( hashPart ,
2020-03-11 19:04:47 +00:00
res . first = = NarInfoDiskCache : : oInvalid ? PathInfoCacheValue { } : PathInfoCacheValue { . value = res . second } ) ;
2016-04-20 12:12:38 +00:00
return res . first = = NarInfoDiskCache : : oValid ;
}
}
2016-06-20 15:39:05 +00:00
bool valid = isValidPathUncached ( storePath ) ;
2016-04-20 12:12:38 +00:00
2016-06-20 15:39:05 +00:00
if ( diskCache & & ! valid )
// FIXME: handle valid = true case.
diskCache - > upsertNarInfo ( getUri ( ) , hashPart , 0 ) ;
return valid ;
2016-04-19 16:50:15 +00:00
}
2017-02-07 18:22:48 +00:00
/* Default implementation for stores that only implement
queryPathInfoUncached ( ) . */
2019-12-05 18:11:09 +00:00
bool Store : : isValidPathUncached ( const StorePath & path )
2017-02-07 18:22:48 +00:00
{
try {
queryPathInfo ( path ) ;
return true ;
} catch ( InvalidPath & ) {
return false ;
}
}
2019-12-05 18:11:09 +00:00
ref < const ValidPathInfo > Store : : queryPathInfo ( const StorePath & storePath )
2016-09-16 16:54:14 +00:00
{
2018-09-25 16:54:16 +00:00
std : : promise < ref < const ValidPathInfo > > promise ;
2016-09-16 16:54:14 +00:00
queryPathInfo ( storePath ,
2018-09-25 16:54:16 +00:00
{ [ & ] ( std : : future < ref < const ValidPathInfo > > result ) {
2018-03-27 20:16:01 +00:00
try {
promise . set_value ( result . get ( ) ) ;
} catch ( . . . ) {
promise . set_exception ( std : : current_exception ( ) ) ;
}
} } ) ;
2016-09-16 16:54:14 +00:00
return promise . get_future ( ) . get ( ) ;
}
2020-07-13 18:17:00 +00:00
static bool goodStorePath ( const StorePath & expected , const StorePath & actual )
{
return
expected . hashPart ( ) = = actual . hashPart ( )
& & ( expected . name ( ) = = Store : : MissingName | | expected . name ( ) = = actual . name ( ) ) ;
}
2019-12-05 18:11:09 +00:00
void Store : : queryPathInfo ( const StorePath & storePath ,
2018-09-25 16:54:16 +00:00
Callback < ref < const ValidPathInfo > > callback ) noexcept
2016-04-19 16:50:15 +00:00
{
2019-09-03 11:00:55 +00:00
std : : string hashPart ;
2016-04-21 15:53:47 +00:00
2016-09-16 16:54:14 +00:00
try {
2020-06-16 12:16:39 +00:00
hashPart = storePath . hashPart ( ) ;
2016-09-16 16:54:14 +00:00
{
auto res = state . lock ( ) - > pathInfoCache . get ( hashPart ) ;
2020-03-11 19:04:47 +00:00
if ( res & & res - > isKnownNow ( ) ) {
2016-09-16 16:54:14 +00:00
stats . narInfoReadAverted + + ;
2020-03-11 19:04:47 +00:00
if ( ! res - > didExist ( ) )
2019-12-05 18:11:09 +00:00
throw InvalidPath ( " path '%s' is not valid " , printStorePath ( storePath ) ) ;
2020-03-11 19:04:47 +00:00
return callback ( ref < const ValidPathInfo > ( res - > value ) ) ;
2016-09-16 16:54:14 +00:00
}
2016-04-19 16:50:15 +00:00
}
2016-09-16 16:54:14 +00:00
if ( diskCache ) {
auto res = diskCache - > lookupNarInfo ( getUri ( ) , hashPart ) ;
if ( res . first ! = NarInfoDiskCache : : oUnknown ) {
stats . narInfoReadAverted + + ;
{
auto state_ ( state . lock ( ) ) ;
state_ - > pathInfoCache . upsert ( hashPart ,
2020-03-11 19:04:47 +00:00
res . first = = NarInfoDiskCache : : oInvalid ? PathInfoCacheValue { } : PathInfoCacheValue { . value = res . second } ) ;
2016-09-16 16:54:14 +00:00
if ( res . first = = NarInfoDiskCache : : oInvalid | |
2020-07-13 18:17:00 +00:00
! goodStorePath ( storePath , res . second - > path ) )
2019-12-05 18:11:09 +00:00
throw InvalidPath ( " path '%s' is not valid " , printStorePath ( storePath ) ) ;
2016-09-16 16:54:14 +00:00
}
2018-09-25 16:54:16 +00:00
return callback ( ref < const ValidPathInfo > ( res . second ) ) ;
2016-09-16 16:54:14 +00:00
}
2016-04-20 12:12:38 +00:00
}
2016-09-16 16:54:14 +00:00
2018-03-27 20:16:01 +00:00
} catch ( . . . ) { return callback . rethrow ( ) ; }
2016-04-20 12:12:38 +00:00
2019-09-03 10:51:35 +00:00
auto callbackPtr = std : : make_shared < decltype ( callback ) > ( std : : move ( callback ) ) ;
2016-09-16 16:54:14 +00:00
queryPathInfoUncached ( storePath ,
2020-07-13 12:35:01 +00:00
{ [ this , storePathS { printStorePath ( storePath ) } , hashPart , callbackPtr ] ( std : : future < std : : shared_ptr < const ValidPathInfo > > fut ) {
2016-04-19 16:50:15 +00:00
2018-03-27 20:16:01 +00:00
try {
auto info = fut . get ( ) ;
2016-04-20 12:12:38 +00:00
2018-03-27 20:16:01 +00:00
if ( diskCache )
diskCache - > upsertNarInfo ( getUri ( ) , hashPart , info ) ;
2016-04-19 16:50:15 +00:00
2018-03-27 20:16:01 +00:00
{
auto state_ ( state . lock ( ) ) ;
2020-03-11 19:04:47 +00:00
state_ - > pathInfoCache . upsert ( hashPart , PathInfoCacheValue { . value = info } ) ;
2018-03-27 20:16:01 +00:00
}
2016-09-16 16:54:14 +00:00
2020-07-13 12:35:01 +00:00
auto storePath = parseStorePath ( storePathS ) ;
2020-07-14 09:55:54 +00:00
if ( ! info | | ! goodStorePath ( storePath , info - > path ) ) {
2018-03-27 20:16:01 +00:00
stats . narInfoMissing + + ;
2020-07-13 12:35:01 +00:00
throw InvalidPath ( " path '%s' is not valid " , storePathS ) ;
2018-03-27 20:16:01 +00:00
}
2016-04-19 16:50:15 +00:00
2018-09-25 16:54:16 +00:00
( * callbackPtr ) ( ref < const ValidPathInfo > ( info ) ) ;
2019-09-03 10:51:35 +00:00
} catch ( . . . ) { callbackPtr - > rethrow ( ) ; }
2018-03-27 20:16:01 +00:00
} } ) ;
2016-02-15 13:48:38 +00:00
}
2020-10-21 19:31:19 +00:00
void Store : : substitutePaths ( const StorePathSet & paths )
{
std : : vector < StorePathWithOutputs > paths2 ;
for ( auto & path : paths )
if ( ! path . isDerivation ( ) )
paths2 . push_back ( { path } ) ;
uint64_t downloadSize , narSize ;
StorePathSet willBuild , willSubstitute , unknown ;
queryMissing ( paths2 ,
willBuild , willSubstitute , unknown , downloadSize , narSize ) ;
if ( ! willSubstitute . empty ( ) )
try {
std : : vector < StorePathWithOutputs > subs ;
for ( auto & p : willSubstitute ) subs . push_back ( { p } ) ;
buildPaths ( subs ) ;
} catch ( Error & e ) {
logWarning ( e . info ( ) ) ;
}
}
2019-12-05 18:11:09 +00:00
StorePathSet Store : : queryValidPaths ( const StorePathSet & paths , SubstituteFlag maybeSubstitute )
2016-10-07 17:20:47 +00:00
{
2016-10-07 17:43:36 +00:00
struct State
{
size_t left ;
2019-12-05 18:11:09 +00:00
StorePathSet valid ;
2016-10-07 17:43:36 +00:00
std : : exception_ptr exc ;
} ;
2016-10-07 17:20:47 +00:00
2019-12-05 18:11:09 +00:00
Sync < State > state_ ( State { paths . size ( ) , StorePathSet ( ) } ) ;
2016-10-07 17:20:47 +00:00
2016-10-07 17:43:36 +00:00
std : : condition_variable wakeup ;
2017-10-25 15:13:49 +00:00
ThreadPool pool ;
2016-10-07 17:43:36 +00:00
2019-12-05 18:11:09 +00:00
auto doQuery = [ & ] ( const Path & path ) {
2017-10-25 15:51:45 +00:00
checkInterrupt ( ) ;
2019-12-05 18:11:09 +00:00
queryPathInfo ( parseStorePath ( path ) , { [ path , this , & state_ , & wakeup ] ( std : : future < ref < const ValidPathInfo > > fut ) {
2018-03-27 20:16:01 +00:00
auto state ( state_ . lock ( ) ) ;
try {
auto info = fut . get ( ) ;
2019-12-05 18:11:09 +00:00
state - > valid . insert ( parseStorePath ( path ) ) ;
2018-03-27 20:16:01 +00:00
} catch ( InvalidPath & ) {
} catch ( . . . ) {
state - > exc = std : : current_exception ( ) ;
}
assert ( state - > left ) ;
if ( ! - - state - > left )
wakeup . notify_one ( ) ;
} } ) ;
2017-10-25 15:13:49 +00:00
} ;
for ( auto & path : paths )
2019-12-05 18:11:09 +00:00
pool . enqueue ( std : : bind ( doQuery , printStorePath ( path ) ) ) ; // FIXME
2017-10-25 15:13:49 +00:00
pool . process ( ) ;
2016-10-07 17:43:36 +00:00
while ( true ) {
auto state ( state_ . lock ( ) ) ;
if ( ! state - > left ) {
if ( state - > exc ) std : : rethrow_exception ( state - > exc ) ;
2019-12-05 18:11:09 +00:00
return std : : move ( state - > valid ) ;
2016-10-07 17:43:36 +00:00
}
state . wait ( wakeup ) ;
}
2016-10-07 17:20:47 +00:00
}
2008-01-29 18:17:36 +00:00
/* Return a string accepted by decodeValidPathInfo() that
registers the specified paths as valid . Note : it ' s the
responsibility of the caller to provide a closure . */
2019-12-05 18:11:09 +00:00
string Store : : makeValidityRegistration ( const StorePathSet & paths ,
2008-01-29 18:17:36 +00:00
bool showDerivers , bool showHash )
{
string s = " " ;
2015-07-17 17:24:28 +00:00
for ( auto & i : paths ) {
2019-12-05 18:11:09 +00:00
s + = printStorePath ( i ) + " \n " ;
2015-07-17 17:24:28 +00:00
2016-04-19 16:50:15 +00:00
auto info = queryPathInfo ( i ) ;
2008-01-29 18:17:36 +00:00
2010-11-16 17:11:46 +00:00
if ( showHash ) {
2017-07-04 12:47:59 +00:00
s + = info - > narHash . to_string ( Base16 , false ) + " \n " ;
2016-04-19 16:50:15 +00:00
s + = ( format ( " %1% \n " ) % info - > narSize ) . str ( ) ;
2010-11-16 17:11:46 +00:00
}
2019-12-05 18:11:09 +00:00
auto deriver = showDerivers & & info - > deriver ? printStorePath ( * info - > deriver ) : " " ;
2008-01-29 18:17:36 +00:00
s + = deriver + " \n " ;
2016-04-19 16:50:15 +00:00
s + = ( format ( " %1% \n " ) % info - > references . size ( ) ) . str ( ) ;
2008-01-29 18:17:36 +00:00
2016-04-19 16:50:15 +00:00
for ( auto & j : info - > references )
2019-12-05 18:11:09 +00:00
s + = printStorePath ( j ) + " \n " ;
2008-01-29 18:17:36 +00:00
}
return s ;
}
2019-12-05 18:11:09 +00:00
void Store : : pathInfoToJSON ( JSONPlaceholder & jsonOut , const StorePathSet & storePaths ,
2020-02-11 22:50:16 +00:00
bool includeImpureInfo , bool showClosureSize ,
Base hashBase ,
AllowInvalidFlag allowInvalid )
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
{
auto jsonList = jsonOut . list ( ) ;
2019-12-05 18:11:09 +00:00
for ( auto & storePath : storePaths ) {
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
auto jsonPath = jsonList . object ( ) ;
2019-12-05 18:11:09 +00:00
jsonPath . attr ( " path " , printStorePath ( storePath ) ) ;
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
2017-07-14 13:27:21 +00:00
try {
auto info = queryPathInfo ( storePath ) ;
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
2017-07-14 13:27:21 +00:00
jsonPath
2020-06-03 10:38:23 +00:00
. attr ( " narHash " , info - > narHash . to_string ( hashBase , true ) )
2017-07-14 13:27:21 +00:00
. attr ( " narSize " , info - > narSize ) ;
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
2017-07-14 13:27:21 +00:00
{
auto jsonRefs = jsonPath . list ( " references " ) ;
for ( auto & ref : info - > references )
2019-12-05 18:11:09 +00:00
jsonRefs . elem ( printStorePath ( ref ) ) ;
2017-07-14 13:27:21 +00:00
}
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
2020-06-01 22:53:31 +00:00
if ( info - > ca )
2020-06-02 00:37:43 +00:00
jsonPath . attr ( " ca " , renderContentAddress ( info - > ca ) ) ;
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
2017-07-14 15:36:49 +00:00
std : : pair < uint64_t , uint64_t > closureSizes ;
if ( showClosureSize ) {
2019-12-05 18:11:09 +00:00
closureSizes = getClosureSize ( info - > path ) ;
2017-07-14 15:36:49 +00:00
jsonPath . attr ( " closureSize " , closureSizes . first ) ;
}
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
2017-07-14 13:27:21 +00:00
if ( includeImpureInfo ) {
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
2019-12-05 18:11:09 +00:00
if ( info - > deriver )
jsonPath . attr ( " deriver " , printStorePath ( * info - > deriver ) ) ;
2017-07-14 13:27:21 +00:00
if ( info - > registrationTime )
jsonPath . attr ( " registrationTime " , info - > registrationTime ) ;
if ( info - > ultimate )
jsonPath . attr ( " ultimate " , info - > ultimate ) ;
if ( ! info - > sigs . empty ( ) ) {
auto jsonSigs = jsonPath . list ( " signatures " ) ;
for ( auto & sig : info - > sigs )
jsonSigs . elem ( sig ) ;
}
2017-05-08 11:36:23 +00:00
2017-07-14 15:36:49 +00:00
auto narInfo = std : : dynamic_pointer_cast < const NarInfo > (
std : : shared_ptr < const ValidPathInfo > ( info ) ) ;
if ( narInfo ) {
2017-11-24 17:08:50 +00:00
if ( ! narInfo - > url . empty ( ) )
jsonPath . attr ( " url " , narInfo - > url ) ;
2017-07-14 15:36:49 +00:00
if ( narInfo - > fileHash )
2020-07-15 21:19:56 +00:00
jsonPath . attr ( " downloadHash " , narInfo - > fileHash - > to_string ( hashBase , true ) ) ;
2017-07-14 15:36:49 +00:00
if ( narInfo - > fileSize )
jsonPath . attr ( " downloadSize " , narInfo - > fileSize ) ;
if ( showClosureSize )
jsonPath . attr ( " closureDownloadSize " , closureSizes . second ) ;
}
2017-05-08 11:36:23 +00:00
}
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
2017-07-14 13:27:21 +00:00
} catch ( InvalidPath & ) {
jsonPath . attr ( " valid " , false ) ;
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
}
}
}
2019-12-05 18:11:09 +00:00
std : : pair < uint64_t , uint64_t > Store : : getClosureSize ( const StorePath & storePath )
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
{
2017-07-14 15:36:49 +00:00
uint64_t totalNarSize = 0 , totalDownloadSize = 0 ;
2019-12-05 18:11:09 +00:00
StorePathSet closure ;
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
computeFSClosure ( storePath , closure , false , false ) ;
2017-07-14 15:36:49 +00:00
for ( auto & p : closure ) {
auto info = queryPathInfo ( p ) ;
totalNarSize + = info - > narSize ;
auto narInfo = std : : dynamic_pointer_cast < const NarInfo > (
std : : shared_ptr < const ValidPathInfo > ( info ) ) ;
if ( narInfo )
totalDownloadSize + = narInfo - > fileSize ;
}
return { totalNarSize , totalDownloadSize } ;
exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as
‘nix path-info --json’. Thus it also includes NAR hashes and sizes.
Example:
[
{
"path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl",
"narSize": 197648,
"references": [
"/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10",
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20939776
},
{
"path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24",
"narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3",
"narSize": 20742128,
"references": [
"/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24"
],
"closureSize": 20742128
}
]
Fixes #1134.
2017-01-26 19:36:20 +00:00
}
2016-04-19 16:50:15 +00:00
const Store : : Stats & Store : : getStats ( )
{
2016-04-20 12:12:38 +00:00
{
auto state_ ( state . lock ( ) ) ;
stats . pathInfoCacheSize = state_ - > pathInfoCache . size ( ) ;
}
2016-04-19 16:50:15 +00:00
return stats ;
}
2016-05-03 12:45:50 +00:00
void copyStorePath ( ref < Store > srcStore , ref < Store > dstStore ,
2019-12-05 18:11:09 +00:00
const StorePath & storePath , RepairFlag repair , CheckSigsFlag checkSigs )
2016-05-03 12:45:50 +00:00
{
2019-07-10 17:46:15 +00:00
auto srcUri = srcStore - > getUri ( ) ;
auto dstUri = dstStore - > getUri ( ) ;
Activity act ( * logger , lvlInfo , actCopyPath ,
srcUri = = " local " | | srcUri = = " daemon "
2019-12-05 18:11:09 +00:00
? fmt ( " copying path '%s' to '%s' " , srcStore - > printStorePath ( storePath ) , dstUri )
2019-07-10 17:46:15 +00:00
: dstUri = = " local " | | dstUri = = " daemon "
2019-12-05 18:11:09 +00:00
? fmt ( " copying path '%s' from '%s' " , srcStore - > printStorePath ( storePath ) , srcUri )
: fmt ( " copying path '%s' from '%s' to '%s' " , srcStore - > printStorePath ( storePath ) , srcUri , dstUri ) ,
{ srcStore - > printStorePath ( storePath ) , srcUri , dstUri } ) ;
2019-07-10 17:46:15 +00:00
PushActivity pact ( act . id ) ;
auto info = srcStore - > queryPathInfo ( storePath ) ;
uint64_t total = 0 ;
2020-06-12 14:49:09 +00:00
// recompute store path on the chance dstStore does it differently
2020-06-22 17:08:11 +00:00
if ( info - > ca & & info - > references . empty ( ) ) {
2019-07-10 17:46:15 +00:00
auto info2 = make_ref < ValidPathInfo > ( * info ) ;
2020-06-22 17:08:11 +00:00
info2 - > path = dstStore - > makeFixedOutputPathFromCA ( info - > path . name ( ) , * info - > ca ) ;
2020-06-17 18:04:46 +00:00
if ( dstStore - > storeDir = = srcStore - > storeDir )
assert ( info - > path = = info2 - > path ) ;
2019-07-10 17:46:15 +00:00
info = info2 ;
}
2017-02-07 18:23:16 +00:00
2019-07-10 17:46:15 +00:00
if ( info - > ultimate ) {
auto info2 = make_ref < ValidPathInfo > ( * info ) ;
info2 - > ultimate = false ;
info = info2 ;
}
2017-05-01 18:03:25 +00:00
2019-07-10 17:46:15 +00:00
auto source = sinkToSource ( [ & ] ( Sink & sink ) {
2020-12-02 13:00:43 +00:00
LambdaSink progressSink ( [ & ] ( std : : string_view data ) {
total + = data . size ( ) ;
2019-07-10 17:46:15 +00:00
act . progress ( total , info - > narSize ) ;
2018-03-16 19:22:34 +00:00
} ) ;
2020-08-13 14:47:53 +00:00
TeeSink tee { sink , progressSink } ;
srcStore - > narFromPath ( storePath , tee ) ;
2019-07-10 17:46:15 +00:00
} , [ & ] ( ) {
2019-12-05 18:11:09 +00:00
throw EndOfFile ( " NAR for '%s' fetched from '%s' is incomplete " , srcStore - > printStorePath ( storePath ) , srcStore - > getUri ( ) ) ;
2019-06-24 19:48:52 +00:00
} ) ;
2019-07-10 17:46:15 +00:00
dstStore - > addToStore ( * info , * source , repair , checkSigs ) ;
2016-05-03 12:45:50 +00:00
}
2020-06-19 18:48:57 +00:00
std : : map < StorePath , StorePath > copyPaths ( ref < Store > srcStore , ref < Store > dstStore , const StorePathSet & storePaths ,
2017-06-28 16:11:01 +00:00
RepairFlag repair , CheckSigsFlag checkSigs , SubstituteFlag substitute )
2016-10-07 17:15:25 +00:00
{
2019-12-05 18:11:09 +00:00
auto valid = dstStore - > queryValidPaths ( storePaths , substitute ) ;
2017-06-28 16:11:01 +00:00
2020-07-28 22:24:55 +00:00
StorePathSet missing ;
2016-10-07 17:15:25 +00:00
for ( auto & path : storePaths )
2020-07-28 22:24:55 +00:00
if ( ! valid . count ( path ) ) missing . insert ( path ) ;
2016-10-07 17:15:25 +00:00
2020-06-19 18:48:57 +00:00
std : : map < StorePath , StorePath > pathsMap ;
2016-10-07 17:15:25 +00:00
for ( auto & path : storePaths )
2020-06-19 18:48:57 +00:00
pathsMap . insert_or_assign ( path , path ) ;
2016-10-07 17:15:25 +00:00
2020-06-19 18:48:57 +00:00
if ( missing . empty ( ) ) return pathsMap ;
2017-10-18 13:02:58 +00:00
2017-08-28 17:13:24 +00:00
Activity act ( * logger , lvlInfo , actCopyPaths , fmt ( " copying %d paths " , missing . size ( ) ) ) ;
2017-08-14 13:28:16 +00:00
2017-08-14 20:12:36 +00:00
std : : atomic < size_t > nrDone { 0 } ;
2018-07-24 15:03:54 +00:00
std : : atomic < size_t > nrFailed { 0 } ;
2017-08-14 17:00:03 +00:00
std : : atomic < uint64_t > bytesExpected { 0 } ;
2017-08-14 20:42:17 +00:00
std : : atomic < uint64_t > nrRunning { 0 } ;
2017-08-14 13:28:16 +00:00
auto showProgress = [ & ] ( ) {
2018-07-24 15:03:54 +00:00
act . progress ( nrDone , missing . size ( ) , nrRunning , nrFailed ) ;
2017-08-14 13:28:16 +00:00
} ;
2017-06-28 16:11:01 +00:00
ThreadPool pool ;
2017-03-16 12:50:01 +00:00
2020-07-28 22:24:55 +00:00
processGraph < StorePath > ( pool ,
StorePathSet ( missing . begin ( ) , missing . end ( ) ) ,
2020-06-12 19:27:28 +00:00
2020-07-28 22:24:55 +00:00
[ & ] ( const StorePath & storePath ) {
2020-06-12 19:27:28 +00:00
auto info = srcStore - > queryPathInfo ( storePath ) ;
2020-06-17 17:18:47 +00:00
auto storePathForDst = storePath ;
2020-06-22 17:08:11 +00:00
if ( info - > ca & & info - > references . empty ( ) ) {
storePathForDst = dstStore - > makeFixedOutputPathFromCA ( storePath . name ( ) , * info - > ca ) ;
2020-06-17 18:04:46 +00:00
if ( dstStore - > storeDir = = srcStore - > storeDir )
assert ( storePathForDst = = storePath ) ;
2020-06-12 20:32:52 +00:00
if ( storePathForDst ! = storePath )
2020-06-17 16:31:01 +00:00
debug ( " replaced path '%s' to '%s' for substituter '%s' " , srcStore - > printStorePath ( storePath ) , dstStore - > printStorePath ( storePathForDst ) , dstStore - > getUri ( ) ) ;
2020-06-12 19:27:28 +00:00
}
2020-06-19 18:48:57 +00:00
pathsMap . insert_or_assign ( storePath , storePathForDst ) ;
2016-10-07 17:15:25 +00:00
2020-07-28 22:24:55 +00:00
if ( dstStore - > isValidPath ( storePath ) ) {
2017-08-14 13:28:16 +00:00
nrDone + + ;
showProgress ( ) ;
2020-07-28 22:24:55 +00:00
return StorePathSet ( ) ;
2017-08-14 13:28:16 +00:00
}
2017-08-14 17:00:03 +00:00
bytesExpected + = info - > narSize ;
2017-08-16 14:38:23 +00:00
act . setExpected ( actCopyPath , bytesExpected ) ;
2017-08-14 17:00:03 +00:00
2020-07-28 22:24:55 +00:00
return info - > references ;
2017-06-28 16:11:01 +00:00
} ,
2016-10-07 17:15:25 +00:00
2020-07-28 22:24:55 +00:00
[ & ] ( const StorePath & storePath ) {
2017-06-28 16:11:01 +00:00
checkInterrupt ( ) ;
2016-10-07 17:15:25 +00:00
2020-06-12 19:27:28 +00:00
auto info = srcStore - > queryPathInfo ( storePath ) ;
2019-12-05 18:11:09 +00:00
2020-06-17 17:18:47 +00:00
auto storePathForDst = storePath ;
2020-06-22 17:08:11 +00:00
if ( info - > ca & & info - > references . empty ( ) ) {
storePathForDst = dstStore - > makeFixedOutputPathFromCA ( storePath . name ( ) , * info - > ca ) ;
2020-06-17 18:04:46 +00:00
if ( dstStore - > storeDir = = srcStore - > storeDir )
assert ( storePathForDst = = storePath ) ;
2020-06-12 20:32:52 +00:00
if ( storePathForDst ! = storePath )
2020-06-17 16:31:01 +00:00
debug ( " replaced path '%s' to '%s' for substituter '%s' " , srcStore - > printStorePath ( storePath ) , dstStore - > printStorePath ( storePathForDst ) , dstStore - > getUri ( ) ) ;
2020-06-12 19:27:28 +00:00
}
2020-06-19 18:48:57 +00:00
pathsMap . insert_or_assign ( storePath , storePathForDst ) ;
2019-12-05 18:11:09 +00:00
2020-06-12 19:27:28 +00:00
if ( ! dstStore - > isValidPath ( storePathForDst ) ) {
2017-08-14 20:42:17 +00:00
MaintainCount < decltype ( nrRunning ) > mc ( nrRunning ) ;
showProgress ( ) ;
2018-07-24 15:03:54 +00:00
try {
copyStorePath ( srcStore , dstStore , storePath , repair , checkSigs ) ;
} catch ( Error & e ) {
nrFailed + + ;
if ( ! settings . keepGoing )
throw e ;
2020-07-28 22:24:55 +00:00
logger - > log ( lvlError , fmt ( " could not copy %s: %s " , dstStore - > printStorePath ( storePath ) , e . what ( ) ) ) ;
2018-07-24 15:03:54 +00:00
showProgress ( ) ;
return ;
}
2017-06-28 16:11:01 +00:00
}
2017-08-14 13:28:16 +00:00
nrDone + + ;
showProgress ( ) ;
2017-06-28 16:11:01 +00:00
} ) ;
2020-06-19 18:48:57 +00:00
return pathsMap ;
2017-06-28 16:11:01 +00:00
}
2016-10-07 17:15:25 +00:00
2017-06-28 16:11:01 +00:00
void copyClosure ( ref < Store > srcStore , ref < Store > dstStore ,
2019-12-05 18:11:09 +00:00
const StorePathSet & storePaths , RepairFlag repair , CheckSigsFlag checkSigs ,
2017-06-28 16:11:01 +00:00
SubstituteFlag substitute )
{
2019-12-05 18:11:09 +00:00
StorePathSet closure ;
srcStore - > computeFSClosure ( storePaths , closure ) ;
2017-06-28 16:11:01 +00:00
copyPaths ( srcStore , dstStore , closure , repair , checkSigs , substitute ) ;
2016-10-07 17:15:25 +00:00
}
2020-08-06 18:31:48 +00:00
std : : optional < ValidPathInfo > decodeValidPathInfo ( const Store & store , std : : istream & str , std : : optional < HashResult > hashGiven )
2007-08-12 00:29:28 +00:00
{
2019-12-05 18:11:09 +00:00
std : : string path ;
getline ( str , path ) ;
if ( str . eof ( ) ) { return { } ; }
2020-08-06 18:31:48 +00:00
if ( ! hashGiven ) {
2008-01-29 18:17:36 +00:00
string s ;
getline ( str , s ) ;
2020-08-06 18:31:48 +00:00
auto narHash = Hash : : parseAny ( s , htSHA256 ) ;
2010-11-16 17:11:46 +00:00
getline ( str , s ) ;
2021-01-08 11:22:21 +00:00
auto narSize = string2Int < uint64_t > ( s ) ;
if ( ! narSize ) throw Error ( " number expected " ) ;
hashGiven = { narHash , * narSize } ;
2008-01-29 18:17:36 +00:00
}
2020-08-06 18:31:48 +00:00
ValidPathInfo info ( store . parseStorePath ( path ) , hashGiven - > first ) ;
info . narSize = hashGiven - > second ;
2019-12-05 18:11:09 +00:00
std : : string deriver ;
getline ( str , deriver ) ;
if ( deriver ! = " " ) info . deriver = store . parseStorePath ( deriver ) ;
2021-01-08 11:22:21 +00:00
string s ;
2007-08-12 00:29:28 +00:00
getline ( str , s ) ;
2021-01-08 11:22:21 +00:00
auto n = string2Int < int > ( s ) ;
if ( ! n ) throw Error ( " number expected " ) ;
while ( ( * n ) - - ) {
2007-08-12 00:29:28 +00:00
getline ( str , s ) ;
2019-12-05 18:11:09 +00:00
info . references . insert ( store . parseStorePath ( s ) ) ;
2007-08-12 00:29:28 +00:00
}
if ( ! str | | str . eof ( ) ) throw Error ( " missing input " ) ;
2019-12-05 18:11:09 +00:00
return std : : optional < ValidPathInfo > ( std : : move ( info ) ) ;
}
std : : string Store : : showPaths ( const StorePathSet & paths )
{
std : : string s ;
for ( auto & i : paths ) {
if ( s . size ( ) ! = 0 ) s + = " , " ;
s + = " ' " + printStorePath ( i ) + " ' " ;
}
return s ;
2007-08-12 00:29:28 +00:00
}
2008-06-09 13:52:45 +00:00
string showPaths ( const PathSet & paths )
{
2019-05-02 19:09:52 +00:00
return concatStringsSep ( " , " , quoteStrings ( paths ) ) ;
2008-06-09 13:52:45 +00:00
}
2019-12-05 18:11:09 +00:00
std : : string ValidPathInfo : : fingerprint ( const Store & store ) const
2016-03-24 10:41:00 +00:00
{
2020-08-05 19:30:38 +00:00
if ( narSize = = 0 )
throw Error ( " cannot calculate fingerprint of path '%s' because its size is not known " ,
2019-12-05 18:11:09 +00:00
store . printStorePath ( path ) ) ;
2016-03-24 10:41:00 +00:00
return
2019-12-05 18:11:09 +00:00
" 1; " + store . printStorePath ( path ) + " ; "
2020-06-03 10:38:23 +00:00
+ narHash . to_string ( Base32 , true ) + " ; "
2016-03-24 10:41:00 +00:00
+ std : : to_string ( narSize ) + " ; "
2019-12-05 18:11:09 +00:00
+ concatStringsSep ( " , " , store . printStorePathSet ( references ) ) ;
2016-03-24 10:41:00 +00:00
}
2019-12-05 18:11:09 +00:00
void ValidPathInfo : : sign ( const Store & store , const SecretKey & secretKey )
2016-03-24 10:41:00 +00:00
{
2019-12-05 18:11:09 +00:00
sigs . insert ( secretKey . signDetached ( fingerprint ( store ) ) ) ;
2016-03-24 10:41:00 +00:00
}
2016-08-03 11:17:11 +00:00
bool ValidPathInfo : : isContentAddressed ( const Store & store ) const
{
2020-06-02 17:04:21 +00:00
if ( ! ca ) return false ;
2016-08-03 11:17:11 +00:00
2020-06-02 17:04:21 +00:00
auto caPath = std : : visit ( overloaded {
[ & ] ( TextHash th ) {
return store . makeTextPath ( path . name ( ) , th . hash , references ) ;
} ,
2020-06-19 15:18:19 +00:00
[ & ] ( FixedOutputHash fsh ) {
2020-06-18 23:01:58 +00:00
auto refs = references ;
2020-06-02 17:04:21 +00:00
bool hasSelfReference = false ;
if ( refs . count ( path ) ) {
hasSelfReference = true ;
refs . erase ( path ) ;
}
return store . makeFixedOutputPath ( fsh . method , fsh . hash , path . name ( ) , refs , hasSelfReference ) ;
}
} , * ca ) ;
2020-06-02 00:37:43 +00:00
2020-06-02 17:04:21 +00:00
bool res = caPath = = path ;
2016-08-03 11:17:11 +00:00
2020-06-02 17:04:21 +00:00
if ( ! res )
printError ( " warning: path '%s' claims to be content-addressed but isn't " , store . printStorePath ( path ) ) ;
2016-08-03 11:17:11 +00:00
2020-06-02 17:04:21 +00:00
return res ;
2016-08-03 11:17:11 +00:00
}
size_t ValidPathInfo : : checkSignatures ( const Store & store , const PublicKeys & publicKeys ) const
2016-03-24 10:41:00 +00:00
{
2016-08-03 11:17:11 +00:00
if ( isContentAddressed ( store ) ) return maxSigs ;
size_t good = 0 ;
2016-03-24 10:41:00 +00:00
for ( auto & sig : sigs )
2019-12-05 18:11:09 +00:00
if ( checkSignature ( store , publicKeys , sig ) )
2016-03-24 10:41:00 +00:00
good + + ;
return good ;
}
2019-12-05 18:11:09 +00:00
bool ValidPathInfo : : checkSignature ( const Store & store , const PublicKeys & publicKeys , const std : : string & sig ) const
2016-04-07 13:14:12 +00:00
{
2019-12-05 18:11:09 +00:00
return verifyDetached ( fingerprint ( store ) , sig , publicKeys ) ;
2016-04-07 13:14:12 +00:00
}
2016-04-20 12:12:38 +00:00
Strings ValidPathInfo : : shortRefs ( ) const
{
Strings refs ;
for ( auto & r : references )
2019-12-05 18:11:09 +00:00
refs . push_back ( std : : string ( r . to_string ( ) ) ) ;
2016-04-20 12:12:38 +00:00
return refs ;
}
2020-06-17 03:56:48 +00:00
Derivation Store : : derivationFromPath ( const StorePath & drvPath )
{
ensurePath ( drvPath ) ;
return readDerivation ( drvPath ) ;
}
2020-12-15 09:54:24 +00:00
Derivation readDerivationCommon ( Store & store , const StorePath & drvPath , bool requireValidPath )
2020-06-17 03:56:48 +00:00
{
2020-12-15 09:54:24 +00:00
auto accessor = store . getFSAccessor ( ) ;
2020-06-17 03:56:48 +00:00
try {
2020-12-15 09:54:24 +00:00
return parseDerivation ( store ,
accessor - > readFile ( store . printStorePath ( drvPath ) , requireValidPath ) ,
2020-08-01 19:38:35 +00:00
Derivation : : nameFromPath ( drvPath ) ) ;
2020-06-17 03:56:48 +00:00
} catch ( FormatError & e ) {
2020-12-15 09:54:24 +00:00
throw Error ( " error parsing derivation '%s': %s " , store . printStorePath ( drvPath ) , e . msg ( ) ) ;
2020-06-17 03:56:48 +00:00
}
}
2020-12-15 09:54:24 +00:00
Derivation Store : : readDerivation ( const StorePath & drvPath )
{ return readDerivationCommon ( * this , drvPath , true ) ; }
2020-11-17 12:58:55 +00:00
Derivation Store : : readInvalidDerivation ( const StorePath & drvPath )
2020-12-15 09:54:24 +00:00
{ return readDerivationCommon ( * this , drvPath , false ) ; }
2020-11-17 12:58:55 +00:00
2006-11-30 17:43:04 +00:00
}
# include "local-store.hh"
2020-10-11 16:01:53 +00:00
# include "uds-remote-store.hh"
2006-11-30 17:43:04 +00:00
namespace nix {
2019-02-21 10:44:25 +00:00
/* Split URI into protocol+hierarchy part and its parameter set. */
std : : pair < std : : string , Store : : Params > splitUriAndParams ( const std : : string & uri_ )
2006-11-30 17:43:04 +00:00
{
2016-04-29 14:26:16 +00:00
auto uri ( uri_ ) ;
2019-02-21 10:44:25 +00:00
Store : : Params params ;
2016-04-29 14:26:16 +00:00
auto q = uri . find ( ' ? ' ) ;
if ( q ! = std : : string : : npos ) {
2020-03-30 14:04:18 +00:00
params = decodeQuery ( uri . substr ( q + 1 ) ) ;
2016-04-29 14:26:16 +00:00
uri = uri_ . substr ( 0 , q ) ;
}
2019-02-21 10:44:25 +00:00
return { uri , params } ;
}
2020-07-21 15:39:47 +00:00
static bool isNonUriPath ( const std : : string & spec ) {
return
// is not a URL
spec . find ( " :// " ) = = std : : string : : npos
// Has at least one path separator, and so isn't a single word that
// might be special like "auto"
& & spec . find ( " / " ) ! = std : : string : : npos ;
}
2016-02-29 15:11:11 +00:00
2020-09-16 22:35:24 +00:00
std : : shared_ptr < Store > openFromNonUri ( const std : : string & uri , const Store : : Params & params )
2016-02-29 15:11:11 +00:00
{
2020-09-16 22:35:24 +00:00
if ( uri = = " " | | uri = = " auto " ) {
auto stateDir = get ( params , " state " ) . value_or ( settings . nixStateDir ) ;
2016-06-02 11:33:49 +00:00
if ( access ( stateDir . c_str ( ) , R_OK | W_OK ) = = 0 )
2020-09-16 22:35:24 +00:00
return std : : make_shared < LocalStore > ( params ) ;
2016-01-31 09:19:14 +00:00
else if ( pathExists ( settings . nixDaemonSocketFile ) )
2020-09-16 22:35:24 +00:00
return std : : make_shared < UDSRemoteStore > ( params ) ;
2016-01-31 09:19:14 +00:00
else
2020-09-16 22:35:24 +00:00
return std : : make_shared < LocalStore > ( params ) ;
} else if ( uri = = " daemon " ) {
return std : : make_shared < UDSRemoteStore > ( params ) ;
} else if ( uri = = " local " ) {
return std : : make_shared < LocalStore > ( params ) ;
} else if ( isNonUriPath ( uri ) ) {
Store : : Params params2 = params ;
params2 [ " root " ] = absPath ( uri ) ;
return std : : make_shared < LocalStore > ( params2 ) ;
2016-09-02 10:39:29 +00:00
} else {
2020-09-16 22:35:24 +00:00
return nullptr ;
2016-01-31 09:19:14 +00:00
}
2020-09-08 12:50:23 +00:00
}
2020-12-05 14:33:16 +00:00
// The `parseURL` function supports both IPv6 URIs as defined in
// RFC2732, but also pure addresses. The latter one is needed here to
// connect to a remote store via SSH (it's possible to do e.g. `ssh root@::1`).
//
// This function now ensures that a usable connection string is available:
// * If the store to be opened is not an SSH store, nothing will be done.
// * If the URL looks like `root@[::1]` (which is allowed by the URL parser and probably
// needed to pass further flags), it
// will be transformed into `root@::1` for SSH (same for `[::1]` -> `::1`).
// * If the URL looks like `root@::1` it will be left as-is.
// * In any other case, the string will be left as-is.
static std : : string extractConnStr ( const std : : string & proto , const std : : string & connStr )
{
if ( proto . rfind ( " ssh " ) ! = std : : string : : npos ) {
std : : smatch result ;
std : : regex v6AddrRegex ( " ^((.*)@)? \\ [(.*) \\ ]$ " ) ;
if ( std : : regex_match ( connStr , result , v6AddrRegex ) ) {
if ( result [ 1 ] . matched ) {
return result . str ( 1 ) + result . str ( 3 ) ;
}
return result . str ( 3 ) ;
}
}
return connStr ;
}
2019-02-21 10:44:25 +00:00
ref < Store > openStore ( const std : : string & uri_ ,
const Store : : Params & extraParams )
{
auto params = extraParams ;
2020-09-11 09:11:05 +00:00
try {
auto parsedUri = parseURL ( uri_ ) ;
params . insert ( parsedUri . query . begin ( ) , parsedUri . query . end ( ) ) ;
2020-12-05 14:33:16 +00:00
auto baseURI = extractConnStr (
parsedUri . scheme ,
parsedUri . authority . value_or ( " " ) + parsedUri . path
) ;
2020-09-11 09:11:05 +00:00
for ( auto implem : * Implementations : : registered ) {
if ( implem . uriSchemes . count ( parsedUri . scheme ) ) {
auto store = implem . create ( parsedUri . scheme , baseURI , params ) ;
if ( store ) {
store - > init ( ) ;
store - > warnUnknownSettings ( ) ;
return ref < Store > ( store ) ;
}
}
}
2020-09-08 12:50:23 +00:00
}
2020-09-16 12:00:21 +00:00
catch ( BadURL & ) {
2020-09-11 09:11:05 +00:00
auto [ uri , uriParams ] = splitUriAndParams ( uri_ ) ;
params . insert ( uriParams . begin ( ) , uriParams . end ( ) ) ;
2016-04-29 14:26:16 +00:00
2020-09-11 09:11:05 +00:00
if ( auto store = openFromNonUri ( uri , params ) ) {
2018-03-27 16:41:31 +00:00
store - > warnUnknownSettings ( ) ;
2017-04-13 13:55:38 +00:00
return ref < Store > ( store ) ;
}
2016-02-24 13:48:16 +00:00
}
2020-09-11 09:11:05 +00:00
throw Error ( " don't know how to open Nix store '%s' " , uri_ ) ;
2016-02-29 15:11:11 +00:00
}
2016-04-29 11:57:08 +00:00
std : : list < ref < Store > > getDefaultSubstituters ( )
{
2017-07-04 14:26:48 +00:00
static auto stores ( [ ] ( ) {
2016-04-29 11:57:08 +00:00
std : : list < ref < Store > > stores ;
2017-07-04 14:26:48 +00:00
StringSet done ;
2016-04-29 11:57:08 +00:00
2017-07-04 14:26:48 +00:00
auto addStore = [ & ] ( const std : : string & uri ) {
2019-10-09 13:51:52 +00:00
if ( ! done . insert ( uri ) . second ) return ;
2018-02-09 13:36:38 +00:00
try {
stores . push_back ( openStore ( uri ) ) ;
} catch ( Error & e ) {
2020-05-03 14:01:25 +00:00
logWarning ( e . info ( ) ) ;
2018-02-09 13:36:38 +00:00
}
2017-07-04 14:26:48 +00:00
} ;
2016-04-29 11:57:08 +00:00
2017-07-04 14:26:48 +00:00
for ( auto uri : settings . substituters . get ( ) )
addStore ( uri ) ;
2017-03-21 16:59:18 +00:00
2017-07-04 14:34:53 +00:00
stores . sort ( [ ] ( ref < Store > & a , ref < Store > & b ) {
2019-12-17 16:17:53 +00:00
return a - > priority < b - > priority ;
2017-07-04 14:34:53 +00:00
} ) ;
2017-07-04 14:26:48 +00:00
return stores ;
} ( ) ) ;
2016-04-29 11:57:08 +00:00
2017-07-04 14:26:48 +00:00
return stores ;
2016-04-29 11:57:08 +00:00
}
2020-09-09 09:18:12 +00:00
std : : vector < StoreFactory > * Implementations : : registered = 0 ;
2016-04-29 11:57:08 +00:00
2006-11-30 17:43:04 +00:00
}