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
53 DiffFileChange53 DiffFileChange
54 DiffFileDel54 DiffFileDel
55 DiffFileRename55 DiffFileRename
56 DiffFileCopy
56)57)
57 58
58// DiffLineExpandDirection represents the DiffLineSection expand direction59// DiffLineExpandDirection represents the DiffLineSection expand direction
@@ -481,7 +482,46 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 422 unmodified lines
481 }482 }
482 line := linebuf.String()483 line := linebuf.String()
483 484
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 {
485 continue525 continue
486 }526 }
487 527
@@ -569,36 +609,10 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 81 unmodified lines
569 break609 break
570 }610 }
571 611
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
595 curFile = &DiffFile{612 curFile = &DiffFile{
596 Name: b,613 Index: len(diff.Files) + 1,
597 OldName: a,614 Type: DiffFileChange,
598 Index: len(diff.Files) + 1,615 Sections: make([]*DiffSection, 0, 10),
599 Type: DiffFileChange,
600 Sections: make([]*DiffSection, 0, 10),
601 IsRenamed: a != b,
602 }616 }
603 diff.Files = append(diff.Files, curFile)617 diff.Files = append(diff.Files, curFile)
604 curFileLinesCount = 0618 curFileLinesCount = 0
@@ -607,6 +621,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 2 unmodified lines
607 curFileLFSPrefix = false621 curFileLFSPrefix = false
608 622
609 // Check file diff type and is submodule.623 // Check file diff type and is submodule.
624 loop:
610 for {625 for {
611 line, err := input.ReadString('\n')626 line, err := input.ReadString('\n')
612 if err != nil {627 if err != nil {
@@ -617,23 +632,67 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 4 unmodified lines
617 }632 }
618 }633 }
619 634
620 switch {635 if curFile.Type != DiffFileRename {
621 case strings.HasPrefix(line, "new file"):636 switch {
622 curFile.Type = DiffFileAdd637 case strings.HasPrefix(line, "new file"):
623 curFile.IsCreated = true638 curFile.Type = DiffFileAdd
624 case strings.HasPrefix(line, "deleted"):639 curFile.IsCreated = true
625 curFile.Type = DiffFileDel640 case strings.HasPrefix(line, "deleted"):
626 curFile.IsDeleted = true641 curFile.Type = DiffFileDel
627 case strings.HasPrefix(line, "index"):642 curFile.IsDeleted = true
628 curFile.Type = DiffFileChange643 case strings.HasPrefix(line, "index"):
629 case strings.HasPrefix(line, "similarity index 100%"):644 curFile.Type = DiffFileChange
630 curFile.Type = DiffFileRename645 case strings.HasPrefix(line, "similarity index 100%"):
631 }646 curFile.Type = DiffFileRename
632 if curFile.Type > 0 {647 }
633 if strings.HasSuffix(line, " 160000\n") {648 if curFile.Type > 0 && curFile.Type != DiffFileRename {
634 curFile.IsSubmodule = true649 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 }
635 }695 }
636 break
637 }696 }
638 }697 }
639 }698 }