From cf4e8699879a2f8b2efad64a3efbbebb9cac39ef Mon Sep 17 00:00:00 2001 From: Alberto Cortés Date: Wed, 22 Feb 2017 15:15:36 +0100 Subject: difftree: ignore permissions changes between regular files Fix issue #279. --- plumbing/difftree/difftree.go | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'plumbing/difftree') 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) } -- cgit