Skip to content

Commit

Permalink
TEMP
Browse files Browse the repository at this point in the history
  • Loading branch information
Ericson2314 committed Jan 20, 2024
1 parent 8163ccf commit ed22314
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 75 deletions.
19 changes: 19 additions & 0 deletions src/libutil/args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,25 @@ Args::Flag Args::Flag::mkHashAlgoOptFlag(std::string && longName, std::optional<
};
}

Args::Flag Args::Flag::mkFileIngestionMethodFlag(FileIngestionMethod * method)
{
return Flag {
.longName = "mode",
.description = R"(
How to compute the hash of the input.
One of:
- `nar` (the default): Serialises the input as an archive (following the [_Nix Archive Format_](https://edolstra.github.io/pubs/phd-thesis.pdf#page=101)) and passes that to the hash function.
- `flat`: Assumes that the input is a single file and directly passes it to the hash function;
)",
.labels = {"hash-mode"},
.handler = {[method](std::string s) {
*method = parseFileIngestionMethod(s);
}},
};
}

static void _completePath(AddCompletions & completions, std::string_view prefix, bool onlyDirs)
{
completions.setType(Completions::Type::Filenames);
Expand Down
5 changes: 5 additions & 0 deletions src/libutil/args.hh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "types.hh"
#include "experimental-features.hh"
#include "file-content-address.hh"

namespace nix {

Expand Down Expand Up @@ -185,7 +186,11 @@ protected:
return mkHashAlgoOptFlag("hash-algo", oha);
}
static Flag mkHashFormatFlagWithDefault(std::string && longName, HashFormat * hf);
static Flag mkHashFormatFlagWithDefault(HashFormat * hf) {
return mkHashFormatFlagWithDefault("hash-format", hf);
}
static Flag mkHashFormatOptFlag(std::string && longName, std::optional<HashFormat> * ohf);
static Flag mkFileIngestionMethodFlag(FileIngestionMethod * method);
};

/**
Expand Down
12 changes: 12 additions & 0 deletions src/libutil/file-content-address.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@

namespace nix {

FileIngestionMethod parseFileIngestionMethod(std::string_view input)
{
if (input == "flat") {
return FileIngestionMethod::Flat;
} else if (input == "nar") {
return FileIngestionMethod::Recursive;
} else {
throw UsageError("Unknown file ingestion method '%s', expect `flat` or `nar`");
}
}


void dumpPath(
SourceAccessor & accessor, const CanonPath & path,
Sink & sink,
Expand Down
8 changes: 8 additions & 0 deletions src/libutil/file-content-address.hh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ enum struct FileIngestionMethod : uint8_t {
Recursive = 1,
};

/**
* Parse a `FileIngestionMethod` by name. Choice of:
*
* - `flat`: `FileIngestionMethod::Flat`
* - `nar`: `FileIngestionMethod::Recursive`
*/
FileIngestionMethod parseFileIngestionMethod(std::string_view input);

/**
* Dump a serialization of the given file system object.
*/
Expand Down
28 changes: 1 addition & 27 deletions src/nix/add-to-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,6 @@

using namespace nix;

static FileIngestionMethod parseIngestionMethod(std::string_view input)
{
if (input == "flat") {
return FileIngestionMethod::Flat;
} else if (input == "nar") {
return FileIngestionMethod::Recursive;
} else {
throw UsageError("Unknown hash mode '%s', expect `flat` or `nar`");
}
}

struct CmdAddToStore : MixDryRun, StoreCommand
{
Path path;
Expand All @@ -37,21 +26,7 @@ struct CmdAddToStore : MixDryRun, StoreCommand
.handler = {&namePart},
});

addFlag({
.longName = "mode",
.description = R"(
How to compute the hash of the input.
One of:
- `nar` (the default): Serialises the input as an archive (following the [_Nix Archive Format_](https://edolstra.github.io/pubs/phd-thesis.pdf#page=101)) and passes that to the hash function.
- `flat`: Assumes that the input is a single file and directly passes it to the hash function;
)",
.labels = {"hash-mode"},
.handler = {[this](std::string s) {
this->caMethod = parseIngestionMethod(s);
}},
});
addFlag(Flag::mkFileIngestionMethodFlag(&caMethod));

addFlag(Flag::mkHashAlgoFlag(&hashAlgo));
}
Expand All @@ -76,7 +51,6 @@ struct CmdAddToStore : MixDryRun, StoreCommand

