* Finally fix diff names #12771 attempted to fix diff by avoiding the git diff line as it is possible to have an ambiguous line here. #12254 attempted to fix diff by assuming that names would quoted if they needed to be and if one was quoted then both would be. Both of these were wrong. I have now discovered `--src-prefix` and `--dst-prefix` which means that we can set this in such a way to force the git diff to always be unambiguous. Therefore this PR rollsback most of the changes in #12771 and uses these options to fix this. Signed-off-by: Andrew Thornton <art27@cantab.net> * Update services/gitdiff/gitdiff.go * Update services/gitdiff/gitdiff.go * Update modules/repofiles/temp_repo.go * fix test Signed-off-by: Andrew Thornton <art27@cantab.net>
Showing the changes to services/gitdiff/gitdiff.go (1 of 3 files). Show all
Unified · Split
| @@ -483,46 +483,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 482 unmodified lines | |||
| 483 | } | 483 | } |
| 484 | line := linebuf.String() | 484 | line := linebuf.String() |
| 485 | 485 | ||
| 486 | if strings.HasPrefix(line, "--- ") { | 486 | if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") || len(line) == 0 { |
| 487 | if line[4] == '"' { | ||
| 488 | fmt.Sscanf(line[4:], "%q", &curFile.OldName) | ||
| 489 | } else { | ||
| 490 | curFile.OldName = line[4:] | ||
| 491 | if strings.Contains(curFile.OldName, " ") { | ||
| 492 | // Git adds a terminal \t if there is a space in the name | ||
| 493 | curFile.OldName = curFile.OldName[:len(curFile.OldName)-1] | ||
| 494 | } | ||
| 495 | } | ||
| 496 | if curFile.OldName[0:2] == "a/" { | ||
| 497 | curFile.OldName = curFile.OldName[2:] | ||
| 498 | } | ||
| 499 | continue | ||
| 500 | } else if strings.HasPrefix(line, "+++ ") { | ||
| 501 | if line[4] == '"' { | ||
| 502 | fmt.Sscanf(line[4:], "%q", &curFile.Name) | ||
| 503 | } else { | ||
| 504 | curFile.Name = line[4:] | ||
| 505 | if strings.Contains(curFile.Name, " ") { | ||
| 506 | // Git adds a terminal \t if there is a space in the name | ||
| 507 | curFile.Name = curFile.Name[:len(curFile.Name)-1] | ||
| 508 | } | ||
| 509 | } | ||
| 510 | if curFile.Name[0:2] == "b/" { | ||
| 511 | curFile.Name = curFile.Name[2:] | ||
| 512 | } | ||
| 513 | curFile.IsRenamed = (curFile.Name != curFile.OldName) && !(curFile.IsCreated || curFile.IsDeleted) | ||
| 514 | if curFile.IsDeleted { | ||
| 515 | curFile.Name = curFile.OldName | ||
| 516 | curFile.OldName = "" | ||
| 517 | } else if curFile.IsCreated { | ||
| 518 | curFile.OldName = "" | ||
| 519 | } | ||
| 520 | continue | ||
| 521 | } else if len(line) == 0 { | ||
| 522 | continue | ||
| 523 | } | ||
| 524 | |||
| 525 | if strings.HasPrefix(line, "+++") || strings.HasPrefix(line, "---") || len(line) == 0 { | ||
| 526 | continue | 487 | continue |
| 527 | } | 488 | } |
| 528 | 489 | ||
| @@ -610,10 +571,42 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 81 unmodified lines | |||
| 610 | break | 571 | break |
| 611 | } | 572 | } |
| 612 | 573 | ||
| 574 | // Note: In case file name is surrounded by double quotes (it happens only in git-shell). | ||
| 575 | // e.g. diff --git "a/xxx" "b/xxx" | ||
| 576 | var a string | ||
| 577 | var b string | ||
| 578 | |||
| 579 | rd := strings.NewReader(line[len(cmdDiffHead):]) | ||
| 580 | char, _ := rd.ReadByte() | ||
| 581 | _ = rd.UnreadByte() | ||
| 582 | if char == '"' { | ||
| 583 | fmt.Fscanf(rd, "%q ", &a) | ||
| 584 | if a[0] == '\\' { | ||
| 585 | a = a[1:] | ||
| 586 | } | ||
| 587 | } else { | ||
| 588 | fmt.Fscanf(rd, "%s ", &a) | ||
| 589 | } | ||
| 590 | char, _ = rd.ReadByte() | ||
| 591 | _ = rd.UnreadByte() | ||
| 592 | if char == '"' { | ||
| 593 | fmt.Fscanf(rd, "%q", &b) | ||
| 594 | if b[0] == '\\' { | ||
| 595 | b = b[1:] | ||
| 596 | } | ||
| 597 | } else { | ||
| 598 | fmt.Fscanf(rd, "%s", &b) | ||
| 599 | } | ||
| 600 | a = a[2:] | ||
| 601 | b = b[2:] | ||
| 602 | |||
| 613 | curFile = &DiffFile{ | 603 | curFile = &DiffFile{ |
| 614 | Index: len(diff.Files) + 1, | 604 | Name: b, |
| 615 | Type: DiffFileChange, | 605 | OldName: a, |
| 616 | Sections: make([]*DiffSection, 0, 10), | 606 | Index: len(diff.Files) + 1, |
| 607 | Type: DiffFileChange, | ||
| 608 | Sections: make([]*DiffSection, 0, 10), | ||
| 609 | IsRenamed: a != b, | ||
| 617 | } | 610 | } |
| 618 | diff.Files = append(diff.Files, curFile) | 611 | diff.Files = append(diff.Files, curFile) |
| 619 | curFileLinesCount = 0 | 612 | curFileLinesCount = 0 |
| @@ -622,7 +615,6 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 2 unmodified lines | |||
| 622 | curFileLFSPrefix = false | 615 | curFileLFSPrefix = false |
| 623 | 616 | ||
| 624 | // Check file diff type and is submodule. | 617 | // Check file diff type and is submodule. |
| 625 | loop: | ||
| 626 | for { | 618 | for { |
| 627 | line, err := input.ReadString('\n') | 619 | line, err := input.ReadString('\n') |
| 628 | if err != nil { | 620 | if err != nil { |
| @@ -633,67 +625,29 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 4 unmodified lines | |||
| 633 | } | 625 | } |
| 634 | } | 626 | } |
| 635 | 627 | ||
| 636 | if curFile.Type != DiffFileRename { | 628 | switch { |
| 637 | switch { | 629 | case strings.HasPrefix(line, "copy from "): |
| 638 | case strings.HasPrefix(line, "new file"): | 630 | curFile.IsRenamed = true |
| 639 | curFile.Type = DiffFileAdd | 631 | curFile.Type = DiffFileCopy |
| 640 | curFile.IsCreated = true | 632 | case strings.HasPrefix(line, "copy to "): |
| 641 | case strings.HasPrefix(line, "deleted"): | 633 | curFile.IsRenamed = true |
| 642 | curFile.Type = DiffFileDel | 634 | curFile.Type = DiffFileCopy |
| 643 | curFile.IsDeleted = true | 635 | case strings.HasPrefix(line, "new file"): |
| 644 | case strings.HasPrefix(line, "index"): | 636 | curFile.Type = DiffFileAdd |
| 645 | curFile.Type = DiffFileChange | 637 | curFile.IsCreated = true |
| 646 | case strings.HasPrefix(line, "similarity index 100%"): | 638 | case strings.HasPrefix(line, "deleted"): |
| 647 | curFile.Type = DiffFileRename | 639 | curFile.Type = DiffFileDel |
| 648 | } | 640 | curFile.IsDeleted = true |
| 649 | if curFile.Type > 0 && curFile.Type != DiffFileRename { | 641 | case strings.HasPrefix(line, "index"): |
| 650 | if strings.HasSuffix(line, " 160000\n") { | 642 | curFile.Type = DiffFileChange |
| 651 | curFile.IsSubmodule = true | 643 | case strings.HasPrefix(line, "similarity index 100%"): |
| 652 | } | 644 | curFile.Type = DiffFileRename |
| 653 | break | 645 | } |
| 654 | } | 646 | if curFile.Type > 0 { |
| 655 | } else { | 647 | if strings.HasSuffix(line, " 160000\n") { |
| 656 | switch { | 648 | curFile.IsSubmodule = true |
| 657 | case strings.HasPrefix(line, "rename from "): | ||
| 658 | if line[12] == '"' { | ||
| 659 | fmt.Sscanf(line[12:], "%q", &curFile.OldName) | ||
| 660 | } else { | ||
| 661 | curFile.OldName = line[12:] | ||
| 662 | curFile.OldName = curFile.OldName[:len(curFile.OldName)-1] | ||
| 663 | } | ||
| 664 | case strings.HasPrefix(line, "rename to "): | ||
| 665 | if line[10] == '"' { | ||
| 666 | fmt.Sscanf(line[10:], "%q", &curFile.Name) | ||
| 667 | } else { | ||
| 668 | curFile.Name = line[10:] | ||
| 669 | curFile.Name = curFile.Name[:len(curFile.Name)-1] | ||
| 670 | } | ||
| 671 | curFile.IsRenamed = true | ||
| 672 | break loop | ||
| 673 | case strings.HasPrefix(line, "copy from "): | ||
| 674 | if line[10] == '"' { | ||
| 675 | fmt.Sscanf(line[10:], "%q", &curFile.OldName) | ||
| 676 | } else { | ||
| 677 | curFile.OldName = line[10:] | ||
| 678 | curFile.OldName = curFile.OldName[:len(curFile.OldName)-1] | ||
| 679 | } | ||
| 680 | case strings.HasPrefix(line, "copy to "): | ||
| 681 | if line[8] == '"' { | ||
| 682 | fmt.Sscanf(line[8:], "%q", &curFile.Name) | ||
| 683 | } else { | ||
| 684 | curFile.Name = line[8:] | ||
| 685 | curFile.Name = curFile.Name[:len(curFile.Name)-1] | ||
| 686 | } | ||
| 687 | curFile.IsRenamed = true | ||
| 688 | curFile.Type = DiffFileCopy | ||
| 689 | break loop | ||
| 690 | default: | ||
| 691 | if strings.HasSuffix(line, " 160000\n") { | ||
| 692 | curFile.IsSubmodule = true | ||
| 693 | } else { | ||
| 694 | break loop | ||
| 695 | } | ||
| 696 | } | 649 | } |
| 650 | break | ||
| 697 | } | 651 | } |
| 698 | } | 652 | } |
| 699 | } | 653 | } |
| @@ -762,7 +716,7 @@ func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID · 62 unmodified lines | |||
| 762 | parentCommit, _ := commit.Parent(0) | 716 | parentCommit, _ := commit.Parent(0) |
| 763 | actualBeforeCommitID = parentCommit.ID.String() | 717 | actualBeforeCommitID = parentCommit.ID.String() |
| 764 | } | 718 | } |
| 765 | diffArgs := []string{"diff", "-M"} | 719 | diffArgs := []string{"diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"} |
| 766 | if len(whitespaceBehavior) != 0 { | 720 | if len(whitespaceBehavior) != 0 { |
| 767 | diffArgs = append(diffArgs, whitespaceBehavior) | 721 | diffArgs = append(diffArgs, whitespaceBehavior) |
| 768 | } | 722 | } |