Comment calculer le sha d'un dossier (=> tree) github

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je souhaite calculer le hash d’un répertoire sans utiliser les lignes de commande git. J’ai donc besoin de connaitre la marche à suivre. J’avais trouvé un article parlant de ça mais impossible de remettre la main dessus. :(

https://api.github.com/repos/<user>/<repos>/git/trees/<sha> <=== Je veux celui la :)

Pour un fichier c’est assez simple. Il suffit de faire :

1
sha1("blob " + data.length + "\0" + data);

Mais pour un dossier, comment dois-je faire ?

1
?

Merci, A.

Si si le sha du commit provient du calcul des fichiers.

A-312

je m’étais mélanger entre deux "arbres", vu que sur github, l’url d’un dossier est <repo>/tree/<sha1 du commit>/<dossier>.

J’ai bien trouvé des gens qui disait qu’il se calculait à partir de son contenu (noms, sha1, permissions, etc. des fichiers/dossiers qu’il contient) mais pas la formule exacte.

Hello,

Chaque objet dans git a un object associé, que tu peux trouver dans .git/object. Tu peux les voir avec git cat-file.

Par exemple, git cat-file -p HEAD te donne une piste de départ de ce que tu peux vouloir cat.

Tu vas typiquement avoir des object qui correspondent à un fichier (blob), des objets qui correspondent à un tree (un dossier) et des objets qui correspondent à un commit ou un tag.

Pour un objet tree, le format est taille + \0 + contenu avec contenu qui est une liste de

1
100644 blob fbcf12d50552354fc878706bacea89fbb3f9f999    toto

C’est-à-dire (avec la tabulation pas transformée)

mode type hash\tfilename

+0 -0

Je n’ai pas réussi : https://api.github.com/repos/zestedesavoir/zds-site/git/trees/8d66139b3acf78fa50e16383693a161c33b5e048

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
const tree = "8d66139b3acf78fa50e16383693a161c33b5e048";

ajax("https://api.github.com/repos/zestedesavoir/zds-site/git/trees/" + tree, function(res, data) {
  const json = raw2json(data);
  let text = "",
      size = 0;
  for (var key in json.tree) {
      if (json.tree.hasOwnProperty(key)) {
          let blob = json.tree[key];
          text += `${blob.mode} ${blob.type} ${blob.sha}\t${blob.path}\n`;
          size += blob.size;
      }
  }
  const pattern = size + "\0\n" + text;
  console.log(pattern);
  console.log((tree !== sha1(pattern) ? "\x1B[91m" : "\x1B[92m") + sha1(pattern) + "\x1B[00m");
});

function sha1(data) {
  return crypto.createHash("sha1").update(data).digest("hex");
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
11875
100644 blob 05392dacd107b9e2bb931c85632e115ae69c22cb    arborescence-back.rst
100644 blob 20084355452644d3a171b54e9331485e73a897ea    featured.rst
100644 blob 82efe44d491fbc69fb99b0fc0829ad349a11aae7    forum.rst
100644 blob e075f6d1fe182e595b950cc50d1c5701c6c48bb1    gallery.rst
100644 blob 157a97545f397f02293a95034989f293cda00ee8    member.rst
100644 blob 30d85eb8babc8608a87272eb02a73685a71623c3    pages.rst
100644 blob 6e4872283841ddb0edf03f7535003b4cb5e2f3ce    private-message.rst
100644 blob a31835f3f39b77408b75548c215d06dcd776d3c2    searchv2.rst
100644 blob e646fef1203c7c9b8137c6420d990fd40c1255ae    tutorialv2.rst
100644 blob 846765fc32bafc05bb58e6b70883acf5de8ae97b    utils.rst

ed5355b0e1aefb1947f86ab1c2838a9c6174a991

Essai n°2 :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
const crypto = require("crypto"),
  https = require("https"),
  fs = require("fs"),
  path = require("path");

const tree = "8d66139b3acf78fa50e16383693a161c33b5e048";

const json = {
  "sha": "8d66139b3acf78fa50e16383693a161c33b5e048",
  "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/8d66139b3acf78fa50e16383693a161c33b5e048",
  "tree": [{
      "path": "arborescence-back.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "05392dacd107b9e2bb931c85632e115ae69c22cb",
      "size": 5422,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/05392dacd107b9e2bb931c85632e115ae69c22cb"
  }, {
      "path": "featured.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "20084355452644d3a171b54e9331485e73a897ea",
      "size": 404,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/20084355452644d3a171b54e9331485e73a897ea"
  }, {
      "path": "forum.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "82efe44d491fbc69fb99b0fc0829ad349a11aae7",
      "size": 446,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/82efe44d491fbc69fb99b0fc0829ad349a11aae7"
  }, {
      "path": "gallery.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "e075f6d1fe182e595b950cc50d1c5701c6c48bb1",
      "size": 353,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/e075f6d1fe182e595b950cc50d1c5701c6c48bb1"
  }, {
      "path": "member.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "157a97545f397f02293a95034989f293cda00ee8",
      "size": 639,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/157a97545f397f02293a95034989f293cda00ee8"
  }, {
      "path": "pages.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "30d85eb8babc8608a87272eb02a73685a71623c3",
      "size": 230,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/30d85eb8babc8608a87272eb02a73685a71623c3"
  }, {
      "path": "private-message.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "6e4872283841ddb0edf03f7535003b4cb5e2f3ce",
      "size": 341,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/6e4872283841ddb0edf03f7535003b4cb5e2f3ce"
  }, {
      "path": "searchv2.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "a31835f3f39b77408b75548c215d06dcd776d3c2",
      "size": 356,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/a31835f3f39b77408b75548c215d06dcd776d3c2"
  }, {
      "path": "tutorialv2.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "e646fef1203c7c9b8137c6420d990fd40c1255ae",
      "size": 1873,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/e646fef1203c7c9b8137c6420d990fd40c1255ae"
  }, {
      "path": "utils.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "846765fc32bafc05bb58e6b70883acf5de8ae97b",
      "size": 1811,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/846765fc32bafc05bb58e6b70883acf5de8ae97b"
  }],
  "truncated": false
};
/*
ajax("https://api.github.com/repos/zestedesavoir/zds-site/git/trees/" + tree, function(res, data) {
  const json = raw2json(data);*/
let text = "",
  size = 0;
for (let key in json.tree) {
  if (json.tree.hasOwnProperty(key)) {
      let blob = json.tree[key];
      text += `\n${blob.mode} ${blob.type} ${blob.sha}\t${blob.path}`;
      size += blob.size;
  }
}
const pattern = "tree " + size + "\0" + text;
console.log(pattern);
console.log((tree !== sha1(pattern) ? "\x1B[91m" : "\x1B[92m") + sha1(pattern) + "\x1B[00m");
/*});*/

function sha1(data) {
  return crypto.createHash("sha1").update(data).digest("hex");
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
tree 11875
100644 blob 05392dacd107b9e2bb931c85632e115ae69c22cb    arborescence-back.rst
100644 blob 20084355452644d3a171b54e9331485e73a897ea    featured.rst
100644 blob 82efe44d491fbc69fb99b0fc0829ad349a11aae7    forum.rst
100644 blob e075f6d1fe182e595b950cc50d1c5701c6c48bb1    gallery.rst
100644 blob 157a97545f397f02293a95034989f293cda00ee8    member.rst
100644 blob 30d85eb8babc8608a87272eb02a73685a71623c3    pages.rst
100644 blob 6e4872283841ddb0edf03f7535003b4cb5e2f3ce    private-message.rst
100644 blob a31835f3f39b77408b75548c215d06dcd776d3c2    searchv2.rst
100644 blob e646fef1203c7c9b8137c6420d990fd40c1255ae    tutorialv2.rst
100644 blob 846765fc32bafc05bb58e6b70883acf5de8ae97b    utils.rst
39fd7b3bec2114888ae3e64b85bd4fd28b74cce9
+0 -0

Le hash final ne correspond. :/ Idem si j’enlève tree :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
11875
100644 blob 05392dacd107b9e2bb931c85632e115ae69c22cb    arborescence-back.rst
100644 blob 20084355452644d3a171b54e9331485e73a897ea    featured.rst
100644 blob 82efe44d491fbc69fb99b0fc0829ad349a11aae7    forum.rst
100644 blob e075f6d1fe182e595b950cc50d1c5701c6c48bb1    gallery.rst
100644 blob 157a97545f397f02293a95034989f293cda00ee8    member.rst
100644 blob 30d85eb8babc8608a87272eb02a73685a71623c3    pages.rst
100644 blob 6e4872283841ddb0edf03f7535003b4cb5e2f3ce    private-message.rst
100644 blob a31835f3f39b77408b75548c215d06dcd776d3c2    searchv2.rst
100644 blob e646fef1203c7c9b8137c6420d990fd40c1255ae    tutorialv2.rst
100644 blob 846765fc32bafc05bb58e6b70883acf5de8ae97b    utils.rst

Bonjour,

Voici un exemple du calcul en shell et une uniligne en perl:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ cat /tmp/toto 
100644 blob 05392dacd107b9e2bb931c85632e115ae69c22cb    arborescence-back.rst
100644 blob 20084355452644d3a171b54e9331485e73a897ea    featured.rst
100644 blob 82efe44d491fbc69fb99b0fc0829ad349a11aae7    forum.rst
100644 blob e075f6d1fe182e595b950cc50d1c5701c6c48bb1    gallery.rst
100644 blob 157a97545f397f02293a95034989f293cda00ee8    member.rst
100644 blob 30d85eb8babc8608a87272eb02a73685a71623c3    pages.rst
100644 blob 6e4872283841ddb0edf03f7535003b4cb5e2f3ce    private-message.rst
100644 blob a31835f3f39b77408b75548c215d06dcd776d3c2    searchv2.rst
100644 blob e646fef1203c7c9b8137c6420d990fd40c1255ae    tutorialv2.rst
100644 blob 846765fc32bafc05bb58e6b70883acf5de8ae97b    utils.rst
$ XX="$(perl -sane '$F[2] =~ s/(..)/\\x$1/g ; print $F[0]." ".$F[3]."\\"."x00".$F[2]' /tmp/toto)"
$ echo -en "$XX" | wc -c
406
$ echo -en "tree 406\x00$XX" | sha1sum 
8d66139b3acf78fa50e16383693a161c33b5e048  -

Ce que je fais: Je crée la chaine suivante:

1
champs1 champs4\x00champs3champs1 champs4\x00champs3....

Avec le champs3 que je transforme en binaire en prenant les caractère 2 à 2 (exemple la chaine 30 devient l’octet 30, la chaine 6e devient l’octet 6e) \x00 c’est l’octet 0.

Et je ne mets pas de retour à la ligne entre chaque ligne. Ensuite je calcul la taille de la chaine entière et je rajoute au début de la chaine:

1
tree <taille>\x00<chaine>

Et il n’y a toujours pas de retour à la ligne.

Puis reste plus qu’à faire le sha1sum

+1 -0

J’aimerais quelques précisions. Je n’ai toujours pas réussi (à avoir le sha) :

EDIT : Ma fonction de debug affiche quelques choses qui ne correspond pas à ce que j’ai (ref ma réponse suivante).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
tree 406\x00
100644 arborescence-back.rst\x00\x59-\xac\xd1\x7\xb9\xe2\xbb\x93\x1c\x85c.\x11Z\xe6\x9c"\xcb
100644 featured.rst\x00 \x8CUE&D\xd3\xa1q\xb5N\x931H\x5es\xa8\x97\xea
100644 forum.rst\x00\x82\xef\xe4MI\x1f\xbci\xfb\x99\xb0\xfc\x8)\xad4\x9a\x11\xaa\xe7
100644 gallery.rst\x00\xe0u\xf6\xd1\xfe\x18.Y\x5b\x95\xc\xc5\xd\x1cW\x1\xc6\xc4\x8b\xb1
100644 member.rst\x00\x15z\x97T_9\x7f\x2)\x3a\x95\x3I\x89\xf2\x93\xcd\xa0\xe\xe8
100644 pages.rst\x00\xd8\x5e\xb8\xba\xbc\x86\x8\xa8rr\xeb\x2\xa76\x85\xa7\x16#\xc3
100644 private-message.rst\x00nHr(8A\xdd\xb0\xed\xf0\x3fu5\x0\x3bL\xb5\xe2\xf3\xce
100644 searchv2.rst\x00\xa3\x185\xf3\xf3\x9bw\x40\x8buT\x8c!\x5d\x6\xdc\xd7v\xd3\xc2
100644 tutorialv2.rst\x00\xe6F\xfe\xf1 \x3c\x7c\x9b\x817\xc6B\xd\x99\xf\xd4\xc\x12U\xae
100644 utils.rst\x00\x84ge\xfc2\xba\xfc\x5\xbbX\xe6\xb7\x8\x83\xac\xf5\xde\x8a\xe9\x7b
53add2eac9b956cf54669d4f9e2bd130d0d979a7

(J’ai rajouté les sauts de ligne uniquement pour le rendu).

Peut tu me dire ce que tu obtiens pour le sha1 en format binaire ?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
let text = "",
    size = 0;
for (let key in json.tree) {
    if (json.tree.hasOwnProperty(key)) {
        let blob = json.tree[key];
        text += `${blob.mode} ${blob.path}\0${blob.sha.replace(/(..)/g, (code) => String.fromCodePoint(parseInt(code,16)))}`;
        size += blob.size;
    }
}

const pattern = "tree " + text.length + "\0" + text;
console.log(pattern.replace(/([^\w -\.])/g, (code) => "\\x"+(+code.charCodeAt(0)).toString(16)).replace(/(100644)/g, "\n$1"));
console.log((tree !== sha1(pattern) ? "\x1B[91m" : "\x1B[92m") + sha1(pattern) + "\x1B[00m");
+0 -0

Je n’obtiens pas la même chose que toi (j’ai aussi rajouter des retour chariot pour visibilité) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
tree \x00
100644 arborescence-back.rst\x00\x05\x39\x2d\xac\xd1\x07\xb9\xe2\xbb\x93\x1c\x85\x63\x2e\x11\x5a\xe6\x9c\x22\xcb
100644 featured.rst\x00\x20\x08\x43\x55\x45\x26\x44\xd3\xa1\x71\xb5\x4e\x93\x31\x48\x5e\x73\xa8\x97\xea
100644 forum.rst\x00\x82\xef\xe4\x4d\x49\x1f\xbc\x69\xfb\x99\xb0\xfc\x08\x29\xad\x34\x9a\x11\xaa\xe7
100644 gallery.rst\x00\xe0\x75\xf6\xd1\xfe\x18\x2e\x59\x5b\x95\x0c\xc5\x0d\x1c\x57\x01\xc6\xc4\x8b\xb1
100644 member.rst\x00\x15\x7a\x97\x54\x5f\x39\x7f\x02\x29\x3a\x95\x03\x49\x89\xf2\x93\xcd\xa0\x0e\xe8
100644 pages.rst\x00\x30\xd8\x5e\xb8\xba\xbc\x86\x08\xa8\x72\x72\xeb\x02\xa7\x36\x85\xa7\x16\x23\xc3
100644 private-message.rst\x00\x6e\x48\x72\x28\x38\x41\xdd\xb0\xed\xf0\x3f\x75\x35\x00\x3b\x4c\xb5\xe2\xf3\xce
100644 searchv2.rst\x00\xa3\x18\x35\xf3\xf3\x9b\x77\x40\x8b\x75\x54\x8c\x21\x5d\x06\xdc\xd7\x76\xd3\xc2
100644 tutorialv2.rst\x00\xe6\x46\xfe\xf1\x20\x3c\x7c\x9b\x81\x37\xc6\x42\x0d\x99\x0f\xd4\x0c\x12\x55\xae
100644 utils.rst\x00\x84\x67\x65\xfc\x32\xba\xfc\x05\xbb\x58\xe6\xb7\x08\x83\xac\xf5\xde\x8a\xe9\x7b

En fait, en regardant juste le début de ton bin:

1
100644 arborescence-back.rst\x0\x59-\xac

ton souci, c’est que lorsque tu transformes tes données en binaire, pour 5 par exemple, tu le transforme en \x5 au lieu de \x05 et donc lors de la transformation final, il va traiter \x59 au lieu de \x059 ou \x05\x39 (\x39 est la valeur binaire du chiffre 9 ascii). En gros, ta transformation mélange 2 mondes et comme il n’y a pas de séparation entre chaque octet, la transco s’y perd.

J’ai vérifié ma fonction qui convertit en octet et elle vole correctement. Elle fait comme la tienne.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
let sha = json.tree[0].sha,
    arr = sha.match(/(..)/g); //8d66139b3acf78fa50e16383693a161c33b5e048

let xStr = ['\x05', '\x39', '\x2d', '\xac', '\xd1', '\x07', '\xb9', '\xe2', '\xbb', '\x93', '\x1c', '\x85', '\x63', '\x2e', '\x11', '\x5a', '\xe6', '\x9c', '\x22', '\xcb'];

let str = "";

for (let i = 0, char; i < arr.length; i++) {
    char = String.fromCharCode(parseInt(arr[i], 16));
    console.log(i, char === xStr[i]);
    str += char;
}

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

C’est juste ma fonction d’affichage pour le debug qui ne vole pas correctement, elle encodait que les caractères compris dans /([^\w -\.])/g et n’ajoutait pas le premier 0. :(

Donc si je retravaille le rendu de debug comme le tien :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
tree 1000\x00
100644 arborescence-back.rst\x00\x05\x39\x2d\xac\xd1\x07\xb9\xe2\xbb\x93\x1c\x85\x63\x2e\x11\x5a\xe6\x9c\x22\xcb
100644 featured.rst\x00\x20\x08\x43\x55\x45\x26\x44\xd3\xa1\x71\xb5\x4e\x93\x31\x48\x5e\x73\xa8\x97\xea
100644 forum.rst\x00\x82\xef\xe4\x4d\x49\x1f\xbc\x69\xfb\x99\xb0\xfc\x08\x29\xad\x34\x9a\x11\xaa\xe7
\x1c\x57\x01\xc6\xc4\x8b\xb175\xf6\xd1\xfe\x18\x2e\x59\x5b\x95\x0c\xc5
100644 member.rst\x00\x15\x7a\x97\x54\x5f\x39\x7f\x02\x29\x3a\x95\x03\x49\x89\xf2\x93\xcd\xa0\x0e\xe8
100644 pages.rst\x00\x30\xd8\x5e\xb8\xba\xbc\x86\x08\xa8\x72\x72\xeb\x02\xa7\x36\x85\xa7\x16\x23\xc3
100644 private-message.rst\x00\x6e\x48\x72\x28\x38\x41\xdd\xb0\xed\xf0\x3f\x75\x35\x00\x3b\x4c\xb5\xe2\xf3\xce
100644 searchv2.rst\x00\xa3\x18\x35\xf3\xf3\x9b\x77\x40\x8b\x75\x54\x8c\x21\x5d\x06\xdc\xd7\x76\xd3\xc2
\x99\x0f\xd4\x0c\x12\x55\xae6\x46\xfe\xf1\x20\x3c\x7c\x9b\x81\x37\xc6\x42
100644 utils.rst\x00\x84\x67\x65\xfc\x32\xba\xfc\x05\xbb\x58\xe6\xb7\x08\x83\xac\xf5\xde\x8a\xe9\x7b

Apparemment mon problème ce situe ailleurs. Avec gallery et tutorial je vais chercher pourquoi.

NB : J’utilise .replace(/(.)/g, (code) => "\\x" + pad((+code.charCodeAt(0)).toString(16), 2)).

+0 -0

C’était la faute à ma regex qui ne remplaçait pas \r par le code correspondant (merci au flag s).

Cette fois je passe par l’objet (class) Buffer de nodejs au lieu d’une regex pour convertir le sha en binaire. Je suis sûr d’avoir la même chaîne mais j’ai encore un sha différent. :( Mais j’obtiens toujours le même sha : 53add2eac9b956cf54669d4f9e2bd130d0d979a7

Donc :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
tree 406\x00
100644 arborescence-back.rst\x00\x05\x39\x2d\xac\xd1\x07\xb9\xe2\xbb\x93\x1c\x85\x63\x2e\x11\x5a\xe6\x9c\x22\xcb
100644 featured.rst\x00\x20\x08\x43\x55\x45\x26\x44\xd3\xa1\x71\xb5\x4e\x93\x31\x48\x5e\x73\xa8\x97\xea
100644 forum.rst\x00\x82\xef\xe4\x4d\x49\x1f\xbc\x69\xfb\x99\xb0\xfc\x08\x29\xad\x34\x9a\x11\xaa\xe7
100644 gallery.rst\x00\xe0\x75\xf6\xd1\xfe\x18\x2e\x59\x5b\x95\x0c\xc5\x0d\x1c\x57\x01\xc6\xc4\x8b\xb1
100644 member.rst\x00\x15\x7a\x97\x54\x5f\x39\x7f\x02\x29\x3a\x95\x03\x49\x89\xf2\x93\xcd\xa0\x0e\xe8
100644 pages.rst\x00\x30\xd8\x5e\xb8\xba\xbc\x86\x08\xa8\x72\x72\xeb\x02\xa7\x36\x85\xa7\x16\x23\xc3
100644 private-message.rst\x00\x6e\x48\x72\x28\x38\x41\xdd\xb0\xed\xf0\x3f\x75\x35\x00\x3b\x4c\xb5\xe2\xf3\xce
100644 searchv2.rst\x00\xa3\x18\x35\xf3\xf3\x9b\x77\x40\x8b\x75\x54\x8c\x21\x5d\x06\xdc\xd7\x76\xd3\xc2
100644 tutorialv2.rst\x00\xe6\x46\xfe\xf1\x20\x3c\x7c\x9b\x81\x37\xc6\x42\x0d\x99\x0f\xd4\x0c\x12\x55\xae
100644 utils.rst\x00\x84\x67\x65\xfc\x32\xba\xfc\x05\xbb\x58\xe6\xb7\x08\x83\xac\xf5\xde\x8a\xe9\x7b

ouput via JSON.stringify:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
tree 406\u0000
100644 arborescence-back.rst\u0000\u00059-¬Ñ\u0007¹â»“\u001c…c.\u0011Zæœ\"Ë
100644 featured.rst\u0000 \bCUE&DÓ¡qµN“1H^s¨—ê
100644 forum.rst\u0000‚ïäMI\u001f¼iû™°ü\b)­4š\u0011ªç
100644 gallery.rst\u0000àuöÑþ\u0018.Y[•\fÅ\r\u001cW\u0001Æċ±
100644 member.rst\u0000\u0015z—T_9\u0002):•\u0003I‰ò“Í \u000eè
100644 pages.rst\u00000Ø^¸º¼†\b¨rrë\u0002§6…§\u0016#Ã
100644 private-message.rst\u0000nHr(8AÝ°íð?u5\u0000;LµâóÎ
100644 searchv2.rst\u0000£\u00185óó›w@‹uTŒ!]\u0006Ü×vÓÂ
100644 tutorialv2.rst\u0000æFþñ <|›7ÆB\r™\u000fÔ\f\u0012U®
100644 utils.rst\u0000„geü2ºü\u0005»Xæ·\bƒ¬õފé{

Mon code :

Je remets mon code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const crypto = require("crypto"),
    fs = require("fs"),
    path = require("path");

const tree = "8d66139b3acf78fa50e16383693a161c33b5e048";

const json = { /* https://api.github.com/repos/zestedesavoir/zds-site/git/trees/8d66139b3acf78fa50e16383693a161c33b5e048 */ };

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

let text = "",
    size = 0;

for (let key in json.tree) {
    if (json.tree.hasOwnProperty(key)) {
        let blob = json.tree[key],
            sha = Buffer.from(blob.sha, "hex").toString("binary");
        //sha = sha.replace(/(.)/gs, (code) => "\\x" + pad((+code.charCodeAt(0)).toString(16), 2))
        text += `${blob.mode} ${blob.path}\x00${sha}`;
        size += blob.size;
    }
}

const pattern = "tree " + text.length + "\0" + text;
console.log((tree !== sha1(pattern) ? "\x1B[91m" : "\x1B[92m") + sha1(pattern) + "\x1B[00m");
console.log(JSON.stringify(pattern).replace(/(100644)/g, "\n$1"));

function sha1(data) {
    return crypto.createHash("sha1").update(data).digest("hex");
}
+0 -0

Ma fonction sha1 en nodejs ne renvoie pas le même hash pour la même chaîne de caractère. Alors qu’en PHP j’obtiens bien le bon sha1. :(

1
mySha = "tree 406\x00100644 arborescence-back.rst\x00\x05\x39\x2d\xac\xd1\x07\xb9\xe2\xbb\x93\x1c\x85\x63\x2e\x11\x5a\xe6\x9c\x22\xcb100644 featured.rst\x00\x20\x08\x43\x55\x45\x26\x44\xd3\xa1\x71\xb5\x4e\x93\x31\x48\x5e\x73\xa8\x97\xea100644 forum.rst\x00\x82\xef\xe4\x4d\x49\x1f\xbc\x69\xfb\x99\xb0\xfc\x08\x29\xad\x34\x9a\x11\xaa\xe7100644 gallery.rst\x00\xe0\x75\xf6\xd1\xfe\x18\x2e\x59\x5b\x95\x0c\xc5\x0d\x1c\x57\x01\xc6\xc4\x8b\xb1100644 member.rst\x00\x15\x7a\x97\x54\x5f\x39\x7f\x02\x29\x3a\x95\x03\x49\x89\xf2\x93\xcd\xa0\x0e\xe8100644 pages.rst\x00\x30\xd8\x5e\xb8\xba\xbc\x86\x08\xa8\x72\x72\xeb\x02\xa7\x36\x85\xa7\x16\x23\xc3100644 private-message.rst\x00\x6e\x48\x72\x28\x38\x41\xdd\xb0\xed\xf0\x3f\x75\x35\x00\x3b\x4c\xb5\xe2\xf3\xce100644 searchv2.rst\x00\xa3\x18\x35\xf3\xf3\x9b\x77\x40\x8b\x75\x54\x8c\x21\x5d\x06\xdc\xd7\x76\xd3\xc2100644 tutorialv2.rst\x00\xe6\x46\xfe\xf1\x20\x3c\x7c\x9b\x81\x37\xc6\x42\x0d\x99\x0f\xd4\x0c\x12\x55\xae100644 utils.rst\x00\x84\x67\x65\xfc\x32\xba\xfc\x05\xbb\x58\xe6\xb7\x08\x83\xac\xf5\xde\x8a\xe9\x7b"

Savez-vous de quoi ça peut venir ?

EDIT :

J’ai la liste des caractères qui différent (entre le JS et le PHP) :

1
 \xac,\xd1,\xb9,\xe2,\xbb,\x93,\x85,\xe6,\x9c,\xcb,\xd3,\xa1,\xb5,\xa8,\x97,\xea,\x82,\xef,\xe4,\xbc,\xfb,\x99,\xb0,\xfc,\xad,\x9a,\xaa,\xe7,\xe0,\xf6,\xfe,\x95,\xc5,\xc6,\xc4,\x8b,\xb1,\x89,\xf2,\xcd,\xa0,\xe8,\xd8,\xb8,\xba,\x86,\xeb,\xa7,\xc3,\xdd,\xed,\xf0,\xf3,\xce,\xa3,\x9b,\x8c,\xdc,\xd7,\xc2,\xf1,\x81,\xd4,\xae,\x84,\xb7,\x83,\xf5,\xde,\x8a,\xe9
+0 -0

C’était si simple…

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

Il suffisait d’ajouter "binary", ceci permet de dire à la fonction de crypto de prendre en compte les bytes et non les caractères d’affichage (cad la représentation UTF8). :magicien:

+0 -0

Dernier up, promis. :pirate: J’ai oublié le plus important. :magicien:

Merci de m’avoir aidé ! C’est grâce à vous que j’ai pu résoudre ce problème qui me suivait depuis la semaine dernière (et qui commençait à me bloquer dans ma programmation). Je marque donc le sujet comme résolu.

J’ai deux problèmes :

  • Si on n’a le malheur d’éditer le fichier sous Windows ça convertit les retours à la ligne en windows -> (\r\n) au lieux d’unix.
  • Comment je connais l’ordre des fichiers pour calculer le sha1 des trees ?

Trouvé pour l’ordre : files.sort((a, b) => a.charCodeAt(0) - b.charCodeAt(0));

+0 -0

Hmmm…

Mon code fonctionne très bien avec H1 : https://api.github.com/repos/zestedesavoir/zds-site/git/trees/8d66139b3acf78fa50e16383693a161c33b5e048

Mais ne fonctionne pas avec H2 : https://api.github.com/repos/zestedesavoir/zds-site/git/trees/4ef57de8e81c8415d6da2b267872e602b1f28cfe

Il ne retourne pas le bon sha. :(

tree 2061
100644 .coveragerc 449170d0faeb75182310345564fd1811c0b9fd73
100644 .editorconfig 75884936ea2d35b531af886acad747d4fd9b2a9e
100644 .flake8 69e872e30d30f5c7de3276d289d6aee81ccf4af7
040000 .github 56b49acad224fdb70fca11809f3e5a4d396cb01c
100644 .gitignore 4832b44b973574253cf1b59ba7a66cfc227cd699
100644 .jshintrc 939efa02939437adece1e3a076d597b2557e36b5
100644 .travis.yml 6b5e4f43790874e2cf9db23e964f72b99deeb0d1
100644 AUTHORS 0b92b7759ce2dd0a7cacf79b273368bb71ac5397
100644 CODE_OF_CONDUCT.md ae61c31efae6cea565e447467e4377da76125679
100644 CONTRIBUTING.md ac71ad378faf7fb7ae927b20d4d28a57c6085bf9
100644 COPYING 94a9ed024d3859793618152ea559a168bbcbb5e2
100644 Gulpfile.js 5dd951ae61f0913605197fafa018f7db49549a68
100644 LICENSE 8a171a155d85927b678068becd046194aea777a9
100644 Makefile cc722c2bc71dfbaa1b025c8c56245ed0fcd61739
100644 README.md a6a9013159a3766da62443c4be5e267435469fd9
040000 assets 1846a32450eb2a7605acb55cab8206028cfb656f
040000 doc f55b804a2b694db577b20c8e9851ad783fea8ee5
040000 errors b37a18162be2bdae7382fc194f1bf2d0ab89bba3
040000 export-assets 3a8b85efa969c389ac3c5e7e6ad62206dbddcaca
040000 fixtures 89cacb4de6feb81a962b9a992b9434cb44d3b0aa
040000 geodata 635d29035ae7528231edb9b74eb09887c22dda2a
100755 manage.py 458f6e2df8b431b9fa819c89e82cebf2e0a91260
100644 package.json 02d231aa0c0fa299581be07bcece0393dc9a9e47
100644 quotes.txt e8e84a048d70bc57c1f725fc12f2101a40c5dcbb
100644 requirements-dev.txt 7297a894036fcf70a7209062bb51f45db1b71d39
100644 requirements-prod.txt 2f957115bcf3794fdecf3c4848f21ae8f428c31b
100644 requirements.txt 805fefa566ef0d8f6a7c7e58d01fa4684078cf50
100644 robots.txt 8ca70253a4bb677cb797a7b409df4c4a9c0baa67
040000 scripts f6a251faaaa14ba4fcf702cd0556675e70cc80f3
100644 suggestions.txt 5e5d11a62a00d3f1aea8f3825c8ec89860d31ad0
040000 templates 5b6dde8b8b616ba078305584e23e55ad0c5b2299
100644 update.md 734cb67218ac7ad952ffe2f816e4820427efe809
100644 yarn.lock 9fed208fbed286860cb606c9904eb3bab2b3d960
040000 zds 45b76aa70ad46e116c491a55def4b396b4ecba89
040000 zmd 89289051d5d1e37ecc12629737d4fc01dd0df06e

Avec le code PERL :

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

echo $SIZE
echo -en "tree $SIZE\x00$XX" | sha1sum

#e99058a233e6da0d83ed8a027b3b533516087804

H1 : Valide :

Original 8d66139b3acf78fa50e16383693a161c33b5e048 Actual : 8d66139b3acf78fa50e16383693a161c33b5e048

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

const json = {
  "sha": "8d66139b3acf78fa50e16383693a161c33b5e048",
  "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/8d66139b3acf78fa50e16383693a161c33b5e048",
  "tree": [
    {
      "path": "arborescence-back.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "05392dacd107b9e2bb931c85632e115ae69c22cb",
      "size": 5422,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/05392dacd107b9e2bb931c85632e115ae69c22cb"
    },
    {
      "path": "featured.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "20084355452644d3a171b54e9331485e73a897ea",
      "size": 404,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/20084355452644d3a171b54e9331485e73a897ea"
    },
    {
      "path": "forum.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "82efe44d491fbc69fb99b0fc0829ad349a11aae7",
      "size": 446,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/82efe44d491fbc69fb99b0fc0829ad349a11aae7"
    },
    {
      "path": "gallery.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "e075f6d1fe182e595b950cc50d1c5701c6c48bb1",
      "size": 353,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/e075f6d1fe182e595b950cc50d1c5701c6c48bb1"
    },
    {
      "path": "member.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "157a97545f397f02293a95034989f293cda00ee8",
      "size": 639,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/157a97545f397f02293a95034989f293cda00ee8"
    },
    {
      "path": "pages.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "30d85eb8babc8608a87272eb02a73685a71623c3",
      "size": 230,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/30d85eb8babc8608a87272eb02a73685a71623c3"
    },
    {
      "path": "private-message.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "6e4872283841ddb0edf03f7535003b4cb5e2f3ce",
      "size": 341,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/6e4872283841ddb0edf03f7535003b4cb5e2f3ce"
    },
    {
      "path": "searchv2.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "a31835f3f39b77408b75548c215d06dcd776d3c2",
      "size": 356,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/a31835f3f39b77408b75548c215d06dcd776d3c2"
    },
    {
      "path": "tutorialv2.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "e646fef1203c7c9b8137c6420d990fd40c1255ae",
      "size": 1873,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/e646fef1203c7c9b8137c6420d990fd40c1255ae"
    },
    {
      "path": "utils.rst",
      "mode": "100644",
      "type": "blob",
      "sha": "846765fc32bafc05bb58e6b70883acf5de8ae97b",
      "size": 1811,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/846765fc32bafc05bb58e6b70883acf5de8ae97b"
    }
  ],
  "truncated": false
};

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

let text = "";

for (let key in json.tree) {
    if (json.tree.hasOwnProperty(key)) {
        let blob = json.tree[key],
            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");
}

H2 : Ne retourne pas le bon sha :(

Original 4ef57de8e81c8415d6da2b267872e602b1f28cfe Actual : e99058a233e6da0d83ed8a027b3b533516087804

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

const json = {
  "sha": "4ef57de8e81c8415d6da2b267872e602b1f28cfe",
  "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/4ef57de8e81c8415d6da2b267872e602b1f28cfe",
  "tree": [
    {
      "path": ".coveragerc",
      "mode": "100644",
      "type": "blob",
      "sha": "449170d0faeb75182310345564fd1811c0b9fd73",
      "size": 163,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/449170d0faeb75182310345564fd1811c0b9fd73"
    },
    {
      "path": ".editorconfig",
      "mode": "100644",
      "type": "blob",
      "sha": "75884936ea2d35b531af886acad747d4fd9b2a9e",
      "size": 328,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/75884936ea2d35b531af886acad747d4fd9b2a9e"
    },
    {
      "path": ".flake8",
      "mode": "100644",
      "type": "blob",
      "sha": "69e872e30d30f5c7de3276d289d6aee81ccf4af7",
      "size": 232,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/69e872e30d30f5c7de3276d289d6aee81ccf4af7"
    },
    {
      "path": ".github",
      "mode": "040000",
      "type": "tree",
      "sha": "56b49acad224fdb70fca11809f3e5a4d396cb01c",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/56b49acad224fdb70fca11809f3e5a4d396cb01c"
    },
    {
      "path": ".gitignore",
      "mode": "100644",
      "type": "blob",
      "sha": "4832b44b973574253cf1b59ba7a66cfc227cd699",
      "size": 1439,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/4832b44b973574253cf1b59ba7a66cfc227cd699"
    },
    {
      "path": ".jshintrc",
      "mode": "100644",
      "type": "blob",
      "sha": "939efa02939437adece1e3a076d597b2557e36b5",
      "size": 319,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/939efa02939437adece1e3a076d597b2557e36b5"
    },
    {
      "path": ".travis.yml",
      "mode": "100644",
      "type": "blob",
      "sha": "6b5e4f43790874e2cf9db23e964f72b99deeb0d1",
      "size": 6040,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/6b5e4f43790874e2cf9db23e964f72b99deeb0d1"
    },
    {
      "path": "AUTHORS",
      "mode": "100644",
      "type": "blob",
      "sha": "0b92b7759ce2dd0a7cacf79b273368bb71ac5397",
      "size": 197,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/0b92b7759ce2dd0a7cacf79b273368bb71ac5397"
    },
    {
      "path": "CODE_OF_CONDUCT.md",
      "mode": "100644",
      "type": "blob",
      "sha": "ae61c31efae6cea565e447467e4377da76125679",
      "size": 2754,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/ae61c31efae6cea565e447467e4377da76125679"
    },
    {
      "path": "CONTRIBUTING.md",
      "mode": "100644",
      "type": "blob",
      "sha": "ac71ad378faf7fb7ae927b20d4d28a57c6085bf9",
      "size": 155,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/ac71ad378faf7fb7ae927b20d4d28a57c6085bf9"
    },
    {
      "path": "COPYING",
      "mode": "100644",
      "type": "blob",
      "sha": "94a9ed024d3859793618152ea559a168bbcbb5e2",
      "size": 35147,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/94a9ed024d3859793618152ea559a168bbcbb5e2"
    },
    {
      "path": "Gulpfile.js",
      "mode": "100644",
      "type": "blob",
      "sha": "5dd951ae61f0913605197fafa018f7db49549a68",
      "size": 6137,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/5dd951ae61f0913605197fafa018f7db49549a68"
    },
    {
      "path": "LICENSE",
      "mode": "100644",
      "type": "blob",
      "sha": "8a171a155d85927b678068becd046194aea777a9",
      "size": 717,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/8a171a155d85927b678068becd046194aea777a9"
    },
    {
      "path": "Makefile",
      "mode": "100644",
      "type": "blob",
      "sha": "cc722c2bc71dfbaa1b025c8c56245ed0fcd61739",
      "size": 3829,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/cc722c2bc71dfbaa1b025c8c56245ed0fcd61739"
    },
    {
      "path": "README.md",
      "mode": "100644",
      "type": "blob",
      "sha": "a6a9013159a3766da62443c4be5e267435469fd9",
      "size": 3280,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/a6a9013159a3766da62443c4be5e267435469fd9"
    },
    {
      "path": "assets",
      "mode": "040000",
      "type": "tree",
      "sha": "1846a32450eb2a7605acb55cab8206028cfb656f",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/1846a32450eb2a7605acb55cab8206028cfb656f"
    },
    {
      "path": "doc",
      "mode": "040000",
      "type": "tree",
      "sha": "f55b804a2b694db577b20c8e9851ad783fea8ee5",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/f55b804a2b694db577b20c8e9851ad783fea8ee5"
    },
    {
      "path": "errors",
      "mode": "040000",
      "type": "tree",
      "sha": "b37a18162be2bdae7382fc194f1bf2d0ab89bba3",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/b37a18162be2bdae7382fc194f1bf2d0ab89bba3"
    },
    {
      "path": "export-assets",
      "mode": "040000",
      "type": "tree",
      "sha": "3a8b85efa969c389ac3c5e7e6ad62206dbddcaca",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/3a8b85efa969c389ac3c5e7e6ad62206dbddcaca"
    },
    {
      "path": "fixtures",
      "mode": "040000",
      "type": "tree",
      "sha": "89cacb4de6feb81a962b9a992b9434cb44d3b0aa",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/89cacb4de6feb81a962b9a992b9434cb44d3b0aa"
    },
    {
      "path": "geodata",
      "mode": "040000",
      "type": "tree",
      "sha": "635d29035ae7528231edb9b74eb09887c22dda2a",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/635d29035ae7528231edb9b74eb09887c22dda2a"
    },
    {
      "path": "manage.py",
      "mode": "100755",
      "type": "blob",
      "sha": "458f6e2df8b431b9fa819c89e82cebf2e0a91260",
      "size": 1536,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/458f6e2df8b431b9fa819c89e82cebf2e0a91260"
    },
    {
      "path": "package.json",
      "mode": "100644",
      "type": "blob",
      "sha": "02d231aa0c0fa299581be07bcece0393dc9a9e47",
      "size": 1402,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/02d231aa0c0fa299581be07bcece0393dc9a9e47"
    },
    {
      "path": "quotes.txt",
      "mode": "100644",
      "type": "blob",
      "sha": "e8e84a048d70bc57c1f725fc12f2101a40c5dcbb",
      "size": 1552,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/e8e84a048d70bc57c1f725fc12f2101a40c5dcbb"
    },
    {
      "path": "requirements-dev.txt",
      "mode": "100644",
      "type": "blob",
      "sha": "7297a894036fcf70a7209062bb51f45db1b71d39",
      "size": 227,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/7297a894036fcf70a7209062bb51f45db1b71d39"
    },
    {
      "path": "requirements-prod.txt",
      "mode": "100644",
      "type": "blob",
      "sha": "2f957115bcf3794fdecf3c4848f21ae8f428c31b",
      "size": 83,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/2f957115bcf3794fdecf3c4848f21ae8f428c31b"
    },
    {
      "path": "requirements.txt",
      "mode": "100644",
      "type": "blob",
      "sha": "805fefa566ef0d8f6a7c7e58d01fa4684078cf50",
      "size": 998,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/805fefa566ef0d8f6a7c7e58d01fa4684078cf50"
    },
    {
      "path": "robots.txt",
      "mode": "100644",
      "type": "blob",
      "sha": "8ca70253a4bb677cb797a7b409df4c4a9c0baa67",
      "size": 948,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/8ca70253a4bb677cb797a7b409df4c4a9c0baa67"
    },
    {
      "path": "scripts",
      "mode": "040000",
      "type": "tree",
      "sha": "f6a251faaaa14ba4fcf702cd0556675e70cc80f3",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/f6a251faaaa14ba4fcf702cd0556675e70cc80f3"
    },
    {
      "path": "suggestions.txt",
      "mode": "100644",
      "type": "blob",
      "sha": "5e5d11a62a00d3f1aea8f3825c8ec89860d31ad0",
      "size": 285,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/5e5d11a62a00d3f1aea8f3825c8ec89860d31ad0"
    },
    {
      "path": "templates",
      "mode": "040000",
      "type": "tree",
      "sha": "5b6dde8b8b616ba078305584e23e55ad0c5b2299",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/5b6dde8b8b616ba078305584e23e55ad0c5b2299"
    },
    {
      "path": "update.md",
      "mode": "100644",
      "type": "blob",
      "sha": "734cb67218ac7ad952ffe2f816e4820427efe809",
      "size": 45743,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/734cb67218ac7ad952ffe2f816e4820427efe809"
    },
    {
      "path": "yarn.lock",
      "mode": "100644",
      "type": "blob",
      "sha": "9fed208fbed286860cb606c9904eb3bab2b3d960",
      "size": 193867,
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/blobs/9fed208fbed286860cb606c9904eb3bab2b3d960"
    },
    {
      "path": "zds",
      "mode": "040000",
      "type": "tree",
      "sha": "45b76aa70ad46e116c491a55def4b396b4ecba89",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/45b76aa70ad46e116c491a55def4b396b4ecba89"
    },
    {
      "path": "zmd",
      "mode": "040000",
      "type": "tree",
      "sha": "89289051d5d1e37ecc12629737d4fc01dd0df06e",
      "url": "https://api.github.com/repos/zestedesavoir/zds-site/git/trees/89289051d5d1e37ecc12629737d4fc01dd0df06e"
    }
  ],
  "truncated": false
};

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

let text = "";

for (let key in json.tree) {
    if (json.tree.hasOwnProperty(key)) {
        let blob = json.tree[key],
            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");
}
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte