Browse Source

repo_editor: able to trigger Git hooks (#4338)

pull/4799/merge
Unknwon 6 years ago
parent
commit
ac73d43444
No known key found for this signature in database
GPG Key ID: 7A02C406FAC875A2
  1. 35
      cmd/hook.go
  2. 3
      cmd/serv.go
  3. 2
      gogs.go
  4. 229
      models/repo_editor.go
  5. 4
      pkg/context/context.go
  6. 33
      routes/repo/editor.go
  7. 38
      routes/repo/http.go
  8. 2
      templates/.VERSION

35
cmd/hook.go

@ -27,7 +27,6 @@ import (
"github.com/gogs/gogs/pkg/mailer" "github.com/gogs/gogs/pkg/mailer"
"github.com/gogs/gogs/pkg/setting" "github.com/gogs/gogs/pkg/setting"
"github.com/gogs/gogs/pkg/template" "github.com/gogs/gogs/pkg/template"
http "github.com/gogs/gogs/routes/repo"
) )
var ( var (
@ -71,7 +70,7 @@ func runHookPreReceive(c *cli.Context) error {
} }
setup(c, "hooks/pre-receive.log", true) setup(c, "hooks/pre-receive.log", true)
isWiki := strings.Contains(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/") isWiki := strings.Contains(os.Getenv(models.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
scanner := bufio.NewScanner(os.Stdin) scanner := bufio.NewScanner(os.Stdin)
@ -92,7 +91,7 @@ func runHookPreReceive(c *cli.Context) error {
branchName := strings.TrimPrefix(string(fields[2]), git.BRANCH_PREFIX) branchName := strings.TrimPrefix(string(fields[2]), git.BRANCH_PREFIX)
// Branch protection // Branch protection
repoID := com.StrTo(os.Getenv(http.ENV_REPO_ID)).MustInt64() repoID := com.StrTo(os.Getenv(models.ENV_REPO_ID)).MustInt64()
protectBranch, err := models.GetProtectBranchOfRepoByName(repoID, branchName) protectBranch, err := models.GetProtectBranchOfRepoByName(repoID, branchName)
if err != nil { if err != nil {
if errors.IsErrBranchNotExist(err) { if errors.IsErrBranchNotExist(err) {
@ -108,7 +107,7 @@ func runHookPreReceive(c *cli.Context) error {
bypassRequirePullRequest := false bypassRequirePullRequest := false
// Check if user is in whitelist when enabled // Check if user is in whitelist when enabled
userID := com.StrTo(os.Getenv(http.ENV_AUTH_USER_ID)).MustInt64() userID := com.StrTo(os.Getenv(models.ENV_AUTH_USER_ID)).MustInt64()
if protectBranch.EnableWhitelist { if protectBranch.EnableWhitelist {
if !models.IsUserInProtectBranchWhitelist(repoID, userID, branchName) { if !models.IsUserInProtectBranchWhitelist(repoID, userID, branchName) {
fail(fmt.Sprintf("Branch '%s' is protected and you are not in the push whitelist", branchName), "") fail(fmt.Sprintf("Branch '%s' is protected and you are not in the push whitelist", branchName), "")
@ -129,7 +128,7 @@ func runHookPreReceive(c *cli.Context) error {
// Check force push // Check force push
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID). output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).
RunInDir(models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))) RunInDir(models.RepoPath(os.Getenv(models.ENV_REPO_OWNER_NAME), os.Getenv(models.ENV_REPO_NAME)))
if err != nil { if err != nil {
fail("Internal error", "Fail to detect force push: %v", err) fail("Internal error", "Fail to detect force push: %v", err)
} else if len(output) > 0 { } else if len(output) > 0 {
@ -137,7 +136,7 @@ func runHookPreReceive(c *cli.Context) error {
} }
} }
customHooksPath := filepath.Join(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), "pre-receive") customHooksPath := filepath.Join(os.Getenv(models.ENV_REPO_CUSTOM_HOOKS_PATH), "pre-receive")
if !com.IsFile(customHooksPath) { if !com.IsFile(customHooksPath) {
return nil return nil
} }
@ -148,7 +147,7 @@ func runHookPreReceive(c *cli.Context) error {
} else { } else {
hookCmd = exec.Command(customHooksPath) hookCmd = exec.Command(customHooksPath)
} }
hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME)) hookCmd.Dir = models.RepoPath(os.Getenv(models.ENV_REPO_OWNER_NAME), os.Getenv(models.ENV_REPO_NAME))
hookCmd.Stdout = os.Stdout hookCmd.Stdout = os.Stdout
hookCmd.Stdin = buf hookCmd.Stdin = buf
hookCmd.Stderr = os.Stderr hookCmd.Stderr = os.Stderr
@ -171,7 +170,7 @@ func runHookUpdate(c *cli.Context) error {
fail("First argument 'refName' is empty", "First argument 'refName' is empty") fail("First argument 'refName' is empty", "First argument 'refName' is empty")
} }
customHooksPath := filepath.Join(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), "update") customHooksPath := filepath.Join(os.Getenv(models.ENV_REPO_CUSTOM_HOOKS_PATH), "update")
if !com.IsFile(customHooksPath) { if !com.IsFile(customHooksPath) {
return nil return nil
} }
@ -182,7 +181,7 @@ func runHookUpdate(c *cli.Context) error {
} else { } else {
hookCmd = exec.Command(customHooksPath, args...) hookCmd = exec.Command(customHooksPath, args...)
} }
hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME)) hookCmd.Dir = models.RepoPath(os.Getenv(models.ENV_REPO_OWNER_NAME), os.Getenv(models.ENV_REPO_NAME))
hookCmd.Stdout = os.Stdout hookCmd.Stdout = os.Stdout
hookCmd.Stdin = os.Stdin hookCmd.Stdin = os.Stdin
hookCmd.Stderr = os.Stderr hookCmd.Stderr = os.Stderr
@ -205,7 +204,7 @@ func runHookPostReceive(c *cli.Context) error {
mailer.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"), mailer.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"),
path.Join(setting.CustomPath, "templates/mail"), template.NewFuncMap()) path.Join(setting.CustomPath, "templates/mail"), template.NewFuncMap())
isWiki := strings.Contains(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/") isWiki := strings.Contains(os.Getenv(models.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
scanner := bufio.NewScanner(os.Stdin) scanner := bufio.NewScanner(os.Stdin)
@ -227,10 +226,10 @@ func runHookPostReceive(c *cli.Context) error {
OldCommitID: string(fields[0]), OldCommitID: string(fields[0]),
NewCommitID: string(fields[1]), NewCommitID: string(fields[1]),
RefFullName: string(fields[2]), RefFullName: string(fields[2]),
PusherID: com.StrTo(os.Getenv(http.ENV_AUTH_USER_ID)).MustInt64(), PusherID: com.StrTo(os.Getenv(models.ENV_AUTH_USER_ID)).MustInt64(),
PusherName: os.Getenv(http.ENV_AUTH_USER_NAME), PusherName: os.Getenv(models.ENV_AUTH_USER_NAME),
RepoUserName: os.Getenv(http.ENV_REPO_OWNER_NAME), RepoUserName: os.Getenv(models.ENV_REPO_OWNER_NAME),
RepoName: os.Getenv(http.ENV_REPO_NAME), RepoName: os.Getenv(models.ENV_REPO_NAME),
} }
if err := models.PushUpdate(options); err != nil { if err := models.PushUpdate(options); err != nil {
log.Error(2, "PushUpdate: %v", err) log.Error(2, "PushUpdate: %v", err)
@ -239,8 +238,8 @@ func runHookPostReceive(c *cli.Context) error {
// Ask for running deliver hook and test pull request tasks // Ask for running deliver hook and test pull request tasks
reqURL := setting.LocalURL + options.RepoUserName + "/" + options.RepoName + "/tasks/trigger?branch=" + reqURL := setting.LocalURL + options.RepoUserName + "/" + options.RepoName + "/tasks/trigger?branch=" +
template.EscapePound(strings.TrimPrefix(options.RefFullName, git.BRANCH_PREFIX)) + template.EscapePound(strings.TrimPrefix(options.RefFullName, git.BRANCH_PREFIX)) +
"&secret=" + os.Getenv(http.ENV_REPO_OWNER_SALT_MD5) + "&secret=" + os.Getenv(models.ENV_REPO_OWNER_SALT_MD5) +
"&pusher=" + os.Getenv(http.ENV_AUTH_USER_ID) "&pusher=" + os.Getenv(models.ENV_AUTH_USER_ID)
log.Trace("Trigger task: %s", reqURL) log.Trace("Trigger task: %s", reqURL)
resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{ resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{
@ -256,7 +255,7 @@ func runHookPostReceive(c *cli.Context) error {
} }
} }
customHooksPath := filepath.Join(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), "post-receive") customHooksPath := filepath.Join(os.Getenv(models.ENV_REPO_CUSTOM_HOOKS_PATH), "post-receive")
if !com.IsFile(customHooksPath) { if !com.IsFile(customHooksPath) {
return nil return nil
} }
@ -267,7 +266,7 @@ func runHookPostReceive(c *cli.Context) error {
} else { } else {
hookCmd = exec.Command(customHooksPath) hookCmd = exec.Command(customHooksPath)
} }
hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME)) hookCmd.Dir = models.RepoPath(os.Getenv(models.ENV_REPO_OWNER_NAME), os.Getenv(models.ENV_REPO_NAME))
hookCmd.Stdout = os.Stdout hookCmd.Stdout = os.Stdout
hookCmd.Stdin = buf hookCmd.Stdin = buf
hookCmd.Stderr = os.Stderr hookCmd.Stderr = os.Stderr

