Skip to content

Commit 6d69df2

Browse files
zeripath6543
andauthored
Add Status Updates whilst Gitea migrations are occurring (#15076)
* Add migrating message Signed-off-by: Andrew Thornton <[email protected]> * simplify messenger Signed-off-by: Andrew Thornton <[email protected]> * make messenger an interface Signed-off-by: Andrew Thornton <[email protected]> * rename Signed-off-by: Andrew Thornton <[email protected]> * prepare for merge Signed-off-by: Andrew Thornton <[email protected]> * as per tech Signed-off-by: Andrew Thornton <[email protected]> Co-authored-by: 6543 <[email protected]>
1 parent 047c39e commit 6d69df2

File tree

13 files changed

+129
-12
lines changed

13 files changed

+129
-12
lines changed

models/migrations/migrations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ var migrations = []Migration{
317317
NewMigration("Add issue resource index table", addIssueResourceIndexTable),
318318
// v183 -> v184
319319
NewMigration("Create PushMirror table", createPushMirrorTable),
320+
// v184 -> v185
321+
NewMigration("Rename Task errors to message", renameTaskErrorsToMessage),
320322
}
321323

322324
// GetCurrentDBVersion returns the current db version

models/migrations/v184.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"fmt"
9+
10+
"code.gitea.io/gitea/modules/setting"
11+
12+
"xorm.io/xorm"
13+
)
14+
15+
func renameTaskErrorsToMessage(x *xorm.Engine) error {
16+
type Task struct {
17+
Errors string `xorm:"TEXT"` // if task failed, saved the error reason
18+
Type int
19+
Status int `xorm:"index"`
20+
}
21+
22+
sess := x.NewSession()
23+
defer sess.Close()
24+
if err := sess.Begin(); err != nil {
25+
return err
26+
}
27+
28+
if err := sess.Sync2(new(Task)); err != nil {
29+
return fmt.Errorf("error on Sync2: %v", err)
30+
}
31+
32+
switch {
33+
case setting.Database.UseMySQL:
34+
if _, err := sess.Exec("ALTER TABLE `task` CHANGE errors message text"); err != nil {
35+
return err
36+
}
37+
case setting.Database.UseMSSQL:
38+
if _, err := sess.Exec("sp_rename 'task.errors', 'message', 'COLUMN'"); err != nil {
39+
return err
40+
}
41+
default:
42+
if _, err := sess.Exec("ALTER TABLE `task` RENAME COLUMN errors TO message"); err != nil {
43+
return err
44+
}
45+
}
46+
return sess.Commit()
47+
}

models/task.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,16 @@ type Task struct {
3232
StartTime timeutil.TimeStamp
3333
EndTime timeutil.TimeStamp
3434
PayloadContent string `xorm:"TEXT"`
35-
Errors string `xorm:"TEXT"` // if task failed, saved the error reason
35+
Message string `xorm:"TEXT"` // if task failed, saved the error reason
3636
Created timeutil.TimeStamp `xorm:"created"`
3737
}
3838

