@@ -78,6 +78,7 @@ type Repository struct {
78
78
NumClosedIssues int
79
79
NumOpenIssues int `xorm:"-"`
80
80
IsPrivate bool
81
+ IsMirror bool
81
82
IsBare bool
82
83
IsGoget bool
83
84
DefaultBranch string
@@ -119,13 +120,92 @@ func IsLegalName(repoName string) bool {
119
120
return true
120
121
}
121
122
123
+ // Mirror represents a mirror information of repository.
124
+ type Mirror struct {
125
+ Id int64
126
+ RepoId int64
127
+ RepoName string // <user name>/<repo name>
128
+ Interval int // Hour.
129
+ Updated time.Time `xorm:"UPDATED"`
130
+ NextUpdate time.Time
131
+ }
132
+
133
+ // MirrorRepository creates a mirror repository from source.
134
+ func MirrorRepository (repoId int64 , userName , repoName , repoPath , url string ) error {
135
+ _ , stderr , err := com .ExecCmd ("git" , "clone" , "--mirror" , url , repoPath )
136
+ if err != nil {
137
+ return err
138
+ } else if strings .Contains (stderr , "fatal:" ) {
139
+ return errors .New (stderr )
140
+ }
141
+
142
+ if _ , err = orm .InsertOne (& Mirror {
143
+ RepoId : repoId ,
144
+ RepoName : strings .ToLower (userName + "/" + repoName ),
145
+ Interval : 24 ,
146
+ NextUpdate : time .Now ().Add (24 * time .Hour ),
147
+ }); err != nil {
148
+ return err
149
+ }
150
+
151
+ return git .UnpackRefs (repoPath )
152
+ }
153
+
154
+ // MigrateRepository migrates a existing repository from other project hosting.
155
+ func MigrateRepository (user * User , name , desc string , private , mirror bool , url string ) (* Repository , error ) {
156
+ repo , err := CreateRepository (user , name , desc , "" , "" , private , mirror , false )
157
+ if err != nil {
158
+ return nil , err
159
+ }
160
+
161
+ // Clone to temprory path and do the init commit.
162
+ tmpDir := filepath .Join (os .TempDir (), fmt .Sprintf ("%d" , time .Now ().Nanosecond ()))
163
+ os .MkdirAll (tmpDir , os .ModePerm )
164
+
165
+ repoPath := RepoPath (user .Name , name )
166
+
167
+ repo .IsBare = false
168
+ if mirror {
169
+ if err = MirrorRepository (repo .Id , user .Name , repo .Name , repoPath , url ); err != nil {
170
+ return repo , err
171
+ }
172
+ repo .IsMirror = true
173
+ return repo , UpdateRepository (repo )
174
+ }
175
+
176
+ // Clone from local repository.
177
+ _ , stderr , err := com .ExecCmd ("git" , "clone" , repoPath , tmpDir )
178
+ if err != nil {
179
+ return repo , err
180
+ } else if strings .Contains (stderr , "fatal:" ) {
181
+ return repo , errors .New ("git clone: " + stderr )
182
+ }
183
+
184
+ // Pull data from source.
185
+ _ , stderr , err = com .ExecCmdDir (tmpDir , "git" , "pull" , url )
186
+ if err != nil {
187
+ return repo , err
188
+ } else if strings .Contains (stderr , "fatal:" ) {
189
+ return repo , errors .New ("git pull: " + stderr )
190
+ }
191
+
192
+ // Push data to local repository.
193
+ if _ , stderr , err = com .ExecCmdDir (tmpDir , "git" , "push" , "origin" , "master" ); err != nil {
194
+ return repo , err
195
+ } else if strings .Contains (stderr , "fatal:" ) {
196
+ return repo , errors .New ("git push: " + stderr )
197
+ }
198
+
199
+ return repo , UpdateRepository (repo )
200
+ }
201
+
122
202
// CreateRepository creates a repository for given user or orgnaziation.
123
- func CreateRepository (user * User , repoName , desc , repoLang , license string , private bool , initReadme bool ) (* Repository , error ) {
124
- if ! IsLegalName (repoName ) {
203
+ func CreateRepository (user * User , name , desc , lang , license string , private , mirror , initReadme bool ) (* Repository , error ) {
204
+ if ! IsLegalName (name ) {
125
205
return nil , ErrRepoNameIllegal
126
206
}
127
207
128
- isExist , err := IsRepositoryExist (user , repoName )
208
+ isExist , err := IsRepositoryExist (user , name )
129
209
if err != nil {
130
210
return nil , err
131
211
} else if isExist {
@@ -134,13 +214,13 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
134
214
135
215
repo := & Repository {
136
216
OwnerId : user .Id ,
137
- Name : repoName ,
138
- LowerName : strings .ToLower (repoName ),
217
+ Name : name ,
218
+ LowerName : strings .ToLower (name ),
139
219
Description : desc ,
140
220
IsPrivate : private ,
141
- IsBare : repoLang == "" && license == "" && ! initReadme ,
221
+ IsBare : lang == "" && license == "" && ! initReadme ,
142
222
}
143
- repoPath := RepoPath (user .Name , repoName )
223
+ repoPath := RepoPath (user .Name , repo . Name )
144
224
145
225
sess := orm .NewSession ()
146
226
defer sess .Close ()
@@ -150,23 +230,27 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
150
230
if err2 := os .RemoveAll (repoPath ); err2 != nil {
151
231
log .Error ("repo.CreateRepository(repo): %v" , err )
152
232
return nil , errors .New (fmt .Sprintf (
153
- "delete repo directory %s/%s failed(1): %v" , user .Name , repoName , err2 ))
233
+ "delete repo directory %s/%s failed(1): %v" , user .Name , repo . Name , err2 ))
154
234
}
155
235
sess .Rollback ()
156
236
return nil , err
157
237
}
158
238
239
+ mode := AU_WRITABLE
240
+ if mirror {
241
+ mode = AU_READABLE
242
+ }
159
243
access := Access {
160
244
UserName : user .LowerName ,
161
245
RepoName : strings .ToLower (path .Join (user .Name , repo .Name )),
162
- Mode : AU_WRITABLE ,
246
+ Mode : mode ,
163
247
}
164
248
if _ , err = sess .Insert (& access ); err != nil {
165
249
sess .Rollback ()
166
250
if err2 := os .RemoveAll (repoPath ); err2 != nil {
167
251
log .Error ("repo.CreateRepository(access): %v" , err )
168
252
return nil , errors .New (fmt .Sprintf (
169
- "delete repo directory %s/%s failed(2): %v" , user .Name , repoName , err2 ))
253
+ "delete repo directory %s/%s failed(2): %v" , user .Name , repo . Name , err2 ))
170
254
}
171
255
return nil , err
172
256
}
@@ -177,7 +261,7 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
177
261
if err2 := os .RemoveAll (repoPath ); err2 != nil {
178
262
log .Error ("repo.CreateRepository(repo count): %v" , err )
179
263
return nil , errors .New (fmt .Sprintf (
180
- "delete repo directory %s/%s failed(3): %v" , user .Name , repoName , err2 ))
264
+ "delete repo directory %s/%s failed(3): %v" , user .Name , repo . Name , err2 ))
181
265
}
182
266
return nil , err
183
267
}
@@ -187,7 +271,7 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
187
271
if err2 := os .RemoveAll (repoPath ); err2 != nil {
188
272
log .Error ("repo.CreateRepository(commit): %v" , err )
189
273
return nil , errors .New (fmt .Sprintf (
190
- "delete repo directory %s/%s failed(3): %v" , user .Name , repoName , err2 ))
274
+ "delete repo directory %s/%s failed(3): %v" , user .Name , repo . Name , err2 ))
191
275
}
192
276
return nil , err
193
277
}
@@ -202,7 +286,12 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
202
286
log .Error ("repo.CreateRepository(WatchRepo): %v" , err )
203
287
}
204
288
205
- if err = initRepository (repoPath , user , repo , initReadme , repoLang , license ); err != nil {
289
+ // No need for init for mirror.
290
+ if mirror {
291
+ return repo , nil
292
+ }
293
+
294
+ if err = initRepository (repoPath , user , repo , initReadme , lang , license ); err != nil {
206
295
return nil , err
207
296
}
208
297
@@ -304,9 +393,13 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep
304
393
tmpDir := filepath .Join (os .TempDir (), fmt .Sprintf ("%d" , time .Now ().Nanosecond ()))
305
394
os .MkdirAll (tmpDir , os .ModePerm )
306
395
307
- if _ , _ , err := com .ExecCmd ("git" , "clone" , repoPath , tmpDir ); err != nil {
396
+ _ , stderr , err := com .ExecCmd ("git" , "clone" , repoPath , tmpDir )
397
+ if err != nil {
308
398
return err
309
399
}
400
+ if len (stderr ) > 0 {
401
+ log .Trace ("repo.initRepository(git clone): %s" , stderr )
402
+ }
310
403
311
404
// README
312
405
if initReadme {
@@ -379,6 +472,7 @@ func GetRepos(num, offset int) ([]UserRepo, error) {
379
472
return urepos , nil
380
473
}
381
474
475
+ // RepoPath returns repository path by given user and repository name.
382
476
func RepoPath (userName , repoName string ) string {
383
477
return filepath .Join (UserPath (userName ), strings .ToLower (repoName )+ ".git" )
384
478
}
@@ -519,15 +613,20 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) {
519
613
sess .Rollback ()
520
614
return err
521
615
}
522
- rawSql := "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?"
523
- if _ , err = sess .Exec (rawSql , userId ); err != nil {
616
+ if _ , err := sess .Delete (& Action {RepoId : repo .Id }); err != nil {
524
617
sess .Rollback ()
525
618
return err
526
619
}
527
620
if _ , err = sess .Delete (& Watch {RepoId : repoId }); err != nil {
528
621
sess .Rollback ()
529
622
return err
530
623
}
624
+
625
+ rawSql := "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?"
626
+ if _ , err = sess .Exec (rawSql , userId ); err != nil {
627
+ sess .Rollback ()
628
+ return err
629
+ }
531
630
if err = sess .Commit (); err != nil {
532
631
sess .Rollback ()
533
632
return err
0 commit comments