* 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.2.0-rc1
| @@ -7,20 +7,18 @@ package cmd | |||||
| import ( | import ( | ||||
| "bufio" | "bufio" | ||||
| "bytes" | "bytes" | ||||
| "crypto/tls" | |||||
| "fmt" | "fmt" | ||||
| "os" | "os" | ||||
| "path/filepath" | |||||
| "strconv" | "strconv" | ||||
| "strings" | "strings" | ||||
| "code.gitea.io/git" | "code.gitea.io/git" | ||||
| "code.gitea.io/gitea/models" | "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/log" | ||||
| "code.gitea.io/gitea/modules/private" | |||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "github.com/Unknwon/com" | |||||
| "github.com/urfave/cli" | "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 { | func runHookPreReceive(c *cli.Context) error { | ||||
| if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { | if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 { | ||||
| return nil | return nil | ||||
| @@ -75,9 +79,7 @@ func runHookPreReceive(c *cli.Context) error { | |||||
| setting.CustomConf = c.GlobalString("config") | 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 | // the environment setted on serv command | ||||
| repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64) | 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) | branchName := strings.TrimPrefix(refFullName, git.BranchPrefix) | ||||
| protectBranch, err := models.GetProtectedBranchBy(repoID, branchName) | |||||
| protectBranch, err := private.GetProtectedBranchBy(repoID, branchName) | |||||
| if err != nil { | if err != nil { | ||||
| log.GitLogger.Fatal(2, "retrieve protected branches information failed") | log.GitLogger.Fatal(2, "retrieve protected branches information failed") | ||||
| } | } | ||||
| if protectBranch != nil { | 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") | 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 | return nil | ||||
| } | } | ||||
| @@ -167,13 +169,10 @@ func runHookPostReceive(c *cli.Context) error { | |||||
| setting.CustomConf = c.GlobalString("config") | 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 | // the environment setted on serv command | ||||
| repoUser := os.Getenv(models.EnvRepoUsername) | repoUser := os.Getenv(models.EnvRepoUsername) | ||||
| repoUserSalt := os.Getenv(models.EnvRepoUserSalt) | |||||
| isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") | isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") | ||||
| repoName := os.Getenv(models.EnvRepoName) | repoName := os.Getenv(models.EnvRepoName) | ||||
| pusherID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64) | pusherID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64) | ||||
| @@ -199,7 +198,7 @@ func runHookPostReceive(c *cli.Context) error { | |||||
| newCommitID := string(fields[1]) | newCommitID := string(fields[1]) | ||||
| refFullName := string(fields[2]) | refFullName := string(fields[2]) | ||||
| if err := models.PushUpdate(models.PushUpdateOptions{ | |||||
| if err := private.PushUpdate(models.PushUpdateOptions{ | |||||
| RefFullName: refFullName, | RefFullName: refFullName, | ||||
| OldCommitID: oldCommitID, | OldCommitID: oldCommitID, | ||||
| NewCommitID: newCommitID, | NewCommitID: newCommitID, | ||||
| @@ -210,23 +209,6 @@ func runHookPostReceive(c *cli.Context) error { | |||||
| }); err != nil { | }); err != nil { | ||||
| log.GitLogger.Error(2, "Update: %v", err) | 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 | return nil | ||||
| @@ -65,11 +65,11 @@ type PushUpdateOptions struct { | |||||
| // PushUpdate must be called for any push actions in order to | // PushUpdate must be called for any push actions in order to | ||||
| // generates necessary push action history feeds. | // 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 | isNewRef := opts.OldCommitID == git.EmptySHA | ||||
| isDelRef := opts.NewCommitID == git.EmptySHA | isDelRef := opts.NewCommitID == git.EmptySHA | ||||
| if isNewRef && isDelRef { | 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) | repoPath := RepoPath(opts.RepoUserName, opts.RepoName) | ||||
| @@ -77,28 +77,28 @@ func PushUpdate(opts PushUpdateOptions) (err error) { | |||||
| gitUpdate := exec.Command("git", "update-server-info") | gitUpdate := exec.Command("git", "update-server-info") | ||||
| gitUpdate.Dir = repoPath | gitUpdate.Dir = repoPath | ||||
| if err = gitUpdate.Run(); err != nil { | 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 { | 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 { | if err != nil { | ||||
| return fmt.Errorf("GetRepositoryByName: %v", err) | |||||
| return nil, fmt.Errorf("OpenRepository: %v", err) | |||||
| } | } | ||||
| if err = repo.UpdateSize(); err != nil { | if err = repo.UpdateSize(); err != nil { | ||||
| @@ -116,14 +116,14 @@ func PushUpdate(opts PushUpdateOptions) (err error) { | |||||
| NewCommitID: opts.NewCommitID, | NewCommitID: opts.NewCommitID, | ||||
| Commits: &PushCommits{}, | Commits: &PushCommits{}, | ||||
| }); err != nil { | }); 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) | newCommit, err := gitRepo.GetCommit(opts.NewCommitID) | ||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("gitRepo.GetCommit: %v", err) | |||||
| return nil, fmt.Errorf("gitRepo.GetCommit: %v", err) | |||||
| } | } | ||||
| // Push new branch. | // Push new branch. | ||||
| @@ -131,12 +131,12 @@ func PushUpdate(opts PushUpdateOptions) (err error) { | |||||
| if isNewRef { | if isNewRef { | ||||
| l, err = newCommit.CommitsBeforeLimit(10) | l, err = newCommit.CommitsBeforeLimit(10) | ||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err) | |||||
| return nil, fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err) | |||||
| } | } | ||||
| } else { | } else { | ||||
| l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID) | l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID) | ||||
| if err != nil { | 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, | NewCommitID: opts.NewCommitID, | ||||
| Commits: ListToPushCommits(l), | Commits: ListToPushCommits(l), | ||||
| }); err != nil { | }); 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 | package private | ||||
| import ( | 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/models" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| macaron "gopkg.in/macaron.v1" | macaron "gopkg.in/macaron.v1" | ||||
| ) | ) | ||||
| @@ -40,5 +41,7 @@ func UpdatePublicKey(ctx *macaron.Context) { | |||||
| func RegisterRoutes(m *macaron.Macaron) { | func RegisterRoutes(m *macaron.Macaron) { | ||||
| m.Group("/", func() { | m.Group("/", func() { | ||||
| m.Post("/ssh/:id/update", UpdatePublicKey) | m.Post("/ssh/:id/update", UpdatePublicKey) | ||||
| m.Post("/push/update", PushUpdate) | |||||
| m.Get("/branch/:id/:branch", GetProtectedBranchBy) | |||||
| }, CheckInternalToken) | }, 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) | |||||
| } | |||||