Fix push-to-create (#9772)
* 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>
This commit is contained in:
parent
8716752d22
commit
176e7fb5d5
1 changed files with 58 additions and 1 deletions
|
@ -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
|
||||
|
|
Reference in a new issue