Skip to content

Commit

Permalink
Merge pull request #2 from obsidiansystems/ipfs-hash-git
Browse files Browse the repository at this point in the history
Add hash-git command
  • Loading branch information
Ericson2314 authored May 28, 2020
2 parents 807a649 + 74ca85e commit 004b792
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 8 deletions.
65 changes: 65 additions & 0 deletions src/libutil/git.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include "archive.hh"
#include "hash.hh"
#include "util.hh"
#include "config.hh"

using namespace std::string_literals;

namespace nix {

void dumpGit(const Path & path, Sink & sink, PathFilter & filter)
{
struct stat st;
if (lstat(path.c_str(), &st))
throw SysError(format("getting attributes of path '%1%'") % path);

if (S_ISREG(st.st_mode)) {
auto s = (format("blob %d\0%s"s) % std::to_string(st.st_size) % readFile(path)).str();

vector<unsigned char> v;
std::copy(s.begin(), s.end(), std::back_inserter(v));
sink(v.data(), v.size());
}

else if (S_ISDIR(st.st_mode)) {
std::string s1 = "";

std::map<string, string> entries;
for (auto & i : readDirectory(path))
entries[i.name] = i.name;

for (auto & i : entries)
if (filter(path + "/" + i.first)) {
HashSink hashSink(htSHA1);
dumpGit(path + "/" + i.first, hashSink, filter);
auto hash = hashSink.finish().first;

struct stat st2;
if (lstat((path + "/" + i.first).c_str(), &st2))
throw SysError(format("getting attributes of path '%1%'") % (path + "/" + i.first));

unsigned int perm;
if (S_ISDIR(st2.st_mode))
perm = 40000;
else if (S_ISREG(st2.st_mode)) {
if (st2.st_mode & S_IXUSR)
perm = 100755;
else
perm = 100644;
} else
throw Error(format("file '%1%' has an unsupported type") % (path + "/" + i.first));

s1 += (format("%6d %s\0%s"s) % perm % i.first % hash.hash).str();
}

std::string s2 = (format("tree %d\0%s"s) % s1.size() % s1).str();

vector<unsigned char> v;
std::copy(s2.begin(), s2.end(), std::back_inserter(v));
sink(v.data(), v.size());
}

else throw Error(format("file '%1%' has an unsupported type") % path);
}

}
10 changes: 10 additions & 0 deletions src/libutil/git.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include "types.hh"
#include "serialise.hh"

namespace nix {

void dumpGit(const Path & path, Sink & sink, PathFilter & filter = defaultPathFilter);

}
23 changes: 15 additions & 8 deletions src/nix/hash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
#include "shared.hh"
#include "references.hh"
#include "archive.hh"
#include "git.hh"

using namespace nix;

struct CmdHash : Command
{
enum Mode { mFile, mPath };
enum Mode { mFile, mPath, mGit };
Mode mode;
Base base = SRI;
bool truncate = false;
Expand All @@ -36,9 +37,12 @@ struct CmdHash : Command

std::string description() override
{
return mode == mFile
? "print cryptographic hash of a regular file"
: "print cryptographic hash of the NAR serialisation of a path";
switch (mode) {
case mFile: return "print cryptographic hash of a regular file";
case mPath: return "print cryptographic hash of the NAR serialisation of a path";
case mGit: return "print cryptographic hash of the Git serialisation of a path";
}
throw;
}

Category category() override { return catUtility; }
Expand All @@ -55,6 +59,8 @@ struct CmdHash : Command

if (mode == mFile)
readFile(path, *hashSink);
else if (mode == mGit)
dumpGit(path, *hashSink);
else
dumpPath(path, *hashSink);

Expand All @@ -67,6 +73,7 @@ struct CmdHash : Command

static RegisterCommand r1("hash-file", [](){ return make_ref<CmdHash>(CmdHash::mFile); });
static RegisterCommand r2("hash-path", [](){ return make_ref<CmdHash>(CmdHash::mPath); });
static RegisterCommand r3("hash-git", [](){ return make_ref<CmdHash>(CmdHash::mGit); });

struct CmdToBase : Command
{
Expand Down Expand Up @@ -98,10 +105,10 @@ struct CmdToBase : Command
}
};

static RegisterCommand r3("to-base16", [](){ return make_ref<CmdToBase>(Base16); });
static RegisterCommand r4("to-base32", [](){ return make_ref<CmdToBase>(Base32); });
static RegisterCommand r5("to-base64", [](){ return make_ref<CmdToBase>(Base64); });
static RegisterCommand r6("to-sri", [](){ return make_ref<CmdToBase>(SRI); });
static RegisterCommand r4("to-base16", [](){ return make_ref<CmdToBase>(Base16); });
static RegisterCommand r5("to-base32", [](){ return make_ref<CmdToBase>(Base32); });
static RegisterCommand r6("to-base64", [](){ return make_ref<CmdToBase>(Base64); });
static RegisterCommand r7("to-sri", [](){ return make_ref<CmdToBase>(SRI); });

/* Legacy nix-hash command. */
static int compatNixHash(int argc, char * * argv)
Expand Down
15 changes: 15 additions & 0 deletions tests/hash.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,18 @@ try3() {
try3 sha1 "800d59cfcd3c05e900cb4e214be48f6b886a08df" "vw46m23bizj4n8afrc0fj19wrp7mj3c0" "gA1Zz808BekAy04hS+SPa4hqCN8="
try3 sha256 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s" "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="
try3 sha512 "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" "12k9jiq29iyqm03swfsgiw5mlqs173qazm3n7daz43infy12pyrcdf30fkk3qwv4yl2ick8yipc2mqnlh48xsvvxl60lbx8vp38yji0" "IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ=="

# Git.
try4 () {
hash=$(nix hash-git --base16 --type sha1 $TEST_ROOT/hash-path)
if test "$hash" != "$1"; then
echo "git hash, expected $1, got $hash"
exit 1
fi
}

rm -rf $TEST_ROOT/hash-path
mkdir $TEST_ROOT/hash-path
echo "Hello World" > $TEST_ROOT/hash-path/hello

try4 "117c62a8c5e01758bd284126a6af69deab9dbbe2"

0 comments on commit 004b792

Please sign in to comment.