Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 294d6f4

Browse files
authored
Merge pull request #285 from alcortesm/fix-issue-279
Fix issue 279
2 parents b5da4e9 + cf4e869 commit 294d6f4

File tree

3 files changed

+72
-9
lines changed

3 files changed

+72
-9
lines changed

plumbing/difftree/difftree.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,62 @@ package difftree
22

33
import (
44
"bytes"
5+
"os"
56

67
"srcd.works/go-git.v4/plumbing/object"
78
"srcd.works/go-git.v4/utils/merkletrie"
89
"srcd.works/go-git.v4/utils/merkletrie/noder"
910
)
1011

12+
// DiffTree compares the content and mode of the blobs found via two
13+
// tree objects.
1114
func DiffTree(a, b *object.Tree) ([]*Change, error) {
1215
from := newTreeNoder(a)
1316
to := newTreeNoder(b)
1417

15-
hashEqual := func(a, b noder.Hasher) bool {
16-
return bytes.Equal(a.Hash(), b.Hash())
17-
}
18-
1918
merkletrieChanges, err := merkletrie.DiffTree(from, to, hashEqual)
2019
if err != nil {
2120
return nil, err
2221
}
2322

2423
return newChanges(merkletrieChanges)
2524
}
25+
26+
// check if the hash of the contents is different, if not, check if
27+
// the permissions are different (but taking into account deprecated
28+
// file modes). On a treenoder, the hash of the contents is codified
29+
// in the first 20 bytes of the data returned by Hash() and the last
30+
// 4 bytes is the mode.
31+
func hashEqual(a, b noder.Hasher) bool {
32+
hashA, hashB := a.Hash(), b.Hash()
33+
contentsA, contentsB := hashA[:20], hashB[:20]
34+
35+
sameContents := bytes.Equal(contentsA, contentsB)
36+
if !sameContents {
37+
return false
38+
}
39+
40+
modeA, modeB := hashA[20:], hashB[20:]
41+
42+
return equivalentMode(modeA, modeB)
43+
}
44+
45+
func equivalentMode(a, b []byte) bool {
46+
if isFilish(a) && isFilish(b) {
47+
return true
48+
}
49+
return bytes.Equal(a, b)
50+
}
51+
52+
var (
53+
file = modeToBytes(object.FileMode)
54+
fileDeprecated = modeToBytes(object.FileModeDeprecated)
55+
// remove this by fixing plumbing.Object mode ASAP
56+
fileGoGit = modeToBytes(os.FileMode(0644))
57+
)
58+
59+
func isFilish(b []byte) bool {
60+
return bytes.Equal(b, file) ||
61+
bytes.Equal(b, fileDeprecated) ||
62+
bytes.Equal(b, fileGoGit)
63+
}

plumbing/difftree/difftree_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package difftree
22

33
import (
4+
"os"
45
"sort"
56
"testing"
67

@@ -353,3 +354,26 @@ func (s *DiffTreeSuite) TestDiffTree(c *C) {
353354
assertChanges(obtained, c)
354355
}
355356
}
357+
358+
func (s *DiffTreeSuite) TestIssue279(c *C) {
359+
// HashEqual should ignore files if the only change is from a 100664
360+
// mode to a 100644 or vice versa.
361+
from := &treeNoder{
362+
hash: plumbing.NewHash("d08e895238bac36d8220586fdc28c27e1a7a76d3"),
363+
mode: os.FileMode(0100664),
364+
}
365+
to := &treeNoder{
366+
hash: plumbing.NewHash("d08e895238bac36d8220586fdc28c27e1a7a76d3"),
367+
mode: os.FileMode(0100644),
368+
}
369+
c.Assert(hashEqual(from, to), Equals, true)
370+
c.Assert(hashEqual(to, from), Equals, true)
371+
372+
// but should detect if the contents of the file also changed.
373+
to = &treeNoder{
374+
hash: plumbing.NewHash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
375+
mode: os.FileMode(0100644),
376+
}
377+
c.Assert(hashEqual(from, to), Equals, false)
378+
c.Assert(hashEqual(to, from), Equals, false)
379+
}

plumbing/object/tree.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ const (
1919
maxTreeDepth = 1024
2020
startingStackSize = 8
2121

22-
FileMode os.FileMode = 0100644
23-
ExecutableMode os.FileMode = 0100755
24-
SubmoduleMode os.FileMode = 0160000
25-
SymlinkMode os.FileMode = 0120000
26-
TreeMode os.FileMode = 0040000
22+
FileMode os.FileMode = 0100644
23+
FileModeDeprecated os.FileMode = 0100664
24+
ExecutableMode os.FileMode = 0100755
25+
SubmoduleMode os.FileMode = 0160000
26+
SymlinkMode os.FileMode = 0120000
27+
TreeMode os.FileMode = 0040000
2728
)
2829

2930
// New errors defined by this package.

0 commit comments

Comments
 (0)