History

Fix yet another bug with diff file names (#12771)

Following further testing it has become apparent that the diff line cannot be used to determine filenames for diffs with any sort of predictability the answer therefore is to use the other lines that are provided with a diff Fix #12768

zeripath committed 6 years ago

Commit 96969dd1 parent 1fbc50f3 files · +247 −51Browse files

Showing the changes to services/gitdiff/gitdiff.go (1 of 3 files). Show all

Unified · Split

services/gitdiff/gitdiff.go+105−46
@@ -53,6 +53,7 @@ const ( · 52 unmodified lines
5353 DiffFileChange
5454 DiffFileDel
5555 DiffFileRename
56+ DiffFileCopy
5657 )
5758
5859 // DiffLineExpandDirection represents the DiffLineSection expand direction
@@ -481,7 +482,46 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 422 unmodified lines
481482 }
482483 line := linebuf.String()
483484
484− if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") || len(line) == 0 {
485+ if strings.HasPrefix(line, "--- ") {
486+ if line[4] == '"' {
487+ fmt.Sscanf(line[4:], "%q", &curFile.OldName)
488+ } else {
489+ curFile.OldName = line[4:]
490+ if strings.Contains(curFile.OldName, " ") {
491+ // Git adds a terminal \t if there is a space in the name
492+ curFile.OldName = curFile.OldName[:len(curFile.OldName)-1]
493+ }
494+ }
495+ if curFile.OldName[0:2] == "a/" {
496+ curFile.OldName = curFile.OldName[2:]
497+ }
498+ continue
499+ } else if strings.HasPrefix(line, "+++ ") {
500+ if line[4] == '"' {
501+ fmt.Sscanf(line[4:], "%q", &curFile.Name)
502+ } else {
503+ curFile.Name = line[4:]
504+ if strings.Contains(curFile.Name, " ") {
505+ // Git adds a terminal \t if there is a space in the name
506+ curFile.Name = curFile.Name[:len(curFile.Name)-1]
507+ }
508+ }
509+ if curFile.Name[0:2] == "b/" {
510+ curFile.Name = curFile.Name[2:]
511+ }
512+ curFile.IsRenamed = (curFile.Name != curFile.OldName) && !(curFile.IsCreated || curFile.IsDeleted)
513+ if curFile.IsDeleted {
514+ curFile.Name = curFile.OldName
515+ curFile.OldName = ""
516+ } else if curFile.IsCreated {
517+ curFile.OldName = ""
518+ }
519+ continue
520+ } else if len(line) == 0 {
521+ continue
522+ }
523+
524+ if strings.HasPrefix(line, "+++") || strings.HasPrefix(line, "---") || len(line) == 0 {
485525 continue
486526 }
487527
@@ -569,36 +609,10 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 81 unmodified lines
569609 break
570610 }
571611
572− // Note: In case file name is surrounded by double quotes (it happens only in git-shell).
573− // e.g. diff --git "a/xxx" "b/xxx"
574− var a string
575− var b string
576−
577− rd := strings.NewReader(line[len(cmdDiffHead):])
578− char, _ := rd.ReadByte()
579− _ = rd.UnreadByte()
580− if char == '"' {
581− fmt.Fscanf(rd, "%q ", &a)
582− } else {
583− fmt.Fscanf(rd, "%s ", &a)
584− }
585− char, _ = rd.ReadByte()
586− _ = rd.UnreadByte()
587− if char == '"' {
588− fmt.Fscanf(rd, "%q", &b)
589− } else {
590− fmt.Fscanf(rd, "%s", &b)
591− }
592− a = a[2:]
593− b = b[2:]
594−
595612 curFile = &DiffFile{
596− Name: b,
597− OldName: a,
598− Index: len(diff.Files) + 1,
599− Type: DiffFileChange,
600− Sections: make([]*DiffSection, 0, 10),
601− IsRenamed: a != b,
613+ Index: len(diff.Files) + 1,
614+ Type: DiffFileChange,
615+ Sections: make([]*DiffSection, 0, 10),
602616 }
603617 diff.Files = append(diff.Files, curFile)
604618 curFileLinesCount = 0
@@ -607,6 +621,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 2 unmodified lines
607621 curFileLFSPrefix = false
608622
609623 // Check file diff type and is submodule.
624+ loop:
610625 for {
611626 line, err := input.ReadString('\n')
612627 if err != nil {
@@ -617,23 +632,67 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 4 unmodified lines
617632 }
618633 }
619634
620− switch {
621− case strings.HasPrefix(line, "new file"):
622− curFile.Type = DiffFileAdd
623− curFile.IsCreated = true
624− case strings.HasPrefix(line, "deleted"):
625− curFile.Type = DiffFileDel
626− curFile.IsDeleted = true
627− case strings.HasPrefix(line, "index"):
628− curFile.Type = DiffFileChange
629− case strings.HasPrefix(line, "similarity index 100%"):
630− curFile.Type = DiffFileRename
631− }
632− if curFile.Type > 0 {
633− if strings.HasSuffix(line, " 160000\n") {
634− curFile.IsSubmodule = true
635+ if curFile.Type != DiffFileRename {
636+ switch {
637+ case strings.HasPrefix(line, "new file"):
638+ curFile.Type = DiffFileAdd
639+ curFile.IsCreated = true
640+ case strings.HasPrefix(line, "deleted"):
641+ curFile.Type = DiffFileDel
642+ curFile.IsDeleted = true
643+ case strings.HasPrefix(line, "index"):
644+ curFile.Type = DiffFileChange
645+ case strings.HasPrefix(line, "similarity index 100%"):
646+ curFile.Type = DiffFileRename
647+ }
648+ if curFile.Type > 0 && curFile.Type != DiffFileRename {
649+ if strings.HasSuffix(line, " 160000\n") {
650+ curFile.IsSubmodule = true
651+ }
652+ break
653+ }
654+ } else {
655+ switch {
656+ case strings.HasPrefix(line, "rename from "):
657+ if line[12] == '"' {
658+ fmt.Sscanf(line[12:], "%q", &curFile.OldName)
659+ } else {
660+ curFile.OldName = line[12:]
661+ curFile.OldName = curFile.OldName[:len(curFile.OldName)-1]
662+ }
663+ case strings.HasPrefix(line, "rename to "):
664+ if line[10] == '"' {
665+ fmt.Sscanf(line[10:], "%q", &curFile.Name)
666+ } else {
667+ curFile.Name = line[10:]
668+ curFile.Name = curFile.Name[:len(curFile.Name)-1]
669+ }
670+ curFile.IsRenamed = true
671+ break loop
672+ case strings.HasPrefix(line, "copy from "):
673+ if line[10] == '"' {
674+ fmt.Sscanf(line[10:], "%q", &curFile.OldName)
675+ } else {
676+ curFile.OldName = line[10:]
677+ curFile.OldName = curFile.OldName[:len(curFile.OldName)-1]
678+ }
679+ case strings.HasPrefix(line, "copy to "):
680+ if line[8] == '"' {
681+ fmt.Sscanf(line[8:], "%q", &curFile.Name)
682+ } else {
683+ curFile.Name = line[8:]
684+ curFile.Name = curFile.Name[:len(curFile.Name)-1]
685+ }
686+ curFile.IsRenamed = true
687+ curFile.Type = DiffFileCopy
688+ break loop
689+ default:
690+ if strings.HasSuffix(line, " 160000\n") {
691+ curFile.IsSubmodule = true
692+ } else {
693+ break loop
694+ }
635695 }
636− break
637696 }
638697 }
639698 }