diff --git a/models/task.go b/models/task.go index 43cb2d4d9..b86314b44 100644 --- a/models/task.go +++ b/models/task.go @@ -147,6 +147,27 @@ func GetMigratingTask(repoID int64) (*Task, error) { return &task, nil } +// GetMigratingTaskByID returns the migrating task by repo's id +func GetMigratingTaskByID(id, doerID int64) (*Task, *migration.MigrateOptions, error) { + var task = Task{ + ID: id, + DoerID: doerID, + Type: structs.TaskTypeMigrateRepo, + } + has, err := x.Get(&task) + if err != nil { + return nil, nil, err + } else if !has { + return nil, nil, ErrTaskDoesNotExist{id, 0, task.Type} + } + + var opts migration.MigrateOptions + if err := json.Unmarshal([]byte(task.PayloadContent), &opts); err != nil { + return nil, nil, err + } + return &task, &opts, nil +} + // FindTaskOptions find all tasks type FindTaskOptions struct { Status int diff --git a/modules/task/migrate.go b/modules/task/migrate.go index d25decaa0..99f0435b2 100644 --- a/modules/task/migrate.go +++ b/modules/task/migrate.go @@ -20,7 +20,7 @@ import ( "code.gitea.io/gitea/modules/util" ) -func handleCreateError(owner *models.User, err error, name string) error { +func handleCreateError(owner *models.User, err error) error { switch { case models.IsErrReachLimitOfRepo(err): return fmt.Errorf("You have already reached your limit of %d repositories", owner.MaxCreationLimit()) @@ -38,8 +38,8 @@ func handleCreateError(owner *models.User, err error, name string) error { func runMigrateTask(t *models.Task) (err error) { defer func() { if e := recover(); e != nil { - err = fmt.Errorf("PANIC whilst trying to do migrate task: %v\nStacktrace: %v", err, log.Stack(2)) - log.Critical("PANIC during runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d]: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, err) + err = fmt.Errorf("PANIC whilst trying to do migrate task: %v", e) + log.Critical("PANIC during runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d]: %v\nStacktrace: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, e, log.Stack(2)) } if err == nil { @@ -55,7 +55,8 @@ func runMigrateTask(t *models.Task) (err error) { t.EndTime = timeutil.TimeStampNow() t.Status = structs.TaskStatusFailed t.Errors = err.Error() - if err := t.UpdateCols("status", "errors", "end_time"); err != nil { + t.RepoID = 0 + if err := t.UpdateCols("status", "errors", "repo_id", "end_time"); err != nil { log.Error("Task UpdateCols failed: %v", err) } @@ -66,8 +67,8 @@ func runMigrateTask(t *models.Task) (err error) { } }() - if err := t.LoadRepo(); err != nil { - return err + if err = t.LoadRepo(); err != nil { + return } // if repository is ready, then just finsih the task @@ -75,33 +76,35 @@ func runMigrateTask(t *models.Task) (err error) { return nil } - if err := t.LoadDoer(); err != nil { - return err + if err = t.LoadDoer(); err != nil { + return } - if err := t.LoadOwner(); err != nil { - return err + if err = t.LoadOwner(); err != nil { + return } t.StartTime = timeutil.TimeStampNow() t.Status = structs.TaskStatusRunning - if err := t.UpdateCols("start_time", "status"); err != nil { - return err + if err = t.UpdateCols("start_time", "status"); err != nil { + return } var opts *migration.MigrateOptions opts, err = t.MigrateConfig() if err != nil { - return err + return } opts.MigrateToRepoID = t.RepoID - repo, err := migrations.MigrateRepository(graceful.GetManager().HammerContext(), t.Doer, t.Owner.Name, *opts) + var repo *models.Repository + repo, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), t.Doer, t.Owner.Name, *opts) if err == nil { log.Trace("Repository migrated [%d]: %s/%s", repo.ID, t.Owner.Name, repo.Name) - return nil + return } if models.IsErrRepoAlreadyExist(err) { - return errors.New("The repository name is already used") + err = errors.New("The repository name is already used") + return } // remoteAddr may contain credentials, so we sanitize it @@ -113,5 +116,7 @@ func runMigrateTask(t *models.Task) (err error) { return fmt.Errorf("Migration failed: %v", err.Error()) } - return handleCreateError(t.Owner, err, "MigratePost") + // do not be tempted to coalesce this line with the return + err = handleCreateError(t.Owner, err) + return } diff --git a/public/img/failed.png b/public/img/failed.png new file mode 100644 index 000000000..b37545f90 Binary files /dev/null and b/public/img/failed.png differ diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 742c952f6..422075032 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -402,19 +402,3 @@ func Download(ctx *context.Context) { ctx.ServeFile(archivePath, ctx.Repo.Repository.Name+"-"+refName+ext) } - -// Status returns repository's status -func Status(ctx *context.Context) { - task, err := models.GetMigratingTask(ctx.Repo.Repository.ID) - if err != nil { - ctx.JSON(500, map[string]interface{}{ - "err": err, - }) - return - } - - ctx.JSON(200, map[string]interface{}{ - "status": ctx.Repo.Repository.Status, - "err": task.Errors, - }) -} diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 135c6b56a..586474a66 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -479,6 +479,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/forgot_password", user.ForgotPasswd) m.Post("/forgot_password", user.ForgotPasswdPost) m.Post("/logout", user.SignOut) + m.Get("/task/:task", user.TaskStatus) }) // ***** END: User ***** @@ -986,8 +987,6 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/archive/*", repo.MustBeNotEmpty, reqRepoCodeReader, repo.Download) - m.Get("/status", reqRepoCodeReader, repo.Status) - m.Group("/branches", func() { m.Get("", repo.Branches) }, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader) diff --git a/routers/user/task.go b/routers/user/task.go new file mode 100644 index 000000000..a88257ee5 --- /dev/null +++ b/routers/user/task.go @@ -0,0 +1,30 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package user + +import ( + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" +) + +// TaskStatus returns task's status +func TaskStatus(ctx *context.Context) { + task, opts, err := models.GetMigratingTaskByID(ctx.ParamsInt64("task"), ctx.User.ID) + if err != nil { + ctx.JSON(500, map[string]interface{}{ + "err": err, + }) + return + } + + ctx.JSON(200, map[string]interface{}{ + "status": task.Status, + "err": task.Errors, + "repo-id": task.RepoID, + "repo-name": opts.RepoName, + "start": task.StartTime, + "end": task.EndTime, + }) +} diff --git a/templates/repo/migrate/migrating.tmpl b/templates/repo/migrate/migrating.tmpl index 0057325e9..fdda33a2c 100644 --- a/templates/repo/migrate/migrating.tmpl +++ b/templates/repo/migrate/migrating.tmpl @@ -7,11 +7,16 @@ {{template "base/alert" .}}
-
+
+
@@ -20,6 +25,7 @@

