diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85 b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85 new file mode 100644 index 00000000000..a46c1925ece Binary files /dev/null and b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85 differ diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c new file mode 100644 index 00000000000..062641bee7d Binary files /dev/null and b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c differ diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master index 1b1d96a1f00..38984b12b78 100644 --- a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master +++ b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master @@ -1 +1 @@ -423313fbd38093bb10d0c8387db9105409c6f196 +0dca5bd9b5d7ef937710e056f575e86c0184ba85 diff --git a/modules/git/tree.go b/modules/git/tree.go index 059f0a8287d..3671f421e97 100644 --- a/modules/git/tree.go +++ b/modules/git/tree.go @@ -6,6 +6,7 @@ package git import ( + "bytes" "strings" ) @@ -45,3 +46,23 @@ func (t *Tree) SubTree(rpath string) (*Tree, error) { } return g, nil } + +// LsTree checks if the given filenames are in the tree +func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error) { + cmd := NewCommand("ls-tree", "-z", "--name-only", "--", ref) + for _, arg := range filenames { + if arg != "" { + cmd.AddArguments(arg) + } + } + res, err := cmd.RunInDirBytes(repo.Path) + if err != nil { + return nil, err + } + filelist := make([]string, 0, len(filenames)) + for _, line := range bytes.Split(res, []byte{'\000'}) { + filelist = append(filelist, string(line)) + } + + return filelist, err +} diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go index 8934a6619f0..bcdb8023acf 100644 --- a/routers/web/repo/wiki_test.go +++ b/routers/web/repo/wiki_test.go @@ -81,7 +81,7 @@ func TestWiki(t *testing.T) { Wiki(ctx) assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) assert.EqualValues(t, "Home", ctx.Data["Title"]) - assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name"}, ctx.Data["Pages"]) + assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name", "Unescaped File"}, ctx.Data["Pages"]) } func TestWikiPages(t *testing.T) { @@ -91,7 +91,7 @@ func TestWikiPages(t *testing.T) { test.LoadRepo(t, ctx, 1) WikiPages(ctx) assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) - assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name"}, ctx.Data["Pages"]) + assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name", "Unescaped File"}, ctx.Data["Pages"]) } func TestNewWiki(t *testing.T) { diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index 94f36ea2f25..f1632c6bf7a 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -88,7 +88,7 @@ func prepareWikiFileName(gitRepo *git.Repository, wikiName string) (bool, string escaped := NameToFilename(wikiName) // Look for both files - filesInIndex, err := gitRepo.LsFiles(unescaped, escaped) + filesInIndex, err := gitRepo.LsTree("master", unescaped, escaped) if err != nil { log.Error("%v", err) return false, escaped, err diff --git a/services/wiki/wiki_test.go b/services/wiki/wiki_test.go index b35b86d655b..a1614b509c2 100644 --- a/services/wiki/wiki_test.go +++ b/services/wiki/wiki_test.go @@ -210,3 +210,54 @@ func TestRepository_DeleteWikiPage(t *testing.T) { _, err = masterTree.GetTreeEntryByPath(wikiPath) assert.Error(t, err) } + +func TestPrepareWikiFileName(t *testing.T) { + models.PrepareTestEnv(t) + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + gitRepo, err := git.OpenRepository(repo.WikiPath()) + defer gitRepo.Close() + assert.NoError(t, err) + + tests := []struct { + name string + arg string + existence bool + wikiPath string + wantErr bool + }{{ + name: "add suffix", + arg: "Home", + existence: true, + wikiPath: "Home.md", + wantErr: false, + }, { + name: "test special chars", + arg: "home of and & or wiki page!", + existence: false, + wikiPath: "home-of-and-%26-or-wiki-page%21.md", + wantErr: false, + }, { + name: "fount unescaped cases", + arg: "Unescaped File", + existence: true, + wikiPath: "Unescaped File.md", + wantErr: false, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + existence, newWikiPath, err := prepareWikiFileName(gitRepo, tt.arg) + if (err != nil) != tt.wantErr { + assert.NoError(t, err) + return + } + if existence != tt.existence { + if existence { + t.Errorf("expect to find no escaped file but we detect one") + } else { + t.Errorf("expect to find an escaped file but we could not detect one") + } + } + assert.Equal(t, tt.wikiPath, newWikiPath) + }) + } +}