struct CmdAdd : CmdAddToStore
{

std::string description() override
{
return "Add a file or directory to the Nix store";
Expand Down
124 changes: 76 additions & 48 deletions src/nix/hash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,47 +19,12 @@ struct CmdHashBase : Command
FileIngestionMethod mode;
HashFormat hashFormat = HashFormat::SRI;
bool truncate = false;
HashAlgorithm ha = HashAlgorithm::SHA256;
HashAlgorithm hashAlgo = HashAlgorithm::SHA256;
std::vector<std::string> paths;
std::optional<std::string> modulus;

explicit CmdHashBase(FileIngestionMethod mode) : mode(mode)
{
addFlag({
.longName = "sri",
.description = "Print the hash in SRI format.",
.handler = {&hashFormat, HashFormat::SRI},
});

addFlag({
.longName = "base64",
.description = "Print the hash in base-64 format.",
.handler = {&hashFormat, HashFormat::Base64},
});

addFlag({
.longName = "base32",
.description = "Print the hash in base-32 (Nix-specific) format.",
.handler = {&hashFormat, HashFormat::Nix32},
});

addFlag({
.longName = "base16",
.description = "Print the hash in base-16 format.",
.handler = {&hashFormat, HashFormat::Base16},
});

addFlag(Flag::mkHashAlgoFlag("type", &ha));

#if 0
addFlag({
.longName = "modulo",
.description = "Compute the hash modulo the specified string.",
.labels = {"modulus"},
.handler = {&modulus},
});
#endif\

expectArgs({
.label = "paths",
.handler = {&paths},
Expand All @@ -85,9 +50,9 @@ struct CmdHashBase : Command

std::unique_ptr<AbstractHashSink> hashSink;
if (modulus)
hashSink = std::make_unique<HashModuloSink>(ha, *modulus);
hashSink = std::make_unique<HashModuloSink>(hashAlgo, *modulus);
else
hashSink = std::make_unique<HashSink>(ha);
hashSink = std::make_unique<HashSink>(hashAlgo);

PosixSourceAccessor accessor;
dumpPath(accessor, CanonPath::fromCwd(path), *hashSink, mode);
Expand All @@ -99,15 +64,78 @@ struct CmdHashBase : Command
}
};

/**
* `nix hash path`
*/
struct CmdHashPath : CmdHashBase
{
CmdHashPath()
: CmdHashBase(FileIngestionMethod::Recursive)
{
addFlag(Flag::mkHashAlgoFlag(&hashAlgo));
addFlag(Flag::mkFileIngestionMethodFlag(&mode));
addFlag(Args::Flag::mkHashFormatFlagWithDefault(&hashFormat));
#if 0
addFlag({
.longName = "modulo",
.description = "Compute the hash modulo the specified string.",
.labels = {"modulus"},
.handler = {&modulus},
});
#endif
}
};

/**
* For deprecated `nix hash file`
*
* Deprecation Issue: https://github.com/NixOS/nix/issues/8876
*/
struct CmdHashFile : CmdHashBase
{
CmdHashFile()
: CmdHashBase(FileIngestionMethod::Flat)
{
addFlag({
.longName = "sri",
.description = "Print the hash in SRI format.",
.handler = {&hashFormat, HashFormat::SRI},
});

addFlag({
.longName = "base64",
.description = "Print the hash in base-64 format.",
.handler = {&hashFormat, HashFormat::Base64},
});

addFlag({
.longName = "base32",
.description = "Print the hash in base-32 (Nix-specific) format.",
.handler = {&hashFormat, HashFormat::Nix32},
});

addFlag({
.longName = "base16",
.description = "Print the hash in base-16 format.",
.handler = {&hashFormat, HashFormat::Base16},
});

addFlag(Flag::mkHashAlgoFlag("type", &hashAlgo));
}
};

/**
* For deprecated `nix hash to-*`
*/
struct CmdToBase : Command
{
HashFormat hashFormat;
std::optional<HashAlgorithm> ht;
std::optional<HashAlgorithm> hashAlgo;
std::vector<std::string> args;

CmdToBase(HashFormat hashFormat) : hashFormat(hashFormat)
{
addFlag(Flag::mkHashAlgoOptFlag("type", &ht));
addFlag(Flag::mkHashAlgoOptFlag("type", &hashAlgo));
expectArgs("strings", &args);
}

Expand All @@ -124,7 +152,7 @@ struct CmdToBase : Command
{
warn("The old format conversion sub commands of `nix hash` where deprecated in favor of `nix hash convert`.");
for (auto s : args)
logger->cout(Hash::parseAny(s, ht).to_string(hashFormat, hashFormat == HashFormat::SRI));
logger->cout(Hash::parseAny(s, hashAlgo).to_string(hashFormat, hashFormat == HashFormat::SRI));
}
};

Expand Down Expand Up @@ -182,8 +210,8 @@ struct CmdHash : NixMultiCommand
"hash",
{
{"convert", []() { return make_ref<CmdHashConvert>();}},
{"file", []() { return make_ref<CmdHashBase>(FileIngestionMethod::Flat);; }},
{"path", []() { return make_ref<CmdHashBase>(FileIngestionMethod::Recursive); }},
{"path", []() { return make_ref<CmdHashPath>(); }},
{"file", []() { return make_ref<CmdHashFile>(); }},
{"to-base16", []() { return make_ref<CmdToBase>(HashFormat::Base16); }},
{"to-base32", []() { return make_ref<CmdToBase>(HashFormat::Nix32); }},
{"to-base64", []() { return make_ref<CmdToBase>(HashFormat::Base64); }},
Expand All @@ -207,7 +235,7 @@ static int compatNixHash(int argc, char * * argv)
// Wait until `nix hash convert` is not hidden behind experimental flags anymore.
// warn("`nix-hash` has been deprecated in favor of `nix hash convert`.");

std::optional<HashAlgorithm> ha;
std::optional<HashAlgorithm> hashAlgo;
bool flat = false;
HashFormat hashFormat = HashFormat::Base16;
bool truncate = false;
Expand All @@ -227,7 +255,7 @@ static int compatNixHash(int argc, char * * argv)
else if (*arg == "--truncate") truncate = true;
else if (*arg == "--type") {
std::string s = getArg(*arg, arg, end);
ha = parseHashAlgo(s);
hashAlgo = parseHashAlgo(s);
}
else if (*arg == "--to-base16") {
op = opTo;
Expand All @@ -254,8 +282,8 @@ static int compatNixHash(int argc, char * * argv)

if (op == opHash) {
CmdHashBase cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive);
if (!ha.has_value()) ha = HashAlgorithm::MD5;
cmd.ha = ha.value();
if (!hashAlgo.has_value()) hashAlgo = HashAlgorithm::MD5;
cmd.hashAlgo = hashAlgo.value();
cmd.hashFormat = hashFormat;
cmd.truncate = truncate;
cmd.paths = ss;
Expand All @@ -265,7 +293,7 @@ static int compatNixHash(int argc, char * * argv)
else {
CmdToBase cmd(hashFormat);
cmd.args = ss;
if (ha.has_value()) cmd.ht = ha;
if (hashAlgo.has_value()) cmd.hashAlgo = hashAlgo;
cmd.run();
}

Expand Down
5 changes: 5 additions & 0 deletions tests/functional/hash.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ try () {
echo "try nix hash: hash $1, expected $3, got $hash"
exit 1
fi
hash="$(nix hash path --mode flat ${FORMAT_FLAG-} --type "$1" "$TEST_ROOT/vector")"
if ! (( "${NO_TEST_NIX_COMMAND-}" )) && test "$hash" != "$3"; then
echo "try nix hash: hash $1, expected $3, got $hash"
exit 1
fi
}

FORMAT_FLAG=--base16
Expand Down

0 comments on commit ed22314

Please sign in to comment.