Skip to content

Commit 1f2ca31

Browse files
committed
fix
1 parent 5191149 commit 1f2ca31

File tree

7 files changed

+71
-89
lines changed

7 files changed

+71
-89
lines changed

models/unittest/fscopy.go

+14-32
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,13 @@ import (
1111
"code.gitea.io/gitea/modules/util"
1212
)
1313

14-
// Copy copies file from source to target path.
15-
func Copy(src, dest string) error {
16-
// Gather file information to set back later.
17-
si, err := os.Lstat(src)
18-
if err != nil {
19-
return err
20-
}
21-
22-
// Handle symbolic link.
23-
if si.Mode()&os.ModeSymlink != 0 {
24-
target, err := os.Readlink(src)
25-
if err != nil {
26-
return err
27-
}
28-
// NOTE: os.Chmod and os.Chtimes don't recognize symbolic link,
29-
// which will lead "no such file or directory" error.
30-
return os.Symlink(target, dest)
31-
}
32-
33-
return util.CopyFile(src, dest)
34-
}
35-
36-
// Sync synchronizes the two files. This is skipped if both files
14+
// SyncFile synchronizes the two files. This is skipped if both files
3715
// exist and the size, modtime, and mode match.
38-
func Sync(srcPath, destPath string) error {
16+
func SyncFile(srcPath, destPath string) error {
3917
dest, err := os.Stat(destPath)
4018
if err != nil {
4119
if os.IsNotExist(err) {
42-
return Copy(srcPath, destPath)
20+
return util.CopyFile(srcPath, destPath)
4321
}
4422
return err
4523
}
@@ -55,7 +33,7 @@ func Sync(srcPath, destPath string) error {
5533
return nil
5634
}
5735

58-
return Copy(srcPath, destPath)
36+
return util.CopyFile(srcPath, destPath)
5937
}
6038

6139
// SyncDirs synchronizes files recursively from source to target directory.
@@ -73,16 +51,20 @@ func SyncDirs(srcPath, destPath string) error {
7351
}
7452
for _, destFile := range destFiles {
7553
destFilePath := filepath.Join(destPath, destFile)
54+
shouldRemove := filepath.Base(destFilePath) == ".keep"
7655
if _, err = os.Stat(filepath.Join(srcPath, destFile)); err != nil {
7756
if os.IsNotExist(err) {
78-
// if src file does not exist, remove dest file
79-
if err = os.RemoveAll(destFilePath); err != nil {
80-
return err
81-
}
57+
shouldRemove = true
8258
} else {
8359
return err
8460
}
8561
}
62+
// if src file does not exist, remove dest file
63+
if shouldRemove {
64+
if err = os.RemoveAll(destFilePath); err != nil {
65+
return err
66+
}
67+
}
8668
}
8769

8870
// sync src files to dest
@@ -95,8 +77,8 @@ func SyncDirs(srcPath, destPath string) error {
9577
// util.ListDirRecursively appends a slash to the directory name
9678
if strings.HasSuffix(srcFile, "/") {
9779
err = os.MkdirAll(destFilePath, os.ModePerm)
98-
} else {
99-
err = Sync(filepath.Join(srcPath, srcFile), destFilePath)
80+
} else if filepath.Base(destFilePath) != ".keep" {
81+
err = SyncFile(filepath.Join(srcPath, srcFile), destFilePath)
10082
}
10183
if err != nil {
10284
return err

routers/web/repo/repo.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func MustBeNotEmpty(ctx *context.Context) {
5151

5252
// MustBeEditable check that repo can be edited
5353
func MustBeEditable(ctx *context.Context) {
54-
if !ctx.Repo.Repository.CanEnableEditor() || ctx.Repo.IsViewCommit {
54+
if !ctx.Repo.Repository.CanEnableEditor() {
5555
ctx.NotFound("", nil)
5656
return
5757
}

routers/web/repo/view_home.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ func handleRepoEmptyOrBroken(ctx *context.Context) {
249249
} else if reallyEmpty {
250250
showEmpty = true // the repo is really empty
251251
updateContextRepoEmptyAndStatus(ctx, true, repo_model.RepositoryReady)
252-
} else if ctx.Repo.Commit == nil {
252+
} else if branches, _, _ := ctx.Repo.GitRepo.GetBranches(0, 1); len(branches) == 0 {
253253
showEmpty = true // it is not really empty, but there is no branch
254254
// at the moment, other repo units like "actions" are not able to handle such case,
255255
// so we just mark the repo as empty to prevent from displaying these units.

routers/web/web.go

+31-33
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,6 @@ func registerRoutes(m *web.Router) {
818818

819819
reqRepoAdmin := context.RequireRepoAdmin()
820820
reqRepoCodeWriter := context.RequireUnitWriter(unit.TypeCode)
821-
canEnableEditor := context.CanEnableEditor()
822821
reqRepoReleaseWriter := context.RequireUnitWriter(unit.TypeReleases)
823822
reqRepoReleaseReader := context.RequireUnitReader(unit.TypeReleases)
824823
reqRepoIssuesOrPullsWriter := context.RequireUnitWriter(unit.TypeIssues, unit.TypePullRequests)
@@ -1153,7 +1152,7 @@ func registerRoutes(m *web.Router) {
11531152
// end "/{username}/{reponame}/settings"
11541153

11551154
// user/org home, including rss feeds
1156-
m.Get("/{username}/{reponame}", optSignIn, context.RepoAssignment, context.RepoRef(), repo.SetEditorconfigIfExists, repo.Home)
1155+
m.Get("/{username}/{reponame}", optSignIn, context.RepoAssignment, context.RepoRefByType(git.RefTypeBranch), repo.SetEditorconfigIfExists, repo.Home)
11571156

11581157
m.Post("/{username}/{reponame}/markup", optSignIn, context.RepoAssignment, reqUnitsWithMarkdown, web.Bind(structs.MarkupOption{}), misc.Markup)
11591158

@@ -1293,26 +1292,31 @@ func registerRoutes(m *web.Router) {
12931292
m.Group("/{username}/{reponame}", func() { // repo code
12941293
m.Group("", func() {
12951294
m.Group("", func() {
1296-
m.Combo("/_edit/*").Get(repo.EditFile).
1295+
m.Combo("/_edit/*").
1296+
Get(repo.EditFile).
12971297
Post(web.Bind(forms.EditRepoFileForm{}), repo.EditFilePost)
1298-
m.Combo("/_new/*").Get(repo.NewFile).
1298+
m.Combo("/_new/*").
1299+
Get(repo.NewFile).
12991300
Post(web.Bind(forms.EditRepoFileForm{}), repo.NewFilePost)
13001301
m.Post("/_preview/*", web.Bind(forms.EditPreviewDiffForm{}), repo.DiffPreviewPost)
1301-
m.Combo("/_delete/*").Get(repo.DeleteFile).
1302+
m.Combo("/_delete/*").
1303+
Get(repo.DeleteFile).
13021304
Post(web.Bind(forms.DeleteRepoFileForm{}), repo.DeleteFilePost)
13031305
m.Combo("/_upload/*", repo.MustBeAbleToUpload).
13041306
Get(repo.UploadFile).
13051307
Post(web.Bind(forms.UploadRepoFileForm{}), repo.UploadFilePost)
1306-
m.Combo("/_diffpatch/*").Get(repo.NewDiffPatch).
1308+
m.Combo("/_diffpatch/*").
1309+
Get(repo.NewDiffPatch).
13071310
Post(web.Bind(forms.EditRepoFileForm{}), repo.NewDiffPatchPost)
1308-
m.Combo("/_cherrypick/{sha:([a-f0-9]{7,64})}/*").Get(repo.CherryPick).
1311+
m.Combo("/_cherrypick/{sha:([a-f0-9]{7,64})}/*").
1312+
Get(repo.CherryPick).
13091313
Post(web.Bind(forms.CherryPickForm{}), repo.CherryPickPost)
1310-
}, repo.MustBeEditable)
1314+
}, context.RepoRefByType(git.RefTypeBranch), context.CanWriteToBranch())
13111315
m.Group("", func() {
13121316
m.Post("/upload-file", repo.UploadFileToServer)
13131317
m.Post("/upload-remove", web.Bind(forms.RemoveUploadFileForm{}), repo.RemoveUploadFileFromServer)
1314-
}, repo.MustBeEditable, repo.MustBeAbleToUpload)
1315-
}, context.RepoRef(), canEnableEditor, context.RepoMustNotBeArchived())
1318+
}, repo.MustBeAbleToUpload, reqRepoCodeWriter)
1319+
}, repo.MustBeEditable, context.RepoMustNotBeArchived())
13161320

13171321
m.Group("/branches", func() {
13181322
m.Group("/_new", func() {
@@ -1333,39 +1337,36 @@ func registerRoutes(m *web.Router) {
13331337
m.Group("/{username}/{reponame}", func() { // repo tags
13341338
m.Group("/tags", func() {
13351339
m.Get("", repo.TagsList)
1336-
m.Get("/list", repo.GetTagList)
13371340
m.Get(".rss", feedEnabled, repo.TagsListFeedRSS)
13381341
m.Get(".atom", feedEnabled, repo.TagsListFeedAtom)
1339-
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed),
1340-
repo.MustBeNotEmpty, context.RepoRefByType(git.RefTypeTag, context.RepoRefByTypeOptions{IgnoreNotExistErr: true}))
1341-
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
1342-
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
1343-
}, optSignIn, context.RepoAssignment, reqUnitCodeReader)
1342+
m.Get("/list", repo.GetTagList)
1343+
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed))
1344+
m.Post("/tags/delete", reqSignIn, reqRepoCodeWriter, context.RepoMustNotBeArchived(), repo.DeleteTag)
1345+
}, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqUnitCodeReader)
13441346
// end "/{username}/{reponame}": repo tags
13451347

13461348
m.Group("/{username}/{reponame}", func() { // repo releases
13471349
m.Group("/releases", func() {
13481350
m.Get("", repo.Releases)
1349-
m.Get("/tag/*", repo.SingleRelease)
1350-
m.Get("/latest", repo.LatestRelease)
13511351
m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS)
13521352
m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom)
1353-
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed),
1354-
repo.MustBeNotEmpty, context.RepoRefByType(git.RefTypeTag, context.RepoRefByTypeOptions{IgnoreNotExistErr: true}))
1355-
m.Get("/releases/attachments/{uuid}", repo.MustBeNotEmpty, repo.GetAttachment)
1356-
m.Get("/releases/download/{vTag}/{fileName}", repo.MustBeNotEmpty, repo.RedirectDownload)
1353+
m.Get("/tag/*", repo.SingleRelease)
1354+
m.Get("/latest", repo.LatestRelease)
1355+
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed))
1356+
m.Get("/releases/attachments/{uuid}", repo.GetAttachment)
1357+
m.Get("/releases/download/{vTag}/{fileName}", repo.RedirectDownload)
13571358
m.Group("/releases", func() {
13581359
m.Get("/new", repo.NewRelease)
13591360
m.Post("/new", web.Bind(forms.NewReleaseForm{}), repo.NewReleasePost)
13601361
m.Post("/delete", repo.DeleteRelease)
13611362
m.Post("/attachments", repo.UploadReleaseAttachment)
13621363
m.Post("/attachments/remove", repo.DeleteAttachment)
1363-
}, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, context.RepoRef())
1364+
}, reqSignIn, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, context.RepoRef())
13641365
m.Group("/releases", func() {
13651366
m.Get("/edit/*", repo.EditRelease)
13661367
m.Post("/edit/*", web.Bind(forms.EditReleaseForm{}), repo.EditReleasePost)
1367-
}, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, repo.CommitInfoCache)
1368-
}, optSignIn, context.RepoAssignment, reqRepoReleaseReader)
1368+
}, reqSignIn, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, repo.CommitInfoCache)
1369+
}, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqRepoReleaseReader)
13691370
// end "/{username}/{reponame}": repo releases
13701371

