* 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 | 484 | line := linebuf.String() |
| 485 | 485 | |
| 486 | − if strings.HasPrefix(line, "--- ") { | |
| 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 { | |
| 486 | + if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") || len(line) == 0 { | |
| 526 | 487 | continue |
| 527 | 488 | } |
| 528 | 489 | |
| @@ -610,10 +571,42 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 81 unmodified lines | ||
| 610 | 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 | 603 | curFile = &DiffFile{ |
| 614 | − Index: len(diff.Files) + 1, | |
| 615 | − Type: DiffFileChange, | |
| 616 | − Sections: make([]*DiffSection, 0, 10), | |
| 604 | + Name: b, | |
| 605 | + OldName: a, | |
| 606 | + Index: len(diff.Files) + 1, | |
| 607 | + Type: DiffFileChange, | |
| 608 | + Sections: make([]*DiffSection, 0, 10), | |
| 609 | + IsRenamed: a != b, | |
| 617 | 610 | } |
| 618 | 611 | diff.Files = append(diff.Files, curFile) |
| 619 | 612 | curFileLinesCount = 0 |
| @@ -622,7 +615,6 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 2 unmodified lines | ||
| 622 | 615 | curFileLFSPrefix = false |
| 623 | 616 | |
| 624 | 617 | // Check file diff type and is submodule. |
| 625 | − loop: | |
| 626 | 618 | for { |
| 627 | 619 | line, err := input.ReadString('\n') |
| 628 | 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 { | |
| 637 | − switch { | |
| 638 | − case strings.HasPrefix(line, "new file"): | |
| 639 | − curFile.Type = DiffFileAdd | |
| 640 | − curFile.IsCreated = true | |
| 641 | − case strings.HasPrefix(line, "deleted"): | |
| 642 | − curFile.Type = DiffFileDel | |
| 643 | − curFile.IsDeleted = true | |
| 644 | − case strings.HasPrefix(line, "index"): | |
| 645 | − curFile.Type = DiffFileChange | |
| 646 | − case strings.HasPrefix(line, "similarity index 100%"): | |
| 647 | − curFile.Type = DiffFileRename | |
| 648 | − } | |
| 649 | − if curFile.Type > 0 && curFile.Type != DiffFileRename { | |
| 650 | − if strings.HasSuffix(line, " 160000\n") { | |
| 651 | − curFile.IsSubmodule = true | |
| 652 | − } | |
| 653 | − break | |
| 654 | − } | |
| 655 | − } else { | |
| 656 | − switch { | |
| 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 | − } | |
| 628 | + switch { | |
| 629 | + case strings.HasPrefix(line, "copy from "): | |
| 630 | + curFile.IsRenamed = true | |
| 631 | + curFile.Type = DiffFileCopy | |
| 632 | + case strings.HasPrefix(line, "copy to "): | |
| 633 | + curFile.IsRenamed = true | |
| 634 | + curFile.Type = DiffFileCopy | |
| 635 | + case strings.HasPrefix(line, "new file"): | |
| 636 | + curFile.Type = DiffFileAdd | |
| 637 | + curFile.IsCreated = true | |
| 638 | + case strings.HasPrefix(line, "deleted"): | |
| 639 | + curFile.Type = DiffFileDel | |
| 640 | + curFile.IsDeleted = true | |
| 641 | + case strings.HasPrefix(line, "index"): | |
| 642 | + curFile.Type = DiffFileChange | |
| 643 | + case strings.HasPrefix(line, "similarity index 100%"): | |
| 644 | + curFile.Type = DiffFileRename | |
| 645 | + } | |
| 646 | + if curFile.Type > 0 { | |
| 647 | + if strings.HasSuffix(line, " 160000\n") { | |
| 648 | + curFile.IsSubmodule = true | |
| 696 | 649 | } |
| 650 | + break | |
| 697 | 651 | } |
| 698 | 652 | } |
| 699 | 653 | } |
| @@ -762,7 +716,7 @@ func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID · 62 unmodified lines | ||
| 762 | 716 | parentCommit, _ := commit.Parent(0) |
| 763 | 717 | actualBeforeCommitID = parentCommit.ID.String() |
| 764 | 718 | } |
| 765 | − diffArgs := []string{"diff", "-M"} | |
| 719 | + diffArgs := []string{"diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"} | |
| 766 | 720 | if len(whitespaceBehavior) != 0 { |
| 767 | 721 | diffArgs = append(diffArgs, whitespaceBehavior) |
| 768 | 722 | } |