{{.i18n.Tr "repo.migrate.migrating_failed" .CloneAddr | Safe}}

+

diff --git a/web_src/js/index.js b/web_src/js/index.js index 9fafe62d3..94238ca3d 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -191,25 +191,32 @@ function updateIssuesMeta(url, action, issueIds, elementId) { function initRepoStatusChecker() { const migrating = $('#repo_migrating'); $('#repo_migrating_failed').hide(); + $('#repo_migrating_failed_image').hide(); if (migrating) { - const repo_name = migrating.attr('repo'); - if (typeof repo_name === 'undefined') { + const task = migrating.attr('task'); + if (typeof task === 'undefined') { return; } $.ajax({ type: 'GET', - url: `${AppSubUrl}/${repo_name}/status`, + url: `${AppSubUrl}/user/task/${task}`, data: { _csrf: csrf, }, complete(xhr) { if (xhr.status === 200) { if (xhr.responseJSON) { - if (xhr.responseJSON.status === 0) { + if (xhr.responseJSON.status === 4) { window.location.reload(); return; + } else if (xhr.responseJSON.status === 3) { + $('#repo_migrating_progress').hide(); + $('#repo_migrating').hide(); + $('#repo_migrating_failed').show(); + $('#repo_migrating_failed_image').show(); + $('#repo_migrating_failed_error').text(xhr.responseJSON.err); + return; } - setTimeout(() => { initRepoStatusChecker(); }, 2000); @@ -217,7 +224,9 @@ function initRepoStatusChecker() { } } $('#repo_migrating_progress').hide(); + $('#repo_migrating').hide(); $('#repo_migrating_failed').show(); + $('#repo_migrating_failed_image').show(); } }); }