13711372
m.Group("/{username}/{reponame}", func() { // to maintain compatibility with old attachments
@@ -1529,21 +1530,19 @@ func registerRoutes(m *web.Router) {
15291530
}, repo.MustBeNotEmpty, context.RepoRef())
15301531

15311532
m.Group("/media", func() {
1533+
m.Get("/blob/{sha}", repo.DownloadByIDOrLFS)
15321534
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.SingleDownloadOrLFS)
15331535
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.SingleDownloadOrLFS)
15341536
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.SingleDownloadOrLFS)
1535-
m.Get("/blob/{sha}", repo.DownloadByIDOrLFS)
1536-
// "/*" route is deprecated, and kept for backward compatibility
1537-
m.Get("/*", context.RepoRefByType(""), repo.SingleDownloadOrLFS)
1537+
m.Get("/*", context.RepoRefByType(""), repo.SingleDownloadOrLFS) // "/*" route is deprecated, and kept for backward compatibility
15381538
}, repo.MustBeNotEmpty)
15391539

15401540
m.Group("/raw", func() {
1541+
m.Get("/blob/{sha}", repo.DownloadByID)
15411542
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.SingleDownload)
15421543
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.SingleDownload)
15431544
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.SingleDownload)
1544-
m.Get("/blob/{sha}", repo.DownloadByID)
1545-
// "/*" route is deprecated, and kept for backward compatibility
1546-
m.Get("/*", context.RepoRefByType(""), repo.SingleDownload)
1545+
m.Get("/*", context.RepoRefByType(""), repo.SingleDownload) // "/*" route is deprecated, and kept for backward compatibility
15471546
}, repo.MustBeNotEmpty)
15481547