3
cmd/serv.go

@ -19,7 +19,6 @@ import (
"github.com/gogs/gogs/models" "github.com/gogs/gogs/models"
"github.com/gogs/gogs/models/errors" "github.com/gogs/gogs/models/errors"
"github.com/gogs/gogs/pkg/setting" "github.com/gogs/gogs/pkg/setting"
http "github.com/gogs/gogs/routes/repo"
) )
const ( const (
@ -252,7 +251,7 @@ func runServ(c *cli.Context) error {
gitCmd = exec.Command(verb, repoFullName) gitCmd = exec.Command(verb, repoFullName)
} }
if requestMode == models.ACCESS_MODE_WRITE { if requestMode == models.ACCESS_MODE_WRITE {
gitCmd.Env = append(os.Environ(), http.ComposeHookEnvs(http.ComposeHookEnvsOptions{ gitCmd.Env = append(os.Environ(), models.ComposeHookEnvs(models.ComposeHookEnvsOptions{
AuthUser: user, AuthUser: user,
OwnerName: owner.Name, OwnerName: owner.Name,
OwnerSalt: owner.Salt, OwnerSalt: owner.Salt,

2
gogs.go

@ -16,7 +16,7 @@ import (
"github.com/gogs/gogs/pkg/setting" "github.com/gogs/gogs/pkg/setting"
) )
const APP_VER = "0.11.62.0817" const APP_VER = "0.11.63.0817"
func init() { func init() {
setting.AppVer = APP_VER setting.AppVer = APP_VER

229
models/repo_editor.go

@ -17,15 +17,50 @@ import (
"github.com/Unknwon/com" "github.com/Unknwon/com"
gouuid "github.com/satori/go.uuid" gouuid "github.com/satori/go.uuid"
log "gopkg.in/clog.v1"
git "github.com/gogs/git-module" "github.com/gogs/git-module"
"github.com/gogs/gogs/models/errors" "github.com/gogs/gogs/models/errors"
"github.com/gogs/gogs/pkg/process" "github.com/gogs/gogs/pkg/process"
"github.com/gogs/gogs/pkg/setting" "github.com/gogs/gogs/pkg/setting"
"github.com/gogs/gogs/pkg/tool"
) )
const (
ENV_AUTH_USER_ID = "GOGS_AUTH_USER_ID"
ENV_AUTH_USER_NAME = "GOGS_AUTH_USER_NAME"
ENV_AUTH_USER_EMAIL = "GOGS_AUTH_USER_EMAIL"
ENV_REPO_OWNER_NAME = "GOGS_REPO_OWNER_NAME"
ENV_REPO_OWNER_SALT_MD5 = "GOGS_REPO_OWNER_SALT_MD5"
ENV_REPO_ID = "GOGS_REPO_ID"
ENV_REPO_NAME = "GOGS_REPO_NAME"
ENV_REPO_CUSTOM_HOOKS_PATH = "GOGS_REPO_CUSTOM_HOOKS_PATH"
)
type ComposeHookEnvsOptions struct {
AuthUser *User
OwnerName string
OwnerSalt string
RepoID int64
RepoName string
RepoPath string
}
func ComposeHookEnvs(opts ComposeHookEnvsOptions) []string {
envs := []string{
"SSH_ORIGINAL_COMMAND=1",
ENV_AUTH_USER_ID + "=" + com.ToStr(opts.AuthUser.ID),
ENV_AUTH_USER_NAME + "=" + opts.AuthUser.Name,
ENV_AUTH_USER_EMAIL + "=" + opts.AuthUser.Email,
ENV_REPO_OWNER_NAME + "=" + opts.OwnerName,
ENV_REPO_OWNER_SALT_MD5 + "=" + tool.MD5(opts.OwnerSalt),
ENV_REPO_ID + "=" + com.ToStr(opts.RepoID),
ENV_REPO_NAME + "=" + opts.RepoName,
ENV_REPO_CUSTOM_HOOKS_PATH + "=" + path.Join(opts.RepoPath, "custom_hooks"),
}
return envs
}
// ___________ .___.__ __ ___________.__.__ // ___________ .___.__ __ ___________.__.__
// \_ _____/ __| _/|__|/ |_ \_ _____/|__| | ____ // \_ _____/ __| _/|__|/ |_ \_ _____/|__| | ____
// | __)_ / __ | | \ __\ | __) | | | _/ __ \ // | __)_ / __ | | \ __\ | __) | | | _/ __ \
@ -88,9 +123,9 @@ func (repo *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) (
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID)) defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
if err = repo.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil { if err = repo.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil {
return fmt.Errorf("DiscardLocalRepoBranchChanges [branch: %s]: %v", opts.OldBranch, err) return fmt.Errorf("discard local repo branch[%s] changes: %v", opts.OldBranch, err)
} else if err = repo.UpdateLocalCopyBranch(opts.OldBranch); err != nil { } else if err = repo.UpdateLocalCopyBranch(opts.OldBranch); err != nil {
return fmt.Errorf("UpdateLocalCopyBranch [branch: %s]: %v", opts.OldBranch, err) return fmt.Errorf("update local copy branch[%s]: %v", opts.OldBranch, err)
} }
repoPath := repo.RepoPath() repoPath := repo.RepoPath()
@ -107,12 +142,12 @@ func (repo *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) (
if err = git.DeleteBranch(localPath, opts.NewBranch, git.DeleteBranchOptions{ if err = git.DeleteBranch(localPath, opts.NewBranch, git.DeleteBranchOptions{
Force: true, Force: true,
}); err != nil { }); err != nil {
return fmt.Errorf("DeleteBranch [name: %s]: %v", opts.NewBranch, err) return fmt.Errorf("delete branch[%s]: %v", opts.NewBranch, err)
} }
} }
if err := repo.CheckoutNewBranch(opts.OldBranch, opts.NewBranch); err != nil { if err := repo.CheckoutNewBranch(opts.OldBranch, opts.NewBranch); err != nil {
return fmt.Errorf("CheckoutNewBranch [old_branch: %s, new_branch: %s]: %v", opts.OldBranch, opts.NewBranch, err) return fmt.Errorf("checkout new branch[%s] from old branch[%s]: %v", opts.NewBranch, opts.OldBranch, err)
} }
} }
@ -131,12 +166,12 @@ func (repo *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) (
// Otherwise, move the file when name changed. // Otherwise, move the file when name changed.
if com.IsFile(oldFilePath) && opts.OldTreeName != opts.NewTreeName { if com.IsFile(oldFilePath) && opts.OldTreeName != opts.NewTreeName {
if err = git.MoveFile(localPath, opts.OldTreeName, opts.NewTreeName); err != nil { if err = git.MoveFile(localPath, opts.OldTreeName, opts.NewTreeName); err != nil {
return fmt.Errorf("git mv %s %s: %v", opts.OldTreeName, opts.NewTreeName, err) return fmt.Errorf("git mv %q %q: %v", opts.OldTreeName, opts.NewTreeName, err)
} }
} }
if err = ioutil.WriteFile(filePath, []byte(opts.Content), 0666); err != nil { if err = ioutil.WriteFile(filePath, []byte(opts.Content), 0666); err != nil {
return fmt.Errorf("WriteFile: %v", err) return fmt.Errorf("write file: %v", err)
} }
if err = git.AddChanges(localPath, true); err != nil { if err = git.AddChanges(localPath, true); err != nil {
@ -145,45 +180,18 @@ func (repo *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) (
Committer: doer.NewGitSig(), Committer: doer.NewGitSig(),
Message: opts.Message, Message: opts.Message,
}); err != nil { }); err != nil {
return fmt.Errorf("CommitChanges: %v", err) return fmt.Errorf("commit changes on %q: %v", localPath, err)
} else if err = git.Push(localPath, "origin", opts.NewBranch); err != nil { } else if err = git.PushWithEnvs(localPath, "origin", opts.NewBranch,
ComposeHookEnvs(ComposeHookEnvsOptions{
AuthUser: doer,
OwnerName: repo.MustOwner().Name,
OwnerSalt: repo.MustOwner().Salt,
RepoID: repo.ID,
RepoName: repo.Name,
RepoPath: repo.RepoPath(),
})); err != nil {
return fmt.Errorf("git push origin %s: %v", opts.NewBranch, err) return fmt.Errorf("git push origin %s: %v", opts.NewBranch, err)
} }
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
log.Error(2, "OpenRepository: %v", err)
return nil
}
commit, err := gitRepo.GetBranchCommit(opts.NewBranch)
if err != nil {
log.Error(2, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
return nil
}
// Simulate push event.
pushCommits := &PushCommits{
Len: 1,
Commits: []*PushCommit{CommitToPushCommit(commit)},
}
oldCommitID := opts.LastCommitID
if opts.NewBranch != opts.OldBranch {
oldCommitID = git.EMPTY_SHA
}
if err := CommitRepoAction(CommitRepoActionOptions{
PusherName: doer.Name,
RepoOwnerID: repo.MustOwner().ID,
RepoName: repo.Name,
RefFullName: git.BRANCH_PREFIX + opts.NewBranch,
OldCommitID: oldCommitID,
NewCommitID: commit.ID.String(),
Commits: pushCommits,
}); err != nil {
log.Error(2, "CommitRepoAction: %v", err)
return nil
}
go AddTestPullRequestTask(doer, repo.ID, opts.NewBranch, true)
return nil return nil
} }
@ -193,16 +201,16 @@ func (repo *Repository) GetDiffPreview(branch, treePath, content string) (diff *
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID)) defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
if err = repo.DiscardLocalRepoBranchChanges(branch); err != nil { if err = repo.DiscardLocalRepoBranchChanges(branch); err != nil {
return nil, fmt.Errorf("DiscardLocalRepoBranchChanges [branch: %s]: %v", branch, err) return nil, fmt.Errorf("discard local repo branch[%s] changes: %v", branch, err)
} else if err = repo.UpdateLocalCopyBranch(branch); err != nil { } else if err = repo.UpdateLocalCopyBranch(branch); err != nil {
return nil, fmt.Errorf("UpdateLocalCopyBranch [branch: %s]: %v", branch, err) return nil, fmt.Errorf("update local copy branch[%s]: %v", branch, err)
} }
localPath := repo.LocalCopyPath() localPath := repo.LocalCopyPath()
filePath := path.Join(localPath, treePath) filePath := path.Join(localPath, treePath)
os.MkdirAll(filepath.Dir(filePath), os.ModePerm) os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
if err = ioutil.WriteFile(filePath, []byte(content), 0666); err != nil { if err = ioutil.WriteFile(filePath, []byte(content), 0666); err != nil {
return nil, fmt.Errorf("WriteFile: %v", err) return nil, fmt.Errorf("write file: %v", err)
} }
cmd := exec.Command("git", "diff", treePath) cmd := exec.Command("git", "diff", treePath)
@ -211,11 +219,11 @@ func (repo *Repository) GetDiffPreview(branch, treePath, content string) (diff *
stdout, err := cmd.StdoutPipe() stdout, err := cmd.StdoutPipe()
if err != nil { if err != nil {
return nil, fmt.Errorf("StdoutPipe: %v", err) return nil, fmt.Errorf("get stdout pipe: %v", err)
} }
if err = cmd.Start(); err != nil { if err = cmd.Start(); err != nil {
return nil, fmt.Errorf("Start: %v", err) return nil, fmt.Errorf("start: %v", err)
} }
pid := process.Add(fmt.Sprintf("GetDiffPreview [repo_path: %s]", repo.RepoPath()), cmd) pid := process.Add(fmt.Sprintf("GetDiffPreview [repo_path: %s]", repo.RepoPath()), cmd)
@ -223,11 +231,11 @@ func (repo *Repository) GetDiffPreview(branch, treePath, content string) (diff *
diff, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdout) diff, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdout)
if err != nil { if err != nil {
return nil, fmt.Errorf("ParsePatch: %v", err) return nil, fmt.Errorf("parse path: %v", err)
} }
if err = cmd.Wait(); err != nil { if err = cmd.Wait(); err != nil {
return nil, fmt.Errorf("Wait: %v", err) return nil, fmt.Errorf("wait: %v", err)
} }
return diff, nil return diff, nil
@ -254,20 +262,20 @@ func (repo *Repository) DeleteRepoFile(doer *User, opts DeleteRepoFileOptions) (
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID)) defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
if err = repo.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil { if err = repo.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil {
return fmt.Errorf("DiscardLocalRepoBranchChanges [branch: %s]: %v", opts.OldBranch, err) return fmt.Errorf("discard local repo branch[%s] changes: %v", opts.OldBranch, err)
} else if err = repo.UpdateLocalCopyBranch(opts.OldBranch); err != nil { } else if err = repo.UpdateLocalCopyBranch(opts.OldBranch); err != nil {
return fmt.Errorf("UpdateLocalCopyBranch [branch: %s]: %v", opts.OldBranch, err) return fmt.Errorf("update local copy branch[%s]: %v", opts.OldBranch, err)
} }
if opts.OldBranch != opts.NewBranch { if opts.OldBranch != opts.NewBranch {
if err := repo.CheckoutNewBranch(opts.OldBranch, opts.NewBranch); err != nil { if err := repo.CheckoutNewBranch(opts.OldBranch, opts.NewBranch); err != nil {
return fmt.Errorf("CheckoutNewBranch [old_branch: %s, new_branch: %s]: %v", opts.OldBranch, opts.NewBranch, err) return fmt.Errorf("checkout new branch[%s] from old branch[%s]: %v", opts.NewBranch, opts.OldBranch, err)
} }
} }
localPath := repo.LocalCopyPath() localPath := repo.LocalCopyPath()
if err = os.Remove(path.Join(localPath, opts.TreePath)); err != nil { if err = os.Remove(path.Join(localPath, opts.TreePath)); err != nil {
return fmt.Errorf("Remove: %v", err) return fmt.Errorf("remove file %q: %v", opts.TreePath, err)
} }
if err = git.AddChanges(localPath, true); err != nil { if err = git.AddChanges(localPath, true); err != nil {
@ -276,41 +284,18 @@ func (repo *Repository) DeleteRepoFile(doer *User, opts DeleteRepoFileOptions) (
Committer: doer.NewGitSig(), Committer: doer.NewGitSig(),
Message: opts.Message, Message: opts.Message,
}); err != nil { }); err != nil {
return fmt.Errorf("CommitChanges: %v", err) return fmt.Errorf("commit changes to %q: %v", localPath, err)
} else if err = git.Push(localPath, "origin", opts.NewBranch); err != nil { } else if err = git.PushWithEnvs(localPath, "origin", opts.NewBranch,
ComposeHookEnvs(ComposeHookEnvsOptions{
AuthUser: doer,
OwnerName: repo.MustOwner().Name,
OwnerSalt: repo.MustOwner().Salt,
RepoID: repo.ID,
RepoName: repo.Name,
RepoPath: repo.RepoPath(),
})); err != nil {
return fmt.Errorf("git push origin %s: %v", opts.NewBranch, err) return fmt.Errorf("git push origin %s: %v", opts.NewBranch, err)
} }
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
log.Error(2, "OpenRepository: %v", err)
return nil
}
commit, err := gitRepo.GetBranchCommit(opts.NewBranch)
if err != nil {
log.Error(2, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
return nil
}
// Simulate push event.
pushCommits := &PushCommits{
Len: 1,
Commits: []*PushCommit{CommitToPushCommit(commit)},
}
if err := CommitRepoAction(CommitRepoActionOptions{
PusherName: doer.Name,
RepoOwnerID: repo.MustOwner().ID,
RepoName: repo.Name,
RefFullName: git.BRANCH_PREFIX + opts.NewBranch,
OldCommitID: opts.LastCommitID,
NewCommitID: commit.ID.String(),
Commits: pushCommits,
}); err != nil {
log.Error(2, "CommitRepoAction: %v", err)
return nil
}
go AddTestPullRequestTask(doer, repo.ID, opts.NewBranch, true)
return nil return nil
} }
@ -348,19 +333,19 @@ func NewUpload(name string, buf []byte, file multipart.File) (_ *Upload, err err
localPath := upload.LocalPath() localPath := upload.LocalPath()
if err = os.MkdirAll(path.Dir(localPath), os.ModePerm); err != nil { if err = os.MkdirAll(path.Dir(localPath), os.ModePerm); err != nil {
return nil, fmt.Errorf("MkdirAll: %v", err) return nil, fmt.Errorf("mkdir all: %v", err)
} }
fw, err := os.Create(localPath) fw, err := os.Create(localPath)
if err != nil { if err != nil {
return nil, fmt.Errorf("Create: %v", err) return nil, fmt.Errorf("create: %v", err)
} }
defer fw.Close() defer fw.Close()
if _, err = fw.Write(buf); err != nil { if _, err = fw.Write(buf); err != nil {
return nil, fmt.Errorf("Write: %v", err) return nil, fmt.Errorf("write: %v", err)
} else if _, err = io.Copy(fw, file); err != nil { } else if _, err = io.Copy(fw, file); err != nil {
return nil, fmt.Errorf("Copy: %v", err) return nil, fmt.Errorf("copy: %v", err)
} }
if _, err := x.Insert(upload); err != nil { if _, err := x.Insert(upload); err != nil {
@ -434,11 +419,11 @@ func DeleteUploadByUUID(uuid string) error {
if IsErrUploadNotExist(err) { if IsErrUploadNotExist(err) {
return nil return nil
} }
return fmt.Errorf("GetUploadByUUID: %v", err) return fmt.Errorf("get upload by UUID[%s]: %v", uuid, err)
} }
if err := DeleteUpload(upload); err != nil { if err := DeleteUpload(upload); err != nil {
return fmt.Errorf("DeleteUpload: %v", err) return fmt.Errorf("delete upload: %v", err)
} }
return nil return nil
@ -450,7 +435,7 @@ type UploadRepoFileOptions struct {
NewBranch string NewBranch string
TreePath string TreePath string
Message string Message string
Files []string // In UUID format. Files []string // In UUID format
} }
func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions) (err error) { func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions) (err error) {
@ -460,21 +445,21 @@ func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions)
uploads, err := GetUploadsByUUIDs(opts.Files) uploads, err := GetUploadsByUUIDs(opts.Files)
if err != nil { if err != nil {
return fmt.Errorf("GetUploadsByUUIDs [uuids: %v]: %v", opts.Files, err) return fmt.Errorf("get uploads by UUIDs[%v]: %v", opts.Files, err)
} }
repoWorkingPool.CheckIn(com.ToStr(repo.ID)) repoWorkingPool.CheckIn(com.ToStr(repo.ID))
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID)) defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
if err = repo.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil { if err = repo.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil {
return fmt.Errorf("DiscardLocalRepoBranchChanges [branch: %s]: %v", opts.OldBranch, err) return fmt.Errorf("discard local repo branch[%s] changes: %v", opts.OldBranch, err)
} else if err = repo.UpdateLocalCopyBranch(opts.OldBranch); err != nil { } else if err = repo.UpdateLocalCopyBranch(opts.OldBranch); err != nil {
return fmt.Errorf("UpdateLocalCopyBranch [branch: %s]: %v", opts.OldBranch, err) return fmt.Errorf("update local copy branch[%s]: %v", opts.OldBranch, err)
} }
if opts.OldBranch != opts.NewBranch { if opts.OldBranch != opts.NewBranch {
if err = repo.CheckoutNewBranch(opts.OldBranch, opts.NewBranch); err != nil { if err = repo.CheckoutNewBranch(opts.OldBranch, opts.NewBranch); err != nil {
return fmt.Errorf("CheckoutNewBranch [old_branch: %s, new_branch: %s]: %v", opts.OldBranch, opts.NewBranch, err) return fmt.Errorf("checkout new branch[%s] from old branch[%s]: %v", opts.NewBranch, opts.OldBranch, err)
} }
} }
@ -491,7 +476,7 @@ func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions)
} }
if err = com.Copy(tmpPath, targetPath); err != nil { if err = com.Copy(tmpPath, targetPath); err != nil {
return fmt.Errorf("Copy: %v", err) return fmt.Errorf("copy: %v", err)
} }
} }
@ -501,40 +486,18 @@ func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions)
Committer: doer.NewGitSig(), Committer: doer.NewGitSig(),
Message: opts.Message, Message: opts.Message,
}); err != nil { }); err != nil {
return fmt.Errorf("CommitChanges: %v", err) return fmt.Errorf("commit changes on %q: %v", localPath, err)
} else if err = git.Push(localPath, "origin", opts.NewBranch); err != nil { } else if err = git.PushWithEnvs(localPath, "origin", opts.NewBranch,
ComposeHookEnvs(ComposeHookEnvsOptions{
AuthUser: doer,
OwnerName: repo.MustOwner().Name,
OwnerSalt: repo.MustOwner().Salt,
RepoID: repo.ID,
RepoName: repo.Name,
RepoPath: repo.RepoPath(),
})); err != nil {
return fmt.Errorf("git push origin %s: %v", opts.NewBranch, err) return fmt.Errorf("git push origin %s: %v", opts.NewBranch, err)
} }
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
log.Error(2, "OpenRepository: %v", err)
return nil
}
commit, err := gitRepo.GetBranchCommit(opts.NewBranch)
if err != nil {
log.Error(2, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
return nil
}
// Simulate push event.
pushCommits := &PushCommits{
Len: 1,
Commits: []*PushCommit{CommitToPushCommit(commit)},
}
if err := CommitRepoAction(CommitRepoActionOptions{
PusherName: doer.Name,
RepoOwnerID: repo.MustOwner().ID,
RepoName: repo.Name,
RefFullName: git.BRANCH_PREFIX + opts.NewBranch,
OldCommitID: opts.LastCommitID,
NewCommitID: commit.ID.String(),
Commits: pushCommits,
}); err != nil {
log.Error(2, "CommitRepoAction: %v", err)
return nil
}
go AddTestPullRequestTask(doer, repo.ID, opts.NewBranch, true)
return DeleteUploads(uploads...) return DeleteUploads(uploads...)
} }

