mirror of
https://github.com/NixOS/nix.git
synced 2025-12-11 19:41:04 +01:00
Improve wrong format message with nix hash convert
We have the machinery to make a more informative error, telling the user what format was actually encountered, and not just that it is not the format that was requested.
This commit is contained in:
parent
5f42e5ebb7
commit
b61885786d
5 changed files with 43 additions and 22 deletions
|
|
@ -182,8 +182,10 @@ Hash Hash::parseSRI(std::string_view original)
|
||||||
*
|
*
|
||||||
* @param resolveAlgo resolves the parsed type (or throws an error when it is not
|
* @param resolveAlgo resolves the parsed type (or throws an error when it is not
|
||||||
* possible.)
|
* possible.)
|
||||||
|
*
|
||||||
|
* @return the parsed hash and the format it was parsed from
|
||||||
*/
|
*/
|
||||||
static Hash parseAnyHelper(std::string_view rest, auto resolveAlgo)
|
static std::pair<Hash, HashFormat> parseAnyHelper(std::string_view rest, auto resolveAlgo)
|
||||||
{
|
{
|
||||||
bool isSRI = false;
|
bool isSRI = false;
|
||||||
|
|
||||||
|
|
@ -203,34 +205,45 @@ static Hash parseAnyHelper(std::string_view rest, auto resolveAlgo)
|
||||||
|
|
||||||
HashAlgorithm algo = resolveAlgo(std::move(optParsedAlgo));
|
HashAlgorithm algo = resolveAlgo(std::move(optParsedAlgo));
|
||||||
|
|
||||||
auto [decode, formatName] = [&]() -> DecodeNamePair {
|
auto [decode, formatName, format] = [&]() -> std::tuple<decltype(base16::decode) *, std::string_view, HashFormat> {
|
||||||
if (isSRI) {
|
if (isSRI) {
|
||||||
/* In the SRI case, we always are using Base64. If the
|
/* In the SRI case, we always are using Base64. If the
|
||||||
length is wrong, get an error later. */
|
length is wrong, get an error later. */
|
||||||
return {base64::decode, "SRI"};
|
return {base64::decode, "SRI", HashFormat::SRI};
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise, decide via the length of the hash (for the
|
/* Otherwise, decide via the length of the hash (for the
|
||||||
given algorithm) what base encoding it is. */
|
given algorithm) what base encoding it is. */
|
||||||
return baseExplicit(baseFromSize(rest, algo));
|
auto format = baseFromSize(rest, algo);
|
||||||
|
auto [decode, formatName] = baseExplicit(format);
|
||||||
|
return {decode, formatName, format};
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
return parseLowLevel(rest, algo, {decode, formatName});
|
return {parseLowLevel(rest, algo, {decode, formatName}), format};
|
||||||
}
|
}
|
||||||
|
|
||||||
Hash Hash::parseAnyPrefixed(std::string_view original)
|
Hash Hash::parseAnyPrefixed(std::string_view original)
|
||||||
{
|
{
|
||||||
return parseAnyHelper(original, [&](std::optional<HashAlgorithm> optParsedAlgo) {
|
return parseAnyHelper(
|
||||||
// Either the string or user must provide the type, if they both do they
|
original,
|
||||||
// must agree.
|
[&](std::optional<HashAlgorithm> optParsedAlgo) {
|
||||||
if (!optParsedAlgo)
|
// Either the string or user must provide the type, if they both do they
|
||||||
throw BadHash("hash '%s' does not include a type", original);
|
// must agree.
|
||||||
|
if (!optParsedAlgo)
|
||||||
|
throw BadHash("hash '%s' does not include a type", original);
|
||||||
|
|
||||||
return *optParsedAlgo;
|
return *optParsedAlgo;
|
||||||
});
|
})
|
||||||
|
.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hash Hash::parseAny(std::string_view original, std::optional<HashAlgorithm> optAlgo)
|
Hash Hash::parseAny(std::string_view original, std::optional<HashAlgorithm> optAlgo)
|
||||||
|
{
|
||||||
|
return parseAnyReturningFormat(original, optAlgo).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Hash, HashFormat>
|
||||||
|
Hash::parseAnyReturningFormat(std::string_view original, std::optional<HashAlgorithm> optAlgo)
|
||||||
{
|
{
|
||||||
return parseAnyHelper(original, [&](std::optional<HashAlgorithm> optParsedAlgo) {
|
return parseAnyHelper(original, [&](std::optional<HashAlgorithm> optParsedAlgo) {
|
||||||
// Either the string or user must provide the type, if they both do they
|
// Either the string or user must provide the type, if they both do they
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,12 @@ struct Hash
|
||||||
*/
|
*/
|
||||||
static Hash parseAny(std::string_view s, std::optional<HashAlgorithm> optAlgo);
|
static Hash parseAny(std::string_view s, std::optional<HashAlgorithm> optAlgo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like `parseAny`, but also returns the format the hash was parsed from.
|
||||||
|
*/
|
||||||
|
static std::pair<Hash, HashFormat>
|
||||||
|
parseAnyReturningFormat(std::string_view s, std::optional<HashAlgorithm> optAlgo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a hash from a string representation like the above, except the
|
* Parse a hash from a string representation like the above, except the
|
||||||
* type prefix is mandatory is there is no separate argument.
|
* type prefix is mandatory is there is no separate argument.
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ R""(
|
||||||
|
|
||||||
```console
|
```console
|
||||||
# nix hash convert --hash-algo sha256 --from nix32 ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
|
# nix hash convert --hash-algo sha256 --from nix32 ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
|
||||||
error: input hash 'ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=' does not have the expected format '--from nix32'
|
error: input hash 'ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=' has format 'base64', but '--from nix32' was specified
|
||||||
|
|
||||||
# nix hash convert --hash-algo sha256 --from nix32 1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s
|
# nix hash convert --hash-algo sha256 --from nix32 1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s
|
||||||
sha256-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
|
sha256-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
|
||||||
|
|
|
||||||
|
|
@ -248,11 +248,13 @@ struct CmdHashConvert : Command
|
||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
for (const auto & s : hashStrings) {
|
for (const auto & s : hashStrings) {
|
||||||
Hash h = from == HashFormat::SRI ? Hash::parseSRI(s) : Hash::parseAny(s, algo);
|
auto [h, parsedFormat] = Hash::parseAnyReturningFormat(s, algo);
|
||||||
if (from && from != HashFormat::SRI
|
if (from && *from != parsedFormat) {
|
||||||
&& h.to_string(*from, false) != (from == HashFormat::Base16 ? toLower(s) : s)) {
|
throw BadHash(
|
||||||
auto from_as_string = printHashFormat(*from);
|
"input hash '%s' has format '%s', but '--from %s' was specified",
|
||||||
throw BadHash("input hash '%s' does not have the expected format for '--from %s'", s, from_as_string);
|
s,
|
||||||
|
printHashFormat(parsedFormat),
|
||||||
|
printHashFormat(*from));
|
||||||
}
|
}
|
||||||
logger->cout(h.to_string(to, to == HashFormat::SRI));
|
logger->cout(h.to_string(to, to == HashFormat::SRI));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,10 @@ try3() {
|
||||||
# Asserting input format fails.
|
# Asserting input format fails.
|
||||||
#
|
#
|
||||||
|
|
||||||
expectStderr 1 nix hash convert --hash-algo "$1" --from sri "$2" | grepQuiet "is not SRI"
|
expectStderr 1 nix hash convert --hash-algo "$1" --from sri "$2" | grepQuiet "'base16', but '--from sri'"
|
||||||
expectStderr 1 nix hash convert --hash-algo "$1" --from nix32 "$2" | grepQuiet "input hash"
|
expectStderr 1 nix hash convert --hash-algo "$1" --from nix32 "$2" | grepQuiet "'base16', but '--from nix32'"
|
||||||
expectStderr 1 nix hash convert --hash-algo "$1" --from base16 "$3" | grepQuiet "input hash"
|
expectStderr 1 nix hash convert --hash-algo "$1" --from base16 "$3" | grepQuiet "'nix32', but '--from base16'"
|
||||||
expectStderr 1 nix hash convert --hash-algo "$1" --from nix32 "$4" | grepQuiet "input hash"
|
expectStderr 1 nix hash convert --hash-algo "$1" --from nix32 "$4" | grepQuiet "'base64', but '--from nix32'"
|
||||||
|
|
||||||
# Base-16 hashes can be in uppercase.
|
# Base-16 hashes can be in uppercase.
|
||||||
nix hash convert --hash-algo "$1" --from base16 "$(echo "$2" | tr '[:lower:]' '[:upper:]')"
|
nix hash convert --hash-algo "$1" --from base16 "$(echo "$2" | tr '[:lower:]' '[:upper:]')"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue