Skip to content

Commit 99e7cee

Browse files
committed
fix AllFilesDetails
1 parent 62da5c3 commit 99e7cee

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

git/diff.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ func NewGitDiff(dir string, oldCommit string, newCommit string) *GitDiff {
6161
func (c *GitDiff) AllFiles() ([]string, error) {
6262
return c.newGit.ListFiles()
6363
}
64+
65+
// AllFilesDetails deprecated, it has bug.
66+
// use AllFilesDetailsV2 instead
6467
func (c *GitDiff) AllFilesDetails() (map[string]*FileDetail, error) {
6568
c.fileDetailsOnce.Do(func() {
6669
allFiles, err := c.AllFiles()
@@ -106,6 +109,53 @@ func (c *GitDiff) AllFilesDetails() (map[string]*FileDetail, error) {
106109
return c.fileDetails, c.fileDetailsErr
107110
}
108111

112+
func (c *GitDiff) AllFilesDetailsV2() (map[string]*FileDetail, error) {
113+
c.fileDetailsOnce.Do(func() {
114+
allFiles, err := c.AllFiles()
115+
if err != nil {
116+
c.fileDetailsErr = fmt.Errorf("get all files err:%v", err)
117+
return
118+
}
119+
updates, err := c.GetUpdates()
120+
if err != nil {
121+
c.fileDetailsErr = fmt.Errorf("get updates err:%v", err)
122+
return
123+
}
124+
added, err := c.GetNew()
125+
if err != nil {
126+
c.fileDetailsErr = fmt.Errorf("get added err:%v", err)
127+
return
128+
}
129+
updateMap := make(map[string]bool, len(updates))
130+
for _, file := range updates {
131+
updateMap[file] = true
132+
}
133+
134+
addedMap := make(map[string]bool, len(added))
135+
for _, file := range added {
136+
addedMap[file] = true
137+
}
138+
139+
fileDetailsMap := make(map[string]*FileDetail, len(allFiles))
140+
for _, file := range allFiles {
141+
fileDetailsMap[file] = &FileDetail{
142+
IsNew: addedMap[file],
143+
ContentChanged: updateMap[file],
144+
}
145+
}
146+
err = FindRenamesV2(c.dir, c.oldCommit, c.newCommit, func(newFile, oldFile, percent string) {
147+
d := fileDetailsMap[newFile]
148+
d.RenamedFrom = oldFile
149+
d.ContentChanged = d.ContentChanged || percent != "100%"
150+
})
151+
if err != nil {
152+
c.fileDetailsErr = fmt.Errorf("get rename files err:%v", err)
153+
return
154+
}
155+
c.fileDetails = fileDetailsMap
156+
})
157+
return c.fileDetails, c.fileDetailsErr
158+
}
109159
func (c *GitDiff) GetUpdateAndRenames() (newToOld map[string]string, err error) {
110160
c.mergeOnce.Do(func() {
111161
renames, err := c.GetRenames()

git/git.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ func FindRenames(dir string, oldCommit string, newCommit string) (map[string]str
1515
repo := &GitRepo{Dir: dir}
1616
return repo.FindRenames(oldCommit, newCommit)
1717
}
18+
func FindRenamesV2(dir string, oldCommit string, newCommit string, fn func(newFile string, oldFile string, percent string)) error {
19+
repo := &GitRepo{Dir: dir}
20+
return repo.FindRenamesV2(oldCommit, newCommit, fn)
21+
}
1822

1923
func FindUpdate(dir string, oldCommit string, newCommit string) ([]string, error) {
2024
repo := &GitRepo{Dir: dir}
@@ -121,6 +125,89 @@ func (c *GitRepo) FindRenames(oldCommit string, newCommit string) (map[string]st
121125
return m, nil
122126
}
123127

128+
func (c *GitRepo) FindRenamesV2(oldCommit string, newCommit string, fn func(newFile string, oldFile string, percent string)) error {
129+
cmd := fmt.Sprintf(`git -C %s diff --diff-filter=R --summary %s %s || true`, sh.Quote(c.Dir), sh.Quote(getRef(oldCommit)), sh.Quote(getRef(newCommit)))
130+
stdout, stderr, err := sh.RunBashCmdOpts(cmd, sh.RunBashOptions{
131+
// Verbose: true,
132+
NeedStdOut: true,
133+
// NeedStdErr: true,
134+
})
135+
// fmt.Printf("stderr:%v", stderr)
136+
_ = stderr
137+
if err != nil {
138+
return err
139+
}
140+
parseRenames(stdout, fn)
141+
return nil
142+
}
143+
144+
func parseRenames(renamedFilesWithSummary string, fn func(newFile string, oldFile string, percent string)) {
145+
renames := splitLinesFilterEmpty(renamedFilesWithSummary)
146+
for _, line := range renames {
147+
line = strings.TrimSpace(line)
148+
if !strings.HasPrefix(line, "rename ") {
149+
continue
150+
}
151+
s := strings.TrimSpace(line[len("rename "):])
152+
153+
// parse percent
154+
// rename src/{module_funder/id/submodule_funder_seabank/cl => module_funder_bke/id}/bcl/task/repair_clawback_task.go (64%)
155+
var percent string
156+
pEidx := strings.LastIndex(s, ")")
157+
if pEidx >= 0 {
158+
s = strings.TrimSpace(s[:pEidx])
159+
pIdx := strings.LastIndex(s, "(")
160+
if pIdx >= 0 {
161+
percent = strings.TrimSpace(s[pIdx+1:])
162+
s = strings.TrimSpace(s[:pIdx])
163+
}
164+
}
165+
166+
bIdx := strings.Index(s, "{")
167+
if bIdx < 0 {
168+
continue
169+
}
170+
bEIdx := strings.LastIndex(s, "}")
171+
if bEIdx < 0 {
172+
continue
173+
}
174+
prefix := s[:bIdx]
175+
var suffix string
176+
if bEIdx+1 < len(s) {
177+
suffix = s[bEIdx+1:]
178+
}
179+
s = s[bIdx+1 : bEIdx]
180+
sep := " => "
181+
toIdx := strings.Index(s, sep)
182+
if toIdx < 0 {
183+
continue
184+
}
185+
oldPath := s[:toIdx]
186+
var newPath string
187+
if toIdx+len(sep) < len(s) {
188+
newPath = s[toIdx+len(sep):]
189+
}
190+
191+
file := joinPath(prefix, newPath, suffix)
192+
oldFile := joinPath(prefix, oldPath, suffix)
193+
194+
fn(file, oldFile, percent)
195+
}
196+
}
197+
198+
func joinPath(p ...string) string {
199+
j := 0
200+
for i := 0; i < len(p); i++ {
201+
e := strings.TrimPrefix(p[i], "/")
202+
e = strings.TrimSuffix(e, "/")
203+
if e != "" {
204+
p[j] = e
205+
j++
206+
}
207+
}
208+
return strings.Join(p[:j], "/")
209+
}
210+
124211
type GitSnapshot struct {
125212
Dir string
126213
Commit string

0 commit comments

Comments
 (0)