Skip to content

Commit b9df9fa

Browse files
authored
Move createrepository from module to service layer (#26927)
Repository creation depends on many models, so moving it to service layer is better.
1 parent b3d88ad commit b9df9fa

26 files changed

+510
-482
lines changed

modules/repository/create.go

-137
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"code.gitea.io/gitea/models/unit"
2323
user_model "code.gitea.io/gitea/models/user"
2424
"code.gitea.io/gitea/models/webhook"
25-
"code.gitea.io/gitea/modules/git"
2625
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
2726
"code.gitea.io/gitea/modules/log"
2827
"code.gitea.io/gitea/modules/setting"
@@ -156,142 +155,6 @@ func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, re
156155
return nil
157156
}
158157

159-
// CreateRepoOptions contains the create repository options
160-
type CreateRepoOptions struct {
161-
Name string
162-
Description string
163-
OriginalURL string
164-
GitServiceType api.GitServiceType
165-
Gitignores string
166-
IssueLabels string
167-
License string
168-
Readme string
169-
DefaultBranch string
170-
IsPrivate bool
171-
IsMirror bool
172-
IsTemplate bool
173-
AutoInit bool
174-
Status repo_model.RepositoryStatus
175-
TrustModel repo_model.TrustModelType
176-
MirrorInterval string
177-
}
178-
179-
// CreateRepository creates a repository for the user/organization.
180-
func CreateRepository(doer, u *user_model.User, opts CreateRepoOptions) (*repo_model.Repository, error) {
181-
if !doer.IsAdmin && !u.CanCreateRepo() {
182-
return nil, repo_model.ErrReachLimitOfRepo{
183-
Limit: u.MaxRepoCreation,
184-
}
185-
}
186-
187-
if len(opts.DefaultBranch) == 0 {
188-
opts.DefaultBranch = setting.Repository.DefaultBranch
189-
}
190-
191-
// Check if label template exist
192-
if len(opts.IssueLabels) > 0 {
193-
if _, err := LoadTemplateLabelsByDisplayName(opts.IssueLabels); err != nil {
194-
return nil, err
195-
}
196-
}
197-
198-
repo := &repo_model.Repository{
199-
OwnerID: u.ID,
200-
Owner: u,
201-
OwnerName: u.Name,
202-
Name: opts.Name,
203-
LowerName: strings.ToLower(opts.Name),
204-
Description: opts.Description,
205-
OriginalURL: opts.OriginalURL,
206-
OriginalServiceType: opts.GitServiceType,
207-
IsPrivate: opts.IsPrivate,
208-
IsFsckEnabled: !opts.IsMirror,
209-
IsTemplate: opts.IsTemplate,
210-
CloseIssuesViaCommitInAnyBranch: setting.Repository.DefaultCloseIssuesViaCommitsInAnyBranch,
211-
Status: opts.Status,
212-
IsEmpty: !opts.AutoInit,
213-
TrustModel: opts.TrustModel,
214-
IsMirror: opts.IsMirror,
215-
DefaultBranch: opts.DefaultBranch,
216-
}
217-
218-
var rollbackRepo *repo_model.Repository
219-
220-
if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
221-
if err := CreateRepositoryByExample(ctx, doer, u, repo, false, false); err != nil {
222-
return err
223-
}
224-
225-
// No need for init mirror.
226-
if opts.IsMirror {
227-
return nil
228-
}
229-
230-
repoPath := repo_model.RepoPath(u.Name, repo.Name)
231-
isExist, err := util.IsExist(repoPath)
232-
if err != nil {
233-
log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
234-
return err
235-
}
236-
if isExist {
237-
// repo already exists - We have two or three options.
238-
// 1. We fail stating that the directory exists
239-
// 2. We create the db repository to go with this data and adopt the git repo
240-
// 3. We delete it and start afresh
241-
//
242-
// Previously Gitea would just delete and start afresh - this was naughty.
243-
// So we will now fail and delegate to other functionality to adopt or delete
244-
log.Error("Files already exist in %s and we are not going to adopt or delete.", repoPath)
245-
return repo_model.ErrRepoFilesAlreadyExist{
246-
Uname: u.Name,
247-
Name: repo.Name,
248-
}
249-
}
250-
251-
if err = initRepository(ctx, repoPath, doer, repo, opts); err != nil {
252-
if err2 := util.RemoveAll(repoPath); err2 != nil {
253-
log.Error("initRepository: %v", err)
254-
return fmt.Errorf(
255-
"delete repo directory %s/%s failed(2): %v", u.Name, repo.Name, err2)
256-
}
257-
return fmt.Errorf("initRepository: %w", err)
258-
}
259-
260-
// Initialize Issue Labels if selected
261-
if len(opts.IssueLabels) > 0 {
262-
if err = InitializeLabels(ctx, repo.ID, opts.IssueLabels, false); err != nil {
263-
rollbackRepo = repo
264-
rollbackRepo.OwnerID = u.ID
265-
return fmt.Errorf("InitializeLabels: %w", err)
266-
}
267-
}
268-
269-
if err := CheckDaemonExportOK(ctx, repo); err != nil {
270-
return fmt.Errorf("checkDaemonExportOK: %w", err)
271-
}
272-
273-
if stdout, _, err := git.NewCommand(ctx, "update-server-info").
274-
SetDescription(fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath)).
275-
RunStdString(&git.RunOpts{Dir: repoPath}); err != nil {
276-
log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err)
277-
rollbackRepo = repo
278-
rollbackRepo.OwnerID = u.ID
279-
return fmt.Errorf("CreateRepository(git update-server-info): %w", err)
280-
}
281-
return nil
282-
}); err != nil {
283-
if rollbackRepo != nil {
284-
if errDelete := models.DeleteRepository(doer, rollbackRepo.OwnerID, rollbackRepo.ID); errDelete != nil {
285-
log.Error("Rollback deleteRepository: %v", errDelete)
286-
}
287-
}
288-
289-
return nil, err
290-
}
291-
292-
return repo, nil
293-
}
294-
295158
const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular
296159

