repo_name_helper = A good repository name is usually composed of short, memorable and unique keywords. | repo_name_helper = A good repository name is usually composed of short, memorable and unique keywords. | ||||
visibility = Visibility | visibility = Visibility | ||||
visiblity_helper = This repository is <span class="ui red text">Private</span> | visiblity_helper = This repository is <span class="ui red text">Private</span> | ||||
visiblity_fork_helper = (Change of this value will affect all forks) | |||||
fork_repo = Fork Repository | fork_repo = Fork Repository | ||||
fork_from = Fork From | fork_from = Fork From | ||||
fork_visiblity_helper = You cannot alter the visibility of a forked repository. | fork_visiblity_helper = You cannot alter the visibility of a forked repository. | ||||
settings.transfer_form_title = Please enter following information to confirm your operation: | settings.transfer_form_title = Please enter following information to confirm your operation: | ||||
settings.delete_notices_1 = - This operation <strong>CANNOT</strong> be undone. | settings.delete_notices_1 = - This operation <strong>CANNOT</strong> be undone. | ||||
settings.delete_notices_2 = - This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators. | settings.delete_notices_2 = - This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators. | ||||
settings.delete_notices_fork_1 = - If this repository is public, all forks will be became independent after deletion. | |||||
settings.delete_notices_fork_2 = - If this repository is private, all forks will be removed at the same time. | |||||
settings.delete_notices_fork_3 = - If you want to keep all forks after deletion, please change visibility of this repository to public first. | |||||
settings.update_settings_success = Repository options has been updated successfully. | settings.update_settings_success = Repository options has been updated successfully. | ||||
settings.transfer_owner = New Owner | settings.transfer_owner = New Owner | ||||
settings.make_transfer = Make Transfer | settings.make_transfer = Make Transfer |
return newRepoAction(x, u, repo) | return newRepoAction(x, u, repo) | ||||
} | } | ||||
func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Repository) (err error) { | |||||
if err = notifyWatchers(e, &Action{ | |||||
ActUserID: actUser.Id, | |||||
ActUserName: actUser.Name, | |||||
ActEmail: actUser.Email, | |||||
OpType: RENAME_REPO, | |||||
RepoID: repo.ID, | |||||
RepoUserName: repo.Owner.Name, | |||||
RepoName: repo.Name, | |||||
IsPrivate: repo.IsPrivate, | |||||
Content: oldRepoName, | |||||
}); err != nil { | |||||
return fmt.Errorf("notify watchers: %v", err) | |||||
} | |||||
log.Trace("action.renameRepoAction: %s/%s", actUser.Name, repo.Name) | |||||
return nil | |||||
} | |||||
// RenameRepoAction adds new action for renaming a repository. | |||||
func RenameRepoAction(actUser *User, oldRepoName string, repo *Repository) error { | |||||
return renameRepoAction(x, actUser, oldRepoName, repo) | |||||
} | |||||
// updateIssuesCommit checks if issues are manipulated by commit message. | // updateIssuesCommit checks if issues are manipulated by commit message. | ||||
func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string, commits []*base.PushCommit) error { | func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string, commits []*base.PushCommit) error { | ||||
for _, c := range commits { | for _, c := range commits { | ||||
return transferRepoAction(x, actUser, oldOwner, newOwner, repo) | return transferRepoAction(x, actUser, oldOwner, newOwner, repo) | ||||
} | } | ||||
func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Repository) (err error) { | |||||
if err = notifyWatchers(e, &Action{ | |||||
ActUserID: actUser.Id, | |||||
ActUserName: actUser.Name, | |||||
ActEmail: actUser.Email, | |||||
OpType: RENAME_REPO, | |||||
RepoUserName: repo.Owner.Name, | |||||
RepoName: repo.Name, | |||||
IsPrivate: repo.IsPrivate, | |||||
Content: oldRepoName, | |||||
}); err != nil { | |||||
return fmt.Errorf("notify watchers: %v", err) | |||||
} | |||||
log.Trace("action.renameRepoAction: %s/%s", actUser.Name, repo.Name) | |||||
return nil | |||||
} | |||||
// RenameRepoAction adds new action for renaming a repository. | |||||
func RenameRepoAction(actUser *User, oldRepoName string, repo *Repository) error { | |||||
return renameRepoAction(x, actUser, oldRepoName, repo) | |||||
} | |||||
// GetFeeds returns action list of given user in given context. | // GetFeeds returns action list of given user in given context. | ||||
func GetFeeds(uid, offset int64, isProfile bool) ([]*Action, error) { | func GetFeeds(uid, offset int64, isProfile bool) ([]*Action, error) { | ||||
actions := make([]*Action, 0, 20) | actions := make([]*Action, 0, 20) |
tables = append(tables, | tables = append(tables, | ||||
new(User), new(PublicKey), new(Oauth2), new(AccessToken), | new(User), new(PublicKey), new(Oauth2), new(AccessToken), | ||||
new(Repository), new(DeployKey), new(Collaboration), new(Access), | new(Repository), new(DeployKey), new(Collaboration), new(Access), | ||||
new(Watch), new(Star), new(Follow), new(Action), | |||||
new(Watch), new(Star), new(ForkInfo), new(Follow), new(Action), | |||||
new(Issue), new(Comment), new(Attachment), new(IssueUser), | new(Issue), new(Comment), new(Attachment), new(IssueUser), | ||||
new(Label), new(IssueLabel), new(Milestone), | new(Label), new(IssueLabel), new(Milestone), | ||||
new(Mirror), new(Release), new(LoginSource), new(Webhook), | new(Mirror), new(Release), new(LoginSource), new(Webhook), |
IsFork bool `xorm:"NOT NULL DEFAULT false"` | IsFork bool `xorm:"NOT NULL DEFAULT false"` | ||||
ForkID int64 | ForkID int64 | ||||
BaseRepo *Repository `xorm:"-"` | BaseRepo *Repository `xorm:"-"` | ||||
ForkInfo *ForkInfo `xorm:"-"` | |||||
Created time.Time `xorm:"CREATED"` | Created time.Time `xorm:"CREATED"` | ||||
Updated time.Time `xorm:"UPDATED"` | Updated time.Time `xorm:"UPDATED"` | ||||
func (repo *Repository) AfterSet(colName string, _ xorm.Cell) { | func (repo *Repository) AfterSet(colName string, _ xorm.Cell) { | ||||
switch colName { | switch colName { | ||||
case "is_fork": | |||||
forkInfo := new(ForkInfo) | |||||
has, err := x.Where("repo_id=?", repo.ID).Get(forkInfo) | |||||
if err != nil { | |||||
log.Error(3, "get fork in[%d]: %v", repo.ID, err) | |||||
return | |||||
} else if has { | |||||
repo.ForkInfo = forkInfo | |||||
} | |||||
case "updated": | case "updated": | ||||
repo.Updated = regulateTimeZone(repo.Updated) | repo.Updated = regulateTimeZone(repo.Updated) | ||||
} | } | ||||
return os.Rename(RepoPath(u.LowerName, oldRepoName), RepoPath(u.LowerName, newRepoName)) | return os.Rename(RepoPath(u.LowerName, oldRepoName), RepoPath(u.LowerName, newRepoName)) | ||||
} | } | ||||
func getRepositoriesByForkID(e Engine, forkID int64) ([]*Repository, error) { | |||||
repos := make([]*Repository, 0, 10) | |||||
return repos, e.Where("fork_id=?", forkID).Find(&repos) | |||||
} | |||||
// GetRepositoriesByForkID returns all repositories with given fork ID. | |||||
func GetRepositoriesByForkID(forkID int64) ([]*Repository, error) { | |||||
return getRepositoriesByForkID(x, forkID) | |||||
} | |||||
func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) { | func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) { | ||||
repo.LowerName = strings.ToLower(repo.Name) | repo.LowerName = strings.ToLower(repo.Name) | ||||
if err = repo.recalculateTeamAccesses(e, 0); err != nil { | if err = repo.recalculateTeamAccesses(e, 0); err != nil { | ||||
return fmt.Errorf("recalculateTeamAccesses: %v", err) | return fmt.Errorf("recalculateTeamAccesses: %v", err) | ||||
} | } | ||||
forkRepos, err := getRepositoriesByForkID(e, repo.ID) | |||||
if err != nil { | |||||
return fmt.Errorf("getRepositoriesByForkID: %v", err) | |||||
} | |||||
for i := range forkRepos { | |||||
forkRepos[i].IsPrivate = repo.IsPrivate | |||||
if err = updateRepository(e, forkRepos[i], true); err != nil { | |||||
return fmt.Errorf("updateRepository[%d]: %v", forkRepos[i].ID, err) | |||||
} | |||||
} | |||||
} | } | ||||
return nil | return nil | ||||
} | } | ||||
// DeleteRepository deletes a repository for a user or organization. | // DeleteRepository deletes a repository for a user or organization. | ||||
func DeleteRepository(uid, repoID int64, userName string) error { | |||||
func DeleteRepository(uid, repoID int64) error { | |||||
repo := &Repository{ID: repoID, OwnerID: uid} | repo := &Repository{ID: repoID, OwnerID: uid} | ||||
has, err := x.Get(repo) | has, err := x.Get(repo) | ||||
if err != nil { | if err != nil { | ||||
if repo.IsFork { | if repo.IsFork { | ||||
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkID); err != nil { | if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkID); err != nil { | ||||
return err | |||||
return fmt.Errorf("decrease fork count: %v", err) | |||||
} else if _, err = sess.Delete(&ForkInfo{RepoID: repo.ID}); err != nil { | |||||
return fmt.Errorf("delete fork info: %v", err) | |||||
} | } | ||||
} | } | ||||
} | } | ||||
// Remove repository files. | // Remove repository files. | ||||
if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { | |||||
desc := fmt.Sprintf("delete repository files(%s/%s): %v", userName, repo.Name, err) | |||||
repoPath, err := repo.RepoPath() | |||||
if err != nil { | |||||
return fmt.Errorf("RepoPath: %v", err) | |||||
} | |||||
if err = os.RemoveAll(repoPath); err != nil { | |||||
desc := fmt.Sprintf("delete repository files[%s]: %v", repoPath, err) | |||||
log.Warn(desc) | log.Warn(desc) | ||||
if err = CreateRepositoryNotice(desc); err != nil { | if err = CreateRepositoryNotice(desc); err != nil { | ||||
log.Error(4, "add notice: %v", err) | log.Error(4, "add notice: %v", err) | ||||
} | } | ||||
} | } | ||||
return sess.Commit() | |||||
if err = sess.Commit(); err != nil { | |||||
return fmt.Errorf("Commit: %v", err) | |||||
} | |||||
if repo.NumForks > 0 { | |||||
if repo.IsPrivate { | |||||
forkRepos, err := GetRepositoriesByForkID(repo.ID) | |||||
if err != nil { | |||||
return fmt.Errorf("getRepositoriesByForkID: %v", err) | |||||
} | |||||
for i := range forkRepos { | |||||
if err = DeleteRepository(forkRepos[i].OwnerID, forkRepos[i].ID); err != nil { | |||||
log.Error(4, "updateRepository[%d]: %v", forkRepos[i].ID, err) | |||||
} | |||||
} | |||||
} else { | |||||
if _, err = x.Exec("UPDATE `repository` SET fork_id=0,is_fork=? WHERE fork_id=?", false, repo.ID); err != nil { | |||||
log.Error(4, "reset 'fork_id' and 'is_fork': %v", err) | |||||
} | |||||
if _, err = x.Delete(&ForkInfo{ForkID: repo.ID}); err != nil { | |||||
log.Error(4, "clear fork infos: %v", err) | |||||
} | |||||
} | |||||
} | |||||
return nil | |||||
} | } | ||||
// GetRepositoryByRef returns a Repository specified by a GFM reference. | // GetRepositoryByRef returns a Repository specified by a GFM reference. | ||||
}) | }) | ||||
} | } | ||||
func CheckRepoStats() { | |||||
if isCheckingRepos { | |||||
return | |||||
} | |||||
isCheckingRepos = true | |||||
defer func() { isCheckingRepos = false }() | |||||
log.Trace("Doing: CheckRepoStats") | |||||
type repoChecker struct { | |||||
querySQL, correctSQL string | |||||
desc string | |||||
} | |||||
// ***** START: Repository.NumWatches ***** | |||||
results, err := x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_watches!=(SELECT COUNT(*) FROM `watch` WHERE repo_id=repo.id)") | |||||
func repoStatsCheck(checker *repoChecker) { | |||||
results, err := x.Query(checker.querySQL) | |||||
if err != nil { | if err != nil { | ||||
log.Error(4, "Select repository check 'watch': %v", err) | |||||
log.Error(4, "Select %s: %v", checker.desc, err) | |||||
return | return | ||||
} | } | ||||
for _, watch := range results { | |||||
repoID := com.StrTo(watch["id"]).MustInt64() | |||||
log.Trace("Updating repository count 'watch': %d", repoID) | |||||
_, err = x.Exec("UPDATE `repository` SET num_watches=(SELECT COUNT(*) FROM `watch` WHERE repo_id=?) WHERE id=?", repoID, repoID) | |||||
for _, result := range results { | |||||
id := com.StrTo(result["id"]).MustInt64() | |||||
log.Trace("Updating %s: %d", checker.desc, id) | |||||
_, err = x.Exec(checker.correctSQL, id, id) | |||||
if err != nil { | if err != nil { | ||||
log.Error(4, "Update repository check 'watch'[%d]: %v", repoID, err) | |||||
log.Error(4, "Update %s[%d]: %v", checker.desc, id, err) | |||||
} | } | ||||
} | } | ||||
// ***** END: Repository.NumWatches ***** | |||||
} | |||||
// ***** START: Repository.NumStars ***** | |||||
results, err = x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_stars!=(SELECT COUNT(*) FROM `star` WHERE repo_id=repo.id)") | |||||
if err != nil { | |||||
log.Error(4, "Select repository check 'star': %v", err) | |||||
func CheckRepoStats() { | |||||
if isCheckingRepos { | |||||
return | return | ||||
} | } | ||||
for _, star := range results { | |||||
repoID := com.StrTo(star["id"]).MustInt64() | |||||
log.Trace("Updating repository count 'star': %d", repoID) | |||||
_, err = x.Exec("UPDATE `repository` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE repo_id=?) WHERE id=?", repoID, repoID) | |||||
if err != nil { | |||||
log.Error(4, "Update repository check 'star'[%d]: %v", repoID, err) | |||||
} | |||||
} | |||||
// ***** END: Repository.NumStars ***** | |||||
isCheckingRepos = true | |||||
defer func() { isCheckingRepos = false }() | |||||
// ***** START: Label.NumIssues ***** | |||||
results, err = x.Query("SELECT label.id FROM `label` WHERE label.num_issues!=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=label.id)") | |||||
if err != nil { | |||||
log.Error(4, "Select label check 'num_issues': %v", err) | |||||
return | |||||
} | |||||
for _, label := range results { | |||||
labelID := com.StrTo(label["id"]).MustInt64() | |||||
log.Trace("Updating label count 'num_issues': %d", labelID) | |||||
_, err = x.Exec("UPDATE `label` SET num_issues=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=?) WHERE id=?", labelID, labelID) | |||||
if err != nil { | |||||
log.Error(4, "Update label check 'num_issues'[%d]: %v", labelID, err) | |||||
} | |||||
} | |||||
// ***** END: Label.NumIssues ***** | |||||
log.Trace("Doing: CheckRepoStats") | |||||
// ***** START: User.NumRepos ***** | |||||
results, err = x.Query("SELECT `user`.id FROM `user` WHERE `user`.num_repos!=(SELECT COUNT(*) FROM `repository` WHERE owner_id=`user`.id)") | |||||
checkers := []*repoChecker{ | |||||
// Repository.NumWatches | |||||
{ | |||||
"SELECT repo.id FROM `repository` repo WHERE repo.num_watches!=(SELECT COUNT(*) FROM `watch` WHERE repo_id=repo.id)", | |||||
"UPDATE `repository` SET num_watches=(SELECT COUNT(*) FROM `watch` WHERE repo_id=?) WHERE id=?", | |||||
"repository count 'num_watches'", | |||||
}, | |||||
// Repository.NumStars | |||||
{ | |||||
"SELECT repo.id FROM `repository` repo WHERE repo.num_stars!=(SELECT COUNT(*) FROM `star` WHERE repo_id=repo.id)", | |||||
"UPDATE `repository` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE repo_id=?) WHERE id=?", | |||||
"repository count 'num_stars'", | |||||
}, | |||||
// Label.NumIssues | |||||
{ | |||||
"SELECT label.id FROM `label` WHERE label.num_issues!=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=label.id)", | |||||
"UPDATE `label` SET num_issues=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=?) WHERE id=?", | |||||
"label count 'num_issues'", | |||||
}, | |||||
// User.NumRepos | |||||
{ | |||||
"SELECT `user`.id FROM `user` WHERE `user`.num_repos!=(SELECT COUNT(*) FROM `repository` WHERE owner_id=`user`.id)", | |||||
"UPDATE `user` SET num_repos=(SELECT COUNT(*) FROM `repository` WHERE owner_id=?) WHERE id=?", | |||||
"user count 'num_repos'", | |||||
}, | |||||
} | |||||
for i := range checkers { | |||||
repoStatsCheck(checkers[i]) | |||||
} | |||||
// FIXME: use checker when v0.8, stop supporting old fork repo format. | |||||
// ***** START: Repository.NumForks ***** | |||||
results, err := x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_forks!=(SELECT COUNT(*) FROM `repository` WHERE fork_id=repo.id)") | |||||
if err != nil { | if err != nil { | ||||
log.Error(4, "Select user check 'num_repos': %v", err) | |||||
return | |||||
} | |||||
for _, user := range results { | |||||
userID := com.StrTo(user["id"]).MustInt64() | |||||
log.Trace("Updating user count 'num_repos': %d", userID) | |||||
_, err = x.Exec("UPDATE `user` SET num_repos=(SELECT COUNT(*) FROM `repository` WHERE owner_id=?) WHERE id=?", userID, userID) | |||||
if err != nil { | |||||
log.Error(4, "Update user check 'num_repos'[%d]: %v", userID, err) | |||||
log.Error(4, "Select repository count 'num_forks': %v", err) | |||||
} else { | |||||
for _, result := range results { | |||||
id := com.StrTo(result["id"]).MustInt64() | |||||
log.Trace("Updating repository count 'num_forks': %d", id) | |||||
repo, err := GetRepositoryByID(id) | |||||
if err != nil { | |||||
log.Error(4, "GetRepositoryByID[%d]: %v", id, err) | |||||
continue | |||||
} | |||||
rawResult, err := x.Query("SELECT COUNT(*) FROM `repository` WHERE fork_id=?", repo.ID) | |||||
if err != nil { | |||||
log.Error(4, "Select count of forks[%d]: %v", repo.ID, err) | |||||
continue | |||||
} | |||||
repo.NumForks = int(parseCountResult(rawResult)) | |||||
if err = UpdateRepository(repo, false); err != nil { | |||||
log.Error(4, "UpdateRepository[%d]: %v", id, err) | |||||
continue | |||||
} | |||||
} | } | ||||
} | } | ||||
// ***** END: User.NumRepos ***** | |||||
// ***** END: Repository.NumForks ***** | |||||
} | } | ||||
// _________ .__ .__ ___. __ .__ | // _________ .__ .__ ___. __ .__ | ||||
// \___ / \____/|__| |__|_ \ | // \___ / \____/|__| |__|_ \ | ||||
// \/ \/ | // \/ \/ | ||||
type ForkInfo struct { | |||||
ID int64 `xorm:"pk autoincr"` | |||||
ForkID int64 | |||||
RepoID int64 `xorm:"UNIQUE"` | |||||
StartCommitID string `xorm:"VARCHAR(40)"` | |||||
} | |||||
// HasForkedRepo checks if given user has already forked a repository with given ID. | // HasForkedRepo checks if given user has already forked a repository with given ID. | ||||
func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) { | func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) { | ||||
repo := new(Repository) | repo := new(Repository) | ||||
func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) { | func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) { | ||||
repo := &Repository{ | repo := &Repository{ | ||||
OwnerID: u.Id, | |||||
Owner: u, | |||||
Name: name, | |||||
LowerName: strings.ToLower(name), | |||||
Description: desc, | |||||
IsPrivate: oldRepo.IsPrivate, | |||||
IsFork: true, | |||||
ForkID: oldRepo.ID, | |||||
OwnerID: u.Id, | |||||
Owner: u, | |||||
Name: name, | |||||
LowerName: strings.ToLower(name), | |||||
Description: desc, | |||||
DefaultBranch: oldRepo.DefaultBranch, | |||||
IsPrivate: oldRepo.IsPrivate, | |||||
IsFork: true, | |||||
ForkID: oldRepo.ID, | |||||
} | } | ||||
sess := x.NewSession() | sess := x.NewSession() | ||||
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.ID); err != nil { | if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.ID); err != nil { | ||||
return nil, err | return nil, err | ||||
} | } | ||||
// else if _, err = sess.Insert(&ForkInfo{ | |||||
// ForkID: oldRepo.ID, | |||||
// RepoID: repo.ID, | |||||
// StartCommitID: "", | |||||
// }); err != nil { | |||||
// return nil, fmt.Errorf("insert fork info: %v", err) | |||||
// } | |||||
oldRepoPath, err := oldRepo.RepoPath() | oldRepoPath, err := oldRepo.RepoPath() | ||||
if err != nil { | if err != nil { |
} | } | ||||
} | } | ||||
func RetrieveBaseRepo(ctx *Context, repo *models.Repository) { | |||||
// Non-fork repository will not return error in this method. | |||||
if err := repo.GetBaseRepo(); err != nil { | |||||
if models.IsErrRepoNotExist(err) { | |||||
repo.IsFork = false | |||||
repo.ForkID = 0 | |||||
return | |||||
} | |||||
ctx.Handle(500, "GetBaseRepo", err) | |||||
return | |||||
} else if err = repo.BaseRepo.GetOwner(); err != nil { | |||||
ctx.Handle(500, "BaseRepo.GetOwner", err) | |||||
return | |||||
} | |||||
bsaeRepo := repo.BaseRepo | |||||
baseGitRepo, err := git.OpenRepository(models.RepoPath(bsaeRepo.Owner.Name, bsaeRepo.Name)) | |||||
if err != nil { | |||||
ctx.Handle(500, "OpenRepository", err) | |||||
return | |||||
} | |||||
if len(bsaeRepo.DefaultBranch) > 0 && baseGitRepo.IsBranchExist(bsaeRepo.DefaultBranch) { | |||||
ctx.Data["BaseDefaultBranch"] = bsaeRepo.DefaultBranch | |||||
} else { | |||||
baseBranches, err := baseGitRepo.GetBranches() | |||||
if err != nil { | |||||
ctx.Handle(500, "GetBranches", err) | |||||
return | |||||
} | |||||
if len(baseBranches) > 0 { | |||||
ctx.Data["BaseDefaultBranch"] = baseBranches[0] | |||||
} | |||||
} | |||||
} | |||||
func RepoAssignment(redirect bool, args ...bool) macaron.Handler { | func RepoAssignment(redirect bool, args ...bool) macaron.Handler { | ||||
return func(ctx *Context) { | return func(ctx *Context) { | ||||
var ( | var ( | ||||
ctx.Repo.Repository.NumTags = len(tags) | ctx.Repo.Repository.NumTags = len(tags) | ||||
if repo.IsFork { | if repo.IsFork { | ||||
// Non-fork repository will not return error in this method. | |||||
if err = repo.GetBaseRepo(); err != nil { | |||||
ctx.Handle(500, "GetBaseRepo", err) | |||||
RetrieveBaseRepo(ctx, repo) | |||||
if ctx.Written() { | |||||
return | return | ||||
} else if repo.BaseRepo.GetOwner(); err != nil { | |||||
ctx.Handle(500, "BaseRepo.GetOwner", err) | |||||
return | |||||
} | |||||
bsaeRepo := repo.BaseRepo | |||||
baseGitRepo, err := git.OpenRepository(models.RepoPath(bsaeRepo.Owner.Name, bsaeRepo.Name)) | |||||
if err != nil { | |||||
ctx.Handle(500, "OpenRepository", err) | |||||
return | |||||
} | |||||
if len(bsaeRepo.DefaultBranch) > 0 && baseGitRepo.IsBranchExist(bsaeRepo.DefaultBranch) { | |||||
ctx.Data["BaseDefaultBranch"] = bsaeRepo.DefaultBranch | |||||
} else { | |||||
baseBranches, err := baseGitRepo.GetBranches() | |||||
if err != nil { | |||||
ctx.Handle(500, "GetBranches", err) | |||||
return | |||||
} | |||||
if len(baseBranches) > 0 { | |||||
ctx.Data["BaseDefaultBranch"] = baseBranches[0] | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
&.new.repo { | &.new.repo { | ||||
.selection.dropdown { | |||||
width: 50%!important; | |||||
} | |||||
#auto-init { | |||||
margin-left: @input-padding+15px; | |||||
.ui.form { | |||||
.selection.dropdown:not(.owner) { | |||||
width: 50%!important; | |||||
} | |||||
#auto-init { | |||||
margin-left: @input-padding+15px; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } |
} else { | } else { | ||||
log.Error(4, "CreateRepository: %v", err) | log.Error(4, "CreateRepository: %v", err) | ||||
if repo != nil { | if repo != nil { | ||||
if err = models.DeleteRepository(ctx.User.Id, repo.ID, ctx.User.Name); err != nil { | |||||
if err = models.DeleteRepository(ctx.User.Id, repo.ID); err != nil { | |||||
log.Error(4, "DeleteRepository: %v", err) | log.Error(4, "DeleteRepository: %v", err) | ||||
} | } | ||||
} | } | ||||
repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, form.Mirror, remoteAddr) | repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, form.Mirror, remoteAddr) | ||||
if err != nil { | if err != nil { | ||||
if repo != nil { | if repo != nil { | ||||
if errDelete := models.DeleteRepository(ctxUser.Id, repo.ID, ctxUser.Name); errDelete != nil { | |||||
if errDelete := models.DeleteRepository(ctxUser.Id, repo.ID); errDelete != nil { | |||||
log.Error(4, "DeleteRepository: %v", errDelete) | log.Error(4, "DeleteRepository: %v", errDelete) | ||||
} | } | ||||
} | } |
} | } | ||||
if repo != nil { | if repo != nil { | ||||
if errDelete := models.DeleteRepository(ctxUser.Id, repo.ID, ctxUser.Name); errDelete != nil { | |||||
if errDelete := models.DeleteRepository(ctxUser.Id, repo.ID); errDelete != nil { | |||||
log.Error(4, "DeleteRepository: %v", errDelete) | log.Error(4, "DeleteRepository: %v", errDelete) | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if repo != nil { | if repo != nil { | ||||
if errDelete := models.DeleteRepository(ctxUser.Id, repo.ID, ctxUser.Name); errDelete != nil { | |||||
if errDelete := models.DeleteRepository(ctxUser.Id, repo.ID); errDelete != nil { | |||||
log.Error(4, "DeleteRepository: %v", errDelete) | log.Error(4, "DeleteRepository: %v", errDelete) | ||||
} | } | ||||
} | } |
return | return | ||||
} | } | ||||
isNameChanged := false | |||||
oldRepoName := repo.Name | oldRepoName := repo.Name | ||||
newRepoName := form.RepoName | newRepoName := form.RepoName | ||||
// Check if repository name has been changed. | // Check if repository name has been changed. | ||||
if repo.LowerName != strings.ToLower(newRepoName) { | if repo.LowerName != strings.ToLower(newRepoName) { | ||||
isNameChanged = true | |||||
if err := models.ChangeRepositoryName(ctx.Repo.Owner, repo.Name, newRepoName); err != nil { | if err := models.ChangeRepositoryName(ctx.Repo.Owner, repo.Name, newRepoName); err != nil { | ||||
ctx.Data["Err_RepoName"] = true | ctx.Data["Err_RepoName"] = true | ||||
switch { | switch { | ||||
} | } | ||||
return | return | ||||
} | } | ||||
log.Trace("Repository name changed: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newRepoName) | log.Trace("Repository name changed: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newRepoName) | ||||
} | } | ||||
// In case it's just a case change. | // In case it's just a case change. | ||||
if err := models.UpdateRepository(repo, visibilityChanged); err != nil { | if err := models.UpdateRepository(repo, visibilityChanged); err != nil { | ||||
ctx.Handle(500, "UpdateRepository", err) | ctx.Handle(500, "UpdateRepository", err) | ||||
return | return | ||||
} else if err = models.RenameRepoAction(ctx.User, oldRepoName, repo); err != nil { | |||||
ctx.Handle(500, "RenameRepoAction", err) | |||||
return | |||||
} | } | ||||
log.Trace("Repository updated: %s/%s", ctx.Repo.Owner.Name, repo.Name) | log.Trace("Repository updated: %s/%s", ctx.Repo.Owner.Name, repo.Name) | ||||
if isNameChanged { | |||||
if err := models.RenameRepoAction(ctx.User, oldRepoName, repo); err != nil { | |||||
log.Error(4, "RenameRepoAction: %v", err) | |||||
} | |||||
} | |||||
if repo.IsMirror { | if repo.IsMirror { | ||||
if form.Interval > 0 { | if form.Interval > 0 { | ||||
ctx.Repo.Mirror.Interval = form.Interval | ctx.Repo.Mirror.Interval = form.Interval | ||||
} | } | ||||
} | } | ||||
if err := models.DeleteRepository(ctx.Repo.Owner.Id, repo.ID, ctx.Repo.Owner.Name); err != nil { | |||||
if err := models.DeleteRepository(ctx.Repo.Owner.Id, repo.ID); err != nil { | |||||
ctx.Handle(500, "DeleteRepository", err) | ctx.Handle(500, "DeleteRepository", err) | ||||
return | return | ||||
} | } |
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
<div class="inline required field {{if .Err_Owner}}error{{end}}"> | <div class="inline required field {{if .Err_Owner}}error{{end}}"> | ||||
<label>{{.i18n.Tr "repo.owner"}}</label> | <label>{{.i18n.Tr "repo.owner"}}</label> | ||||
<div class="ui selection dropdown"> | |||||
<div class="ui selection owner dropdown"> | |||||
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.Id}}" required> | <input type="hidden" id="uid" name="uid" value="{{.ContextUser.Id}}" required> | ||||
<span class="text"> | <span class="text"> | ||||
<img class="ui mini image" src="{{.ContextUser.AvatarLink}}"> | <img class="ui mini image" src="{{.ContextUser.AvatarLink}}"> |
</div> | </div> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>{{.i18n.Tr "repo.visibility"}}</label> | <label>{{.i18n.Tr "repo.visibility"}}</label> | ||||
<div class="ui read-only toggle checkbox"> | |||||
<div class="ui read-only checkbox"> | |||||
<input type="checkbox" {{if .IsPrivate}}checked{{end}}> | <input type="checkbox" {{if .IsPrivate}}checked{{end}}> | ||||
<label>{{.i18n.Tr "repo.visiblity_helper" | Safe}}</label> | <label>{{.i18n.Tr "repo.visiblity_helper" | Safe}}</label> | ||||
</div> | </div> |
<label>{{.i18n.Tr "repo.visibility"}}</label> | <label>{{.i18n.Tr "repo.visibility"}}</label> | ||||
<div class="ui checkbox"> | <div class="ui checkbox"> | ||||
<input name="private" type="checkbox" {{if .Repository.IsPrivate}}checked{{end}}> | <input name="private" type="checkbox" {{if .Repository.IsPrivate}}checked{{end}}> | ||||
<label>{{.i18n.Tr "repo.visiblity_helper" | Safe}}</label> | |||||
<label>{{.i18n.Tr "repo.visiblity_helper" | Safe}} {{if .Repository.NumForks}}<span class="text red">{{.i18n.Tr "repo.visiblity_fork_helper"}}</span>{{end}}</label> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
<div class="ui warning message text left"> | <div class="ui warning message text left"> | ||||
{{.i18n.Tr "repo.settings.delete_notices_1" | Safe}} <br> | {{.i18n.Tr "repo.settings.delete_notices_1" | Safe}} <br> | ||||
{{.i18n.Tr "repo.settings.delete_notices_2" | Safe}} | {{.i18n.Tr "repo.settings.delete_notices_2" | Safe}} | ||||
{{if .Repository.NumForks}}<br> | |||||
{{.i18n.Tr "repo.settings.delete_notices_fork_1" | Safe}} <br> | |||||
{{.i18n.Tr "repo.settings.delete_notices_fork_2" | Safe}} <br> | |||||
{{.i18n.Tr "repo.settings.delete_notices_fork_3" | Safe}} | |||||
{{end}} | |||||
</div> | </div> | ||||
<form class="ui form" action="{{.Link}}" method="post"> | <form class="ui form" action="{{.Link}}" method="post"> | ||||
{{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} |