@@ -87,18 +87,35 @@ struct CmdHashBase : Command
8787 return std::make_unique<HashSink>(hashAlgo);
8888 };
8989
90- auto path2 = PosixSourceAccessor::createAtRoot (path);
90+ auto makeSourcePath = [&]() -> SourcePath {
91+ return PosixSourceAccessor::createAtRoot (makeParentCanonical (path));
92+ };
93+
9194 Hash h { HashAlgorithm::SHA256 }; // throwaway def to appease C++
9295 switch (mode) {
9396 case FileIngestionMethod::Flat:
97+ {
98+ // While usually we could use the some code as for NixArchive,
99+ // the Flat method needs to support FIFOs, such as those
100+ // produced by bash process substitution, e.g.:
101+ // nix hash --mode flat <(echo hi)
102+ // Also symlinks semantics are unambiguous in the flat case,
103+ // so we don't need to go low-level, or reject symlink `path`s.
104+ auto hashSink = makeSink ();
105+ readFile (path, *hashSink);
106+ h = hashSink->finish ().first ;
107+ break ;
108+ }
94109 case FileIngestionMethod::NixArchive:
95110 {
111+ auto sourcePath = makeSourcePath ();
96112 auto hashSink = makeSink ();
97- dumpPath (path2 , *hashSink, (FileSerialisationMethod) mode);
113+ dumpPath (sourcePath , *hashSink, (FileSerialisationMethod) mode);
98114 h = hashSink->finish ().first ;
99115 break ;
100116 }
101117 case FileIngestionMethod::Git: {
118+ auto sourcePath = makeSourcePath ();
102119 std::function<git::DumpHook> hook;
103120 hook = [&](const SourcePath & path) -> git::TreeEntry {
104121 auto hashSink = makeSink ();
@@ -109,7 +126,7 @@ struct CmdHashBase : Command
109126 .hash = hash,
110127 };
111128 };
112- h = hook (path2 ).hash ;
129+ h = hook (sourcePath ).hash ;
113130 break ;
114131 }
115132 }
0 commit comments