4
pkg/context/context.go

@ -72,6 +72,10 @@ func (c *Context) RequireAutosize() {
c.Require("Autosize") c.Require("Autosize")
} }
func (c *Context) RequireDropzone() {
c.Require("Dropzone")
}
// FormErr sets "Err_xxx" field in template data. // FormErr sets "Err_xxx" field in template data.
func (c *Context) FormErr(names ...string) { func (c *Context) FormErr(names ...string) {
for i := range names { for i := range names {

33
routes/repo/editor.go

@ -89,7 +89,7 @@ func editFile(c *context.Context, isNewFile bool) {
buf = append(buf, d...) buf = append(buf, d...)
if err, content := template.ToUTF8WithErr(buf); err != nil { if err, content := template.ToUTF8WithErr(buf); err != nil {
if err != nil { if err != nil {
log.Error(2, "ToUTF8WithErr: %v", err) log.Error(2, "Failed to convert encoding to UTF-8: %v", err)
} }
c.Data["FileContent"] = string(buf) c.Data["FileContent"] = string(buf)
} else { } else {
@ -324,18 +324,18 @@ func DiffPreviewPost(c *context.Context, f form.EditPreviewDiff) {
} }
func DeleteFile(c *context.Context) { func DeleteFile(c *context.Context) {
c.Data["PageIsDelete"] = true c.PageIs("Delete")
c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + c.Repo.BranchName c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + c.Repo.BranchName
c.Data["TreePath"] = c.Repo.TreePath c.Data["TreePath"] = c.Repo.TreePath
c.Data["commit_summary"] = "" c.Data["commit_summary"] = ""
c.Data["commit_message"] = "" c.Data["commit_message"] = ""
c.Data["commit_choice"] = "direct" c.Data["commit_choice"] = "direct"
c.Data["new_branch_name"] = "" c.Data["new_branch_name"] = ""
c.HTML(200, DELETE_FILE) c.Success(DELETE_FILE)
} }
func DeleteFilePost(c *context.Context, f form.DeleteRepoFile) { func DeleteFilePost(c *context.Context, f form.DeleteRepoFile) {
c.Data["PageIsDelete"] = true c.PageIs("Delete")
c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + c.Repo.BranchName c.Data["BranchLink"] = c.Repo.RepoLink + "/src/" + c.Repo.BranchName
c.Data["TreePath"] = c.Repo.TreePath c.Data["TreePath"] = c.Repo.TreePath
@ -351,13 +351,13 @@ func DeleteFilePost(c *context.Context, f form.DeleteRepoFile) {
c.Data["new_branch_name"] = branchName c.Data["new_branch_name"] = branchName
if c.HasError() { if c.HasError() {
c.HTML(200, DELETE_FILE) c.Success(DELETE_FILE)
return return
} }
if oldBranchName != branchName { if oldBranchName != branchName {
if _, err := c.Repo.Repository.GetBranch(branchName); err == nil { if _, err := c.Repo.Repository.GetBranch(branchName); err == nil {
c.Data["Err_NewBranchName"] = true c.FormErr("NewBranchName")
c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), DELETE_FILE, &f) c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), DELETE_FILE, &f)
return return
} }
@ -380,7 +380,7 @@ func DeleteFilePost(c *context.Context, f form.DeleteRepoFile) {
TreePath: c.Repo.TreePath, TreePath: c.Repo.TreePath,
Message: message, Message: message,
}); err != nil { }); err != nil {
c.Handle(500, "DeleteRepoFile", err) c.ServerError("DeleteRepoFile", err)
return return
} }
@ -393,14 +393,14 @@ func DeleteFilePost(c *context.Context, f form.DeleteRepoFile) {
} }
func renderUploadSettings(c *context.Context) { func renderUploadSettings(c *context.Context) {
c.Data["RequireDropzone"] = true c.RequireDropzone()
c.Data["UploadAllowedTypes"] = strings.Join(setting.Repository.Upload.AllowedTypes, ",") c.Data["UploadAllowedTypes"] = strings.Join(setting.Repository.Upload.AllowedTypes, ",")
c.Data["UploadMaxSize"] = setting.Repository.Upload.FileMaxSize c.Data["UploadMaxSize"] = setting.Repository.Upload.FileMaxSize
c.Data["UploadMaxFiles"] = setting.Repository.Upload.MaxFiles c.Data["UploadMaxFiles"] = setting.Repository.Upload.MaxFiles
} }
func UploadFile(c *context.Context) { func UploadFile(c *context.Context) {
c.Data["PageIsUpload"] = true c.PageIs("Upload")
renderUploadSettings(c) renderUploadSettings(c)
treeNames, treePaths := getParentTreeFields(c.Repo.TreePath) treeNames, treePaths := getParentTreeFields(c.Repo.TreePath)
@ -416,12 +416,11 @@ func UploadFile(c *context.Context) {
c.Data["commit_message"] = "" c.Data["commit_message"] = ""
c.Data["commit_choice"] = "direct" c.Data["commit_choice"] = "direct"
c.Data["new_branch_name"] = "" c.Data["new_branch_name"] = ""
c.Success(UPLOAD_FILE)
c.HTML(200, UPLOAD_FILE)
} }
func UploadFilePost(c *context.Context, f form.UploadRepoFile) { func UploadFilePost(c *context.Context, f form.UploadRepoFile) {
c.Data["PageIsUpload"] = true c.PageIs("Upload")
renderUploadSettings(c) renderUploadSettings(c)
oldBranchName := c.Repo.BranchName oldBranchName := c.Repo.BranchName
@ -448,13 +447,13 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) {
c.Data["new_branch_name"] = branchName c.Data["new_branch_name"] = branchName
if c.HasError() { if c.HasError() {
c.HTML(200, UPLOAD_FILE) c.Success(UPLOAD_FILE)
return return
} }
if oldBranchName != branchName { if oldBranchName != branchName {
if _, err := c.Repo.Repository.GetBranch(branchName); err == nil { if _, err := c.Repo.Repository.GetBranch(branchName); err == nil {
c.Data["Err_NewBranchName"] = true c.FormErr("NewBranchName")
c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), UPLOAD_FILE, &f) c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), UPLOAD_FILE, &f)
return return
} }
@ -470,13 +469,13 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) {
break break
} }
c.Handle(500, "Repo.Commit.GetTreeEntryByPath", err) c.ServerError("GetTreeEntryByPath", err)
return return
} }
// User can only upload files to a directory. // User can only upload files to a directory.
if !entry.IsDir() { if !entry.IsDir() {
c.Data["Err_TreePath"] = true c.FormErr("TreePath")
c.RenderWithErr(c.Tr("repo.editor.directory_is_a_file", part), UPLOAD_FILE, &f) c.RenderWithErr(c.Tr("repo.editor.directory_is_a_file", part), UPLOAD_FILE, &f)
return return
} }
@ -500,7 +499,7 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) {
Message: message, Message: message,
Files: f.Files, Files: f.Files,
}); err != nil { }); err != nil {
c.Data["Err_TreePath"] = true c.FormErr("TreePath")
c.RenderWithErr(c.Tr("repo.editor.unable_to_upload_files", f.TreePath, err), UPLOAD_FILE, &f) c.RenderWithErr(c.Tr("repo.editor.unable_to_upload_files", f.TreePath, err), UPLOAD_FILE, &f)
return return
} }

