loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[GITEA] Find README.md for user profiles case insensitively

When trying to find a `README.md` in a `.profile` repo, do so case
insensitively. This change does not make it possible to render readmes
in formats other than Markdown, it just removes the hard-coded
"README.md".

Also adds a few tests to make sure the change works.

Fixes #1494.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
(cherry picked from commit edd219d8e9d69becb9814ab0a8359555e80fcd4f)
(cherry picked from commit 2c0105ef17b9673e6892a66aa689af7c5c87b8a1)
(cherry picked from commit 3975a9f3aaf8ed3ceb5788abc325dbe8e89225d3)
(cherry picked from commit dee4a18423151ac7f22221e6fce12d863921c200)
(cherry picked from commit 60aee6370fb15b12fffc6f29582dd4a235f87d94)

authored by

Gergely Nagy and committed by
Earl Warren
e019eb33 159dc74c

+142 -1
+21
modules/git/tree_blob.go
··· 1 1 // Copyright 2015 The Gogs Authors. All rights reserved. 2 2 // Copyright 2019 The Gitea Authors. All rights reserved. 3 + // Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved. 3 4 // SPDX-License-Identifier: MIT 4 5 5 6 package git 7 + 8 + import "strings" 6 9 7 10 // GetBlobByPath get the blob object according the path 8 11 func (t *Tree) GetBlobByPath(relpath string) (*Blob, error) { ··· 17 20 18 21 return nil, ErrNotExist{"", relpath} 19 22 } 23 + 24 + // GetBlobByFoldedPath returns the blob object at relpath, regardless of the 25 + // case of relpath. If there are multiple files with the same case-insensitive 26 + // name, the first one found will be returned. 27 + func (t *Tree) GetBlobByFoldedPath(relpath string) (*Blob, error) { 28 + entries, err := t.ListEntries() 29 + if err != nil { 30 + return nil, err 31 + } 32 + 33 + for _, entry := range entries { 34 + if strings.EqualFold(entry.Name(), relpath) { 35 + return t.GetBlobByPath(entry.Name()) 36 + } 37 + } 38 + 39 + return nil, ErrNotExist{"", relpath} 40 + }
+1 -1
routers/web/shared/user/header.go
··· 97 97 if commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch); err != nil { 98 98 log.Error("FindUserProfileReadme failed to GetBranchCommit: %v", err) 99 99 } else { 100 - profileReadmeBlob, _ = commit.GetBlobByPath("README.md") 100 + profileReadmeBlob, _ = commit.GetBlobByFoldedPath("README.md") 101 101 } 102 102 } 103 103 }
+120
tests/integration/user_profile_test.go
··· 1 + // Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved. 2 + // SPDX-License-Identifier: MIT 3 + 4 + package integration 5 + 6 + import ( 7 + "net/http" 8 + "net/url" 9 + "strings" 10 + "testing" 11 + "time" 12 + 13 + "code.gitea.io/gitea/models/db" 14 + "code.gitea.io/gitea/models/unittest" 15 + user_model "code.gitea.io/gitea/models/user" 16 + "code.gitea.io/gitea/modules/git" 17 + repo_service "code.gitea.io/gitea/services/repository" 18 + files_service "code.gitea.io/gitea/services/repository/files" 19 + "code.gitea.io/gitea/tests" 20 + 21 + "github.com/stretchr/testify/assert" 22 + ) 23 + 24 + func createProfileRepo(t *testing.T, readmeName string) func() { 25 + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 26 + 27 + // Create a new repository 28 + repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{ 29 + Name: ".profile", 30 + DefaultBranch: "main", 31 + IsPrivate: false, 32 + AutoInit: true, 33 + Readme: "Default", 34 + }) 35 + assert.NoError(t, err) 36 + assert.NotEmpty(t, repo) 37 + 38 + deleteInitialReadmeResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, 39 + &files_service.ChangeRepoFilesOptions{ 40 + Files: []*files_service.ChangeRepoFile{ 41 + { 42 + Operation: "delete", 43 + TreePath: "README.md", 44 + }, 45 + }, 46 + Message: "Delete the initial readme", 47 + Author: &files_service.IdentityOptions{ 48 + Name: user2.Name, 49 + Email: user2.Email, 50 + }, 51 + Committer: &files_service.IdentityOptions{ 52 + Name: user2.Name, 53 + Email: user2.Email, 54 + }, 55 + Dates: &files_service.CommitDateOptions{ 56 + Author: time.Now(), 57 + Committer: time.Now(), 58 + }, 59 + }) 60 + assert.NoError(t, err) 61 + assert.NotEmpty(t, deleteInitialReadmeResp) 62 + 63 + if readmeName != "" { 64 + addReadmeResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, 65 + &files_service.ChangeRepoFilesOptions{ 66 + Files: []*files_service.ChangeRepoFile{ 67 + { 68 + Operation: "create", 69 + TreePath: readmeName, 70 + ContentReader: strings.NewReader("# Hi!\n"), 71 + }, 72 + }, 73 + Message: "Add a readme", 74 + Author: &files_service.IdentityOptions{ 75 + Name: user2.Name, 76 + Email: user2.Email, 77 + }, 78 + Committer: &files_service.IdentityOptions{ 79 + Name: user2.Name, 80 + Email: user2.Email, 81 + }, 82 + Dates: &files_service.CommitDateOptions{ 83 + Author: time.Now(), 84 + Committer: time.Now(), 85 + }, 86 + }) 87 + 88 + assert.NoError(t, err) 89 + assert.NotEmpty(t, addReadmeResp) 90 + } 91 + 92 + return func() { 93 + repo_service.DeleteRepository(db.DefaultContext, user2, repo, false) 94 + } 95 + } 96 + 97 + func TestUserProfile(t *testing.T) { 98 + onGiteaRun(t, func(t *testing.T, u *url.URL) { 99 + checkReadme := func(t *testing.T, title, readmeFilename string, expectedCount int) { 100 + t.Run(title, func(t *testing.T) { 101 + defer tests.PrintCurrentTest(t)() 102 + defer createProfileRepo(t, readmeFilename)() 103 + 104 + req := NewRequest(t, "GET", "/user2") 105 + resp := MakeRequest(t, req, http.StatusOK) 106 + 107 + doc := NewHTMLParser(t, resp.Body) 108 + readmeCount := doc.Find("#readme_profile").Length() 109 + 110 + assert.Equal(t, expectedCount, readmeCount) 111 + }) 112 + } 113 + 114 + checkReadme(t, "No readme", "", 0) 115 + checkReadme(t, "README.md", "README.md", 1) 116 + checkReadme(t, "readme.md", "readme.md", 1) 117 + checkReadme(t, "ReadMe.mD", "ReadMe.mD", 1) 118 + checkReadme(t, "readme.org does not render", "README.org", 0) 119 + }) 120 + }