aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/difftree
diff options
context:
space:
mode:
authorAlberto Cortés <alberto@sourced.tech>2017-02-22 15:15:36 +0100
committerAlberto Cortés <alberto@sourced.tech>2017-02-22 17:37:39 +0100
commitcf4e8699879a2f8b2efad64a3efbbebb9cac39ef (patch)
tree96f136e2449f5dad9db06b769b63a5ad95aec8fa /plumbing/difftree
parentd27c741e3b68357e46cc0a85a33a184fecc05c29 (diff)
downloadgo-git-cf4e8699879a2f8b2efad64a3efbbebb9cac39ef.tar.gz
difftree: ignore permissions changes between regular files
Fix issue #279.
Diffstat (limited to 'plumbing/difftree')
-rw-r--r--plumbing/difftree/difftree.go40
1 files changed, 39 insertions, 1 deletions
diff --git a/plumbing/difftree/difftree.go b/plumbing/difftree/difftree.go
index d38ad2c..ff1ceaf 100644
--- a/plumbing/difftree/difftree.go
+++ b/plumbing/difftree/difftree.go
@@ -2,12 +2,15 @@ package difftree
import (
"bytes"
+ "os"
"srcd.works/go-git.v4/plumbing/object"
"srcd.works/go-git.v4/utils/merkletrie"
"srcd.works/go-git.v4/utils/merkletrie/noder"
)
+// DiffTree compares the content and mode of the blobs found via two
+// tree objects.
func DiffTree(a, b *object.Tree) ([]*Change, error) {
from := newTreeNoder(a)
to := newTreeNoder(b)
@@ -20,6 +23,41 @@ func DiffTree(a, b *object.Tree) ([]*Change, error) {
return newChanges(merkletrieChanges)
}
+// check if the hash of the contents is different, if not, check if
+// the permissions are different (but taking into account deprecated
+// file modes). On a treenoder, the hash of the contents is codified
+// in the first 20 bytes of the data returned by Hash() and the last
+// 4 bytes is the mode.
func hashEqual(a, b noder.Hasher) bool {
- return bytes.Equal(a.Hash(), b.Hash())
+ hashA, hashB := a.Hash(), b.Hash()
+ contentsA, contentsB := hashA[:20], hashB[:20]
+
+ sameContents := bytes.Equal(contentsA, contentsB)
+ if !sameContents {
+ return false
+ }
+
+ modeA, modeB := hashA[20:], hashB[20:]
+
+ return equivalentMode(modeA, modeB)
+}
+
+func equivalentMode(a, b []byte) bool {
+ if isFilish(a) && isFilish(b) {
+ return true
+ }
+ return bytes.Equal(a, b)
+}
+
+var (
+ file = modeToBytes(object.FileMode)
+ fileDeprecated = modeToBytes(object.FileModeDeprecated)
+ // remove this by fixing plumbing.Object mode ASAP
+ fileGoGit = modeToBytes(os.FileMode(0644))
+)
+
+func isFilish(b []byte) bool {
+ return bytes.Equal(b, file) ||
+ bytes.Equal(b, fileDeprecated) ||
+ bytes.Equal(b, fileGoGit)
}