code.gitea.io/gitea@v1.21.7/services/repository/repository.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package repository 5 6 import ( 7 "context" 8 "fmt" 9 10 "code.gitea.io/gitea/models/db" 11 "code.gitea.io/gitea/models/git" 12 issues_model "code.gitea.io/gitea/models/issues" 13 "code.gitea.io/gitea/models/organization" 14 packages_model "code.gitea.io/gitea/models/packages" 15 repo_model "code.gitea.io/gitea/models/repo" 16 system_model "code.gitea.io/gitea/models/system" 17 "code.gitea.io/gitea/models/unit" 18 user_model "code.gitea.io/gitea/models/user" 19 "code.gitea.io/gitea/modules/graceful" 20 "code.gitea.io/gitea/modules/log" 21 repo_module "code.gitea.io/gitea/modules/repository" 22 "code.gitea.io/gitea/modules/setting" 23 "code.gitea.io/gitea/modules/structs" 24 notify_service "code.gitea.io/gitea/services/notify" 25 pull_service "code.gitea.io/gitea/services/pull" 26 ) 27 28 // WebSearchRepository represents a repository returned by web search 29 type WebSearchRepository struct { 30 Repository *structs.Repository `json:"repository"` 31 LatestCommitStatus *git.CommitStatus `json:"latest_commit_status"` 32 LocaleLatestCommitStatus string `json:"locale_latest_commit_status"` 33 } 34 35 // WebSearchResults results of a successful web search 36 type WebSearchResults struct { 37 OK bool `json:"ok"` 38 Data []*WebSearchRepository `json:"data"` 39 } 40 41 // CreateRepository creates a repository for the user/organization. 42 func CreateRepository(ctx context.Context, doer, owner *user_model.User, opts CreateRepoOptions) (*repo_model.Repository, error) { 43 repo, err := CreateRepositoryDirectly(ctx, doer, owner, opts) 44 if err != nil { 45 // No need to rollback here we should do this in CreateRepository... 46 return nil, err 47 } 48 49 notify_service.CreateRepository(ctx, doer, owner, repo) 50 51 return repo, nil 52 } 53 54 // DeleteRepository deletes a repository for a user or organization. 55 func DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, notify bool) error { 56 if err := pull_service.CloseRepoBranchesPulls(ctx, doer, repo); err != nil { 57 log.Error("CloseRepoBranchesPulls failed: %v", err) 58 } 59 60 if notify { 61 // If the repo itself has webhooks, we need to trigger them before deleting it... 62 notify_service.DeleteRepository(ctx, doer, repo) 63 } 64 65 if err := DeleteRepositoryDirectly(ctx, doer, repo.OwnerID, repo.ID); err != nil { 66 return err 67 } 68 69 return packages_model.UnlinkRepositoryFromAllPackages(ctx, repo.ID) 70 } 71 72 // PushCreateRepo creates a repository when a new repository is pushed to an appropriate namespace 73 func PushCreateRepo(ctx context.Context, authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) { 74 if !authUser.IsAdmin { 75 if owner.IsOrganization() { 76 if ok, err := organization.CanCreateOrgRepo(ctx, owner.ID, authUser.ID); err != nil { 77 return nil, err 78 } else if !ok { 79 return nil, fmt.Errorf("cannot push-create repository for org") 80 } 81 } else if authUser.ID != owner.ID { 82 return nil, fmt.Errorf("cannot push-create repository for another user") 83 } 84 } 85 86 repo, err := CreateRepository(ctx, authUser, owner, CreateRepoOptions{ 87 Name: repoName, 88 IsPrivate: setting.Repository.DefaultPushCreatePrivate, 89 }) 90 if err != nil { 91 return nil, err 92 } 93 94 return repo, nil 95 } 96 97 // Init start repository service 98 func Init(ctx context.Context) error { 99 if err := repo_module.LoadRepoConfig(); err != nil { 100 return err 101 } 102 system_model.RemoveAllWithNotice(ctx, "Clean up temporary repository uploads", setting.Repository.Upload.TempPath) 103 system_model.RemoveAllWithNotice(ctx, "Clean up temporary repositories", repo_module.LocalCopyPath()) 104 if err := initPushQueue(); err != nil { 105 return err 106 } 107 return initBranchSyncQueue(graceful.GetManager().ShutdownContext()) 108 } 109 110 // UpdateRepository updates a repository 111 func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) { 112 ctx, committer, err := db.TxContext(ctx) 113 if err != nil { 114 return err 115 } 116 defer committer.Close() 117 118 if err = repo_module.UpdateRepository(ctx, repo, visibilityChanged); err != nil { 119 return fmt.Errorf("updateRepository: %w", err) 120 } 121 122 return committer.Commit() 123 } 124 125 // LinkedRepository returns the linked repo if any 126 func LinkedRepository(ctx context.Context, a *repo_model.Attachment) (*repo_model.Repository, unit.Type, error) { 127 if a.IssueID != 0 { 128 iss, err := issues_model.GetIssueByID(ctx, a.IssueID) 129 if err != nil { 130 return nil, unit.TypeIssues, err 131 } 132 repo, err := repo_model.GetRepositoryByID(ctx, iss.RepoID) 133 unitType := unit.TypeIssues 134 if iss.IsPull { 135 unitType = unit.TypePullRequests 136 } 137 return repo, unitType, err 138 } else if a.ReleaseID != 0 { 139 rel, err := repo_model.GetReleaseByID(ctx, a.ReleaseID) 140 if err != nil { 141 return nil, unit.TypeReleases, err 142 } 143 repo, err := repo_model.GetRepositoryByID(ctx, rel.RepoID) 144 return repo, unit.TypeReleases, err 145 } 146 return nil, -1, nil 147 }