38
routes/repo/http.go

@ -17,7 +17,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/Unknwon/com"
log "gopkg.in/clog.v1" log "gopkg.in/clog.v1"
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
@ -28,17 +27,6 @@ import (
"github.com/gogs/gogs/pkg/tool" "github.com/gogs/gogs/pkg/tool"
) )
const (
ENV_AUTH_USER_ID = "GOGS_AUTH_USER_ID"
ENV_AUTH_USER_NAME = "GOGS_AUTH_USER_NAME"
ENV_AUTH_USER_EMAIL = "GOGS_AUTH_USER_EMAIL"
ENV_REPO_OWNER_NAME = "GOGS_REPO_OWNER_NAME"
ENV_REPO_OWNER_SALT_MD5 = "GOGS_REPO_OWNER_SALT_MD5"
ENV_REPO_ID = "GOGS_REPO_ID"
ENV_REPO_NAME = "GOGS_REPO_NAME"
ENV_REPO_CUSTOM_HOOKS_PATH = "GOGS_REPO_CUSTOM_HOOKS_PATH"
)
type HTTPContext struct { type HTTPContext struct {
*context.Context *context.Context
OwnerName string OwnerName string
@ -228,30 +216,6 @@ func (h *serviceHandler) sendFile(contentType string) {
http.ServeFile(h.w, h.r, reqFile) http.ServeFile(h.w, h.r, reqFile)
} }
type ComposeHookEnvsOptions struct {
AuthUser *models.User
OwnerName string
OwnerSalt string
RepoID int64
RepoName string
RepoPath string
}
func ComposeHookEnvs(opts ComposeHookEnvsOptions) []string {
envs := []string{
"SSH_ORIGINAL_COMMAND=1",
ENV_AUTH_USER_ID + "=" + com.ToStr(opts.AuthUser.ID),
ENV_AUTH_USER_NAME + "=" + opts.AuthUser.Name,
ENV_AUTH_USER_EMAIL + "=" + opts.AuthUser.Email,
ENV_REPO_OWNER_NAME + "=" + opts.OwnerName,
ENV_REPO_OWNER_SALT_MD5 + "=" + tool.MD5(opts.OwnerSalt),
ENV_REPO_ID + "=" + com.ToStr(opts.RepoID),
ENV_REPO_NAME + "=" + opts.RepoName,
ENV_REPO_CUSTOM_HOOKS_PATH + "=" + path.Join(opts.RepoPath, "custom_hooks"),
}
return envs
}
func serviceRPC(h serviceHandler, service string) { func serviceRPC(h serviceHandler, service string) {
defer h.r.Body.Close() defer h.r.Body.Close()
@ -279,7 +243,7 @@ func serviceRPC(h serviceHandler, service string) {
var stderr bytes.Buffer var stderr bytes.Buffer
cmd := exec.Command("git", service, "--stateless-rpc", h.dir) cmd := exec.Command("git", service, "--stateless-rpc", h.dir)
if service == "receive-pack" { if service == "receive-pack" {
cmd.Env = append(os.Environ(), ComposeHookEnvs(ComposeHookEnvsOptions{ cmd.Env = append(os.Environ(), models.ComposeHookEnvs(models.ComposeHookEnvsOptions{
AuthUser: h.authUser, AuthUser: h.authUser,
OwnerName: h.ownerName, OwnerName: h.ownerName,
OwnerSalt: h.ownerSalt, OwnerSalt: h.ownerSalt,

2
templates/.VERSION

@ -1 +1 @@
0.11.62.0817 0.11.63.0817

Loading…
Cancel
Save