aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/hook.go127
-rw-r--r--cmd/serv.go (renamed from cmd/serve.go)102
-rw-r--r--cmd/update.go58
-rw-r--r--cmd/web.go3
4 files changed, 184 insertions, 106 deletions
diff --git a/cmd/hook.go b/cmd/hook.go
new file mode 100644
index 00000000..a917554d
--- /dev/null
+++ b/cmd/hook.go
@@ -0,0 +1,127 @@
+// Copyright 2014 The Gogs 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 cmd
+
+import (
+ "bufio"
+ "bytes"
+ "os"
+ "os/exec"
+ "path/filepath"
+
+ "github.com/urfave/cli"
+
+ "github.com/gogits/gogs/models"
+)
+
+var (
+ CmdHook = cli.Command{
+ Name: "hook",
+ Usage: "Delegate commands to corresponding Git hooks",
+ Description: "All sub-commands should only be called by Git",
+ Flags: []cli.Flag{
+ stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+ },
+ Subcommands: []cli.Command{
+ subcmdHookPreReceive,
+ subcmdHookUpadte,
+ subcmdHookPostReceive,
+ },
+ }
+
+ subcmdHookPreReceive = cli.Command{
+ Name: "pre-receive",
+ Usage: "Delegate pre-receive Git hook",
+ Description: "This command should only be called by Git",
+ Action: runHookPreReceive,
+ }
+ subcmdHookUpadte = cli.Command{
+ Name: "update",
+ Usage: "Delegate update Git hook",
+ Description: "This command should only be called by Git",
+ Action: runHookUpdate,
+ }
+ subcmdHookPostReceive = cli.Command{
+ Name: "post-receive",
+ Usage: "Delegate post-receive Git hook",
+ Description: "This command should only be called by Git",
+ Action: runHookPostReceive,
+ }
+)
+
+func runHookPreReceive(c *cli.Context) error {
+ if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
+ return nil
+ }
+ setup(c, "hooks/pre-receive.log")
+
+ buf := bytes.NewBuffer(nil)
+ scanner := bufio.NewScanner(os.Stdin)
+ for scanner.Scan() {
+ buf.Write(scanner.Bytes())
+ buf.WriteByte('\n')
+ }
+
+ customHooksPath := os.Getenv(_ENV_REPO_CUSTOM_HOOKS_PATH)
+ hookCmd := exec.Command(filepath.Join(customHooksPath, "pre-receive"))
+ hookCmd.Stdout = os.Stdout
+ hookCmd.Stdin = buf
+ hookCmd.Stderr = os.Stderr
+ if err := hookCmd.Run(); err != nil {
+ fail("Internal error", "Fail to execute custom pre-receive hook: %v", err)
+ }
+ return nil
+}
+
+func runHookUpdate(c *cli.Context) error {
+ if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
+ return nil
+ }
+ setup(c, "hooks/update.log")
+
+ args := c.Args()
+ if len(args) != 3 {
+ fail("Arguments received are not equal to three", "Arguments received are not equal to three")
+ } else if len(args[0]) == 0 {
+ fail("First argument 'refName' is empty", "First argument 'refName' is empty")
+ }
+
+ uuid := os.Getenv(_ENV_UPDATE_TASK_UUID)
+ if err := models.AddUpdateTask(&models.UpdateTask{
+ UUID: uuid,
+ RefName: args[0],
+ OldCommitID: args[1],
+ NewCommitID: args[2],
+ }); err != nil {
+ fail("Internal error", "Fail to add update task '%s': %v", uuid, err)
+ }
+
+ customHooksPath := os.Getenv(_ENV_REPO_CUSTOM_HOOKS_PATH)
+ hookCmd := exec.Command(filepath.Join(customHooksPath, "update"), args...)
+ hookCmd.Stdout = os.Stdout
+ hookCmd.Stdin = os.Stdin
+ hookCmd.Stderr = os.Stderr
+ if err := hookCmd.Run(); err != nil {
+ fail("Internal error", "Fail to execute custom pre-receive hook: %v", err)
+ }
+ return nil
+}
+
+func runHookPostReceive(c *cli.Context) error {
+ if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
+ return nil
+ }
+ setup(c, "hooks/post-receive.log")
+
+ customHooksPath := os.Getenv(_ENV_REPO_CUSTOM_HOOKS_PATH)
+ hookCmd := exec.Command(filepath.Join(customHooksPath, "post-receive"))
+ hookCmd.Stdout = os.Stdout
+ hookCmd.Stdin = os.Stdin
+ hookCmd.Stderr = os.Stderr
+ if err := hookCmd.Run(); err != nil {
+ fail("Internal error", "Fail to execute custom post-receive hook: %v", err)
+ }
+ return nil
+}
diff --git a/cmd/serve.go b/cmd/serv.go
index ef9b451d..b15f4e41 100644
--- a/cmd/serve.go
+++ b/cmd/serv.go
@@ -14,7 +14,7 @@ import (
"time"
"github.com/Unknwon/com"
- git "github.com/gogits/git-module"
+ "github.com/gogits/git-module"
gouuid "github.com/satori/go.uuid"
"github.com/urfave/cli"
log "gopkg.in/clog.v1"
@@ -26,10 +26,12 @@ import (
)
const (
- _ACCESS_DENIED_MESSAGE = "Repository does not exist or you do not have access"
+ _ACCESS_DENIED_MESSAGE = "Repository does not exist or you do not have access"
+ _ENV_UPDATE_TASK_UUID = "UPDATE_TASK_UUID"
+ _ENV_REPO_CUSTOM_HOOKS_PATH = "REPO_CUSTOM_HOOKS_PATH"
)
-var CmdServ = cli.Command{
+var Serv = cli.Command{
Name: "serv",
Usage: "This command should only be called by SSH shell",
Description: `Serv provide access auth for repositories`,
@@ -39,7 +41,13 @@ var CmdServ = cli.Command{
},
}
-func setup(logPath string) {
+func setup(c *cli.Context, logPath string) {
+ if c.IsSet("config") {
+ setting.CustomConf = c.String("config")
+ } else if c.GlobalIsSet("config") {
+ setting.CustomConf = c.GlobalString("config")
+ }
+
setting.NewContext()
setting.NewService()
log.New(log.FILE, log.FileConfig{
@@ -54,7 +62,7 @@ func setup(logPath string) {
models.LoadConfigs()
- if setting.UseSQLite3 || setting.UseTiDB {
+ if setting.UseSQLite3 {
workDir, _ := setting.WorkDir()
os.Chdir(workDir)
}
@@ -62,7 +70,7 @@ func setup(logPath string) {
models.SetEngine()
}
-func parseCmd(cmd string) (string, string) {
+func parseSSHCmd(cmd string) (string, string) {
ss := strings.SplitN(cmd, " ", 2)
if len(ss) != 2 {
return "", ""
@@ -157,11 +165,7 @@ func handleUpdateTask(uuid string, user, repoUser *models.User, reponame string,
}
func runServ(c *cli.Context) error {
- if c.IsSet("config") {
- setting.CustomConf = c.String("config")
- }
-
- setup("serv.log")
+ setup(c, "serv.log")
if setting.SSH.Disabled {
println("Gogs: SSH has been disabled")
@@ -172,21 +176,21 @@ func runServ(c *cli.Context) error {
fail("Not enough arguments", "Not enough arguments")
}
- cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
- if len(cmd) == 0 {
+ sshCmd := os.Getenv("SSH_ORIGINAL_COMMAND")
+ if len(sshCmd) == 0 {
println("Hi there, You've successfully authenticated, but Gogs does not provide shell access.")
println("If this is unexpected, please log in with password and setup Gogs under another user.")
return nil
}
- verb, args := parseCmd(cmd)
- repoPath := strings.ToLower(strings.Trim(args, "'"))
- rr := strings.SplitN(repoPath, "/", 2)
- if len(rr) != 2 {
+ verb, args := parseSSHCmd(sshCmd)
+ repoFullName := strings.ToLower(strings.Trim(args, "'"))
+ repoFields := strings.SplitN(repoFullName, "/", 2)
+ if len(repoFields) != 2 {
fail("Invalid repository path", "Invalid repository path: %v", args)
}
- username := strings.ToLower(rr[0])
- reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
+ username := strings.ToLower(repoFields[0])
+ reponame := strings.ToLower(strings.TrimSuffix(repoFields[1], ".git"))
isWiki := false
if strings.HasSuffix(reponame, ".wiki") {
@@ -194,29 +198,30 @@ func runServ(c *cli.Context) error {
reponame = reponame[:len(reponame)-5]
}
- repoUser, err := models.GetUserByName(username)
+ repoOwner, err := models.GetUserByName(username)
if err != nil {
if models.IsErrUserNotExist(err) {
fail("Repository owner does not exist", "Unregistered owner: %s", username)
}
- fail("Internal error", "Failed to get repository owner (%s): %v", username, err)
+ fail("Internal error", "Fail to get repository owner '%s': %v", username, err)
}
- repo, err := models.GetRepositoryByName(repoUser.ID, reponame)
+ repo, err := models.GetRepositoryByName(repoOwner.ID, reponame)
if err != nil {
if models.IsErrRepoNotExist(err) {
- fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", repoUser.Name, reponame)
+ fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", repoOwner.Name, reponame)
}
- fail("Internal error", "Failed to get repository: %v", err)
+ fail("Internal error", "Fail to get repository: %v", err)
}
+ repo.Owner = repoOwner
- requestedMode, has := allowedCommands[verb]
- if !has {
- fail("Unknown git command", "Unknown git command %s", verb)
+ requestMode, ok := allowedCommands[verb]
+ if !ok {
+ fail("Unknown git command", "Unknown git command '%s'", verb)
}
// Prohibit push to mirror repositories.
- if requestedMode > models.ACCESS_MODE_READ && repo.IsMirror {
+ if requestMode > models.ACCESS_MODE_READ && repo.IsMirror {
fail("mirror repository is read-only", "")
}
@@ -225,33 +230,35 @@ func runServ(c *cli.Context) error {
key, err := models.GetPublicKeyByID(com.StrTo(strings.TrimPrefix(c.Args()[0], "key-")).MustInt64())
if err != nil {
- fail("Invalid key ID", "Invalid key ID [%s]: %v", c.Args()[0], err)
+ fail("Invalid key ID", "Invalid key ID '%s': %v", c.Args()[0], err)
}
- if requestedMode == models.ACCESS_MODE_WRITE || repo.IsPrivate {
+ if requestMode == models.ACCESS_MODE_WRITE || repo.IsPrivate {
// Check deploy key or user key.
if key.IsDeployKey() {
- if key.Mode < requestedMode {
+ if key.Mode < requestMode {
fail("Key permission denied", "Cannot push with deployment key: %d", key.ID)
}
checkDeployKey(key, repo)
} else {
user, err = models.GetUserByKeyID(key.ID)
if err != nil {
- fail("internal error", "Failed to get user by key ID(%d): %v", key.ID, err)
+ fail("Internal error", "Fail to get user by key ID '%d': %v", key.ID, err)
}
mode, err := models.AccessLevel(user, repo)
if err != nil {
fail("Internal error", "Fail to check access: %v", err)
- } else if mode < requestedMode {
+ }
+
+ if mode < requestMode {
clientMessage := _ACCESS_DENIED_MESSAGE
if mode >= models.ACCESS_MODE_READ {
clientMessage = "You do not have sufficient authorization for this action"
}
fail(clientMessage,
- "User %s does not have level %v access to repository %s",
- user.Name, requestedMode, repoPath)
+ "User '%s' does not have level '%v' access to repository '%s'",
+ user.Name, requestMode, repoFullName)
}
}
} else {
@@ -265,30 +272,31 @@ func runServ(c *cli.Context) error {
}
uuid := gouuid.NewV4().String()
- os.Setenv("uuid", uuid)
+ os.Setenv(_ENV_UPDATE_TASK_UUID, uuid)
+ os.Setenv(_ENV_REPO_CUSTOM_HOOKS_PATH, filepath.Join(repo.RepoPath(), "custom_hooks"))
// Special handle for Windows.
if setting.IsWindows {
verb = strings.Replace(verb, "-", " ", 1)
}
- var gitcmd *exec.Cmd
+ var gitCmd *exec.Cmd
verbs := strings.Split(verb, " ")
if len(verbs) == 2 {
- gitcmd = exec.Command(verbs[0], verbs[1], repoPath)
+ gitCmd = exec.Command(verbs[0], verbs[1], repoFullName)
} else {
- gitcmd = exec.Command(verb, repoPath)
+ gitCmd = exec.Command(verb, repoFullName)
}
- gitcmd.Dir = setting.RepoRootPath
- gitcmd.Stdout = os.Stdout
- gitcmd.Stdin = os.Stdin
- gitcmd.Stderr = os.Stderr
- if err = gitcmd.Run(); err != nil {
- fail("Internal error", "Failed to execute git command: %v", err)
+ gitCmd.Dir = setting.RepoRootPath
+ gitCmd.Stdout = os.Stdout
+ gitCmd.Stdin = os.Stdin
+ gitCmd.Stderr = os.Stderr
+ if err = gitCmd.Run(); err != nil {
+ fail("Internal error", "Fail to execute git command: %v", err)
}
- if requestedMode == models.ACCESS_MODE_WRITE {
- handleUpdateTask(uuid, user, repoUser, reponame, isWiki)
+ if requestMode == models.ACCESS_MODE_WRITE {
+ handleUpdateTask(uuid, user, repoOwner, reponame, isWiki)
}
// Update user key activity.
diff --git a/cmd/update.go b/cmd/update.go
deleted file mode 100644
index da7f3093..00000000
--- a/cmd/update.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2014 The Gogs 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 cmd
-
-import (
- "os"
-
- "github.com/urfave/cli"
- log "gopkg.in/clog.v1"
-
- "github.com/gogits/gogs/models"
- "github.com/gogits/gogs/modules/setting"
-)
-
-var CmdUpdate = cli.Command{
- Name: "update",
- Usage: "This command should only be called by Git hook",
- Description: `Update get pushed info and insert into database`,
- Action: runUpdate,
- Flags: []cli.Flag{
- stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
- },
-}
-
-func runUpdate(c *cli.Context) error {
- if c.IsSet("config") {
- setting.CustomConf = c.String("config")
- }
-
- setup("update.log")
-
- if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
- log.Trace("SSH_ORIGINAL_COMMAND is empty")
- return nil
- }
-
- args := c.Args()
- if len(args) != 3 {
- log.Fatal(2, "Arguments received are not equal to three")
- } else if len(args[0]) == 0 {
- log.Fatal(2, "First argument 'refName' is empty, shouldn't use")
- }
-
- task := models.UpdateTask{
- UUID: os.Getenv("uuid"),
- RefName: args[0],
- OldCommitID: args[1],
- NewCommitID: args[2],
- }
-
- if err := models.AddUpdateTask(&task); err != nil {
- log.Fatal(2, "AddUpdateTask: %v", err)
- }
-
- return nil
-}
diff --git a/cmd/web.go b/cmd/web.go
index b0277c25..6f8049a3 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -84,6 +84,7 @@ func checkVersion() {
}
// Check dependency version.
+ // LEGACY [0.11]: no need to check version as we check in vendor into version control
checkers := []VerChecker{
{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.6.0"},
{"github.com/go-macaron/binding", binding.Version, "0.3.2"},
@@ -94,7 +95,7 @@ func checkVersion() {
{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"},
{"gopkg.in/ini.v1", ini.Version, "1.8.4"},
{"gopkg.in/macaron.v1", macaron.Version, "1.1.7"},
- {"github.com/gogits/git-module", git.Version, "0.4.6"},
+ {"github.com/gogits/git-module", git.Version, "0.4.7"},
{"github.com/gogits/go-gogs-client", gogs.Version, "0.12.1"},
}
for _, c := range checkers {