diff options
Diffstat (limited to 'routers/repo/http.go')
-rw-r--r-- | routers/repo/http.go | 196 |
1 files changed, 35 insertions, 161 deletions
diff --git a/routers/repo/http.go b/routers/repo/http.go index 4c143f66d0..dc29651847 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -8,20 +8,15 @@ import ( "bytes" "compress/gzip" "fmt" - "io" - "io/ioutil" "net/http" "os" "os/exec" "path" "regexp" - "runtime" "strconv" "strings" "time" - "code.gitea.io/git" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" @@ -59,7 +54,7 @@ func HTTP(ctx *context.Context) { isWiki := false if strings.HasSuffix(reponame, ".wiki") { isWiki = true - reponame = reponame[:len(reponame) - 5] + reponame = reponame[:len(reponame)-5] } repoUser, err := models.GetUserByName(username) @@ -89,6 +84,7 @@ func HTTP(ctx *context.Context) { authUser *models.User authUsername string authPasswd string + environ []string ) // check access @@ -182,94 +178,42 @@ func HTTP(ctx *context.Context) { } } } - } - callback := func(rpc string, input []byte) { - if rpc != "receive-pack" || isWiki { - return + environ = []string{ + models.EnvRepoUsername + "=" + username, + models.EnvRepoName + "=" + reponame, + models.EnvRepoUserSalt + "=" + repoUser.Salt, + models.EnvPusherName + "=" + authUser.Name, + models.EnvPusherID + fmt.Sprintf("=%d", authUser.ID), + models.ProtectedBranchRepoID + fmt.Sprintf("=%d", repo.ID), } - - var lastLine int64 - for { - head := input[lastLine: lastLine + 2] - if head[0] == '0' && head[1] == '0' { - size, err := strconv.ParseInt(string(input[lastLine + 2:lastLine + 4]), 16, 32) - if err != nil { - log.Error(4, "%v", err) - return - } - - if size == 0 { - //fmt.Println(string(input[lastLine:])) - break - } - - line := input[lastLine: lastLine + size] - idx := bytes.IndexRune(line, '\000') - if idx > -1 { - line = line[:idx] - } - - fields := strings.Fields(string(line)) - if len(fields) >= 3 { - oldCommitID := fields[0][4:] - newCommitID := fields[1] - refFullName := fields[2] - - // FIXME: handle error. - if err = models.PushUpdate(models.PushUpdateOptions{ - RefFullName: refFullName, - OldCommitID: oldCommitID, - NewCommitID: newCommitID, - PusherID: authUser.ID, - PusherName: authUser.Name, - RepoUserName: username, - RepoName: reponame, - }); err == nil { - go models.AddTestPullRequestTask(authUser, repo.ID, strings.TrimPrefix(refFullName, git.BranchPrefix), true) - } - - } - lastLine = lastLine + size - } else { - break - } - } - } - - params := make(map[string]string) - - if askAuth { - params[models.ProtectedBranchUserID] = fmt.Sprintf("%d", authUser.ID) - if err == nil { - params[models.ProtectedBranchAccessMode] = accessMode.String() + if isWiki { + environ = append(environ, models.EnvRepoIsWiki+"=true") + } else { + environ = append(environ, models.EnvRepoIsWiki+"=false") } - params[models.ProtectedBranchRepoID] = fmt.Sprintf("%d", repo.ID) } HTTPBackend(ctx, &serviceConfig{ UploadPack: true, ReceivePack: true, - Params: params, - OnSucceed: callback, + Env: environ, })(ctx.Resp, ctx.Req.Request) - - runtime.GC() } type serviceConfig struct { UploadPack bool ReceivePack bool - Params map[string]string - OnSucceed func(rpc string, input []byte) + Env []string } type serviceHandler struct { - cfg *serviceConfig - w http.ResponseWriter - r *http.Request - dir string - file string + cfg *serviceConfig + w http.ResponseWriter + r *http.Request + dir string + file string + environ []string } func (h *serviceHandler) setHeaderNoCache() { @@ -278,42 +222,6 @@ func (h *serviceHandler) setHeaderNoCache() { h.w.Header().Set("Cache-Control", "no-cache, max-age=0, must-revalidate") } -func (h *serviceHandler) getBranch(input []byte) string { - var lastLine int64 - var branchName string - for { - head := input[lastLine : lastLine+2] - if head[0] == '0' && head[1] == '0' { - size, err := strconv.ParseInt(string(input[lastLine+2:lastLine+4]), 16, 32) - if err != nil { - log.Error(4, "%v", err) - return branchName - } - - if size == 0 { - //fmt.Println(string(input[lastLine:])) - break - } - - line := input[lastLine : lastLine+size] - idx := bytes.IndexRune(line, '\000') - if idx > -1 { - line = line[:idx] - } - - fields := strings.Fields(string(line)) - if len(fields) >= 3 { - refFullName := fields[2] - branchName = strings.TrimPrefix(refFullName, git.BranchPrefix) - } - lastLine = lastLine + size - } else { - break - } - } - return branchName -} - func (h *serviceHandler) setHeaderCacheForever() { now := time.Now().Unix() expires := now + 31536000 @@ -370,7 +278,7 @@ func gitCommand(dir string, args ...string) []byte { func getGitConfig(option, dir string) string { out := string(gitCommand(dir, "config", option)) - return out[0: len(out) - 1] + return out[0 : len(out)-1] } func getConfigSetting(service, dir string) bool { @@ -414,13 +322,8 @@ func serviceRPC(h serviceHandler, service string) { h.w.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-result", service)) - var ( - reqBody = h.r.Body - input []byte - br io.Reader - err error - branchName string - ) + var err error + var reqBody = h.r.Body // Handle GZIP. if h.r.Header.Get("Content-Encoding") == "gzip" { @@ -432,52 +335,23 @@ func serviceRPC(h serviceHandler, service string) { } } - if h.cfg.OnSucceed != nil { - input, err = ioutil.ReadAll(reqBody) - if err != nil { - log.GitLogger.Error(2, "fail to read request body: %v", err) - h.w.WriteHeader(http.StatusInternalServerError) - return - } - - branchName = h.getBranch(input) - br = bytes.NewReader(input) - } else { - br = reqBody - } - - // check protected branch - repoID, _ := strconv.ParseInt(h.cfg.Params[models.ProtectedBranchRepoID], 10, 64) - accessMode := models.ParseAccessMode(h.cfg.Params[models.ProtectedBranchAccessMode]) - // skip admin or owner AccessMode - if accessMode == models.AccessModeWrite { - protectBranch, err := models.GetProtectedBranchBy(repoID, branchName) - if err != nil { - log.GitLogger.Error(2, "fail to get protected branch information: %v", err) - h.w.WriteHeader(http.StatusInternalServerError) - return - } - - if protectBranch != nil { - log.GitLogger.Error(2, "protected branches can not be pushed to") - h.w.WriteHeader(http.StatusForbidden) - return - } - } + // set this for allow pre-receive and post-receive execute + h.environ = append(h.environ, "SSH_ORIGINAL_COMMAND="+service) + var stderr bytes.Buffer cmd := exec.Command("git", service, "--stateless-rpc", h.dir) cmd.Dir = h.dir + if service == "receive-pack" { + cmd.Env = append(os.Environ(), h.environ...) + } cmd.Stdout = h.w - cmd.Stdin = br + cmd.Stdin = reqBody + cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - log.GitLogger.Error(2, "fail to serve RPC(%s): %v", service, err) + log.GitLogger.Error(2, "fail to serve RPC(%s): %v - %v", service, err, stderr) h.w.WriteHeader(http.StatusInternalServerError) return } - - if h.cfg.OnSucceed != nil { - h.cfg.OnSucceed(service, input) - } } func serviceUploadPack(h serviceHandler) { @@ -501,7 +375,7 @@ func updateServerInfo(dir string) []byte { } func packetWrite(str string) []byte { - s := strconv.FormatInt(int64(len(str) + 4), 16) + s := strconv.FormatInt(int64(len(str)+4), 16) if len(s)%4 != 0 { s = strings.Repeat("0", 4-len(s)%4) + s } @@ -593,7 +467,7 @@ func HTTPBackend(ctx *context.Context, cfg *serviceConfig) http.HandlerFunc { return } - route.handler(serviceHandler{cfg, w, r, dir, file}) + route.handler(serviceHandler{cfg, w, r, dir, file, cfg.Env}) return } } |