aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--routers/repo/http.go59
1 files changed, 58 insertions, 1 deletions
diff --git a/routers/repo/http.go b/routers/repo/http.go
index b97feed51d..d0a2b289b7 100644
--- a/routers/repo/http.go
+++ b/routers/repo/http.go
@@ -10,6 +10,7 @@ import (
"compress/gzip"
gocontext "context"
"fmt"
+ "io/ioutil"
"net/http"
"os"
"os/exec"
@@ -17,6 +18,7 @@ import (
"regexp"
"strconv"
"strings"
+ "sync"
"time"
"code.gitea.io/gitea/models"
@@ -65,11 +67,12 @@ func HTTP(ctx *context.Context) {
return
}
- var isPull bool
+ var isPull, receivePack bool
service := ctx.Query("service")
if service == "git-receive-pack" ||
strings.HasSuffix(ctx.Req.URL.Path, "git-receive-pack") {
isPull = false
+ receivePack = true
} else if service == "git-upload-pack" ||
strings.HasSuffix(ctx.Req.URL.Path, "git-upload-pack") {
isPull = true
@@ -282,6 +285,11 @@ func HTTP(ctx *context.Context) {
}
if !repoExist {
+ if !receivePack {
+ ctx.HandleText(http.StatusNotFound, "Repository not found")
+ return
+ }
+
if owner.IsOrganization() && !setting.Repository.EnablePushCreateOrg {
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for organizations.")
return
@@ -290,6 +298,13 @@ func HTTP(ctx *context.Context) {
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for users.")
return
}
+
+ // Return dummy payload if GET receive-pack
+ if ctx.Req.Method == http.MethodGet {
+ dummyInfoRefs(ctx)
+ return
+ }
+
repo, err = repo_service.PushCreateRepo(authUser, owner, reponame)
if err != nil {
log.Error("pushCreateRepo: %v", err)
@@ -352,6 +367,48 @@ func HTTP(ctx *context.Context) {
ctx.NotFound("Smart Git HTTP", nil)
}
+var (
+ infoRefsCache []byte
+ infoRefsOnce sync.Once
+)
+
+func dummyInfoRefs(ctx *context.Context) {
+ infoRefsOnce.Do(func() {
+ tmpDir, err := ioutil.TempDir(os.TempDir(), "gitea-info-refs-cache")
+ if err != nil {
+ log.Error("Failed to create temp dir for git-receive-pack cache: %v", err)
+ return
+ }
+
+ defer func() {
+ if err := os.RemoveAll(tmpDir); err != nil {
+ log.Error("RemoveAll: %v", err)
+ }
+ }()
+
+ if err := git.InitRepository(tmpDir, true); err != nil {
+ log.Error("Failed to init bare repo for git-receive-pack cache: %v", err)
+ return
+ }
+
+ refs, err := git.NewCommand("receive-pack", "--stateless-rpc", "--advertise-refs", ".").RunInDirBytes(tmpDir)
+ if err != nil {
+ log.Error(fmt.Sprintf("%v - %s", err, string(refs)))
+ }
+
+ log.Debug("populating infoRefsCache: \n%s", string(refs))
+ infoRefsCache = refs
+ })
+
+ ctx.Header().Set("Expires", "Fri, 01 Jan 1980 00:00:00 GMT")
+ ctx.Header().Set("Pragma", "no-cache")
+ ctx.Header().Set("Cache-Control", "no-cache, max-age=0, must-revalidate")
+ ctx.Header().Set("Content-Type", "application/x-git-receive-pack-advertisement")
+ _, _ = ctx.Write(packetWrite("# service=git-receive-pack\n"))
+ _, _ = ctx.Write([]byte("0000"))
+ _, _ = ctx.Write(infoRefsCache)
+}
+
type serviceConfig struct {
UploadPack bool
ReceivePack bool