* move all database operations from hook command to web command and instead of internal routes * bug fixed * adjust the import path sequences * remove unused return value on hookSetuptags/v1.21.12.1
| @@ -7,20 +7,18 @@ package cmd | |||
| import ( | |||
| "bufio" | |||
| "bytes" | |||
| "crypto/tls" | |||
| "fmt" | |||
| "os" | |||
| "path/filepath" | |||
| "strconv" | |||
| "strings" | |||
| "code.gitea.io/git" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/base" | |||
| "code.gitea.io/gitea/modules/httplib" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/private" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "github.com/Unknwon/com" | |||
| "github.com/urfave/cli" | |||
| ) | |||
| @@ -64,6 +62,12 @@ var ( | |||
| } | |||
| ) | |||
| func hookSetup(logPath string) { | |||
| setting.NewContext() | |||
| log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath)) | |||
| models.LoadConfigs() | |||
| } | |||
| func runHookPreReceive(c *cli.Context) error { | |||
| if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { | |||
| return nil | |||
| @@ -75,9 +79,7 @@ func runHookPreReceive(c *cli.Context) error { | |||
| setting.CustomConf = c.GlobalString("config") | |||
| } | |||
| if err := setup("hooks/pre-receive.log"); err != nil { | |||
| fail("Hook pre-receive init failed", fmt.Sprintf("setup: %v", err)) | |||
| } | |||
| hookSetup("hooks/pre-receive.log") | |||
| // the environment setted on serv command | |||
| repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64) | |||
| @@ -119,18 +121,20 @@ func runHookPreReceive(c *cli.Context) error { | |||
| }*/ | |||
| branchName := strings.TrimPrefix(refFullName, git.BranchPrefix) | |||
| protectBranch, err := models.GetProtectedBranchBy(repoID, branchName) | |||
| protectBranch, err := private.GetProtectedBranchBy(repoID, branchName) | |||
| if err != nil { | |||
| log.GitLogger.Fatal(2, "retrieve protected branches information failed") | |||
| } | |||
| if protectBranch != nil { | |||
| // check and deletion | |||
| if newCommitID == git.EmptySHA { | |||
| fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "") | |||
| } else { | |||
| fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "") | |||
| //fail(fmt.Sprintf("branch %s is protected from force push", branchName), "") | |||
| if !protectBranch.CanPush { | |||
| // check and deletion | |||
| if newCommitID == git.EmptySHA { | |||
| fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "") | |||
| } else { | |||
| fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "") | |||
| //fail(fmt.Sprintf("branch %s is protected from force push", branchName), "") | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -149,9 +153,7 @@ func runHookUpdate(c *cli.Context) error { | |||
| setting.CustomConf = c.GlobalString("config") | |||
| } | |||
| if err := setup("hooks/update.log"); err != nil { | |||
| fail("Hook update init failed", fmt.Sprintf("setup: %v", err)) | |||
| } | |||
| hookSetup("hooks/update.log") | |||
| return nil | |||
| } | |||
| @@ -167,13 +169,10 @@ func runHookPostReceive(c *cli.Context) error { | |||
| setting.CustomConf = c.GlobalString("config") | |||
| } | |||
| if err := setup("hooks/post-receive.log"); err != nil { | |||
| fail("Hook post-receive init failed", fmt.Sprintf("setup: %v", err)) | |||
| } | |||
| hookSetup("hooks/post-receive.log") | |||
| // the environment setted on serv command | |||
| repoUser := os.Getenv(models.EnvRepoUsername) | |||
| repoUserSalt := os.Getenv(models.EnvRepoUserSalt) | |||
| isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") | |||
| repoName := os.Getenv(models.EnvRepoName) | |||
| pusherID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64) | |||
| @@ -199,7 +198,7 @@ func runHookPostReceive(c *cli.Context) error { | |||
| newCommitID := string(fields[1]) | |||
| refFullName := string(fields[2]) | |||
| if err := models.PushUpdate(models.PushUpdateOptions{ | |||
| if err := private.PushUpdate(models.PushUpdateOptions{ | |||
| RefFullName: refFullName, | |||
| OldCommitID: oldCommitID, | |||
| NewCommitID: newCommitID, | |||
| @@ -210,23 +209,6 @@ func runHookPostReceive(c *cli.Context) error { | |||
| }); err != nil { | |||
| log.GitLogger.Error(2, "Update: %v", err) | |||
| } | |||
| // Ask for running deliver hook and test pull request tasks. | |||
| reqURL := setting.LocalURL + repoUser + "/" + repoName + "/tasks/trigger?branch=" + | |||
| strings.TrimPrefix(refFullName, git.BranchPrefix) + "&secret=" + base.EncodeMD5(repoUserSalt) + "&pusher=" + com.ToStr(pusherID) | |||
| log.GitLogger.Trace("Trigger task: %s", reqURL) | |||
| resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{ | |||
| InsecureSkipVerify: true, | |||
| }).Response() | |||
| if err == nil { | |||
| resp.Body.Close() | |||
| if resp.StatusCode/100 != 2 { | |||
| log.GitLogger.Error(2, "Failed to trigger task: not 2xx response code") | |||
| } | |||
| } else { | |||
| log.GitLogger.Error(2, "Failed to trigger task: %v", err) | |||
| } | |||
| } | |||
| return nil | |||
| @@ -65,11 +65,11 @@ type PushUpdateOptions struct { | |||
| // PushUpdate must be called for any push actions in order to | |||
| // generates necessary push action history feeds. | |||
| func PushUpdate(opts PushUpdateOptions) (err error) { | |||
| func PushUpdate(opts PushUpdateOptions) (repo *Repository, err error) { | |||
| isNewRef := opts.OldCommitID == git.EmptySHA | |||
| isDelRef := opts.NewCommitID == git.EmptySHA | |||
| if isNewRef && isDelRef { | |||
| return fmt.Errorf("Old and new revisions are both %s", git.EmptySHA) | |||
| return nil, fmt.Errorf("Old and new revisions are both %s", git.EmptySHA) | |||
| } | |||
| repoPath := RepoPath(opts.RepoUserName, opts.RepoName) | |||
| @@ -77,28 +77,28 @@ func PushUpdate(opts PushUpdateOptions) (err error) { | |||
| gitUpdate := exec.Command("git", "update-server-info") | |||
| gitUpdate.Dir = repoPath | |||
| if err = gitUpdate.Run(); err != nil { | |||
| return fmt.Errorf("Failed to call 'git update-server-info': %v", err) | |||
| return nil, fmt.Errorf("Failed to call 'git update-server-info': %v", err) | |||
| } | |||
| if isDelRef { | |||
| log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %s", | |||
| opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName) | |||
| return nil | |||
| owner, err := GetUserByName(opts.RepoUserName) | |||
| if err != nil { | |||
| return nil, fmt.Errorf("GetUserByName: %v", err) | |||
| } | |||
| gitRepo, err := git.OpenRepository(repoPath) | |||
| repo, err = GetRepositoryByName(owner.ID, opts.RepoName) | |||
| if err != nil { | |||
| return fmt.Errorf("OpenRepository: %v", err) | |||
| return nil, fmt.Errorf("GetRepositoryByName: %v", err) | |||
| } | |||
| owner, err := GetUserByName(opts.RepoUserName) | |||
| if err != nil { | |||
| return fmt.Errorf("GetUserByName: %v", err) | |||
| if isDelRef { | |||
| log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %s", | |||
| opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName) | |||
| return repo, nil | |||
| } | |||
| repo, err := GetRepositoryByName(owner.ID, opts.RepoName) | |||
| gitRepo, err := git.OpenRepository(repoPath) | |||
| if err != nil { | |||
| return fmt.Errorf("GetRepositoryByName: %v", err) | |||
| return nil, fmt.Errorf("OpenRepository: %v", err) | |||
| } | |||
| if err = repo.UpdateSize(); err != nil { | |||
| @@ -116,14 +116,14 @@ func PushUpdate(opts PushUpdateOptions) (err error) { | |||
| NewCommitID: opts.NewCommitID, | |||
| Commits: &PushCommits{}, | |||
| }); err != nil { | |||
| return fmt.Errorf("CommitRepoAction (tag): %v", err) | |||
| return nil, fmt.Errorf("CommitRepoAction (tag): %v", err) | |||
| } | |||
| return nil | |||
| return repo, nil | |||
| } | |||
| newCommit, err := gitRepo.GetCommit(opts.NewCommitID) | |||
| if err != nil { | |||
| return fmt.Errorf("gitRepo.GetCommit: %v", err) | |||
| return nil, fmt.Errorf("gitRepo.GetCommit: %v", err) | |||
| } | |||
| // Push new branch. | |||
| @@ -131,12 +131,12 @@ func PushUpdate(opts PushUpdateOptions) (err error) { | |||
| if isNewRef { | |||
| l, err = newCommit.CommitsBeforeLimit(10) | |||
| if err != nil { | |||
| return fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err) | |||
| return nil, fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err) | |||
| } | |||
| } else { | |||
| l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID) | |||
| if err != nil { | |||
| return fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err) | |||
| return nil, fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err) | |||
| } | |||
| } | |||
| @@ -149,7 +149,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) { | |||
| NewCommitID: opts.NewCommitID, | |||
| Commits: ListToPushCommits(l), | |||
| }); err != nil { | |||
| return fmt.Errorf("CommitRepoAction (branch): %v", err) | |||
| return nil, fmt.Errorf("CommitRepoAction (branch): %v", err) | |||
| } | |||
| return nil | |||
| return repo, nil | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| // Copyright 2017 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package private | |||
| import ( | |||
| "crypto/tls" | |||
| "encoding/json" | |||
| "fmt" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| ) | |||
| // GetProtectedBranchBy get protected branch information | |||
| func GetProtectedBranchBy(repoID int64, branchName string) (*models.ProtectedBranch, error) { | |||
| // Ask for running deliver hook and test pull request tasks. | |||
| reqURL := setting.LocalURL + fmt.Sprintf("api/internal/branch/%d/%s", repoID, branchName) | |||
| log.GitLogger.Trace("GetProtectedBranchBy: %s", reqURL) | |||
| resp, err := newRequest(reqURL, "GET").SetTLSClientConfig(&tls.Config{ | |||
| InsecureSkipVerify: true, | |||
| }).Response() | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var branch models.ProtectedBranch | |||
| if err := json.NewDecoder(resp.Body).Decode(&branch); err != nil { | |||
| return nil, err | |||
| } | |||
| defer resp.Body.Close() | |||
| // All 2XX status codes are accepted and others will return an error | |||
| if resp.StatusCode/100 != 2 { | |||
| return nil, fmt.Errorf("Failed to update public key: %s", decodeJSONError(resp).Err) | |||
| } | |||
| return &branch, nil | |||
| } | |||
| @@ -1,3 +1,7 @@ | |||
| // Copyright 2017 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package private | |||
| import ( | |||
| @@ -0,0 +1,43 @@ | |||
| // Copyright 2017 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package private | |||
| import ( | |||
| "crypto/tls" | |||
| "encoding/json" | |||
| "fmt" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| ) | |||
| // PushUpdate update publick key updates | |||
| func PushUpdate(opt models.PushUpdateOptions) error { | |||
| // Ask for running deliver hook and test pull request tasks. | |||
| reqURL := setting.LocalURL + "api/internal/push/update" | |||
| log.GitLogger.Trace("PushUpdate: %s", reqURL) | |||
| body, err := json.Marshal(&opt) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| resp, err := newRequest(reqURL, "POST").Body(body).SetTLSClientConfig(&tls.Config{ | |||
| InsecureSkipVerify: true, | |||
| }).Response() | |||
| if err != nil { | |||
| return err | |||
| } | |||
| defer resp.Body.Close() | |||
| // All 2XX status codes are accepted and others will return an error | |||
| if resp.StatusCode/100 != 2 { | |||
| return fmt.Errorf("Failed to update public key: %s", decodeJSONError(resp).Err) | |||
| } | |||
| return nil | |||
| } | |||
| @@ -0,0 +1,30 @@ | |||
| // Copyright 2017 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package private | |||
| import ( | |||
| "code.gitea.io/gitea/models" | |||
| macaron "gopkg.in/macaron.v1" | |||
| ) | |||
| // GetProtectedBranchBy get protected branch information | |||
| func GetProtectedBranchBy(ctx *macaron.Context) { | |||
| repoID := ctx.ParamsInt64(":id") | |||
| branchName := ctx.Params(":branch") | |||
| protectBranch, err := models.GetProtectedBranchBy(repoID, branchName) | |||
| if err != nil { | |||
| ctx.JSON(500, map[string]interface{}{ | |||
| "err": err.Error(), | |||
| }) | |||
| return | |||
| } else if protectBranch != nil { | |||
| ctx.JSON(200, protectBranch) | |||
| } else { | |||
| ctx.JSON(200, &models.ProtectedBranch{ | |||
| CanPush: true, | |||
| }) | |||
| } | |||
| } | |||
| @@ -10,6 +10,7 @@ import ( | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| macaron "gopkg.in/macaron.v1" | |||
| ) | |||
| @@ -40,5 +41,7 @@ func UpdatePublicKey(ctx *macaron.Context) { | |||
| func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Group("/", func() { | |||
| m.Post("/ssh/:id/update", UpdatePublicKey) | |||
| m.Post("/push/update", PushUpdate) | |||
| m.Get("/branch/:id/:branch", GetProtectedBranchBy) | |||
| }, CheckInternalToken) | |||
| } | |||
| @@ -0,0 +1,60 @@ | |||
| // Copyright 2017 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package private | |||
| import ( | |||
| "encoding/json" | |||
| "strings" | |||
| "code.gitea.io/git" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/log" | |||
| macaron "gopkg.in/macaron.v1" | |||
| ) | |||
| // PushUpdate update public key updates | |||
| func PushUpdate(ctx *macaron.Context) { | |||
| var opt models.PushUpdateOptions | |||
| if err := json.NewDecoder(ctx.Req.Request.Body).Decode(&opt); err != nil { | |||
| ctx.JSON(500, map[string]interface{}{ | |||
| "err": err.Error(), | |||
| }) | |||
| return | |||
| } | |||
| branch := strings.TrimPrefix(opt.RefFullName, git.BranchPrefix) | |||
| if len(branch) == 0 || opt.PusherID <= 0 { | |||
| ctx.Error(404) | |||
| log.Trace("PushUpdate: branch or secret is empty, or pusher ID is not valid") | |||
| return | |||
| } | |||
| repo, err := models.PushUpdate(opt) | |||
| if err != nil { | |||
| ctx.JSON(500, map[string]interface{}{ | |||
| "err": err.Error(), | |||
| }) | |||
| return | |||
| } | |||
| pusher, err := models.GetUserByID(opt.PusherID) | |||
| if err != nil { | |||
| if models.IsErrUserNotExist(err) { | |||
| ctx.Error(404) | |||
| } else { | |||
| ctx.JSON(500, map[string]interface{}{ | |||
| "err": err.Error(), | |||
| }) | |||
| } | |||
| return | |||
| } | |||
| log.Trace("TriggerTask '%s/%s' by %s", repo.Name, branch, pusher.Name) | |||
| go models.HookQueue.Add(repo.ID) | |||
| go models.AddTestPullRequestTask(pusher, repo.ID, branch, true) | |||
| ctx.Status(202) | |||
| } | |||