#include "libutil/hash.hh" #include "libmain/shared.hh" #include "nix/command.hh" #include "nix/legacy.hh" using namespace nix; struct CmdHash final : Command { enum Mode { mFile, mPath }; Mode mode; Base base = SRI; bool truncate = false; HashType ht = htSHA256; std::vector paths; explicit CmdHash(Mode mode) : mode(mode) { mkFlag(0, "sri", "print hash in SRI format", &base, SRI); mkFlag(0, "base64", "print hash in base-64", &base, Base64); mkFlag(0, "base32", "print hash in base-32 (Nix-specific)", &base, Base32); mkFlag(0, "base16", "print hash in base-16", &base, Base16); mkFlag().longName("type").mkHashTypeFlag(&ht); expectArgs("paths", &paths); } std::string name() override { return mode == mFile ? "hash-file" : "hash-path"; } std::string description() override { return mode == mFile ? "print cryptographic hash of a regular file" : "print cryptographic hash of the NAR serialisation of a path"; } void run() override { for (const auto& path : paths) { Hash h = mode == mFile ? hashFile(ht, path) : hashPath(ht, path).first; if (truncate && h.hashSize > 20) { h = compressHash(h, 20); } std::cout << format("%1%\n") % h.to_string(base, base == SRI); } } }; static RegisterCommand r1(make_ref(CmdHash::mFile)); static RegisterCommand r2(make_ref(CmdHash::mPath)); struct CmdToBase final : Command { Base base; HashType ht = htUnknown; std::vector args; explicit CmdToBase(Base base) : base(base) { mkFlag().longName("type").mkHashTypeFlag(&ht); expectArgs("strings", &args); } std::string name() override { return base == Base16 ? "to-base16" : base == Base32 ? "to-base32" : base == Base64 ? "to-base64" : "to-sri"; } std::string description() override { return fmt( "convert a hash to %s representation", base == Base16 ? "base-16" : base == Base32 ? "base-32" : base == Base64 ? "base-64" : "SRI"); } void run() override { for (const auto& s : args) { auto hash_ = Hash::deserialize(s, ht); if (hash_.ok()) { std::cout << hash_->to_string(base, base == SRI) << "\n"; } else { std::cerr << "failed to parse: " << hash_.status().ToString() << "\n"; // create a matching blank line, for scripting std::cout << "\n"; } } } }; static RegisterCommand r3(make_ref(Base16)); static RegisterCommand r4(make_ref(Base32)); static RegisterCommand r5(make_ref(Base64)); static RegisterCommand r6(make_ref(SRI)); /* Legacy nix-hash command. */ static int compatNixHash(int argc, char** argv) { HashType ht = htMD5; bool flat = false; bool base32 = false; bool truncate = false; enum { opHash, opTo32, opTo16 } op = opHash; std::vector ss; parseCmdLine(argc, argv, [&](Strings::iterator& arg, const Strings::iterator& end) { if (*arg == "--help") { showManPage("nix-hash"); } else if (*arg == "--version") { printVersion("nix-hash"); } else if (*arg == "--flat") { flat = true; } else if (*arg == "--base32") { base32 = true; } else if (*arg == "--truncate") { truncate = true; } else if (*arg == "--type") { std::string s = getArg(*arg, arg, end); ht = parseHashType(s); if (ht == htUnknown) { throw UsageError(format("unknown hash type '%1%'") % s); } } else if (*arg == "--to-base16") { op = opTo16; } else if (*arg == "--to-base32") { op = opTo32; } else if (*arg != "" && arg->at(0) == '-') { return false; } else { ss.push_back(*arg); } return true; }); if (op == opHash) { CmdHash cmd(flat ? CmdHash::mFile : CmdHash::mPath); cmd.ht = ht; cmd.base = base32 ? Base32 : Base16; cmd.truncate = truncate; cmd.paths = ss; cmd.run(); } else { CmdToBase cmd(op == opTo32 ? Base32 : Base16); cmd.args = ss; cmd.ht = ht; cmd.run(); } return 0; } static RegisterLegacyCommand s1("nix-hash", compatNixHash);