![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true) | ![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true) | ||||
##### Current tip version: 0.9.82 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | |||||
##### Current tip version: 0.9.83 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | |||||
| Web | UI | Preview | | | Web | UI | Preview | | ||||
|:-------------:|:-------:|:-------:| | |:-------------:|:-------:|:-------:| |
} | } | ||||
if err = models.PushUpdate(models.PushUpdateOptions{ | if err = models.PushUpdate(models.PushUpdateOptions{ | ||||
RefName: task.RefName, | |||||
RefFullName: task.RefName, | |||||
OldCommitID: task.OldCommitID, | OldCommitID: task.OldCommitID, | ||||
NewCommitID: task.NewCommitID, | NewCommitID: task.NewCommitID, | ||||
PusherID: user.ID, | PusherID: user.ID, |
"github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
) | ) | ||||
const APP_VER = "0.9.82.0816" | |||||
const APP_VER = "0.9.83.0816" | |||||
func init() { | func init() { | ||||
runtime.GOMAXPROCS(runtime.NumCPU()) | runtime.GOMAXPROCS(runtime.NumCPU()) |
OpType ActionType | OpType ActionType | ||||
ActUserID int64 // Action user id. | ActUserID int64 // Action user id. | ||||
ActUserName string // Action user name. | ActUserName string // Action user name. | ||||
ActEmail string | |||||
ActAvatar string `xorm:"-"` | ActAvatar string `xorm:"-"` | ||||
RepoID int64 | RepoID int64 | ||||
RepoUserName string | RepoUserName string | ||||
return base.EllipsisString(a.ActUserName, 20) | return base.EllipsisString(a.ActUserName, 20) | ||||
} | } | ||||
func (a *Action) GetActEmail() string { | |||||
return a.ActEmail | |||||
} | |||||
func (a *Action) GetRepoUserName() string { | func (a *Action) GetRepoUserName() string { | ||||
return a.RepoUserName | return a.RepoUserName | ||||
} | } | ||||
if err = notifyWatchers(e, &Action{ | if err = notifyWatchers(e, &Action{ | ||||
ActUserID: u.ID, | ActUserID: u.ID, | ||||
ActUserName: u.Name, | ActUserName: u.Name, | ||||
ActEmail: u.Email, | |||||
OpType: ACTION_CREATE_REPO, | OpType: ACTION_CREATE_REPO, | ||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
RepoUserName: repo.Owner.Name, | RepoUserName: repo.Owner.Name, | ||||
if err = notifyWatchers(e, &Action{ | if err = notifyWatchers(e, &Action{ | ||||
ActUserID: actUser.ID, | ActUserID: actUser.ID, | ||||
ActUserName: actUser.Name, | ActUserName: actUser.Name, | ||||
ActEmail: actUser.Email, | |||||
OpType: ACTION_RENAME_REPO, | OpType: ACTION_RENAME_REPO, | ||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
RepoUserName: repo.Owner.Name, | RepoUserName: repo.Owner.Name, | ||||
return push.avatars[email] | return push.avatars[email] | ||||
} | } | ||||
// updateIssuesCommit checks if issues are manipulated by commit message. | |||||
func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string, commits []*PushCommit) error { | |||||
// UpdateIssuesCommit checks if issues are manipulated by commit message. | |||||
func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) error { | |||||
// Commits are appended in the reverse order. | // Commits are appended in the reverse order. | ||||
for i := len(commits) - 1; i >= 0; i-- { | for i := len(commits) - 1; i >= 0; i-- { | ||||
c := commits[i] | c := commits[i] | ||||
// Add repo name if missing | // Add repo name if missing | ||||
if ref[0] == '#' { | if ref[0] == '#' { | ||||
ref = fmt.Sprintf("%s/%s%s", repoUserName, repoName, ref) | |||||
ref = fmt.Sprintf("%s%s", repo.FullName(), ref) | |||||
} else if !strings.Contains(ref, "/") { | } else if !strings.Contains(ref, "/") { | ||||
// FIXME: We don't support User#ID syntax yet | // FIXME: We don't support User#ID syntax yet | ||||
// return ErrNotImplemented | // return ErrNotImplemented | ||||
} | } | ||||
refMarked[issue.ID] = true | refMarked[issue.ID] = true | ||||
url := fmt.Sprintf("%s/%s/%s/commit/%s", setting.AppSubUrl, repoUserName, repoName, c.Sha1) | |||||
message := fmt.Sprintf(`<a href="%s">%s</a>`, url, c.Message) | |||||
if err = CreateRefComment(u, repo, issue, message, c.Sha1); err != nil { | |||||
message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, repo.Link(), c.Sha1, c.Message) | |||||
if err = CreateRefComment(doer, repo, issue, message, c.Sha1); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
// Add repo name if missing | // Add repo name if missing | ||||
if ref[0] == '#' { | if ref[0] == '#' { | ||||
ref = fmt.Sprintf("%s/%s%s", repoUserName, repoName, ref) | |||||
ref = fmt.Sprintf("%s%s", repo.FullName(), ref) | |||||
} else if !strings.Contains(ref, "/") { | } else if !strings.Contains(ref, "/") { | ||||
// We don't support User#ID syntax yet | // We don't support User#ID syntax yet | ||||
// return ErrNotImplemented | // return ErrNotImplemented | ||||
continue | continue | ||||
} | } | ||||
if err = issue.ChangeStatus(u, repo, true); err != nil { | |||||
if err = issue.ChangeStatus(doer, repo, true); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
// Add repo name if missing | // Add repo name if missing | ||||
if ref[0] == '#' { | if ref[0] == '#' { | ||||
ref = fmt.Sprintf("%s/%s%s", repoUserName, repoName, ref) | |||||
ref = fmt.Sprintf("%s%s", repo.FullName(), ref) | |||||
} else if !strings.Contains(ref, "/") { | } else if !strings.Contains(ref, "/") { | ||||
// We don't support User#ID syntax yet | // We don't support User#ID syntax yet | ||||
// return ErrNotImplemented | // return ErrNotImplemented | ||||
continue | continue | ||||
} | } | ||||
if err = issue.ChangeStatus(u, repo, false); err != nil { | |||||
if err = issue.ChangeStatus(doer, repo, false); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
return nil | return nil | ||||
} | } | ||||
// CommitRepoAction adds new action for committing repository. | |||||
// TODO: use CommitRepoActionOptions | |||||
func CommitRepoAction( | |||||
userID, repoUserID int64, | |||||
userName, actEmail string, | |||||
repoID int64, | |||||
repoUserName, repoName string, | |||||
refFullName string, | |||||
commit *PushCommits, | |||||
oldCommitID string, newCommitID string) error { | |||||
type CommitRepoActionOptions struct { | |||||
PusherName string | |||||
RepoOwnerID int64 | |||||
RepoName string | |||||
RefFullName string | |||||
OldCommitID string | |||||
NewCommitID string | |||||
Commits *PushCommits | |||||
} | |||||
u, err := GetUserByID(userID) | |||||
// CommitRepoAction adds new commit actio to the repository, and prepare corresponding webhooks. | |||||
func CommitRepoAction(opts CommitRepoActionOptions) error { | |||||
pusher, err := GetUserByName(opts.PusherName) | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("GetUserByID: %v", err) | |||||
return fmt.Errorf("GetUserByName [%s]: %v", opts.PusherName, err) | |||||
} | } | ||||
repo, err := GetRepositoryByName(repoUserID, repoName) | |||||
repo, err := GetRepositoryByName(opts.RepoOwnerID, opts.RepoName) | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("GetRepositoryByName: %v", err) | |||||
} else if err = repo.GetOwner(); err != nil { | |||||
return fmt.Errorf("GetOwner: %v", err) | |||||
return fmt.Errorf("GetRepositoryByName [owner_id: %d, name: %s]: %v", opts.RepoOwnerID, opts.RepoName, err) | |||||
} | } | ||||
// Change repository bare status and update last updated time. | // Change repository bare status and update last updated time. | ||||
isNewBranch := false | isNewBranch := false | ||||
opType := ACTION_COMMIT_REPO | opType := ACTION_COMMIT_REPO | ||||
// Check it's tag push or branch. | // Check it's tag push or branch. | ||||
if strings.HasPrefix(refFullName, "refs/tags/") { | |||||
if strings.HasPrefix(opts.RefFullName, git.TAG_PREFIX) { | |||||
opType = ACTION_PUSH_TAG | opType = ACTION_PUSH_TAG | ||||
commit = &PushCommits{} | |||||
opts.Commits = &PushCommits{} | |||||
} else { | } else { | ||||
// if not the first commit, set the compareUrl | |||||
if !strings.HasPrefix(oldCommitID, "0000000") { | |||||
commit.CompareURL = repo.ComposeCompareURL(oldCommitID, newCommitID) | |||||
} else { | |||||
// if not the first commit, set the compare URL. | |||||
if opts.OldCommitID == git.EMPTY_SHA { | |||||
isNewBranch = true | isNewBranch = true | ||||
} else { | |||||
opts.Commits.CompareURL = repo.ComposeCompareURL(opts.OldCommitID, opts.NewCommitID) | |||||
} | } | ||||
if err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits); err != nil { | |||||
if err = UpdateIssuesCommit(pusher, repo, opts.Commits.Commits); err != nil { | |||||
log.Error(4, "updateIssuesCommit: %v", err) | log.Error(4, "updateIssuesCommit: %v", err) | ||||
} | } | ||||
} | } | ||||
if len(commit.Commits) > setting.UI.FeedMaxCommitNum { | |||||
commit.Commits = commit.Commits[:setting.UI.FeedMaxCommitNum] | |||||
if len(opts.Commits.Commits) > setting.UI.FeedMaxCommitNum { | |||||
opts.Commits.Commits = opts.Commits.Commits[:setting.UI.FeedMaxCommitNum] | |||||
} | } | ||||
bs, err := json.Marshal(commit) | |||||
data, err := json.Marshal(opts.Commits) | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("Marshal: %v", err) | return fmt.Errorf("Marshal: %v", err) | ||||
} | } | ||||
refName := git.RefEndName(refFullName) | |||||
refName := git.RefEndName(opts.RefFullName) | |||||
if err = NotifyWatchers(&Action{ | if err = NotifyWatchers(&Action{ | ||||
ActUserID: u.ID, | |||||
ActUserName: userName, | |||||
ActEmail: actEmail, | |||||
ActUserID: pusher.ID, | |||||
ActUserName: pusher.Name, | |||||
OpType: opType, | OpType: opType, | ||||
Content: string(bs), | |||||
Content: string(data), | |||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
RepoUserName: repoUserName, | |||||
RepoUserName: repo.MustOwner().Name, | |||||
RepoName: repo.Name, | RepoName: repo.Name, | ||||
RefName: refName, | RefName: refName, | ||||
IsPrivate: repo.IsPrivate, | IsPrivate: repo.IsPrivate, | ||||
return fmt.Errorf("NotifyWatchers: %v", err) | return fmt.Errorf("NotifyWatchers: %v", err) | ||||
} | } | ||||
pusher, err := GetUserByName(userName) | |||||
if err != nil { | |||||
return fmt.Errorf("GetUserByName: %v", err) | |||||
} | |||||
apiPusher := pusher.APIFormat() | |||||
defer func() { | |||||
go HookQueue.Add(repo.ID) | |||||
}() | |||||
apiPusher := pusher.APIFormat() | |||||
apiRepo := repo.APIFormat(nil) | apiRepo := repo.APIFormat(nil) | ||||
switch opType { | switch opType { | ||||
case ACTION_COMMIT_REPO: // Push | case ACTION_COMMIT_REPO: // Push | ||||
if err = PrepareWebhooks(repo, HOOK_EVENT_PUSH, &api.PushPayload{ | if err = PrepareWebhooks(repo, HOOK_EVENT_PUSH, &api.PushPayload{ | ||||
Ref: refFullName, | |||||
Before: oldCommitID, | |||||
After: newCommitID, | |||||
CompareURL: setting.AppUrl + commit.CompareURL, | |||||
Commits: commit.ToApiPayloadCommits(repo.HTMLURL()), | |||||
Ref: opts.RefFullName, | |||||
Before: opts.OldCommitID, | |||||
After: opts.NewCommitID, | |||||
CompareURL: setting.AppUrl + opts.Commits.CompareURL, | |||||
Commits: opts.Commits.ToApiPayloadCommits(repo.HTMLURL()), | |||||
Repo: apiRepo, | Repo: apiRepo, | ||||
Pusher: apiPusher, | Pusher: apiPusher, | ||||
Sender: apiPusher, | Sender: apiPusher, | ||||
return nil | return nil | ||||
} | } | ||||
func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repository) (err error) { | |||||
func transferRepoAction(e Engine, doer, oldOwner *User, repo *Repository) (err error) { | |||||
if err = notifyWatchers(e, &Action{ | if err = notifyWatchers(e, &Action{ | ||||
ActUserID: actUser.ID, | |||||
ActUserName: actUser.Name, | |||||
ActEmail: actUser.Email, | |||||
ActUserID: doer.ID, | |||||
ActUserName: doer.Name, | |||||
OpType: ACTION_TRANSFER_REPO, | OpType: ACTION_TRANSFER_REPO, | ||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
RepoUserName: newOwner.Name, | |||||
RepoUserName: repo.Owner.Name, | |||||
RepoName: repo.Name, | RepoName: repo.Name, | ||||
IsPrivate: repo.IsPrivate, | IsPrivate: repo.IsPrivate, | ||||
Content: path.Join(oldOwner.Name, repo.Name), | Content: path.Join(oldOwner.Name, repo.Name), | ||||
}); err != nil { | }); err != nil { | ||||
return fmt.Errorf("notify watchers '%d/%d': %v", actUser.ID, repo.ID, err) | |||||
return fmt.Errorf("notifyWatchers: %v", err) | |||||
} | } | ||||
// Remove watch for organization. | // Remove watch for organization. | ||||
if repo.Owner.IsOrganization() { | |||||
if err = watchRepo(e, repo.Owner.ID, repo.ID, false); err != nil { | |||||
return fmt.Errorf("watch repository: %v", err) | |||||
if oldOwner.IsOrganization() { | |||||
if err = watchRepo(e, oldOwner.ID, repo.ID, false); err != nil { | |||||
return fmt.Errorf("watchRepo [false]: %v", err) | |||||
} | } | ||||
} | } | ||||
log.Trace("action.transferRepoAction: %s/%s", actUser.Name, repo.Name) | |||||
return nil | return nil | ||||
} | } | ||||
// TransferRepoAction adds new action for transferring repository. | |||||
func TransferRepoAction(actUser, oldOwner, newOwner *User, repo *Repository) error { | |||||
return transferRepoAction(x, actUser, oldOwner, newOwner, repo) | |||||
// TransferRepoAction adds new action for transferring repository, | |||||
// the Owner field of repository is assumed to be new owner. | |||||
func TransferRepoAction(doer, oldOwner *User, repo *Repository) error { | |||||
return transferRepoAction(x, doer, oldOwner, repo) | |||||
} | } | ||||
func mergePullRequestAction(e Engine, actUser *User, repo *Repository, pull *Issue) error { | |||||
func mergePullRequestAction(e Engine, doer *User, repo *Repository, issue *Issue) error { | |||||
return notifyWatchers(e, &Action{ | return notifyWatchers(e, &Action{ | ||||
ActUserID: actUser.ID, | |||||
ActUserName: actUser.Name, | |||||
ActEmail: actUser.Email, | |||||
ActUserID: doer.ID, | |||||
ActUserName: doer.Name, | |||||
OpType: ACTION_MERGE_PULL_REQUEST, | OpType: ACTION_MERGE_PULL_REQUEST, | ||||
Content: fmt.Sprintf("%d|%s", pull.Index, pull.Title), | |||||
Content: fmt.Sprintf("%d|%s", issue.Index, issue.Title), | |||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
RepoUserName: repo.Owner.Name, | RepoUserName: repo.Owner.Name, | ||||
RepoName: repo.Name, | RepoName: repo.Name, |
if err = NotifyWatchers(&Action{ | if err = NotifyWatchers(&Action{ | ||||
ActUserID: issue.Poster.ID, | ActUserID: issue.Poster.ID, | ||||
ActUserName: issue.Poster.Name, | ActUserName: issue.Poster.Name, | ||||
ActEmail: issue.Poster.Email, | |||||
OpType: ACTION_CREATE_ISSUE, | OpType: ACTION_CREATE_ISSUE, | ||||
Content: fmt.Sprintf("%d|%s", issue.Index, issue.Title), | Content: fmt.Sprintf("%d|%s", issue.Index, issue.Title), | ||||
RepoID: repo.ID, | RepoID: repo.ID, |
act := &Action{ | act := &Action{ | ||||
ActUserID: opts.Doer.ID, | ActUserID: opts.Doer.ID, | ||||
ActUserName: opts.Doer.Name, | ActUserName: opts.Doer.Name, | ||||
ActEmail: opts.Doer.Email, | |||||
Content: fmt.Sprintf("%d|%s", opts.Issue.Index, strings.Split(opts.Content, "\n")[0]), | Content: fmt.Sprintf("%d|%s", opts.Issue.Index, strings.Split(opts.Content, "\n")[0]), | ||||
RepoID: opts.Repo.ID, | RepoID: opts.Repo.ID, | ||||
RepoUserName: opts.Repo.Owner.Name, | RepoUserName: opts.Repo.Owner.Name, |
if err = NotifyWatchers(&Action{ | if err = NotifyWatchers(&Action{ | ||||
ActUserID: pull.Poster.ID, | ActUserID: pull.Poster.ID, | ||||
ActUserName: pull.Poster.Name, | ActUserName: pull.Poster.Name, | ||||
ActEmail: pull.Poster.Email, | |||||
OpType: ACTION_CREATE_PULL_REQUEST, | OpType: ACTION_CREATE_PULL_REQUEST, | ||||
Content: fmt.Sprintf("%d|%s", pull.Index, pull.Title), | Content: fmt.Sprintf("%d|%s", pull.Index, pull.Title), | ||||
RepoID: repo.ID, | RepoID: repo.ID, |
return filepath.Join(repo.RepoPath(), "config") | return filepath.Join(repo.RepoPath(), "config") | ||||
} | } | ||||
func (repo *Repository) Link() string { | |||||
return setting.AppSubUrl + "/" + repo.MustOwner().Name + "/" + repo.Name | |||||
func (repo *Repository) RelLink() string { | |||||
return "/" + repo.FullName() | |||||
} | } | ||||
func (repo *Repository) RelLink() string { | |||||
return "/" + repo.MustOwner().Name + "/" + repo.Name | |||||
func (repo *Repository) Link() string { | |||||
return setting.AppSubUrl + "/" + repo.FullName() | |||||
} | } | ||||
func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) string { | func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) string { | ||||
} | } | ||||
// TransferOwnership transfers all corresponding setting from old user to new one. | // TransferOwnership transfers all corresponding setting from old user to new one. | ||||
func TransferOwnership(u *User, newOwnerName string, repo *Repository) error { | |||||
func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error { | |||||
newOwner, err := GetUserByName(newOwnerName) | newOwner, err := GetUserByName(newOwnerName) | ||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("get new owner '%s': %v", newOwnerName, err) | return fmt.Errorf("get new owner '%s': %v", newOwnerName, err) | ||||
owner := repo.Owner | owner := repo.Owner | ||||
// Note: we have to set value here to make sure recalculate accesses is based on | // Note: we have to set value here to make sure recalculate accesses is based on | ||||
// new owner. | |||||
// new owner. | |||||
repo.OwnerID = newOwner.ID | repo.OwnerID = newOwner.ID | ||||
repo.Owner = newOwner | repo.Owner = newOwner | ||||
if err = watchRepo(sess, newOwner.ID, repo.ID, true); err != nil { | if err = watchRepo(sess, newOwner.ID, repo.ID, true); err != nil { | ||||
return fmt.Errorf("watchRepo: %v", err) | return fmt.Errorf("watchRepo: %v", err) | ||||
} else if err = transferRepoAction(sess, u, owner, newOwner, repo); err != nil { | |||||
} else if err = transferRepoAction(sess, doer, owner, repo); err != nil { | |||||
return fmt.Errorf("transferRepoAction: %v", err) | return fmt.Errorf("transferRepoAction: %v", err) | ||||
} | } | ||||
} | } | ||||
// GetRepositoryByName returns the repository by given name under user if exists. | // GetRepositoryByName returns the repository by given name under user if exists. | ||||
func GetRepositoryByName(uid int64, repoName string) (*Repository, error) { | |||||
func GetRepositoryByName(ownerID int64, name string) (*Repository, error) { | |||||
repo := &Repository{ | repo := &Repository{ | ||||
OwnerID: uid, | |||||
LowerName: strings.ToLower(repoName), | |||||
OwnerID: ownerID, | |||||
LowerName: strings.ToLower(name), | |||||
} | } | ||||
has, err := x.Get(repo) | has, err := x.Get(repo) | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
} else if !has { | } else if !has { | ||||
return nil, ErrRepoNotExist{0, uid, repoName} | |||||
return nil, ErrRepoNotExist{0, ownerID, name} | |||||
} | } | ||||
return repo, err | return repo, err | ||||
} | } |
if opts.NewBranch != opts.OldBranch { | if opts.NewBranch != opts.OldBranch { | ||||
oldCommitID = git.EMPTY_SHA | oldCommitID = git.EMPTY_SHA | ||||
} | } | ||||
if err := CommitRepoAction(doer.ID, repo.MustOwner().ID, doer.Name, doer.Email, | |||||
repo.ID, repo.MustOwner().Name, repo.Name, git.BRANCH_PREFIX+opts.NewBranch, | |||||
pushCommits, oldCommitID, commit.ID.String()); err != nil { | |||||
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(4, "CommitRepoAction: %v", err) | log.Error(4, "CommitRepoAction: %v", err) | ||||
return nil | return nil | ||||
} | } | ||||
go HookQueue.Add(repo.ID) | |||||
return nil | return nil | ||||
} | } | ||||
// \/ \/ \/ \/ \/ \/ | // \/ \/ \/ \/ \/ \/ | ||||
// | // | ||||
func (repo *Repository) DeleteRepoFile(doer *User, oldCommitID, branch, treeName, message string) (err error) { | |||||
type DeleteRepoFileOptions struct { | |||||
LastCommitID string | |||||
Branch string | |||||
TreePath string | |||||
Message string | |||||
} | |||||
func (repo *Repository) DeleteRepoFile(doer *User, opts DeleteRepoFileOptions) (err error) { | |||||
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)) | ||||
localPath := repo.LocalCopyPath() | localPath := repo.LocalCopyPath() | ||||
if err = discardLocalRepoBranchChanges(localPath, branch); err != nil { | |||||
return fmt.Errorf("discardLocalRepoChanges: %v", err) | |||||
} else if err = repo.UpdateLocalCopyBranch(branch); err != nil { | |||||
return fmt.Errorf("UpdateLocalCopyBranch: %v", err) | |||||
if err = discardLocalRepoBranchChanges(localPath, opts.Branch); err != nil { | |||||
return fmt.Errorf("discardLocalRepoBranchChanges [branch: %s]: %v", opts.Branch, err) | |||||
} else if err = repo.UpdateLocalCopyBranch(opts.Branch); err != nil { | |||||
return fmt.Errorf("UpdateLocalCopyBranch [branch: %s]: %v", opts.Branch, err) | |||||
} | } | ||||
filePath := path.Join(localPath, treeName) | |||||
os.Remove(filePath) | |||||
if err = os.Remove(path.Join(localPath, opts.TreePath)); err != nil { | |||||
return fmt.Errorf("Remove: %v", err) | |||||
} | |||||
if len(message) == 0 { | |||||
message = "Delete file '" + treeName + "'" | |||||
if len(opts.Message) == 0 { | |||||
opts.Message = "Delete file '" + opts.TreePath + "'" | |||||
} | } | ||||
if err = git.AddChanges(localPath, true); err != nil { | if err = git.AddChanges(localPath, true); err != nil { | ||||
return fmt.Errorf("AddChanges: %v", err) | |||||
} else if err = git.CommitChanges(localPath, message, doer.NewGitSig()); err != nil { | |||||
return fmt.Errorf("CommitChanges: %v", err) | |||||
} else if err = git.Push(localPath, "origin", branch); err != nil { | |||||
return fmt.Errorf("Push: %v", err) | |||||
return fmt.Errorf("git add --all: %v", err) | |||||
} | |||||
signaure := doer.NewGitSig() | |||||
if err = git.CommitChanges(localPath, opts.Message, signaure); err != nil { | |||||
return fmt.Errorf("git commit -m %s --author='%s <%s>': %v", opts.Message, signaure.Name, signaure.Email, err) | |||||
} else if err = git.Push(localPath, "origin", opts.Branch); err != nil { | |||||
return fmt.Errorf("git push origin %s: %v", opts.Branch, err) | |||||
} | } | ||||
gitRepo, err := git.OpenRepository(repo.RepoPath()) | gitRepo, err := git.OpenRepository(repo.RepoPath()) | ||||
log.Error(4, "OpenRepository: %v", err) | log.Error(4, "OpenRepository: %v", err) | ||||
return nil | return nil | ||||
} | } | ||||
commit, err := gitRepo.GetBranchCommit(branch) | |||||
commit, err := gitRepo.GetBranchCommit(opts.Branch) | |||||
if err != nil { | if err != nil { | ||||
log.Error(4, "GetBranchCommit [branch: %s]: %v", branch, err) | |||||
log.Error(4, "GetBranchCommit [branch: %s]: %v", opts.Branch, err) | |||||
return nil | return nil | ||||
} | } | ||||
// Simulate push event. | |||||
pushCommits := &PushCommits{ | pushCommits := &PushCommits{ | ||||
Len: 1, | Len: 1, | ||||
Commits: []*PushCommit{CommitToPushCommit(commit)}, | Commits: []*PushCommit{CommitToPushCommit(commit)}, | ||||
} | } | ||||
if err := CommitRepoAction(doer.ID, repo.MustOwner().ID, doer.Name, doer.Email, | |||||
repo.ID, repo.MustOwner().Name, repo.Name, git.BRANCH_PREFIX+branch, | |||||
pushCommits, oldCommitID, commit.ID.String()); err != nil { | |||||
if err := CommitRepoAction(CommitRepoActionOptions{ | |||||
PusherName: doer.Name, | |||||
RepoOwnerID: repo.MustOwner().ID, | |||||
RepoName: repo.Name, | |||||
RefFullName: git.BRANCH_PREFIX + opts.Branch, | |||||
OldCommitID: opts.LastCommitID, | |||||
NewCommitID: commit.ID.String(), | |||||
Commits: pushCommits, | |||||
}); err != nil { | |||||
log.Error(4, "CommitRepoAction: %v", err) | log.Error(4, "CommitRepoAction: %v", err) | ||||
return nil | return nil | ||||
} | } | ||||
go HookQueue.Add(repo.ID) | |||||
return nil | return nil | ||||
} | } |
} | } | ||||
type PushUpdateOptions struct { | type PushUpdateOptions struct { | ||||
RefName string | |||||
OldCommitID string | |||||
NewCommitID string | |||||
PusherID int64 | PusherID int64 | ||||
PusherName string | PusherName string | ||||
RepoUserName string | RepoUserName string | ||||
RepoName string | RepoName string | ||||
RefFullName string | |||||
OldCommitID string | |||||
NewCommitID string | |||||
} | } | ||||
// 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) (err error) { | ||||
isNewRef := strings.HasPrefix(opts.OldCommitID, "0000000") | |||||
isDelRef := strings.HasPrefix(opts.NewCommitID, "0000000") | |||||
isNewRef := opts.OldCommitID == git.EMPTY_SHA | |||||
isDelRef := opts.NewCommitID == git.EMPTY_SHA | |||||
if isNewRef && isDelRef { | if isNewRef && isDelRef { | ||||
return fmt.Errorf("Old and new revisions both start with 000000") | |||||
return fmt.Errorf("Old and new revisions are both %s", git.EMPTY_SHA) | |||||
} | } | ||||
repoPath := RepoPath(opts.RepoUserName, opts.RepoName) | repoPath := RepoPath(opts.RepoUserName, opts.RepoName) | ||||
if isDelRef { | if isDelRef { | ||||
log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %d", | log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %d", | ||||
opts.RefName, opts.RepoUserName, opts.RepoName, opts.PusherName) | |||||
opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName) | |||||
return nil | return nil | ||||
} | } | ||||
return fmt.Errorf("OpenRepository: %v", err) | return fmt.Errorf("OpenRepository: %v", err) | ||||
} | } | ||||
repoUser, err := GetUserByName(opts.RepoUserName) | |||||
owner, err := GetUserByName(opts.RepoUserName) | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("GetUserByName: %v", err) | return fmt.Errorf("GetUserByName: %v", err) | ||||
} | } | ||||
repo, err := GetRepositoryByName(repoUser.ID, opts.RepoName) | |||||
repo, err := GetRepositoryByName(owner.ID, opts.RepoName) | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("GetRepositoryByName: %v", err) | return fmt.Errorf("GetRepositoryByName: %v", err) | ||||
} | } | ||||
// Push tags. | // Push tags. | ||||
if strings.HasPrefix(opts.RefName, "refs/tags/") { | |||||
tag, err := gitRepo.GetTag(git.RefEndName(opts.RefName)) | |||||
if err != nil { | |||||
return fmt.Errorf("gitRepo.GetTag: %v", err) | |||||
} | |||||
// When tagger isn't available, fall back to get committer email. | |||||
var actEmail string | |||||
if tag.Tagger != nil { | |||||
actEmail = tag.Tagger.Email | |||||
} else { | |||||
cmt, err := tag.Commit() | |||||
if err != nil { | |||||
return fmt.Errorf("tag.Commit: %v", err) | |||||
} | |||||
actEmail = cmt.Committer.Email | |||||
} | |||||
commit := &PushCommits{} | |||||
if err = CommitRepoAction(opts.PusherID, repoUser.ID, opts.PusherName, actEmail, | |||||
repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, commit, opts.OldCommitID, opts.NewCommitID); err != nil { | |||||
if strings.HasPrefix(opts.RefFullName, git.TAG_PREFIX) { | |||||
if err := CommitRepoAction(CommitRepoActionOptions{ | |||||
PusherName: opts.PusherName, | |||||
RepoOwnerID: owner.ID, | |||||
RepoName: repo.Name, | |||||
RefFullName: opts.RefFullName, | |||||
OldCommitID: opts.OldCommitID, | |||||
NewCommitID: opts.NewCommitID, | |||||
Commits: &PushCommits{}, | |||||
}); err != nil { | |||||
return fmt.Errorf("CommitRepoAction (tag): %v", err) | return fmt.Errorf("CommitRepoAction (tag): %v", err) | ||||
} | } | ||||
return err | |||||
return nil | |||||
} | } | ||||
newCommit, err := gitRepo.GetCommit(opts.NewCommitID) | newCommit, err := gitRepo.GetCommit(opts.NewCommitID) | ||||
} | } | ||||
} | } | ||||
if err = CommitRepoAction(opts.PusherID, repoUser.ID, opts.PusherName, repoUser.Email, | |||||
repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, ListToPushCommits(l), | |||||
opts.OldCommitID, opts.NewCommitID); err != nil { | |||||
if err := CommitRepoAction(CommitRepoActionOptions{ | |||||
PusherName: opts.PusherName, | |||||
RepoOwnerID: owner.ID, | |||||
RepoName: repo.Name, | |||||
RefFullName: opts.RefFullName, | |||||
OldCommitID: opts.OldCommitID, | |||||
NewCommitID: opts.NewCommitID, | |||||
Commits: ListToPushCommits(l), | |||||
}); err != nil { | |||||
return fmt.Errorf("CommitRepoAction (branch): %v", err) | return fmt.Errorf("CommitRepoAction (branch): %v", err) | ||||
} | } | ||||
return nil | return nil |
type Actioner interface { | type Actioner interface { | ||||
GetOpType() int | GetOpType() int | ||||
GetActUserName() string | GetActUserName() string | ||||
GetActEmail() string | |||||
GetRepoUserName() string | GetRepoUserName() string | ||||
GetRepoName() string | GetRepoName() string | ||||
GetRepoPath() string | GetRepoPath() string |
"outputPathIsOutsideProject": 0, | "outputPathIsOutsideProject": 0, | ||||
"outputPathIsSetByUser": 0, | "outputPathIsSetByUser": 0, | ||||
"outputStyle": 1, | "outputStyle": 1, | ||||
"syntaxCheckerStyle": 1 | |||||
"syntaxCheckerStyle": 0 | |||||
}, | }, | ||||
"\/js\/jquery-1.11.3.min.js": { | "\/js\/jquery-1.11.3.min.js": { | ||||
"fileType": 64, | "fileType": 64, |
}).trigger('keyup'); | }).trigger('keyup'); | ||||
editArea = $('.repository.editor textarea#edit_area'); | editArea = $('.repository.editor textarea#edit_area'); | ||||
if (!editArea.length) | if (!editArea.length) | ||||
return; | return; | ||||
} | } | ||||
// Else we are going to use CodeMirror | // Else we are going to use CodeMirror | ||||
if (!cmEditor) { | |||||
if (!setCodeMirror()) | |||||
return; | |||||
if (!cmEditor && !setCodeMirror()) { | |||||
return; | |||||
} | } | ||||
if (mode) { | if (mode) { |
return | return | ||||
} | } | ||||
if err := ctx.Repo.Repository.DeleteRepoFile(ctx.User, ctx.Repo.CommitID, branchName, treeName, form.CommitSummary); err != nil { | |||||
if err := ctx.Repo.Repository.DeleteRepoFile(ctx.User, models.DeleteRepoFileOptions{ | |||||
LastCommitID: ctx.Repo.CommitID, | |||||
Branch: branchName, | |||||
TreePath: treeName, | |||||
Message: form.CommitSummary, | |||||
}); err != nil { | |||||
ctx.Handle(500, "DeleteRepoFile", err) | ctx.Handle(500, "DeleteRepoFile", err) | ||||
return | return | ||||
} | } |
if len(fields) >= 3 { | if len(fields) >= 3 { | ||||
oldCommitId := fields[0][4:] | oldCommitId := fields[0][4:] | ||||
newCommitId := fields[1] | newCommitId := fields[1] | ||||
refName := fields[2] | |||||
refFullName := fields[2] | |||||
// FIXME: handle error. | // FIXME: handle error. | ||||
if err = models.PushUpdate(models.PushUpdateOptions{ | if err = models.PushUpdate(models.PushUpdateOptions{ | ||||
RefName: refName, | |||||
RefFullName: refFullName, | |||||
OldCommitID: oldCommitId, | OldCommitID: oldCommitId, | ||||
NewCommitID: newCommitId, | NewCommitID: newCommitId, | ||||
PusherID: authUser.ID, | PusherID: authUser.ID, | ||||
RepoUserName: username, | RepoUserName: username, | ||||
RepoName: reponame, | RepoName: reponame, | ||||
}); err == nil { | }); err == nil { | ||||
go models.HookQueue.Add(repo.ID) | |||||
go models.AddTestPullRequestTask(authUser, repo.ID, strings.TrimPrefix(refName, git.BRANCH_PREFIX), true) | |||||
go models.AddTestPullRequestTask(authUser, repo.ID, strings.TrimPrefix(refFullName, git.BRANCH_PREFIX), true) | |||||
} | } | ||||
} | } |
package repo | package repo | ||||
import ( | import ( | ||||
"fmt" | |||||
"net/http" | |||||
"path" | |||||
"strings" | "strings" | ||||
"fmt" | |||||
git "github.com/gogits/git-module" | |||||
"github.com/gogits/gogs/models" | "github.com/gogits/gogs/models" | ||||
"github.com/gogits/gogs/modules/auth" | "github.com/gogits/gogs/modules/auth" | ||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
"github.com/gogits/gogs/modules/context" | "github.com/gogits/gogs/modules/context" | ||||
"github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
"github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
"net/http" | |||||
"path" | |||||
) | ) | ||||
const ( | const ( | ||||
if branchName != oldBranchName { | if branchName != oldBranchName { | ||||
oldCommitID = "0000000000000000000000000000000000000000" // New Branch so we use all 0s | oldCommitID = "0000000000000000000000000000000000000000" // New Branch so we use all 0s | ||||
} | } | ||||
if err := models.CommitRepoAction(ctx.User.ID, ctx.Repo.Owner.ID, ctx.User.LowerName, ctx.Repo.Owner.Email, | |||||
ctx.Repo.Repository.ID, ctx.Repo.Owner.LowerName, ctx.Repo.Repository.Name, "refs/heads/"+branchName, pc, | |||||
oldCommitID, newCommitID); err != nil { | |||||
if err := models.CommitRepoAction(models.CommitRepoActionOptions{ | |||||
PusherName: ctx.User.Name, | |||||
RepoOwnerID: ctx.Repo.Owner.ID, | |||||
RepoName: ctx.Repo.Owner.Name, | |||||
RefFullName: git.BRANCH_PREFIX + branchName, | |||||
OldCommitID: oldCommitID, | |||||
NewCommitID: newCommitID, | |||||
Commits: pc, | |||||
}); err != nil { | |||||
log.Error(4, "models.CommitRepoAction(branch = %s): %v", branchName, err) | log.Error(4, "models.CommitRepoAction(branch = %s): %v", branchName, err) | ||||
} | } | ||||
models.HookQueue.Add(ctx.Repo.Repository.ID) | |||||
} | } | ||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + treeName) | ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + treeName) |
0.9.82.0816 | |||||
0.9.83.0816 |