1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 20:16:03 +01:00

Implement support for Git hashing with SHA-256

SHA-256 is Git's next hash algorithm. The world is still basically stuck
on SHA-1 with git, but shouldn't be. We can at least do our part to get
ready.

On the C++ implementation side, only a little bit of generalization was
needed, and that was fairly straight-forward. The tests (unit and
system) were actually bigger, and care was taken to make sure they were
all cover both algorithms equally.
This commit is contained in:
John Ericson 2025-07-24 14:44:05 -04:00
parent 7f4acb9f10
commit d21e3f88ec
20 changed files with 350 additions and 181 deletions

View file

@ -59,7 +59,7 @@ void parseBlob(
{
xpSettings.require(Xp::GitHashing);
unsigned long long size = std::stoi(getStringUntil(source, 0));
const unsigned long long size = std::stoi(getStringUntil(source, 0));
auto doRegularFile = [&](bool executable) {
sink.createRegularFile(sinkPath, [&](auto & crf) {
@ -114,10 +114,11 @@ void parseTree(
FileSystemObjectSink & sink,
const CanonPath & sinkPath,
Source & source,
HashAlgorithm hashAlgo,
std::function<SinkHook> hook,
const ExperimentalFeatureSettings & xpSettings)
{
unsigned long long size = std::stoi(getStringUntil(source, 0));
const unsigned long long size = std::stoi(getStringUntil(source, 0));
unsigned long long left = size;
sink.createDirectory(sinkPath);
@ -137,10 +138,15 @@ void parseTree(
left -= name.size();
left -= 1;
std::string hashs = getString(source, 20);
left -= 20;
const auto hashSize = regularHashSize(hashAlgo);
std::string hashs = getString(source, hashSize);
left -= hashSize;
Hash hash(HashAlgorithm::SHA1);
if (!(hashAlgo == HashAlgorithm::SHA1 || hashAlgo == HashAlgorithm::SHA256)) {
throw Error("Unsupported hash algorithm for git trees: %s", printHashAlgo(hashAlgo));
}
Hash hash(hashAlgo);
std::copy(hashs.begin(), hashs.end(), hash.hash);
hook(
@ -171,6 +177,7 @@ void parse(
const CanonPath & sinkPath,
Source & source,
BlobMode rootModeIfBlob,
HashAlgorithm hashAlgo,
std::function<SinkHook> hook,
const ExperimentalFeatureSettings & xpSettings)
{
@ -183,7 +190,7 @@ void parse(
parseBlob(sink, sinkPath, source, rootModeIfBlob, xpSettings);
break;
case ObjectType::Tree:
parseTree(sink, sinkPath, source, hook, xpSettings);
parseTree(sink, sinkPath, source, hashAlgo, hook, xpSettings);
break;
default:
assert(false);
@ -210,9 +217,9 @@ std::optional<Mode> convertMode(SourceAccessor::Type type)
}
}
void restore(FileSystemObjectSink & sink, Source & source, std::function<RestoreHook> hook)
void restore(FileSystemObjectSink & sink, Source & source, HashAlgorithm hashAlgo, std::function<RestoreHook> hook)
{
parse(sink, CanonPath::root, source, BlobMode::Regular, [&](CanonPath name, TreeEntry entry) {
parse(sink, CanonPath::root, source, BlobMode::Regular, hashAlgo, [&](CanonPath name, TreeEntry entry) {
auto [accessor, from] = hook(entry.hash);
auto stat = accessor->lstat(from);
auto gotOpt = convertMode(stat.type);