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

L’auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

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.

✈️ // 🐺 Ami des loups // 🎮 Coding Game // 🐤 Twitter @A312_zds // :B // L’hiver vient // @**A-312** pour me ping

+0 -0

ça ne se calcule pas, c’est le sha-1 d’un commit.

je viens de comprendre ton message, je ne sais pas (je vais quand même me renseigner, ça m’intéresse.

Édité par minirop

+0 -0

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.

+0 -0

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

Édité par unidan

+1 -0
Auteur du sujet

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

Édité par A-312

✈️ // 🐺 Ami des loups // 🎮 Coding Game // 🐤 Twitter @A312_zds // :B // L’hiver vient // @**A-312** pour me ping

+0 -0
Auteur du sujet

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

✈️ // 🐺 Ami des loups // 🎮 Coding Game // 🐤 Twitter @A312_zds // :B // L’hiver vient // @**A-312** pour me ping

+0 -0

Cette réponse a aidé l’auteur du sujet

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

Édité par disedorgue

+2 -0
Auteur du sujet

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");

Édité par A-312

✈️ // 🐺 Ami des loups // 🎮 Coding Game // 🐤 Twitter @A312_zds // :B // L’hiver vient // @**A-312** pour me ping

+0 -0

Cette réponse a aidé l’auteur du sujet

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.

+1 -0
Auteur du sujet

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)).

Édité par A-312

✈️ // 🐺 Ami des loups // 🎮 Coding Game // 🐤 Twitter @A312_zds // :B // L’hiver vient // @**A-312** pour me ping

+0 -0
Auteur du sujet

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");
}

Édité par A-312

✈️ // 🐺 Ami des loups // 🎮 Coding Game // 🐤 Twitter @A312_zds // :B // L’hiver vient // @**A-312** pour me ping

+0 -0
Auteur du sujet

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

Édité par A-312

✈️ // 🐺 Ami des loups // 🎮 Coding Game // 🐤 Twitter @A312_zds // :B // L’hiver vient // @**A-312** pour me ping

+0 -0
Auteur du sujet

Cette réponse a aidé l’auteur du sujet

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:

Édité par A-312

✈️ // 🐺 Ami des loups // 🎮 Coding Game // 🐤 Twitter @A312_zds // :B // L’hiver vient // @**A-312** pour me ping

+0 -0
Auteur du sujet

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.

✈️ // 🐺 Ami des loups // 🎮 Coding Game // 🐤 Twitter @A312_zds // :B // L’hiver vient // @**A-312** pour me ping

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

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