Skip to content

Commit

Permalink
diff: capture both old and new of index and mode (#73)
Browse files Browse the repository at this point in the history
Co-authored-by: Joe Chen <[email protected]>
aymanbagabas and unknwon authored Mar 26, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 93f85f8 commit 2a8fce5
Showing 4 changed files with 186 additions and 73 deletions.
60 changes: 52 additions & 8 deletions diff.go
Original file line number Diff line number Diff line change
@@ -108,8 +108,10 @@ type DiffFile struct {
// The type of the file.
Type DiffFileType
// The index (SHA1 hash) of the file. For a changed/new file, it is the new SHA,
// and for a deleted file it is the old SHA.
// and for a deleted file it becomes "000000".
Index string
// OldIndex is the old index (SHA1 hash) of the file.
OldIndex string
// The sections in the file.
Sections []*DiffSection

@@ -118,6 +120,9 @@ type DiffFile struct {

oldName string

mode EntryMode
oldMode EntryMode

isBinary bool
isSubmodule bool
isIncomplete bool
@@ -158,6 +163,16 @@ func (f *DiffFile) OldName() string {
return f.oldName
}

// Mode returns the mode of the file.
func (f *DiffFile) Mode() EntryMode {
return f.mode
}

// OldMode returns the old mode of the file if it's changed.
func (f *DiffFile) OldMode() EntryMode {
return f.oldMode
}

// IsBinary returns true if the file is in binary format.
func (f *DiffFile) IsBinary() bool {
return f.isBinary
@@ -268,8 +283,9 @@ func (p *diffParser) parseFileHeader() (*DiffFile, error) {
}

file := &DiffFile{
Name: a,
Type: DiffFileChange,
Name: a,
oldName: b,
Type: DiffFileChange,
}

// Check file diff type and submodule
@@ -291,20 +307,38 @@ checkType:
case strings.HasPrefix(line, "new file"):
file.Type = DiffFileAdd
file.isSubmodule = strings.HasSuffix(line, " 160000")
fields := strings.Fields(line)
if len(fields) > 0 {
mode, _ := strconv.ParseUint(fields[len(fields)-1], 8, 64)
file.mode = EntryMode(mode)
if file.oldMode == 0 {
file.oldMode = file.mode
}
}
case strings.HasPrefix(line, "deleted"):
file.Type = DiffFileDelete
file.isSubmodule = strings.HasSuffix(line, " 160000")
fields := strings.Fields(line)
if len(fields) > 0 {
mode, _ := strconv.ParseUint(fields[len(fields)-1], 8, 64)
file.mode = EntryMode(mode)
if file.oldMode == 0 {
file.oldMode = file.mode
}
}
case strings.HasPrefix(line, "index"): // e.g. index ee791be..9997571 100644
fields := strings.Fields(line[6:])
shas := strings.Split(fields[0], "..")
if len(shas) != 2 {
return nil, errors.New("malformed index: expect two SHAs in the form of <old>..<new>")
}

if file.IsDeleted() {
file.Index = shas[0]
} else {
file.Index = shas[1]
file.OldIndex = shas[0]
file.Index = shas[1]
if len(fields) > 1 {
mode, _ := strconv.ParseUint(fields[1], 8, 64)
file.mode = EntryMode(mode)
file.oldMode = EntryMode(mode)
}
break checkType
case strings.HasPrefix(line, "similarity index "):
@@ -316,8 +350,18 @@ checkType:
if strings.HasSuffix(line, "100%") {
break checkType
}
case strings.HasPrefix(line, "new mode"):
fields := strings.Fields(line)
if len(fields) > 0 {
mode, _ := strconv.ParseUint(fields[len(fields)-1], 8, 64)
file.mode = EntryMode(mode)
}
case strings.HasPrefix(line, "old mode"):
break checkType
fields := strings.Fields(line)
if len(fields) > 0 {
mode, _ := strconv.ParseUint(fields[len(fields)-1], 8, 64)
file.oldMode = EntryMode(mode)
}
}
}

122 changes: 88 additions & 34 deletions diff_test.go
Original file line number Diff line number Diff line change
@@ -144,6 +144,8 @@ func TestDiff(t *testing.T) {
isBinary: false,
isSubmodule: false,
isIncomplete: false,
mode: 100644,
oldMode: 100644,
},
},
totalAdditions: 10,
@@ -185,9 +187,10 @@ index 0000000..6b08f76
expDiff: &Diff{
Files: []*DiffFile{
{
Name: ".gitmodules",
Type: DiffFileAdd,
Index: "6abde17",
Name: ".gitmodules",
Type: DiffFileAdd,
Index: "6abde17",
OldIndex: "0000000",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -217,15 +220,18 @@ index 0000000..6b08f76
},
numAdditions: 3,
numDeletions: 0,
oldName: "",
oldName: ".gitmodules",
isBinary: false,
isSubmodule: false,
isIncomplete: false,
mode: 0100644,
oldMode: 0100644,
},
{
Name: "gogs/docs-api",
Type: DiffFileAdd,
Index: "6b08f76",
Name: "gogs/docs-api",
Type: DiffFileAdd,
Index: "6b08f76",
OldIndex: "0000000",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -245,10 +251,12 @@ index 0000000..6b08f76
},
numAdditions: 1,
numDeletions: 0,
oldName: "",
oldName: "gogs/docs-api",
isBinary: false,
isSubmodule: true,
isIncomplete: false,
mode: 0160000,
oldMode: 0160000,
},
},
totalAdditions: 4,
@@ -273,9 +281,10 @@ index ee791be..9997571 100644
expDiff: &Diff{
Files: []*DiffFile{
{
Name: "pom.xml",
Type: DiffFileChange,
Index: "9997571",
Name: "pom.xml",
Type: DiffFileChange,
Index: "9997571",
OldIndex: "ee791be",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -330,10 +339,12 @@ index ee791be..9997571 100644
},
numAdditions: 1,
numDeletions: 1,
oldName: "",
oldName: "pom.xml",
isBinary: false,
isSubmodule: false,
isIncomplete: false,
oldMode: 0100644,
mode: 0100644,
},
},
totalAdditions: 1,
@@ -352,13 +363,16 @@ Binary files /dev/null and b/img/sourcegraph.png differ`,
Name: "img/sourcegraph.png",
Type: DiffFileAdd,
Index: "2ce9188",
OldIndex: "0000000",
Sections: nil,
numAdditions: 0,
numDeletions: 0,
oldName: "",
oldName: "img/sourcegraph.png",
isBinary: true,
isSubmodule: false,
isIncomplete: false,
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 0,
@@ -375,14 +389,17 @@ index e69de29..0000000`,
{
Name: "fix.txt",
Type: DiffFileDelete,
Index: "e69de29",
Index: "0000000",
OldIndex: "e69de29",
Sections: nil,
numAdditions: 0,
numDeletions: 0,
oldName: "",
oldName: "fix.txt",
isBinary: false,
isSubmodule: false,
isIncomplete: false,
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 0,
@@ -431,9 +448,10 @@ index b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0..ab80bda5dd90d8b42be25ac2c7a071b7
expDiff: &Diff{
Files: []*DiffFile{
{
Name: "dir/file.txt",
Type: DiffFileChange,
Index: "ab80bda5dd90d8b42be25ac2c7a071b722171f09",
Name: "dir/file.txt",
Type: DiffFileChange,
Index: "ab80bda5dd90d8b42be25ac2c7a071b722171f09",
OldIndex: "b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -468,10 +486,12 @@ index b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0..ab80bda5dd90d8b42be25ac2c7a071b7
},
numAdditions: 3,
numDeletions: 1,
oldName: "",
oldName: "dir/file.txt",
isBinary: false,
isSubmodule: false,
isIncomplete: false,
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 3,
@@ -499,9 +519,10 @@ index ce53c7e..56a156b 100644
expDiff: &Diff{
Files: []*DiffFile{
{
Name: "src/app/tabs/friends/friends.module.ts",
Type: DiffFileRename,
Index: "56a156b",
Name: "src/app/tabs/friends/friends.module.ts",
Type: DiffFileRename,
Index: "56a156b",
OldIndex: "ce53c7e",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -557,6 +578,8 @@ index ce53c7e..56a156b 100644
numAdditions: 2,
numDeletions: 2,
oldName: "src/app/tabs/teacher/teacher.module.ts",
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 2,
@@ -590,9 +613,10 @@ index 335db7ea..51d7543e 100644
expDiff: &Diff{
Files: []*DiffFile{
{
Name: ".travis.yml",
Type: DiffFileChange,
Index: "51d7543e",
Name: ".travis.yml",
Type: DiffFileChange,
Index: "51d7543e",
OldIndex: "335db7ea",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -652,10 +676,12 @@ index 335db7ea..51d7543e 100644
},
numAdditions: 0,
numDeletions: 3,
oldName: "",
oldName: ".travis.yml",
isBinary: false,
isSubmodule: false,
isIncomplete: true,
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 0,
@@ -677,9 +703,10 @@ index 0000000..6abde17
expDiff: &Diff{
Files: []*DiffFile{
{
Name: ".gitmodules",
Type: DiffFileAdd,
Index: "6abde17",
Name: ".gitmodules",
Type: DiffFileAdd,
Index: "6abde17",
OldIndex: "0000000",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -704,10 +731,12 @@ index 0000000..6abde17
},
numAdditions: 2,
numDeletions: 0,
oldName: "",
oldName: ".gitmodules",
isBinary: false,
isSubmodule: false,
isIncomplete: true,
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 2,
@@ -738,9 +767,10 @@ index 0000000..6b08f76
expDiff: &Diff{
Files: []*DiffFile{
{
Name: ".gitmodules",
Type: DiffFileAdd,
Index: "6abde17",
Name: ".gitmodules",
Type: DiffFileAdd,
Index: "6abde17",
OldIndex: "0000000",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -765,17 +795,41 @@ index 0000000..6b08f76
},
numAdditions: 2,
numDeletions: 0,
oldName: "",
oldName: ".gitmodules",
isBinary: false,
isSubmodule: false,
isIncomplete: true,
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 2,
totalDeletions: 0,
isIncomplete: true,
},
},
{
input: `diff --git a/go.mod b/go.mod
old mode 100644
new mode 100755`,
maxFileLines: 0,
maxLineChars: 0,
maxFiles: 1,
expDiff: &Diff{
Files: []*DiffFile{
{
Name: "go.mod",
oldName: "go.mod",
Type: DiffFileChange,
mode: 0100755,
oldMode: 0100644,
},
},
totalAdditions: 0,
totalDeletions: 0,
isIncomplete: false,
},
},
}
for _, test := range tests {
t.Run("", func(t *testing.T) {
10 changes: 5 additions & 5 deletions repo_diff.go
Original file line number Diff line number Diff line change
@@ -97,17 +97,17 @@ func (r *Repository) RawDiff(rev string, diffType RawDiffFormat, w io.Writer, op
switch diffType {
case RawDiffNormal:
if commit.ParentsCount() == 0 {
cmd.AddArgs("show", rev)
cmd.AddArgs("show", "--full-index", rev)
} else {
c, _ := commit.Parent(0)
cmd.AddArgs("diff", "-M", c.ID.String(), rev)
cmd.AddArgs("diff", "--full-index", "-M", c.ID.String(), rev)
}
case RawDiffPatch:
if commit.ParentsCount() == 0 {
cmd.AddArgs("format-patch", "--no-signature", "--stdout", "--root", rev)
cmd.AddArgs("format-patch", "--full-index", "--no-signature", "--stdout", "--root", rev)
} else {
c, _ := commit.Parent(0)
cmd.AddArgs("format-patch", "--no-signature", "--stdout", rev+"..."+c.ID.String())
cmd.AddArgs("format-patch", "--full-index", "--no-signature", "--stdout", rev+"..."+c.ID.String())
}
default:
return fmt.Errorf("invalid diffType: %s", diffType)
@@ -135,5 +135,5 @@ func (r *Repository) DiffBinary(base, head string, opts ...DiffBinaryOptions) ([
opt = opts[0]
}

return NewCommand("diff", "--binary", base, head).RunInDirWithTimeout(opt.Timeout, r.path)
return NewCommand("diff", "--full-index", "--binary", base, head).RunInDirWithTimeout(opt.Timeout, r.path)
}
67 changes: 41 additions & 26 deletions repo_diff_test.go
Original file line number Diff line number Diff line change
@@ -29,14 +29,17 @@ func TestRepository_Diff(t *testing.T) {
{
Name: "fix.txt",
Type: DiffFileDelete,
Index: "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
Index: "0000000000000000000000000000000000000000",
OldIndex: "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
Sections: nil,
numAdditions: 0,
numDeletions: 0,
oldName: "",
oldName: "fix.txt",
isBinary: false,
isSubmodule: false,
isIncomplete: false,
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 0,
@@ -49,9 +52,10 @@ func TestRepository_Diff(t *testing.T) {
expDiff: &Diff{
Files: []*DiffFile{
{
Name: "README.txt",
Type: DiffFileAdd,
Index: "1e24b564bf2298965d8037af42d3ae15ad7d225a",
Name: "README.txt",
Type: DiffFileAdd,
Index: "1e24b564bf2298965d8037af42d3ae15ad7d225a",
OldIndex: "0000000000000000000000000000000000000000",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -131,15 +135,18 @@ func TestRepository_Diff(t *testing.T) {
},
numAdditions: 11,
numDeletions: 0,
oldName: "",
oldName: "README.txt",
isBinary: false,
isSubmodule: false,
isIncomplete: false,
mode: 0100644,
oldMode: 0100644,
},
{
Name: "resources/labels.properties",
Type: DiffFileAdd,
Index: "fbdcfef007c0c09061199e687087b18c3cf8e083",
Name: "resources/labels.properties",
Type: DiffFileAdd,
Index: "fbdcfef007c0c09061199e687087b18c3cf8e083",
OldIndex: "0000000000000000000000000000000000000000",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -177,15 +184,18 @@ func TestRepository_Diff(t *testing.T) {
},
numAdditions: 4,
numDeletions: 0,
oldName: "",
oldName: "resources/labels.properties",
isBinary: false,
isSubmodule: false,
isIncomplete: false,
mode: 0100644,
oldMode: 0100644,
},
{
Name: "src/Main.groovy",
Type: DiffFileAdd,
Index: "51680791956b43effdb2f16bccd2b4752d66078f",
Name: "src/Main.groovy",
Type: DiffFileAdd,
Index: "51680791956b43effdb2f16bccd2b4752d66078f",
OldIndex: "0000000000000000000000000000000000000000",
Sections: []*DiffSection{
{
Lines: []*DiffLine{
@@ -235,10 +245,12 @@ func TestRepository_Diff(t *testing.T) {
},
numAdditions: 6,
numDeletions: 0,
oldName: "",
oldName: "src/Main.groovy",
isBinary: false,
isSubmodule: false,
isIncomplete: false,
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 21,
@@ -256,14 +268,17 @@ func TestRepository_Diff(t *testing.T) {
{
Name: "fix.txt",
Type: DiffFileDelete,
Index: "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
Index: "0000000000000000000000000000000000000000",
OldIndex: "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
Sections: nil,
numAdditions: 0,
numDeletions: 0,
oldName: "",
oldName: "fix.txt",
isBinary: false,
isSubmodule: false,
isIncomplete: false,
mode: 0100644,
oldMode: 0100644,
},
},
totalAdditions: 0,
@@ -306,7 +321,7 @@ func TestRepository_RawDiff(t *testing.T) {
diffType: RawDiffNormal,
expOutput: `diff --git a/fix.txt b/fix.txt
deleted file mode 100644
index e69de29..0000000
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
`,
},
{
@@ -322,7 +337,7 @@ Subject: [PATCH] Delete fix.txt
diff --git a/fix.txt b/fix.txt
deleted file mode 100644
index e69de29..0000000
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
`,
},
{
@@ -340,7 +355,7 @@ Date: Mon Nov 24 21:22:01 2008 -0700
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..1e24b56
index 0000000000000000000000000000000000000000..1e24b564bf2298965d8037af42d3ae15ad7d225a
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,11 @@
@@ -358,7 +373,7 @@ index 0000000..1e24b56
\ No newline at end of file
diff --git a/resources/labels.properties b/resources/labels.properties
new file mode 100644
index 0000000..fbdcfef
index 0000000000000000000000000000000000000000..fbdcfef007c0c09061199e687087b18c3cf8e083
--- /dev/null
+++ b/resources/labels.properties
@@ -0,0 +1,4 @@
@@ -368,7 +383,7 @@ index 0000000..fbdcfef
+cli.usage=This application doesn't use a command line interface
diff --git a/src/Main.groovy b/src/Main.groovy
new file mode 100644
index 0000000..5168079
index 0000000000000000000000000000000000000000..51680791956b43effdb2f16bccd2b4752d66078f
--- /dev/null
+++ b/src/Main.groovy
@@ -0,0 +1,6 @@
@@ -401,7 +416,7 @@ Subject: [PATCH] Addition of the README and basic Groovy source samples.
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..1e24b56
index 0000000000000000000000000000000000000000..1e24b564bf2298965d8037af42d3ae15ad7d225a
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,11 @@
@@ -419,7 +434,7 @@ index 0000000..1e24b56
\ No newline at end of file
diff --git a/resources/labels.properties b/resources/labels.properties
new file mode 100644
index 0000000..fbdcfef
index 0000000000000000000000000000000000000000..fbdcfef007c0c09061199e687087b18c3cf8e083
--- /dev/null
+++ b/resources/labels.properties
@@ -0,0 +1,4 @@
@@ -429,7 +444,7 @@ index 0000000..fbdcfef
+cli.usage=This application doesn't use a command line interface
diff --git a/src/Main.groovy b/src/Main.groovy
new file mode 100644
index 0000000..5168079
index 0000000000000000000000000000000000000000..51680791956b43effdb2f16bccd2b4752d66078f
--- /dev/null
+++ b/src/Main.groovy
@@ -0,0 +1,6 @@
@@ -475,7 +490,7 @@ func TestRepository_DiffBinary(t *testing.T) {
head: "4e59b72440188e7c2578299fc28ea425fbe9aece",
expOutput: `diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..6abde17
index 0000000000000000000000000000000000000000..6abde17f49a6d43df40366e57d8964fee0dfda11
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
@@ -484,7 +499,7 @@ index 0000000..6abde17
+ url = https://github.com/gogs/docs-api.git
diff --git a/gogs/docs-api b/gogs/docs-api
new file mode 160000
index 0000000..6b08f76
index 0000000000000000000000000000000000000000..6b08f76a5313fa3d26859515b30aa17a5faa2807
--- /dev/null
+++ b/gogs/docs-api
@@ -0,0 +1 @@

0 comments on commit 2a8fce5

Please sign in to comment.