@@ -7,20 +7,27 @@ 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 "code.gitea.io/gitea/models/unit"
1722 user_model "code.gitea.io/gitea/models/user"
1823 "code.gitea.io/gitea/modules/graceful"
24+ issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
1925 "code.gitea.io/gitea/modules/log"
2026 "code.gitea.io/gitea/modules/queue"
2127 repo_module "code.gitea.io/gitea/modules/repository"
2228 "code.gitea.io/gitea/modules/setting"
2329 "code.gitea.io/gitea/modules/structs"
30+ "code.gitea.io/gitea/modules/util"
2431 notify_service "code.gitea.io/gitea/services/notify"
2532 pull_service "code.gitea.io/gitea/services/pull"
2633)
@@ -109,42 +116,32 @@ func Init(ctx context.Context) error {
109116
110117// UpdateRepository updates a repository
111118func 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- func UpdateRepositoryVisibility (ctx context.Context , repo * repo_model.Repository , isPrivate bool ) (err error ) {
126- ctx , committer , err := db .TxContext (ctx )
127- if err != nil {
128- return err
129- }
130-
131- defer committer .Close ()
132-
133- repo .IsPrivate = isPrivate
134-
135- if err = repo_module .UpdateRepository (ctx , repo , true ); err != nil {
136- return fmt .Errorf ("UpdateRepositoryVisibility: %w" , err )
137- }
138-
139- return committer .Commit ()
119+ return db .WithTx (ctx , func (ctx context.Context ) error {
120+ if err = updateRepository (ctx , repo , visibilityChanged ); err != nil {
121+ return fmt .Errorf ("updateRepository: %w" , err )
122+ }
123+ return nil
124+ })
140125}
141126
142127func MakeRepoPublic (ctx context.Context , repo * repo_model.Repository ) (err error ) {
143- return UpdateRepositoryVisibility (ctx , repo , false )
128+ return db .WithTx (ctx , func (ctx context.Context ) error {
129+ repo .IsPrivate = false
130+ if err = updateRepository (ctx , repo , true ); err != nil {
131+ return fmt .Errorf ("MakeRepoPublic: %w" , err )
132+ }
133+ return nil
134+ })
144135}
145136
146137func MakeRepoPrivate (ctx context.Context , repo * repo_model.Repository ) (err error ) {
147- return UpdateRepositoryVisibility (ctx , repo , true )
138+ return db .WithTx (ctx , func (ctx context.Context ) error {
139+ repo .IsPrivate = true
140+ if err = updateRepository (ctx , repo , true ); err != nil {
141+ return fmt .Errorf ("MakeRepoPrivate: %w" , err )
142+ }
143+ return nil
144+ })
148145}
149146
150147// LinkedRepository returns the linked repo if any
@@ -170,3 +167,97 @@ func LinkedRepository(ctx context.Context, a *repo_model.Attachment) (*repo_mode
170167 }
171168 return nil , - 1 , nil
172169}
170+
171+ // checkDaemonExportOK creates/removes git-daemon-export-ok for git-daemon...
172+ func checkDaemonExportOK (ctx context.Context , repo * repo_model.Repository ) error {
173+ if err := repo .LoadOwner (ctx ); err != nil {
174+ return err
175+ }
176+
177+ // Create/Remove git-daemon-export-ok for git-daemon...
178+ daemonExportFile := filepath .Join (repo .RepoPath (), `git-daemon-export-ok` )
179+
180+ isExist , err := util .IsExist (daemonExportFile )
181+ if err != nil {
182+ log .Error ("Unable to check if %s exists. Error: %v" , daemonExportFile , err )
183+ return err
184+ }
185+
186+ isPublic := ! repo .IsPrivate && repo .Owner .Visibility == structs .VisibleTypePublic
187+ if ! isPublic && isExist {
188+ if err = util .Remove (daemonExportFile ); err != nil {
189+ log .Error ("Failed to remove %s: %v" , daemonExportFile , err )
190+ }
191+ } else if isPublic && ! isExist {
192+ if f , err := os .Create (daemonExportFile ); err != nil {
193+ log .Error ("Failed to create %s: %v" , daemonExportFile , err )
194+ } else {
195+ f .Close ()
196+ }
197+ }
198+
199+ return nil
200+ }
201+
202+ // updateRepository updates a repository with db context
203+ func updateRepository (ctx context.Context , repo * repo_model.Repository , visibilityChanged bool ) (err error ) {
204+ repo .LowerName = strings .ToLower (repo .Name )
205+
206+ e := db .GetEngine (ctx )
207+
208+ if _ , err = e .ID (repo .ID ).AllCols ().Update (repo ); err != nil {
209+ return fmt .Errorf ("update: %w" , err )
210+ }
211+
212+ if err = repo_module .UpdateRepoSize (ctx , repo ); err != nil {
213+ log .Error ("Failed to update size for repository: %v" , err )
214+ }
215+
216+ if visibilityChanged {
217+ if err = repo .LoadOwner (ctx ); err != nil {
218+ return fmt .Errorf ("LoadOwner: %w" , err )
219+ }
220+ if repo .Owner .IsOrganization () {
221+ // Organization repository need to recalculate access table when visibility is changed.
222+ if err = access_model .RecalculateTeamAccesses (ctx , repo , 0 ); err != nil {
223+ return fmt .Errorf ("recalculateTeamAccesses: %w" , err )
224+ }
225+ }
226+
227+ // If repo has become private, we need to set its actions to private.
228+ if repo .IsPrivate {
229+ _ , err = e .Where ("repo_id = ?" , repo .ID ).Cols ("is_private" ).Update (& activities_model.Action {
230+ IsPrivate : true ,
231+ })
232+ if err != nil {
233+ return err
234+ }
235+
236+ if err = repo_model .ClearRepoStars (ctx , repo .ID ); err != nil {
237+ return err
238+ }
239+ }
240+
241+ // Create/Remove git-daemon-export-ok for git-daemon...
242+ if err := checkDaemonExportOK (ctx , repo ); err != nil {
243+ return err
244+ }
245+
246+ forkRepos , err := repo_model .GetRepositoriesByForkID (ctx , repo .ID )
247+ if err != nil {
248+ return fmt .Errorf ("getRepositoriesByForkID: %w" , err )
249+ }
250+ for i := range forkRepos {
251+ forkRepos [i ].IsPrivate = repo .IsPrivate || repo .Owner .Visibility == structs .VisibleTypePrivate
252+ if err = updateRepository (ctx , forkRepos [i ], true ); err != nil {
253+ return fmt .Errorf ("updateRepository[%d]: %w" , forkRepos [i ].ID , err )
254+ }
255+ }
256+
257+ // If visibility is changed, we need to update the issue indexer.
258+ // Since the data in the issue indexer have field to indicate if the repo is public or not.
259+ issue_indexer .UpdateRepoIndexer (ctx , repo .ID )
260+ }
261+
262+ return nil
263+ }
0 commit comments