* Fix push-to-create Signed-off-by: jolheiser <john.olheiser@gmail.com> * Check URL path and service Signed-off-by: jolheiser <john.olheiser@gmail.com> * Send dummy payload on receive-pack GET Signed-off-by: jolheiser <john.olheiser@gmail.com> * The space was actually a NUL byte Signed-off-by: jolheiser <john.olheiser@gmail.com> * Use real bare repo instead of manufactured payload Signed-off-by: jolheiser <john.olheiser@gmail.com> Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
parent
c8bb0ecf52
commit
3521177a34
1 changed files with 58 additions and 1 deletions
|
@ -10,6 +10,7 @@ import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
gocontext "context"
|
gocontext "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -17,6 +18,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
@ -65,11 +67,12 @@ func HTTP(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var isPull bool
|
var isPull, receivePack bool
|
||||||
service := ctx.Query("service")
|
service := ctx.Query("service")
|
||||||
if service == "git-receive-pack" ||
|
if service == "git-receive-pack" ||
|
||||||
strings.HasSuffix(ctx.Req.URL.Path, "git-receive-pack") {
|
strings.HasSuffix(ctx.Req.URL.Path, "git-receive-pack") {
|
||||||
isPull = false
|
isPull = false
|
||||||
|
receivePack = true
|
||||||
} else if service == "git-upload-pack" ||
|
} else if service == "git-upload-pack" ||
|
||||||
strings.HasSuffix(ctx.Req.URL.Path, "git-upload-pack") {
|
strings.HasSuffix(ctx.Req.URL.Path, "git-upload-pack") {
|
||||||
isPull = true
|
isPull = true
|
||||||
|
@ -282,6 +285,11 @@ func HTTP(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !repoExist {
|
if !repoExist {
|
||||||
|
if !receivePack {
|
||||||
|
ctx.HandleText(http.StatusNotFound, "Repository not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if owner.IsOrganization() && !setting.Repository.EnablePushCreateOrg {
|
if owner.IsOrganization() && !setting.Repository.EnablePushCreateOrg {
|
||||||
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for organizations.")
|
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for organizations.")
|
||||||
return
|
return
|
||||||
|
@ -290,6 +298,13 @@ func HTTP(ctx *context.Context) {
|
||||||
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for users.")
|
ctx.HandleText(http.StatusForbidden, "Push to create is not enabled for users.")
|
||||||
return
|
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)
|
repo, err = repo_service.PushCreateRepo(authUser, owner, reponame)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("pushCreateRepo: %v", err)
|
log.Error("pushCreateRepo: %v", err)
|
||||||
|
@ -352,6 +367,48 @@ func HTTP(ctx *context.Context) {
|
||||||
ctx.NotFound("Smart Git HTTP", nil)
|
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 {
|
type serviceConfig struct {
|
||||||
UploadPack bool
|
UploadPack bool
|
||||||
ReceivePack bool
|
ReceivePack bool
|
||||||
|
|
Reference in a new issue