Skip to content

Commit

Permalink
nix hash convert: added
Browse files Browse the repository at this point in the history
This deviated from the proposal! See comments on the issue.

NixOS#8876
  • Loading branch information
kolloch committed Nov 25, 2023
1 parent 3d0d7d0 commit cdf700f
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
63 changes: 63 additions & 0 deletions src/nix/hash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,73 @@ struct CmdToBase : Command
}
};

/**
* `nix hash convert`
*/
struct CmdHashConvert : Command
{
std::optional<HashFormat> from;
HashFormat to;
std::optional<HashType> type;
std::vector<std::string> hashStrings;

CmdHashConvert(): to(HashFormat::SRI) {
addFlag({
.longName = "from",
// TODO: List format choices. Maybe introduce a constant?
.description = "The format of the input hash.",
.labels = {"hash format"},
.handler = {[this](std::string str) {
from = parseHashFormat(str);
}},
});
addFlag({
.longName = "to",
// TODO: List format choices. Maybe introduce a constant?
.description = "The format of the output hash.",
.labels = {"hash format"},
.handler = {[this](std::string str) {
to = parseHashFormat(str);
}},
});
addFlag({
.longName = "type",
.description = "Specify the type if it can't be auto-detected.",
.labels = {"hash type"},
.handler = {[this](std::string str) {
type = parseHashType(str);
}},
});
expectArgs({
.label = "hashes",
.handler = {&hashStrings},
});
}

std::string description() override
{
return "convert between different hash formats, e.g. base16 and sri.";
}

Category category() override { return catUtility; }

void run() override {
for (const auto& s: hashStrings) {
Hash h = Hash::parseAny(s, type);
if (from && h.to_string(*from, from == HashFormat::SRI) != s) {
auto from_as_string = printHashFormat(*from);
throw BadHash("input hash '%s' does not have the expected format '--from %s'", s, from_as_string);
}
logger->cout(h.to_string(to, to == HashFormat::SRI));
}
}
};

struct CmdHash : NixMultiCommand
{
CmdHash()
: MultiCommand({
{"convert", []() { return make_ref<CmdHashConvert>();}},
{"file", []() { return make_ref<CmdHashBase>(FileIngestionMethod::Flat);; }},
{"path", []() { return make_ref<CmdHashBase>(FileIngestionMethod::Recursive); }},
{"to-base16", []() { return make_ref<CmdToBase>(HashFormat::Base16); }},
Expand Down
19 changes: 18 additions & 1 deletion tests/functional/hash.sh
Original file line number Diff line number Diff line change
Expand Up @@ -81,24 +81,41 @@ rm $TEST_ROOT/hash-path/hello
ln -s x $TEST_ROOT/hash-path/hello
try2 md5 "f78b733a68f5edbdf9413899339eaa4a"

# Conversion.
# Conversion with `nix hash` `nix-hash` and `nix hash convert`
try3() {
# $1 = hash type
# $2 = expected hash in base16
# $3 = expected hash in base32
# $4 = expected hash in base64
h64=$(nix hash convert --type "$1" --to base64 "$2")
[ "$h64" = "$4" ]
h64=$(nix-hash --type "$1" --to-base64 "$2")
[ "$h64" = "$4" ]
# Deprecated experiment
h64=$(nix hash to-base64 --type "$1" "$2")
[ "$h64" = "$4" ]

sri=$(nix hash convert --type "$1" --to sri "$2")
[ "$sri" = "$1-$4" ]
sri=$(nix-hash --type "$1" --to-sri "$2")
[ "$sri" = "$1-$4" ]
sri=$(nix hash to-sri --type "$1" "$2")
[ "$sri" = "$1-$4" ]
h32=$(nix hash convert --type "$1" --to base32 "$2")
[ "$h32" = "$3" ]
h32=$(nix-hash --type "$1" --to-base32 "$2")
[ "$h32" = "$3" ]
h32=$(nix hash to-base32 --type "$1" "$2")
[ "$h32" = "$3" ]
h16=$(nix-hash --type "$1" --to-base16 "$h32")
[ "$h16" = "$2" ]

h16=$(nix hash convert --type "$1" --to base16 "$h64")
[ "$h16" = "$2" ]
h16=$(nix hash to-base16 --type "$1" "$h64")
[ "$h16" = "$2" ]
h16=$(nix hash convert --to base16 "$sri")
[ "$h16" = "$2" ]
h16=$(nix hash to-base16 "$sri")
[ "$h16" = "$2" ]
}
Expand Down

0 comments on commit cdf700f

Please sign in to comment.