55package repo
66
77import (
8- "bytes"
9- "errors"
108 "fmt"
119 "net/http"
1210 "strings"
1311
1412 "code.gitea.io/gitea/models"
1513 "code.gitea.io/gitea/modules/context"
1614 "code.gitea.io/gitea/modules/convert"
17- "code.gitea.io/gitea/modules/graceful "
15+ auth "code.gitea.io/gitea/modules/forms "
1816 "code.gitea.io/gitea/modules/lfs"
1917 "code.gitea.io/gitea/modules/log"
2018 "code.gitea.io/gitea/modules/migrations"
2119 "code.gitea.io/gitea/modules/migrations/base"
22- "code.gitea.io/gitea/modules/notification"
23- repo_module "code.gitea.io/gitea/modules/repository"
2420 "code.gitea.io/gitea/modules/setting"
2521 api "code.gitea.io/gitea/modules/structs"
22+ "code.gitea.io/gitea/modules/task"
2623 "code.gitea.io/gitea/modules/util"
2724 "code.gitea.io/gitea/modules/web"
2825 "code.gitea.io/gitea/services/forms"
@@ -53,6 +50,31 @@ func Migrate(ctx *context.APIContext) {
5350 form := web .GetForm (ctx ).(* api.MigrateRepoOptions )
5451
5552 //get repoOwner
53+ if setting .Repository .DisableMigrations {
54+ ctx .Error (http .StatusForbidden , "MigrationsGlobalDisabled" , fmt .Errorf ("the site administrator has disabled migrations" ))
55+ return
56+ }
57+
58+ if form .Mirror && setting .Repository .DisableMirrors {
59+ ctx .Error (http .StatusForbidden , "MirrorsGlobalDisabled" , fmt .Errorf ("the site administrator has disabled mirrors" ))
60+ return
61+ }
62+
63+ form .LFS = form .LFS && setting .LFS .StartServer
64+
65+ if form .LFS && len (form .LFSEndpoint ) > 0 {
66+ ep := lfs .DetermineEndpoint ("" , form .LFSEndpoint )
67+ if ep == nil {
68+ ctx .Error (http .StatusInternalServerError , "" , ctx .Tr ("repo.migrate.invalid_lfs_endpoint" ))
69+ return
70+ }
71+ err = migrations .IsMigrateURLAllowed (ep .String (), ctx .User )
72+ if err != nil {
73+ handleRemoteAddrError (ctx , err )
74+ return
75+ }
76+ }
77+
5678 var (
5779 repoOwner * models.User
5880 err error
@@ -108,31 +130,6 @@ func Migrate(ctx *context.APIContext) {
108130
109131 gitServiceType := convert .ToGitServiceType (form .Service )
110132
111- if form .Mirror && setting .Repository .DisableMirrors {
112- ctx .Error (http .StatusForbidden , "MirrorsGlobalDisabled" , fmt .Errorf ("the site administrator has disabled mirrors" ))
113- return
114- }
115-
116- if setting .Repository .DisableMigrations {
117- ctx .Error (http .StatusForbidden , "MigrationsGlobalDisabled" , fmt .Errorf ("the site administrator has disabled migrations" ))
118- return
119- }
120-
121- form .LFS = form .LFS && setting .LFS .StartServer
122-
123- if form .LFS && len (form .LFSEndpoint ) > 0 {
124- ep := lfs .DetermineEndpoint ("" , form .LFSEndpoint )
125- if ep == nil {
126- ctx .Error (http .StatusInternalServerError , "" , ctx .Tr ("repo.migrate.invalid_lfs_endpoint" ))
127- return
128- }
129- err = migrations .IsMigrateURLAllowed (ep .String (), ctx .User )
130- if err != nil {
131- handleRemoteAddrError (ctx , err )
132- return
133- }
134- }
135-
136133 var opts = migrations.MigrateOptions {
137134 CloneAddr : remoteAddr ,
138135 RepoName : form .RepoName ,
@@ -145,7 +142,7 @@ func Migrate(ctx *context.APIContext) {
145142 AuthPassword : form .AuthPassword ,
146143 AuthToken : form .AuthToken ,
147144 Wiki : form .Wiki ,
148- Issues : form .Issues ,
145+ Issues : form .Issues || form . PullRequests ,
149146 Milestones : form .Milestones ,
150147 Labels : form .Labels ,
151148 Comments : true ,
@@ -163,63 +160,33 @@ func Migrate(ctx *context.APIContext) {
163160 opts .Releases = false
164161 }
165162
166- repo , err := repo_module .CreateRepository (ctx .User , repoOwner , models.CreateRepoOptions {
167- Name : opts .RepoName ,
168- Description : opts .Description ,
169- OriginalURL : form .CloneAddr ,
170- GitServiceType : gitServiceType ,
171- IsPrivate : opts .Private ,
172- IsMirror : opts .Mirror ,
173- Status : models .RepositoryBeingMigrated ,
174- })
175- if err != nil {
176- handleMigrateError (ctx , repoOwner , remoteAddr , err )
163+ if err = models .CheckCreateRepository (ctx .User , repoOwner , opts .RepoName , false ); err != nil {
164+ handleMigrateError (ctx , repoOwner , & opts , err )
177165 return
178166 }
179167
180- opts .MigrateToRepoID = repo .ID
181-
182- defer func () {
183- if e := recover (); e != nil {
184- var buf bytes.Buffer
185- fmt .Fprintf (& buf , "Handler crashed with error: %v" , log .Stack (2 ))
186-
187- err = errors .New (buf .String ())
188- }
189-
190- if err == nil {
191- notification .NotifyMigrateRepository (ctx .User , repoOwner , repo )
192- return
193- }
194-
195- if repo != nil {
196- if errDelete := models .DeleteRepository (ctx .User , repoOwner .ID , repo .ID ); errDelete != nil {
197- log .Error ("DeleteRepository: %v" , errDelete )
198- }
199- }
200- }()
201-
202- if _ , err = migrations .MigrateRepository (graceful .GetManager ().HammerContext (), ctx .User , repoOwner .Name , opts , nil ); err != nil {
203- handleMigrateError (ctx , repoOwner , remoteAddr , err )
168+ repo , err := task .MigrateRepository (ctx .User , repoOwner , opts )
169+ if err == nil {
170+ log .Trace ("Repository migrated: %s/%s" , repoOwner .Name , form .RepoName )
171+ ctx .JSON (http .StatusCreated , convert .ToRepo (repo , models .AccessModeAdmin ))
204172 return
205173 }
206174
207- log .Trace ("Repository migrated: %s/%s" , repoOwner .Name , form .RepoName )
208- ctx .JSON (http .StatusCreated , convert .ToRepo (repo , models .AccessModeAdmin ))
175+ handleMigrateError (ctx , repoOwner , & opts , err )
209176}
210177
211- func handleMigrateError (ctx * context.APIContext , repoOwner * models.User , remoteAddr string , err error ) {
178+ func handleMigrateError (ctx * context.APIContext , repoOwner * models.User , migrationOpts * migrations. MigrateOptions , err error ) {
212179 switch {
213- case models .IsErrRepoAlreadyExist (err ):
214- ctx .Error (http .StatusConflict , "" , "The repository with the same name already exists." )
215- case models .IsErrRepoFilesAlreadyExist (err ):
216- ctx .Error (http .StatusConflict , "" , "Files already exist for this repository. Adopt them or delete them." )
217180 case migrations .IsRateLimitError (err ):
218181 ctx .Error (http .StatusUnprocessableEntity , "" , "Remote visit addressed rate limitation." )
219182 case migrations .IsTwoFactorAuthError (err ):
220183 ctx .Error (http .StatusUnprocessableEntity , "" , "Remote visit required two factors authentication." )
221184 case models .IsErrReachLimitOfRepo (err ):
222185 ctx .Error (http .StatusUnprocessableEntity , "" , fmt .Sprintf ("You have already reached your limit of %d repositories." , repoOwner .MaxCreationLimit ()))
186+ case models .IsErrRepoAlreadyExist (err ):
187+ ctx .Error (http .StatusConflict , "" , "The repository with the same name already exists." )
188+ case models .IsErrRepoFilesAlreadyExist (err ):
189+ ctx .Error (http .StatusConflict , "" , "Files already exist for this repository. Adopt them or delete them." )
223190 case models .IsErrNameReserved (err ):
224191 ctx .Error (http .StatusUnprocessableEntity , "" , fmt .Sprintf ("The username '%s' is reserved." , err .(models.ErrNameReserved ).Name ))
225192 case models .IsErrNameCharsNotAllowed (err ):
@@ -231,6 +198,7 @@ func handleMigrateError(ctx *context.APIContext, repoOwner *models.User, remoteA
231198 case base .IsErrNotSupported (err ):
232199 ctx .Error (http .StatusUnprocessableEntity , "" , err )
233200 default :
201+ remoteAddr , _ := auth .ParseRemoteAddr (migrationOpts .CloneAddr , migrationOpts .AuthUsername , migrationOpts .AuthPassword )
234202 err = util .NewStringURLSanitizedError (err , remoteAddr , true )
235203 if strings .Contains (err .Error (), "Authentication failed" ) ||
236204 strings .Contains (err .Error (), "Bad credentials" ) ||
@@ -267,3 +235,36 @@ func handleRemoteAddrError(ctx *context.APIContext, err error) {
267235 ctx .Error (http .StatusInternalServerError , "ParseRemoteAddr" , err )
268236 }
269237}
238+
239+ // GetMigratingTask returns the migrating task by repo's id
240+ func GetMigratingTask (ctx * context.APIContext ) {
241+ // swagger:operation GET /repos/migrate/status task
242+ // ---
243+ // summary: Get the migration status of a repository by its id
244+ // produces:
245+ // - application/json
246+ // parameters:
247+ // - name: repo_id
248+ // in: query
249+ // description: repository id
250+ // type: int64
251+ // responses:
252+ // "200":
253+ // "$ref": "#/responses/"
254+ // "404":
255+ // "$ref": "#/response/"
256+ t , err := models .GetMigratingTask (ctx .QueryInt64 ("repo_id" ))
257+
258+ if err != nil {
259+ ctx .JSON (http .StatusNotFound , err )
260+ return
261+ }
262+
263+ ctx .JSON (200 , map [string ]interface {}{
264+ "status" : t .Status ,
265+ "err" : t .Errors ,
266+ "repo-id" : t .RepoID ,
267+ "start" : t .StartTime ,
268+ "end" : t .EndTime ,
269+ })
270+ }
0 commit comments