7
7
"errors"
8
8
"fmt"
9
9
"strings"
10
+ "time"
10
11
11
- "code.gitea.io/gitea/models"
12
12
admin_model "code.gitea.io/gitea/models/admin"
13
13
"code.gitea.io/gitea/models/db"
14
14
repo_model "code.gitea.io/gitea/models/repo"
@@ -28,13 +28,13 @@ import (
28
28
func handleCreateError (owner * user_model.User , err error ) error {
29
29
switch {
30
30
case repo_model .IsErrReachLimitOfRepo (err ):
31
- return fmt .Errorf ("You have already reached your limit of %d repositories" , owner .MaxCreationLimit ())
31
+ return fmt .Errorf ("you have already reached your limit of %d repositories" , owner .MaxCreationLimit ())
32
32
case repo_model .IsErrRepoAlreadyExist (err ):
33
- return errors .New ("The repository name is already used" )
33
+ return errors .New ("the repository name is already used" )
34
34
case db .IsErrNameReserved (err ):
35
- return fmt .Errorf ("The repository name '%s' is reserved" , err .(db.ErrNameReserved ).Name )
35
+ return fmt .Errorf ("the repository name '%s' is reserved" , err .(db.ErrNameReserved ).Name )
36
36
case db .IsErrNamePatternNotAllowed (err ):
37
- return fmt .Errorf ("The pattern '%s' is not allowed in a repository name" , err .(db.ErrNamePatternNotAllowed ).Pattern )
37
+ return fmt .Errorf ("the pattern '%s' is not allowed in a repository name" , err .(db.ErrNamePatternNotAllowed ).Pattern )
38
38
default :
39
39
return err
40
40
}
@@ -57,22 +57,17 @@ func runMigrateTask(t *admin_model.Task) (err error) {
57
57
log .Error ("FinishMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d] failed: %v" , t .ID , t .DoerID , t .RepoID , t .OwnerID , err )
58
58
}
59
59
60
+ log .Error ("runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d] failed: %v" , t .ID , t .DoerID , t .RepoID , t .OwnerID , err )
61
+
60
62
t .EndTime = timeutil .TimeStampNow ()
61
63
t .Status = structs .TaskStatusFailed
62
64
t .Message = err .Error ()
63
- // Ensure that the repo loaded before we zero out the repo ID from the task - thus ensuring that we can delete it
64
- _ = t .LoadRepo ()
65
65
66
- t .RepoID = 0
67
- if err := t .UpdateCols ("status" , "errors" , "repo_id" , "end_time" ); err != nil {
66
+ if err := t .UpdateCols ("status" , "message" , "end_time" ); err != nil {
68
67
log .Error ("Task UpdateCols failed: %v" , err )
69
68
}
70
69
71
- if t .Repo != nil {
72
- if errDelete := models .DeleteRepository (t .Doer , t .OwnerID , t .Repo .ID ); errDelete != nil {
73
- log .Error ("DeleteRepository: %v" , errDelete )
74
- }
75
- }
70
+ // then, do not delete the repository, otherwise the users won't be able to see the last error
76
71
}()
77
72
78
73
if err = t .LoadRepo (); err != nil {
@@ -100,7 +95,7 @@ func runMigrateTask(t *admin_model.Task) (err error) {
100
95
opts .MigrateToRepoID = t .RepoID
101
96
102
97
pm := process .GetManager ()
103
- ctx , _ , finished := pm .AddContext (graceful .GetManager ().ShutdownContext (), fmt .Sprintf ("MigrateTask: %s/%s" , t .Owner .Name , opts .RepoName ))
98
+ ctx , cancel , finished := pm .AddContext (graceful .GetManager ().ShutdownContext (), fmt .Sprintf ("MigrateTask: %s/%s" , t .Owner .Name , opts .RepoName ))
104
99
defer finished ()
105
100
106
101
t .StartTime = timeutil .TimeStampNow ()
@@ -109,6 +104,23 @@ func runMigrateTask(t *admin_model.Task) (err error) {
109
104
return
110
105
}
111
106
107
+ // check whether the task should be canceled, this goroutine is also managed by process manager
108
+ go func () {
109
+ for {
110
+ select {
111
+ case <- time .After (2 * time .Second ):
112
+ case <- ctx .Done ():
113
+ return
114
+ }
115
+ task , _ := admin_model .GetMigratingTask (t .RepoID )
116
+ if task != nil && task .Status != structs .TaskStatusRunning {
117
+ log .Debug ("MigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d] is canceled due to status is not 'running'" , t .ID , t .DoerID , t .RepoID , t .OwnerID )
118
+ cancel ()
119
+ return
120
+ }
121
+ }
122
+ }()
123
+
112
124
t .Repo , err = migrations .MigrateRepository (ctx , t .Doer , t .Owner .Name , * opts , func (format string , args ... interface {}) {
113
125
message := admin_model.TranslatableMessage {
114
126
Format : format ,
@@ -118,23 +130,24 @@ func runMigrateTask(t *admin_model.Task) (err error) {
118
130
t .Message = string (bs )
119
131
_ = t .UpdateCols ("message" )
120
132
})
133
+
121
134
if err == nil {
122
135
log .Trace ("Repository migrated [%d]: %s/%s" , t .Repo .ID , t .Owner .Name , t .Repo .Name )
123
136
return
124
137
}
125
138
126
139
if repo_model .IsErrRepoAlreadyExist (err ) {
127
- err = errors .New ("The repository name is already used" )
140
+ err = errors .New ("the repository name is already used" )
128
141
return
129
142
}
130
143
131
144
// remoteAddr may contain credentials, so we sanitize it
132
145
err = util .SanitizeErrorCredentialURLs (err )
133
146
if strings .Contains (err .Error (), "Authentication failed" ) ||
134
147
strings .Contains (err .Error (), "could not read Username" ) {
135
- return fmt .Errorf ("Authentication failed: %w" , err )
148
+ return fmt .Errorf ("authentication failed: %w" , err )
136
149
} else if strings .Contains (err .Error (), "fatal:" ) {
137
- return fmt .Errorf ("Migration failed: %w" , err )
150
+ return fmt .Errorf ("migration failed: %w" , err )
138
151
}
139
152
140
153
// do not be tempted to coalesce this line with the return
0 commit comments