@@ -10,13 +10,15 @@ import (
1010 "compress/gzip"
1111 gocontext "context"
1212 "fmt"
13+ "io/ioutil"
1314 "net/http"
1415 "os"
1516 "os/exec"
1617 "path"
1718 "regexp"
1819 "strconv"
1920 "strings"
21+ "sync"
2022 "time"
2123
2224 "code.gitea.io/gitea/models"
@@ -65,11 +67,12 @@ func HTTP(ctx *context.Context) {
6567 return
6668 }
6769
68- var isPull bool
70+ var isPull , receivePack bool
6971 service := ctx .Query ("service" )
7072 if service == "git-receive-pack" ||
7173 strings .HasSuffix (ctx .Req .URL .Path , "git-receive-pack" ) {
7274 isPull = false
75+ receivePack = true
7376 } else if service == "git-upload-pack" ||
7477 strings .HasSuffix (ctx .Req .URL .Path , "git-upload-pack" ) {
7578 isPull = true
@@ -282,6 +285,11 @@ func HTTP(ctx *context.Context) {
282285 }
283286
284287 if ! repoExist {
288+ if ! receivePack {
289+ ctx .HandleText (http .StatusNotFound , "Repository not found" )
290+ return
291+ }
292+
285293 if owner .IsOrganization () && ! setting .Repository .EnablePushCreateOrg {
286294 ctx .HandleText (http .StatusForbidden , "Push to create is not enabled for organizations." )
287295 return
@@ -290,6 +298,13 @@ func HTTP(ctx *context.Context) {
290298 ctx .HandleText (http .StatusForbidden , "Push to create is not enabled for users." )
291299 return
292300 }
301+
302+ // Return dummy payload if GET receive-pack
303+ if ctx .Req .Method == http .MethodGet {
304+ dummyInfoRefs (ctx )
305+ return
306+ }
307+
293308 repo , err = repo_service .PushCreateRepo (authUser , owner , reponame )
294309 if err != nil {
295310 log .Error ("pushCreateRepo: %v" , err )
@@ -352,6 +367,48 @@ func HTTP(ctx *context.Context) {
352367 ctx .NotFound ("Smart Git HTTP" , nil )
353368}
354369
370+ var (
371+ infoRefsCache []byte
372+ infoRefsOnce sync.Once
373+ )
374+
375+ func dummyInfoRefs (ctx * context.Context ) {
376+ infoRefsOnce .Do (func () {
377+ tmpDir , err := ioutil .TempDir (os .TempDir (), "gitea-info-refs-cache" )
378+ if err != nil {
379+ log .Error ("Failed to create temp dir for git-receive-pack cache: %v" , err )
380+ return
381+ }
382+
383+ defer func () {
384+ if err := os .RemoveAll (tmpDir ); err != nil {
385+ log .Error ("RemoveAll: %v" , err )
386+ }
387+ }()
388+
389+ if err := git .InitRepository (tmpDir , true ); err != nil {
390+ log .Error ("Failed to init bare repo for git-receive-pack cache: %v" , err )
391+ return
392+ }
393+
394+ refs , err := git .NewCommand ("receive-pack" , "--stateless-rpc" , "--advertise-refs" , "." ).RunInDirBytes (tmpDir )
395+ if err != nil {
396+ log .Error (fmt .Sprintf ("%v - %s" , err , string (refs )))
397+ }
398+
399+ log .Debug ("populating infoRefsCache: \n %s" , string (refs ))
400+ infoRefsCache = refs
401+ })
402+
403+ ctx .Header ().Set ("Expires" , "Fri, 01 Jan 1980 00:00:00 GMT" )
404+ ctx .Header ().Set ("Pragma" , "no-cache" )
405+ ctx .Header ().Set ("Cache-Control" , "no-cache, max-age=0, must-revalidate" )
406+ ctx .Header ().Set ("Content-Type" , "application/x-git-receive-pack-advertisement" )
407+ _ , _ = ctx .Write (packetWrite ("# service=git-receive-pack\n " ))
408+ _ , _ = ctx .Write ([]byte ("0000" ))
409+ _ , _ = ctx .Write (infoRefsCache )
410+ }
411+
355412type serviceConfig struct {
356413 UploadPack bool
357414 ReceivePack bool
0 commit comments