@@ -100,29 +100,29 @@ func HTTP(ctx *context.Context) {
100
100
return
101
101
}
102
102
103
+ repoExist := true
103
104
repo , err := models .GetRepositoryByName (owner .ID , reponame )
104
105
if err != nil {
105
106
if models .IsErrRepoNotExist (err ) {
106
- redirectRepoID , err := models .LookupRepoRedirect (owner .ID , reponame )
107
- if err == nil {
107
+ if redirectRepoID , err := models .LookupRepoRedirect (owner .ID , reponame ); err == nil {
108
108
context .RedirectToRepo (ctx , redirectRepoID )
109
- } else {
110
- ctx .NotFoundOrServerError ("GetRepositoryByName" , models .IsErrRepoRedirectNotExist , err )
109
+ return
111
110
}
111
+ repoExist = false
112
112
} else {
113
113
ctx .ServerError ("GetRepositoryByName" , err )
114
+ return
114
115
}
115
- return
116
116
}
117
117
118
118
// Don't allow pushing if the repo is archived
119
- if repo .IsArchived && ! isPull {
119
+ if repoExist && repo .IsArchived && ! isPull {
120
120
ctx .HandleText (http .StatusForbidden , "This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests." )
121
121
return
122
122
}
123
123
124
124
// Only public pull don't need auth.
125
- isPublicPull := ! repo .IsPrivate && isPull
125
+ isPublicPull := repoExist && ! repo .IsPrivate && isPull
126
126
var (
127
127
askAuth = ! isPublicPull || setting .Service .RequireSignInView
128
128
authUser * models.User
@@ -243,28 +243,29 @@ func HTTP(ctx *context.Context) {
243
243
}
244
244
}
245
245
246
- perm , err := models .GetUserRepoPermission (repo , authUser )
247
- if err != nil {
248
- ctx .ServerError ("GetUserRepoPermission" , err )
249
- return
250
- }
246
+ if repoExist {
247
+ perm , err := models .GetUserRepoPermission (repo , authUser )
248
+ if err != nil {
249
+ ctx .ServerError ("GetUserRepoPermission" , err )
250
+ return
251
+ }
251
252
252
- if ! perm .CanAccess (accessMode , unitType ) {
253
- ctx .HandleText (http .StatusForbidden , "User permission denied" )
254
- return
255
- }
253
+ if ! perm .CanAccess (accessMode , unitType ) {
254
+ ctx .HandleText (http .StatusForbidden , "User permission denied" )
255
+ return
256
+ }
256
257
257
- if ! isPull && repo .IsMirror {
258
- ctx .HandleText (http .StatusForbidden , "mirror repository is read-only" )
259
- return
258
+ if ! isPull && repo .IsMirror {
259
+ ctx .HandleText (http .StatusForbidden , "mirror repository is read-only" )
260
+ return
261
+ }
260
262
}
261
263
262
264
environ = []string {
263
265
models .EnvRepoUsername + "=" + username ,
264
266
models .EnvRepoName + "=" + reponame ,
265
267
models .EnvPusherName + "=" + authUser .Name ,
266
268
models .EnvPusherID + fmt .Sprintf ("=%d" , authUser .ID ),
267
- models .ProtectedBranchRepoID + fmt .Sprintf ("=%d" , repo .ID ),
268
269
models .EnvIsDeployKey + "=false" ,
269
270
}
270
271
@@ -279,6 +280,25 @@ func HTTP(ctx *context.Context) {
279
280
}
280
281
}
281
282
283
+ if ! repoExist {
284
+ if owner .IsOrganization () && ! setting .Repository .EnablePushCreateOrg {
285
+ ctx .HandleText (http .StatusForbidden , "Push to create is not enabled for organizations." )
286
+ return
287
+ }
288
+ if ! owner .IsOrganization () && ! setting .Repository .EnablePushCreateUser {
289
+ ctx .HandleText (http .StatusForbidden , "Push to create is not enabled for users." )
290
+ return
291
+ }
292
+ repo , err = pushCreateRepo (authUser , owner , reponame )
293
+ if err != nil {
294
+ log .Error ("pushCreateRepo: %v" , err )
295
+ ctx .Status (http .StatusNotFound )
296
+ return
297
+ }
298
+ }
299
+
300
+ environ = append (environ , models .ProtectedBranchRepoID + fmt .Sprintf ("=%d" , repo .ID ))
301
+
282
302
w := ctx .Resp
283
303
r := ctx .Req .Request
284
304
cfg := & serviceConfig {
@@ -331,6 +351,37 @@ func HTTP(ctx *context.Context) {
331
351
ctx .NotFound ("Smart Git HTTP" , nil )
332
352
}
333
353
354
+ func pushCreateRepo (authUser , owner * models.User , repoName string ) (* models.Repository , error ) {
355
+ if ! authUser .IsAdmin {
356
+ if owner .IsOrganization () {
357
+ team , err := owner .GetOwnerTeam ()
358
+ if err != nil {
359
+ return nil , err
360
+ }
361
+ if ! team .IsMember (authUser .ID ) {
362
+ return nil , fmt .Errorf ("non-owners cannot push-create repository for an org" )
363
+ }
364
+ } else if authUser .ID != owner .ID {
365
+ return nil , fmt .Errorf ("cannot push-create repository for another user" )
366
+ }
367
+ }
368
+
369
+ repo , err := models .CreateRepository (authUser , owner , models.CreateRepoOptions {
370
+ Name : repoName ,
371
+ IsPrivate : true ,
372
+ })
373
+ if err == nil {
374
+ return repo , nil
375
+ }
376
+
377
+ if repo != nil {
378
+ if errDelete := models .DeleteRepository (authUser , owner .ID , repo .ID ); errDelete != nil {
379
+ log .Error ("DeleteRepository: %v" , errDelete )
380
+ }
381
+ }
382
+ return repo , err
383
+ }
384
+
334
385
type serviceConfig struct {
335
386
UploadPack bool
336
387
ReceivePack bool
0 commit comments