diff --git a/conf/app.ini b/conf/app.ini index 3333434230fad..db0d457b24def 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -49,6 +49,8 @@ ALLOWED_TYPES = FILE_MAX_SIZE = 3 ; Max number of files per upload. Defaults to 5 MAX_FILES = 5 +; Create repository on upload if it doesn't exists +AUTO_CREATE = false [ui] ; Number of repositories that are showed in one explore page diff --git a/integrations/repo_test.go b/integrations/repo_test.go index 8465bbdc5aa62..64b2cb3fa6f5f 100644 --- a/integrations/repo_test.go +++ b/integrations/repo_test.go @@ -10,6 +10,7 @@ import ( "testing" "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/sdk/gitea" "github.com/stretchr/testify/assert" ) @@ -74,3 +75,45 @@ func TestViewRepo1CloneLinkAuthorized(t *testing.T) { sshURL := fmt.Sprintf("%s@%s:user2/repo1.git", setting.RunUser, setting.SSH.Domain) assert.Equal(t, sshURL, link) } + +func TestAutoCreateRepo(t *testing.T) { + prepareTestEnv(t) + + session := loginUser(t, "user2") + + // repo should not exist + req := NewRequest(t, "GET", "/api/v1/repos/user2/autocreated") + MakeRequest(t, req, http.StatusNotFound) + + // + // if 'AUTO_CREATE = false', the repo should not be created if it doesn't exist + // + setting.Repository.Upload.AutoCreate = false + req = NewRequest(t, "GET", "/user2/autocreated.git/info/refs?service=git-receive-pack") + session.MakeRequest(t, req, http.StatusNotFound) + + req = NewRequest(t, "GET", "/api/v1/repos/user2/autocreated") + MakeRequest(t, req, http.StatusNotFound) + + // + // if 'AUTO_CREATE = true', the repos should be created + // + setting.Repository.Upload.AutoCreate = true + req = NewRequest(t, "GET", "/user2/autocreated.git/info/refs?service=git-receive-pack") + // we don't get a successful response code here, because we don't execute a real 'git push ...' + session.MakeRequest(t, req, NoExpectedStatus) + + // repo should exist + req = NewRequest(t, "GET", "/api/v1/repos/user2/autocreated") + resp := MakeRequest(t, req, http.StatusOK) + + var repo api.Repository + DecodeJSON(t, resp, &repo) + assert.Equal(t, repo.Name, "autocreated") + + // + // cleanup + // + req = NewRequest(t, "DELETE", "/api/v1/repos/user2/autocreated") + session.MakeRequest(t, req, http.StatusNoContent) +} diff --git a/modules/setting/setting.go b/modules/setting/setting.go index a5908bacaa057..1fe38e143a665 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -176,6 +176,7 @@ var ( AllowedTypes []string `delim:"|"` FileMaxSize int64 MaxFiles int + AutoCreate bool } `ini:"-"` // Repository local settings @@ -208,12 +209,14 @@ var ( AllowedTypes []string `delim:"|"` FileMaxSize int64 MaxFiles int + AutoCreate bool }{ Enabled: true, TempPath: "data/tmp/uploads", AllowedTypes: []string{}, FileMaxSize: 3, MaxFiles: 5, + AutoCreate: false, }, // Repository local settings diff --git a/routers/repo/http.go b/routers/repo/http.go index 4265c80ac49d6..31791108eb63b 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -95,6 +95,13 @@ func HTTP(ctx *context.Context) { } repo, err := models.GetRepositoryByName(repoUser.ID, reponame) + if models.IsErrRepoNotExist(err) && setting.Repository.Upload.AutoCreate { + + // if 'CreateRepository' fails, the error are handled in the next 'if err != nil' block + repo, err = models.CreateRepository(repoUser, repoUser, models.CreateRepoOptions{ + Name: reponame, + }) + } if err != nil { if models.IsErrRepoNotExist(err) { ctx.Handle(http.StatusNotFound, "GetRepositoryByName", nil)