Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Open a deleted file instead of failing the page

bef0c093da662024c936eb2c230cf2a3521ecbb9 · Keenan Nemetz · 8d ago · parent f64c77e4

Open a deleted file instead of failing the page

A deletion has an old path and no new one, and pathspec returned both sides to
git. Git refuses an empty pathspec outright, so opening a deleted file on a
commit page answered 500 and the file could not be reviewed at all. The per-file
read this branch gives the Files tab would have extended that to every deleted
file in a change.

Return one path for a deletion, both only for a rename, and none when a row has
no paths at all. No paths means there is no patch to ask for, which is not the
same as every path: callers stop before asking git instead of printing the whole
commit into a single file's pane.

TestPathspecNamesTheSideThatExists pins the four shapes, and
TestCommitPageShowsADeletedFile is the page that used to 500. The request Files
test now carries a deletion too, and opens it.

server/issues_changes_test.go +18−2

@@ -718,6 +718,14 @@ func TestRequestFilesListsEveryChangedFile(t *testing.T) {
718 718 files[name] = name + "\n"
719 719 }
720 720 feature, _ := f.cloneWithChange(t, files, "a big change")
721 // A deletion rides along: it has one path and no new one, which is the shape
722 // that used to make the page fail when it was opened.
723 if _, errs, err := runGit(t, feature, "rm", "-q", "readme.md"); err != nil {
724 t.Fatalf("rm: %s", errs)
725 }
726 if _, errs, err := runGit(t, feature, "commit", "-qm", "drop the readme"); err != nil {
727 t.Fatalf("commit: %s", errs)
728 }
721 729 if _, errs, err := f.git(feature, "push", f.sshURL(f.repo), "HEAD:refs/heads/feature"); err != nil {
722 730 t.Fatalf("feature push: %s", errs)
723 731 }
@@ -733,10 +741,10 @@ func TestRequestFilesListsEveryChangedFile(t *testing.T) {
733 741
734 742 filesURL := "/r/" + f.repo + "/requests/" + id + "/files"
735 743 _, page := f.browserGet(t, filesURL, cookie)
736 if !strings.Contains(page, "4 changed") {
744 if !strings.Contains(page, "5 changed") {
737 745 t.Errorf("the tree does not count every file:\n%.2000s", page)
738 746 }
739 for _, name := range []string{"a-big.txt", "b.txt", "docs/c.txt", "z.txt"} {
747 for _, name := range []string{"a-big.txt", "b.txt", "docs/c.txt", "readme.md", "z.txt"} {
740 748 if !strings.Contains(page, filesURL+"/"+name) {
741 749 t.Errorf("the tree is missing %s:\n%.2000s", name, page)
742 750 }
@@ -747,6 +755,14 @@ func TestRequestFilesListsEveryChangedFile(t *testing.T) {
747 755 !strings.Contains(page, `data-highlight-side="new">z.txt<`) {
748 756 t.Fatalf("the selected file has no patch:\n%.2000s", page)
749 757 }
758 // The deletion opens too: one path, no new one, and its removed lines.
759 resp, page = f.browserGet(t, filesURL+"/readme.md", cookie)
760 if resp.StatusCode != http.StatusOK {
761 t.Fatalf("deleted file = %d:\n%.2000s", resp.StatusCode, page)
762 }
763 if !strings.Contains(page, `data-highlight-side="old">v1<`) {
764 t.Fatalf("the deleted file has no patch:\n%.2000s", page)
765 }
750 766 }
751 767
752 768 func TestLineAnchoredReviewCommentFromTheWeb(t *testing.T) {