Thursday, 10 January 2019

How can I calculate git tree hash?

For a nodejs project I need to determinate the hash of my folder to check the version. Actually, I made a script to test my code (without filesystem, directly of git api for my test). But it works half the time.

A1 work and A2 doesn't work because I don't get the same hash.

I made a Perl script version to check my code js code. It returns the same things. I think my error is in Object.values(json.tree).forEach(function (blob) the pattern must be not good with text += blob.mode + " " + blob.path + "\0" + sha;. I don't know why.

My js script :

(Live demo : https://repl.it/repls/FearfulWhiteShelfware)

const crypto = require("crypto"),
      fs = require("fs"),
      path = require("path");

const json = /* Paste the json of : 
                  - A1 : https://api.github.com/repos/zestedesavoir/zds-site/git/trees/8d66139b3acf78fa50e16383693a161c33b5e048 work
                  - A2 : https://api.github.com/repos/zestedesavoir/zds-site/git/trees/4ef57de8e81c8415d6da2b267872e602b1f28cfe doesn't work
              */;

//json.tree.sort((a, b) => a.path.charCodeAt(0) - b.path.charCodeAt(0));

function pad(num, length) {
    const pad = new Array(1 + length).join("0");
    return (pad + num).slice(-pad.length);
}

let text = "";

Object.values(json.tree).forEach(function (blob) {
    const sha = Buffer.from(blob.sha, "hex").toString("binary");
    text += blob.mode + " " + blob.path + "\0" + sha;
});

console.log("Original " + json.sha);

const pattern = "tree " + text.length + "\0" + text;
console.log("Actual : " + sha1(pattern));

function sha1(data) {
    return crypto.createHash("sha1").update(data, "binary").digest("hex");
}

Output :

A1 : 
Original 8d66139b3acf78fa50e16383693a161c33b5e048
Actual : 8d66139b3acf78fa50e16383693a161c33b5e048
A2 :
Original 4ef57de8e81c8415d6da2b267872e602b1f28cfe
Actual : e99058a233e6da0d83ed8a027b3b533516087804

Wanted Output :

A1 : 
Original 8d66139b3acf78fa50e16383693a161c33b5e048
Actual : 8d66139b3acf78fa50e16383693a161c33b5e048
A2 :
Original 4ef57de8e81c8415d6da2b267872e602b1f28cfe
Actual : 4ef57de8e81c8415d6da2b267872e602b1f28cfe


I made a Perl script version to check my code and understand this issue.

Perl :

Files :

Perl script : (Live demo : https://repl.it/repls/VainPrizeDebugmonitor)

XX="$(perl -sane '$F[2] =~ s/(..)/\\x$1/g ; print $F[0]." ".$F[1]."\\"."x00".$F[2]' output_a1)"
SIZE=$(echo -en "$XX" | wc -c)

echo "original: 8d66139b3acf78fa50e16383693a161c33b5e048 output:"
echo -en "tree $SIZE\x00$XX" | sha1sum

XX="$(perl -sane '$F[2] =~ s/(..)/\\x$1/g ; print $F[0]." ".$F[1]."\\"."x00".$F[2]' output_a2)"
SIZE=$(echo -en "$XX" | wc -c)

echo "original: 4ef57de8e81c8415d6da2b267872e602b1f28cfe output:"
echo -en "tree $SIZE\x00$XX" | sha1sum

Output :

original: 8d66139b3acf78fa50e16383693a161c33b5e048 output:
8d66139b3acf78fa50e16383693a161c33b5e048  -
original: 4ef57de8e81c8415d6da2b267872e602b1f28cfe output:
e99058a233e6da0d83ed8a027b3b533516087804  -

Then we see that my JS and Perl Script return the same thing. That mean, that my pattern was malformed, I don't know why.



from How can I calculate git tree hash?

No comments:

Post a Comment