@@ -7,21 +7,28 @@ import (
77 "context"
88 "errors"
99 "fmt"
10+ "os"
11+ "path/filepath"
12+ "strings"
1013
14+ activities_model "code.gitea.io/gitea/models/activities"
1115 "code.gitea.io/gitea/models/db"
1216 "code.gitea.io/gitea/models/git"
1317 issues_model "code.gitea.io/gitea/models/issues"
1418 "code.gitea.io/gitea/models/organization"
19+ access_model "code.gitea.io/gitea/models/perm/access"
1520 repo_model "code.gitea.io/gitea/models/repo"
1621 system_model "code.gitea.io/gitea/models/system"
1722 "code.gitea.io/gitea/models/unit"
1823 user_model "code.gitea.io/gitea/models/user"
1924 "code.gitea.io/gitea/modules/graceful"
25+ issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
2026 "code.gitea.io/gitea/modules/log"
2127 "code.gitea.io/gitea/modules/queue"
2228 repo_module "code.gitea.io/gitea/modules/repository"
2329 "code.gitea.io/gitea/modules/setting"
2430 "code.gitea.io/gitea/modules/structs"
31+ "code.gitea.io/gitea/modules/util"
2532 notify_service "code.gitea.io/gitea/services/notify"
2633 pull_service "code.gitea.io/gitea/services/pull"
2734)
@@ -112,42 +119,32 @@ func Init(ctx context.Context) error {
112119
113120// UpdateRepository updates a repository
114121func UpdateRepository (ctx context.Context , repo * repo_model.Repository , visibilityChanged bool ) (err error ) {
115- ctx , committer , err := db .TxContext (ctx )
116- if err != nil {
117- return err
118- }
119- defer committer .Close ()
120-
121- if err = repo_module .UpdateRepository (ctx , repo , visibilityChanged ); err != nil {
122- return fmt .Errorf ("updateRepository: %w" , err )
123- }
124-
125- return committer .Commit ()
126- }
127-
128- func UpdateRepositoryVisibility (ctx context.Context , repo * repo_model.Repository , isPrivate bool ) (err error ) {
129- ctx , committer , err := db .TxContext (ctx )
130- if err != nil {
131- return err
132- }
133-
134- defer committer .Close ()
135-
136- repo .IsPrivate = isPrivate
137-
138- if err = repo_module .UpdateRepository (ctx , repo , true ); err != nil {
139- return fmt .Errorf ("UpdateRepositoryVisibility: %w" , err )
140- }
141-
142- return committer .Commit ()
122+ return db .WithTx (ctx , func (ctx context.Context ) error {
123+ if err = updateRepository (ctx , repo , visibilityChanged ); err != nil {
124+ return fmt .Errorf ("updateRepository: %w" , err )
125+ }
126+ return nil
127+ })
143128}
144129
145130func MakeRepoPublic (ctx context.Context , repo * repo_model.Repository ) (err error ) {
146- return UpdateRepositoryVisibility (ctx , repo , false )
131+ return db .WithTx (ctx , func (ctx context.Context ) error {
132+ repo .IsPrivate = false
133+ if err = updateRepository (ctx , repo , true ); err != nil {
134+ return fmt .Errorf ("MakeRepoPublic: %w" , err )
135+ }
136+ return nil
137+ })
147138}
148139
149140func MakeRepoPrivate (ctx context.Context , repo * repo_model.Repository ) (err error ) {
150- return UpdateRepositoryVisibility (ctx , repo , true )
141+ return db .WithTx (ctx , func (ctx context.Context ) error {
142+ repo .IsPrivate = true
143+ if err = updateRepository (ctx , repo , true ); err != nil {
144+ return fmt .Errorf ("MakeRepoPrivate: %w" , err )
145+ }
146+ return nil
147+ })
151148}
152149
153150// LinkedRepository returns the linked repo if any
@@ -173,3 +170,97 @@ func LinkedRepository(ctx context.Context, a *repo_model.Attachment) (*repo_mode
173170 }
174171 return nil , - 1 , nil
175172}
173+
174+ // checkDaemonExportOK creates/removes git-daemon-export-ok for git-daemon...
175+ func checkDaemonExportOK (ctx context.Context , repo * repo_model.Repository ) error {
176+ if err := repo .LoadOwner (ctx ); err != nil {
177+ return err
178+ }
179+
180+ // Create/Remove git-daemon-export-ok for git-daemon...
181+ daemonExportFile := filepath .Join (repo .RepoPath (), `git-daemon-export-ok` )
182+
183+ isExist , err := util .IsExist (daemonExportFile )
184+ if err != nil {
185+ log .Error ("Unable to check if %s exists. Error: %v" , daemonExportFile , err )
186+ return err
187+ }
188+
189+ isPublic := ! repo .IsPrivate && repo .Owner .Visibility == structs .VisibleTypePublic
190+ if ! isPublic && isExist {
191+ if err = util .Remove (daemonExportFile ); err != nil {
192+ log .Error ("Failed to remove %s: %v" , daemonExportFile , err )
193+ }
194+ } else if isPublic && ! isExist {
195+ if f , err := os .Create (daemonExportFile ); err != nil {
196+ log .Error ("Failed to create %s: %v" , daemonExportFile , err )
197+ } else {
198+ f .Close ()
199+ }
200+ }
201+
202+ return nil
203+ }
204+
205+ // updateRepository updates a repository with db context
206+ func updateRepository (ctx context.Context , repo * repo_model.Repository , visibilityChanged bool ) (err error ) {
207+ repo .LowerName = strings .ToLower (repo .Name )
208+
209+ e := db .GetEngine (ctx )
210+
211+ if _ , err = e .ID (repo .ID ).AllCols ().Update (repo ); err != nil {
212+ return fmt .Errorf ("update: %w" , err )
213+ }
214+
215+ if err = repo_module .UpdateRepoSize (ctx , repo ); err != nil {
216+ log .Error ("Failed to update size for repository: %v" , err )
217+ }
218+
219+ if visibilityChanged {
220+ if err = repo .LoadOwner (ctx ); err != nil {
221+ return fmt .Errorf ("LoadOwner: %w" , err )
222+ }
223+ if repo .Owner .IsOrganization () {
224+ // Organization repository need to recalculate access table when visibility is changed.
225+ if err = access_model .RecalculateTeamAccesses (ctx , repo , 0 ); err != nil {
226+ return fmt .Errorf ("recalculateTeamAccesses: %w" , err )
227+ }
228+ }
229+
230+ // If repo has become private, we need to set its actions to private.
231+ if repo .IsPrivate {
232+ _ , err = e .Where ("repo_id = ?" , repo .ID ).Cols ("is_private" ).Update (& activities_model.Action {
233+ IsPrivate : true ,
234+ })
235+ if err != nil {
236+ return err
237+ }
238+
239+ if err = repo_model .ClearRepoStars (ctx , repo .ID ); err != nil {
240+ return err
241+ }
242+ }
243+
244+ // Create/Remove git-daemon-export-ok for git-daemon...
245+ if err := checkDaemonExportOK (ctx , repo ); err != nil {
246+ return err
247+ }
248+
249+ forkRepos , err := repo_model .GetRepositoriesByForkID (ctx , repo .ID )
250+ if err != nil {
251+ return fmt .Errorf ("getRepositoriesByForkID: %w" , err )
252+ }
253+ for i := range forkRepos {
254+ forkRepos [i ].IsPrivate = repo .IsPrivate || repo .Owner .Visibility == structs .VisibleTypePrivate
255+ if err = updateRepository (ctx , forkRepos [i ], true ); err != nil {
256+ return fmt .Errorf ("updateRepository[%d]: %w" , forkRepos [i ].ID , err )
257+ }
258+ }
259+
260+ // If visibility is changed, we need to update the issue indexer.
261+ // Since the data in the issue indexer have field to indicate if the repo is public or not.
262+ issue_indexer .UpdateRepoIndexer (ctx , repo .ID )
263+ }
264+
265+ return nil
266+ }
0 commit comments