297160
// getDirectorySize returns the disk consumption for a given path

modules/repository/create_test.go

-135
Original file line numberDiff line numberDiff line change
@@ -4,151 +4,16 @@
44
package repository
55

66
import (
7-
"fmt"
87
"testing"
98

10-
"code.gitea.io/gitea/models"
119
activities_model "code.gitea.io/gitea/models/activities"
1210
"code.gitea.io/gitea/models/db"
13-
"code.gitea.io/gitea/models/organization"
14-
"code.gitea.io/gitea/models/perm"
1511
repo_model "code.gitea.io/gitea/models/repo"
1612
"code.gitea.io/gitea/models/unittest"
17-
user_model "code.gitea.io/gitea/models/user"
18-
"code.gitea.io/gitea/modules/structs"
1913

2014
"github.com/stretchr/testify/assert"
2115
)
2216

23-
func TestIncludesAllRepositoriesTeams(t *testing.T) {
24-
assert.NoError(t, unittest.PrepareTestDatabase())
25-
26-
testTeamRepositories := func(teamID int64, repoIds []int64) {
27-
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID})
28-
assert.NoError(t, team.LoadRepositories(db.DefaultContext), "%s: GetRepositories", team.Name)
29-
assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name)
30-
assert.Len(t, team.Repos, len(repoIds), "%s: repo count", team.Name)
31-
for i, rid := range repoIds {
32-
if rid > 0 {
33-
assert.True(t, models.HasRepository(team, rid), "%s: HasRepository(%d) %d", rid, i)
34-
}
35-
}
36-
}
37-
38-
// Get an admin user.
39-
user, err := user_model.GetUserByID(db.DefaultContext, 1)
40-
assert.NoError(t, err, "GetUserByID")
41-
42-
// Create org.
43-
org := &organization.Organization{
44-
Name: "All_repo",
45-
IsActive: true,
46-
Type: user_model.UserTypeOrganization,
47-
Visibility: structs.VisibleTypePublic,
48-
}
49-
assert.NoError(t, organization.CreateOrganization(org, user), "CreateOrganization")
50-
51-
// Check Owner team.
52-
ownerTeam, err := org.GetOwnerTeam(db.DefaultContext)
53-
assert.NoError(t, err, "GetOwnerTeam")
54-
assert.True(t, ownerTeam.IncludesAllRepositories, "Owner team includes all repositories")
55-
56-
// Create repos.
57-
repoIds := make([]int64, 0)
58-
for i := 0; i < 3; i++ {
59-
r, err := CreateRepository(user, org.AsUser(), CreateRepoOptions{Name: fmt.Sprintf("repo-%d", i)})
60-
assert.NoError(t, err, "CreateRepository %d", i)
61-
if r != nil {
62-
repoIds = append(repoIds, r.ID)
63-
}
64-
}
65-
// Get fresh copy of Owner team after creating repos.
66-
ownerTeam, err = org.GetOwnerTeam(db.DefaultContext)
67-
assert.NoError(t, err, "GetOwnerTeam")
68-
69-
// Create teams and check repositories.
70-
teams := []*organization.Team{
71-
ownerTeam,
72-
{
73-
OrgID: org.ID,
74-
Name: "team one",
75-
AccessMode: perm.AccessModeRead,
76-
IncludesAllRepositories: true,
77-
},
78-
{
79-
OrgID: org.ID,
80-
Name: "team 2",
81-
AccessMode: perm.AccessModeRead,
82-
IncludesAllRepositories: false,
83-
},
84-
{
85-
OrgID: org.ID,
86-
Name: "team three",
87-
AccessMode: perm.AccessModeWrite,
88-
IncludesAllRepositories: true,
89-
},
90-
{
91-
OrgID: org.ID,
92-
Name: "team 4",
93-
AccessMode: perm.AccessModeWrite,
94-
IncludesAllRepositories: false,
95-
},
96-
}
97-
teamRepos := [][]int64{
98-
repoIds,
99-
repoIds,
100-
{},
101-
repoIds,
102-
{},
103-
}
104-
for i, team := range teams {
105-
if i > 0 { // first team is Owner.
106-
assert.NoError(t, models.NewTeam(team), "%s: NewTeam", team.Name)
107-
}
108-
testTeamRepositories(team.ID, teamRepos[i])
109-
}
110-
111-
// Update teams and check repositories.
112-
teams[3].IncludesAllRepositories = false
113-
teams[4].IncludesAllRepositories = true
114-
teamRepos[4] = repoIds
115-
for i, team := range teams {
116-
assert.NoError(t, models.UpdateTeam(team, false, true), "%s: UpdateTeam", team.Name)
117-
testTeamRepositories(team.ID, teamRepos[i])
118-
}
119-
120-
// Create repo and check teams repositories.
121-
r, err := CreateRepository(user, org.AsUser(), CreateRepoOptions{Name: "repo-last"})
122-
assert.NoError(t, err, "CreateRepository last")
123-
if r != nil {
124-
repoIds = append(repoIds, r.ID)
125-
}
126-
teamRepos[0] = repoIds
127-
teamRepos[1] = repoIds
128-
teamRepos[4] = repoIds
129-
for i, team := range teams {
130-
testTeamRepositories(team.ID, teamRepos[i])
131-
}
132-
133-
// Remove repo and check teams repositories.
134-
assert.NoError(t, models.DeleteRepository(user, org.ID, repoIds[0]), "DeleteRepository")
135-
teamRepos[0] = repoIds[1:]
136-
teamRepos[1] = repoIds[1:]
137-
teamRepos[3] = repoIds[1:3]
138-
teamRepos[4] = repoIds[1:]
139-
for i, team := range teams {
140-
testTeamRepositories(team.ID, teamRepos[i])
141-
}
142-
143-
// Wipe created items.
144-
for i, rid := range repoIds {
145-
if i > 0 { // first repo already deleted.
146-
assert.NoError(t, models.DeleteRepository(user, org.ID, rid), "DeleteRepository %d", i)
147-
}
148-
}
149-
assert.NoError(t, organization.DeleteOrganization(db.DefaultContext, org), "DeleteOrganization")
150-
}
151-
15217
func TestUpdateRepositoryVisibilityChanged(t *testing.T) {
15318
assert.NoError(t, unittest.PrepareTestDatabase())
15419

modules/repository/generate.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
241241
defaultBranch = templateRepo.DefaultBranch
242242
}
243243

244-
return initRepoCommit(ctx, tmpDir, repo, repo.Owner, defaultBranch)
244+
return InitRepoCommit(ctx, tmpDir, repo, repo.Owner, defaultBranch)
245245
}
246246

247247
func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *repo_model.Repository) (err error) {
@@ -356,7 +356,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
356356
}
357357
}
358358

359-
if err = checkInitRepository(ctx, owner.Name, generateRepo.Name); err != nil {
359+
if err = CheckInitRepository(ctx, owner.Name, generateRepo.Name); err != nil {
360360
return generateRepo, err
361361
}
362362

modules/repository/hooks.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,7 @@ done
108108
}
109109

110110
// CreateDelegateHooks creates all the hooks scripts for the repo
111-
func CreateDelegateHooks(repoPath string) error {
112-
return createDelegateHooks(repoPath)
113-
}
114-
115-
// createDelegateHooks creates all the hooks scripts for the repo
116-
func createDelegateHooks(repoPath string) (err error) {
111+
func CreateDelegateHooks(repoPath string) (err error) {
117112
hookNames, hookTpls, giteaHookTpls := getHookTemplates()
118113
hookDir := filepath.Join(repoPath, "hooks")
119114

0 commit comments

Comments
 (0)