39+
// TranslatableMessage represents JSON struct that can be translated with a Locale
40+
type TranslatableMessage struct {
41+
Format string
42+
Args []interface{} `json:"omitempty"`
43+
}
44+
3945
// LoadRepo loads repository of the task
4046
func (task *Task) LoadRepo() error {
4147
return task.loadRepo(x)

modules/migrations/base/messenger.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package base
6+
7+
// Messenger is a formatting function similar to i18n.Tr
8+
type Messenger func(key string, args ...interface{})
9+
10+
// NilMessenger represents an empty formatting function
11+
func NilMessenger(string, ...interface{}) {}

modules/migrations/dump.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ func DumpRepository(ctx context.Context, baseDir, ownerName string, opts base.Mi
555555
return err
556556
}
557557

558-
if err := migrateRepository(downloader, uploader, opts); err != nil {
558+
if err := migrateRepository(downloader, uploader, opts, nil); err != nil {
559559
if err1 := uploader.Rollback(); err1 != nil {
560560
log.Error("rollback failed: %v", err1)
561561
}
@@ -620,7 +620,7 @@ func RestoreRepository(ctx context.Context, baseDir string, ownerName, repoName
620620
}
621621
updateOptionsUnits(&migrateOpts, units)
622622

623-
if err = migrateRepository(downloader, uploader, migrateOpts); err != nil {
623+
if err = migrateRepository(downloader, uploader, migrateOpts, nil); err != nil {
624624
if err1 := uploader.Rollback(); err1 != nil {
625625
log.Error("rollback failed: %v", err1)
626626
}

modules/migrations/gitea_uploader_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func TestGiteaUploadRepo(t *testing.T) {
4747
PullRequests: true,
4848
Private: true,
4949
Mirror: false,
50-
})
50+
}, nil)
5151
assert.NoError(t, err)
5252

5353
repo := models.AssertExistsAndLoadBean(t, &models.Repository{OwnerID: user.ID, Name: repoName}).(*models.Repository)

modules/migrations/migrate.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func IsMigrateURLAllowed(remoteURL string, doer *models.User) error {
9999
}
100100

101101
// MigrateRepository migrate repository according MigrateOptions
102-
func MigrateRepository(ctx context.Context, doer *models.User, ownerName string, opts base.MigrateOptions) (*models.Repository, error) {
102+
func MigrateRepository(ctx context.Context, doer *models.User, ownerName string, opts base.MigrateOptions, messenger base.Messenger) (*models.Repository, error) {
103103
err := IsMigrateURLAllowed(opts.CloneAddr, doer)
104104
if err != nil {
105105
return nil, err
@@ -118,7 +118,7 @@ func MigrateRepository(ctx context.Context, doer *models.User, ownerName string,
118118
var uploader = NewGiteaLocalUploader(ctx, doer, ownerName, opts.RepoName)
119119
uploader.gitServiceType = opts.GitServiceType
120120

121-
if err := migrateRepository(downloader, uploader, opts); err != nil {
121+
if err := migrateRepository(downloader, uploader, opts, messenger); err != nil {
122122
if err1 := uploader.Rollback(); err1 != nil {
123123
log.Error("rollback failed: %v", err1)
124124
}
@@ -167,7 +167,11 @@ func newDownloader(ctx context.Context, ownerName string, opts base.MigrateOptio
167167
// migrateRepository will download information and then upload it to Uploader, this is a simple
168168
// process for small repository. For a big repository, save all the data to disk
169169
// before upload is better
170-
func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts base.MigrateOptions) error {
170+
func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts base.MigrateOptions, messenger base.Messenger) error {
171+
if messenger == nil {
172+
messenger = base.NilMessenger
173+
}
174+
171175
repo, err := downloader.GetRepoInfo()
172176
if err != nil {
173177
if !base.IsErrNotSupported(err) {
@@ -185,12 +189,14 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
185189
}
186190

187191
log.Trace("migrating git data from %s", repo.CloneURL)
192+
messenger("repo.migrate.migrating_git")
188193
if err = uploader.CreateRepo(repo, opts); err != nil {
189194
return err
190195
}
191196
defer uploader.Close()
192197

193198
log.Trace("migrating topics")
199+
messenger("repo.migrate.migrating_topics")
194200
topics, err := downloader.GetTopics()
195201
if err != nil {
196202
if !base.IsErrNotSupported(err) {
@@ -206,6 +212,7 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
206212

207213
if opts.Milestones {
208214
log.Trace("migrating milestones")
215+
messenger("repo.migrate.migrating_milestones")
209216
milestones, err := downloader.GetMilestones()
210217
if err != nil {
211218
if !base.IsErrNotSupported(err) {
@@ -229,6 +236,7 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
229236

230237
if opts.Labels {
231238
log.Trace("migrating labels")
239+
messenger("repo.migrate.migrating_labels")
232240
labels, err := downloader.GetLabels()
233241
if err != nil {
234242
if !base.IsErrNotSupported(err) {
@@ -252,6 +260,7 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
252260

253261
if opts.Releases {
254262
log.Trace("migrating releases")
263+
messenger("repo.migrate.migrating_releases")
255264
releases, err := downloader.GetReleases()
256265
if err != nil {
257266
if !base.IsErrNotSupported(err) {
@@ -285,6 +294,7 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
285294

286295
if opts.Issues {
287296
log.Trace("migrating issues and comments")
297+
messenger("repo.migrate.migrating_issues")
288298
var issueBatchSize = uploader.MaxBatchInsertSize("issue")
289299

290300
for i := 1; ; i++ {
@@ -339,6 +349,7 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
339349

340350
if opts.PullRequests {
341351
log.Trace("migrating pull requests and comments")
352+
messenger("repo.migrate.migrating_pulls")
342353
var prBatchSize = uploader.MaxBatchInsertSize("pullrequest")
343354
for i := 1; ; i++ {
344355
prs, isEnd, err := downloader.GetPullRequests(i, prBatchSize)

modules/task/migrate.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"code.gitea.io/gitea/modules/structs"
2121
"code.gitea.io/gitea/modules/timeutil"
2222
"code.gitea.io/gitea/modules/util"
23+
jsoniter "github.com/json-iterator/go"
2324
)
2425

2526
func handleCreateError(owner *models.User, err error) error {
@@ -56,7 +57,7 @@ func runMigrateTask(t *models.Task) (err error) {
5657

5758
t.EndTime = timeutil.TimeStampNow()
5859
t.Status = structs.TaskStatusFailed
59-
t.Errors = err.Error()
60+
t.Message = err.Error()
6061
t.RepoID = 0
6162
if err := t.UpdateCols("status", "errors", "repo_id", "end_time"); err != nil {
6263
log.Error("Task UpdateCols failed: %v", err)
@@ -106,7 +107,16 @@ func runMigrateTask(t *models.Task) (err error) {
106107
return
107108
}
108109

109-
repo, err = migrations.MigrateRepository(ctx, t.Doer, t.Owner.Name, *opts)
110+
repo, err = migrations.MigrateRepository(ctx, t.Doer, t.Owner.Name, *opts, func(format string, args ...interface{}) {
111+
message := models.TranslatableMessage{
112+
Format: format,
113+
Args: args,
114+
}
115+
json := jsoniter.ConfigCompatibleWithStandardLibrary
116+
bs, _ := json.Marshal(message)
117+
t.Message = string(bs)
118+
_ = t.UpdateCols("message")
119+
})
110120
if err == nil {
111121
log.Trace("Repository migrated [%d]: %s/%s", repo.ID, t.Owner.Name, repo.Name)
112122
return

options/locale/locale_en-US.ini

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,11 +824,19 @@ migrated_from_fake = Migrated From %[1]s
824824
migrate.migrate = Migrate From %s
825825
migrate.migrating = Migrating from <b>%s</b> ...
826826
migrate.migrating_failed = Migrating from <b>%s</b> failed.
827+
migrate.migrating_failed.error = Error: %s
827828
migrate.github.description = Migrating data from Github.com or Github Enterprise.
828829
migrate.git.description = Migrating or Mirroring git data from Git services
829830
migrate.gitlab.description = Migrating data from GitLab.com or Self-Hosted gitlab server.
830831
migrate.gitea.description = Migrating data from Gitea.com or Self-Hosted Gitea server.
831832
migrate.gogs.description = Migrating data from notabug.org or other Self-Hosted Gogs server.
833+
migrate.migrating_git = Migrating Git Data
834+
migrate.migrating_topics = Migrating Topics
835+
migrate.migrating_milestones = Migrating Milestones
836+
migrate.migrating_labels = Migrating Labels
837+
migrate.migrating_releases = Migrating Releases
838+
migrate.migrating_issues = Migrating Issues
839+
migrate.migrating_pulls = Migrating Pull Requests
832840

833841
mirror_from = mirror of
834842
forked_from = forked from

routers/api/v1/repo/migrate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ func Migrate(ctx *context.APIContext) {
199199
}
200200
}()
201201

202-
if _, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), ctx.User, repoOwner.Name, opts); err != nil {
202+
if _, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), ctx.User, repoOwner.Name, opts, nil); err != nil {
203203
handleMigrateError(ctx, repoOwner, remoteAddr, err)
204204
return
205205
}

routers/web/user/task.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"code.gitea.io/gitea/models"
1111
"code.gitea.io/gitea/modules/context"
12+
jsoniter "github.com/json-iterator/go"
1213
)
1314

1415
// TaskStatus returns task's status
@@ -21,9 +22,24 @@ func TaskStatus(ctx *context.Context) {
2122
return
2223
}
2324

25+
message := task.Message
26+
27+
if task.Message != "" && task.Message[0] == '{' {
28+
// assume message is actually a translatable string
29+
json := jsoniter.ConfigCompatibleWithStandardLibrary
30+
var translatableMessage models.TranslatableMessage
31+
if err := json.Unmarshal([]byte(message), &translatableMessage); err != nil {
32+
translatableMessage = models.TranslatableMessage{
33+
Format: "migrate.migrating_failed.error",
34+
Args: []interface{}{task.Message},
35+
}
36+
}
37+
message = ctx.Tr(translatableMessage.Format, translatableMessage.Args...)
38+
}
39+
2440
ctx.JSON(http.StatusOK, map[string]interface{}{
2541
"status": task.Status,
26-
"err": task.Errors,
42+
"message": message,
2743
"repo-id": task.RepoID,
2844
"repo-name": opts.RepoName,
2945
"start": task.StartTime,

templates/repo/migrate/migrating.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<div class="sixteen wide center aligned centered column">
2323
<div id="repo_migrating_progress">
2424
<p>{{.i18n.Tr "repo.migrate.migrating" .CloneAddr | Safe}}</p>
25+
<p id="repo_migrating_progress_message"></p>
2526
</div>
2627
<div id="repo_migrating_failed" hidden>
2728
<p>{{.i18n.Tr "repo.migrate.migrating_failed" .CloneAddr | Safe}}</p>

web_src/js/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ function initRepoStatusChecker() {
202202
const migrating = $('#repo_migrating');
203203
$('#repo_migrating_failed').hide();
204204
$('#repo_migrating_failed_image').hide();
205+
$('#repo_migrating_progress_message').hide();
205206
if (migrating) {
206207
const task = migrating.attr('task');
207208
if (typeof task === 'undefined') {
@@ -223,9 +224,13 @@ function initRepoStatusChecker() {
223224
$('#repo_migrating').hide();
224225
$('#repo_migrating_failed').show();
225226
$('#repo_migrating_failed_image').show();
226-
$('#repo_migrating_failed_error').text(xhr.responseJSON.err);
227+
$('#repo_migrating_failed_error').text(xhr.responseJSON.message);
227228
return;
228229
}
230+
if (xhr.responseJSON.message) {
231+
$('#repo_migrating_progress_message').show();
232+
$('#repo_migrating_progress_message').text(xhr.responseJSON.message);
233+
}
229234
setTimeout(() => {
230235
initRepoStatusChecker();
231236
}, 2000);

0 commit comments

Comments
 (0)