15491548
m.Group("/render", func() {
@@ -1557,8 +1556,7 @@ func registerRoutes(m *web.Router) {
15571556
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.RefCommits)
15581557
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.RefCommits)
15591558
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.RefCommits)
1560-
// "/*" route is deprecated, and kept for backward compatibility
1561-
m.Get("/*", context.RepoRefByType(""), repo.RefCommits)
1559+
m.Get("/*", context.RepoRefByType(""), repo.RefCommits) // "/*" route is deprecated, and kept for backward compatibility
15621560
}, repo.MustBeNotEmpty)
15631561

15641562
m.Group("/blame", func() {

services/context/permission.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ func RequireRepoAdmin() func(ctx *Context) {
2121
}
2222
}
2323

24-
// CanEnableEditor checks if the user is allowed to write to the branch of the repo
25-
func CanEnableEditor() func(ctx *Context) {
24+
// CanWriteToBranch checks if the user is allowed to write to the branch of the repo
25+
func CanWriteToBranch() func(ctx *Context) {
2626
return func(ctx *Context) {
2727
if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) {
2828
ctx.NotFound("CanWriteToBranch denies permission", nil)

services/context/repo.go

+5-20
Original file line numberDiff line numberDiff line change
@@ -679,10 +679,11 @@ func RepoAssignment(ctx *Context) {
679679

680680
const headRefName = "HEAD"
681681

682-
// RepoRef handles repository reference names when the ref name is not
683-
// explicitly given
684682
func RepoRef() func(*Context) {
685-
// since no ref name is explicitly specified, ok to just use branch
683+
if !setting.IsProd || setting.IsInTesting {
684+
// RepoRef should not be used, the handler should explicit use the ref it needs
685+
return nil
686+
}
686687
return RepoRefByType(git.RefTypeBranch)
687688
}
688689

@@ -776,10 +777,6 @@ func getRefName(ctx *Base, repo *Repository, path string, refType git.RefType) s
776777
return ""
777778
}
778779

779-
type RepoRefByTypeOptions struct {
780-
IgnoreNotExistErr bool
781-
}
782-
783780
func repoRefFullName(typ git.RefType, shortName string) git.RefName {
784781
switch typ {
785782
case git.RefTypeBranch:
@@ -796,8 +793,7 @@ func repoRefFullName(typ git.RefType, shortName string) git.RefName {
796793

797794
// RepoRefByType handles repository reference name for a specific type
798795
// of repository reference
799-
func RepoRefByType(detectRefType git.RefType, opts ...RepoRefByTypeOptions) func(*Context) {
800-
opt := util.OptionalArg(opts)
796+
func RepoRefByType(detectRefType git.RefType) func(*Context) {
801797
return func(ctx *Context) {
802798
var err error
803799
refType := detectRefType
@@ -813,14 +809,6 @@ func RepoRefByType(detectRefType git.RefType, opts ...RepoRefByTypeOptions) func
813809
return
814810
}
815811

816-
if ctx.Repo.GitRepo == nil {
817-
ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository)
818-
if err != nil {
819-
ctx.ServerError(fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err)
820-
return
821-
}
822-
}
823-
824812
// Get default branch.
825813
var refShortName string
826814
reqPath := ctx.PathParam("*")
@@ -908,9 +896,6 @@ func RepoRefByType(detectRefType git.RefType, opts ...RepoRefByTypeOptions) func
908896
ctx.RespHeader().Set("Link", fmt.Sprintf(`<%s>; rel="canonical"`, canonicalURL))
909897
}
910898
} else {
911-
if opt.IgnoreNotExistErr {
912-
return
913-
}
914899
ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refShortName))
915900
return
916901
}

tests/integration/empty_repo_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"testing"
1515

1616
auth_model "code.gitea.io/gitea/models/auth"
17+
"code.gitea.io/gitea/models/db"
1718
repo_model "code.gitea.io/gitea/models/repo"
1819
"code.gitea.io/gitea/models/unittest"
1920
user_model "code.gitea.io/gitea/models/user"
@@ -24,6 +25,7 @@ import (
2425
"code.gitea.io/gitea/tests"
2526

2627
"github.com/stretchr/testify/assert"
28+
"github.com/stretchr/testify/require"
2729
)
2830

2931
func testAPINewFile(t *testing.T, session *TestSession, user, repo, branch, treePath, content string) *httptest.ResponseRecorder {
@@ -82,6 +84,21 @@ func TestEmptyRepoAddFile(t *testing.T) {
8284
req = NewRequest(t, "GET", redirect)
8385
resp = session.MakeRequest(t, req, http.StatusOK)
8486
assert.Contains(t, resp.Body.String(), "newly-added-test-file")
87+
88+
// the repo is not empty anymore
89+
req = NewRequest(t, "GET", "/user30/empty")
90+
resp = session.MakeRequest(t, req, http.StatusOK)
91+
assert.Contains(t, resp.Body.String(), "test-file.md")
92+
93+
// if the repo is in incorrect state, it should be able to self-heal (recover to correct state)
94+
user30EmptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 30, Name: "empty"})
95+
user30EmptyRepo.IsEmpty = true
96+
user30EmptyRepo.DefaultBranch = "no-such"
97+
_, err := db.GetEngine(db.DefaultContext).ID(user30EmptyRepo.ID).Update(user30EmptyRepo)
98+
require.NoError(t, err)
99+
req = NewRequest(t, "GET", "/user30/empty")
100+
resp = session.MakeRequest(t, req, http.StatusOK)
101+
assert.Contains(t, resp.Body.String(), "test-file.md")
85102
}
86103

87104
func TestEmptyRepoUploadFile(t *testing.T) {

0 commit comments

Comments
 (0)