#1021 Forked repo unavailable after deleting original repo
This commit is contained in:
parent
dde9ace91b
commit
398569f6f8
|
@ -319,6 +319,7 @@ repo_name = Repository Name
|
||||||
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.
|
||||||
|
@ -508,6 +509,9 @@ settings.transfer_notices_2 = - You will conserve access if new owner is an orga
|
||||||
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
|
||||||
|
|
|
@ -158,6 +158,30 @@ func NewRepoAction(u *User, repo *Repository) (err error) {
|
||||||
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 {
|
||||||
|
@ -502,29 +526,6 @@ func TransferRepoAction(actUser, oldOwner, newOwner *User, repo *Repository) err
|
||||||
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)
|
||||||
|
|
|
@ -78,7 +78,7 @@ func init() {
|
||||||
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),
|
||||||
|
|
207
models/repo.go
207
models/repo.go
|
@ -160,6 +160,7 @@ type Repository struct {
|
||||||
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"`
|
||||||
|
@ -167,6 +168,15 @@ type Repository struct {
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -883,6 +893,16 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error)
|
||||||
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)
|
||||||
|
|
||||||
|
@ -909,6 +929,17 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e
|
||||||
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
|
||||||
|
@ -929,7 +960,7 @@ func UpdateRepository(repo *Repository, visibilityChanged bool) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
|
@ -1015,7 +1046,9 @@ func DeleteRepository(uid, repoID int64, userName string) error {
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1024,8 +1057,12 @@ func DeleteRepository(uid, repoID int64, userName string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove repository files.
|
// Remove repository files.
|
||||||
if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil {
|
repoPath, err := repo.RepoPath()
|
||||||
desc := fmt.Sprintf("delete repository files(%s/%s): %v", userName, repo.Name, err)
|
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)
|
||||||
|
@ -1039,7 +1076,32 @@ func DeleteRepository(uid, repoID int64, userName string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
||||||
|
@ -1275,6 +1337,27 @@ func GitGcRepos() error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type repoChecker struct {
|
||||||
|
querySQL, correctSQL string
|
||||||
|
desc string
|
||||||
|
}
|
||||||
|
|
||||||
|
func repoStatsCheck(checker *repoChecker) {
|
||||||
|
results, err := x.Query(checker.querySQL)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(4, "Select %s: %v", checker.desc, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
log.Error(4, "Update %s[%d]: %v", checker.desc, id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func CheckRepoStats() {
|
func CheckRepoStats() {
|
||||||
if isCheckingRepos {
|
if isCheckingRepos {
|
||||||
return
|
return
|
||||||
|
@ -1284,69 +1367,66 @@ func CheckRepoStats() {
|
||||||
|
|
||||||
log.Trace("Doing: CheckRepoStats")
|
log.Trace("Doing: CheckRepoStats")
|
||||||
|
|
||||||
// ***** START: Repository.NumWatches *****
|
checkers := []*repoChecker{
|
||||||
results, err := x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_watches!=(SELECT COUNT(*) FROM `watch` WHERE repo_id=repo.id)")
|
// Repository.NumWatches
|
||||||
if err != nil {
|
{
|
||||||
log.Error(4, "Select repository check 'watch': %v", err)
|
"SELECT repo.id FROM `repository` repo WHERE repo.num_watches!=(SELECT COUNT(*) FROM `watch` WHERE repo_id=repo.id)",
|
||||||
return
|
"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 _, watch := range results {
|
for i := range checkers {
|
||||||
repoID := com.StrTo(watch["id"]).MustInt64()
|
repoStatsCheck(checkers[i])
|
||||||
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)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(4, "Update repository check 'watch'[%d]: %v", repoID, err)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// ***** END: Repository.NumWatches *****
|
|
||||||
|
|
||||||
// ***** START: Repository.NumStars *****
|
// FIXME: use checker when v0.8, stop supporting old fork repo format.
|
||||||
results, err = x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_stars!=(SELECT COUNT(*) FROM `star` WHERE repo_id=repo.id)")
|
// ***** 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 repository check 'star': %v", err)
|
log.Error(4, "Select repository count 'num_forks': %v", err)
|
||||||
return
|
} else {
|
||||||
}
|
for _, result := range results {
|
||||||
for _, star := range results {
|
id := com.StrTo(result["id"]).MustInt64()
|
||||||
repoID := com.StrTo(star["id"]).MustInt64()
|
log.Trace("Updating repository count 'num_forks': %d", id)
|
||||||
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 *****
|
|
||||||
|
|
||||||
// ***** START: Label.NumIssues *****
|
repo, err := GetRepositoryByID(id)
|
||||||
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 {
|
if err != nil {
|
||||||
log.Error(4, "Select label check 'num_issues': %v", err)
|
log.Error(4, "GetRepositoryByID[%d]: %v", id, err)
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
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 *****
|
|
||||||
|
|
||||||
// ***** START: User.NumRepos *****
|
rawResult, err := x.Query("SELECT COUNT(*) FROM `repository` WHERE fork_id=?", repo.ID)
|
||||||
results, err = x.Query("SELECT `user`.id FROM `user` WHERE `user`.num_repos!=(SELECT COUNT(*) FROM `repository` WHERE owner_id=`user`.id)")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(4, "Select user check 'num_repos': %v", err)
|
log.Error(4, "Select count of forks[%d]: %v", repo.ID, err)
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
for _, user := range results {
|
repo.NumForks = int(parseCountResult(rawResult))
|
||||||
userID := com.StrTo(user["id"]).MustInt64()
|
|
||||||
log.Trace("Updating user count 'num_repos': %d", userID)
|
if err = UpdateRepository(repo, false); err != nil {
|
||||||
_, err = x.Exec("UPDATE `user` SET num_repos=(SELECT COUNT(*) FROM `repository` WHERE owner_id=?) WHERE id=?", userID, userID)
|
log.Error(4, "UpdateRepository[%d]: %v", id, err)
|
||||||
if err != nil {
|
continue
|
||||||
log.Error(4, "Update user check 'num_repos'[%d]: %v", userID, err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ***** END: User.NumRepos *****
|
}
|
||||||
|
// ***** END: Repository.NumForks *****
|
||||||
}
|
}
|
||||||
|
|
||||||
// _________ .__ .__ ___. __ .__
|
// _________ .__ .__ ___. __ .__
|
||||||
|
@ -1589,6 +1669,13 @@ func IsStaring(uid, repoId int64) bool {
|
||||||
// \___ / \____/|__| |__|_ \
|
// \___ / \____/|__| |__|_ \
|
||||||
// \/ \/
|
// \/ \/
|
||||||
|
|
||||||
|
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)
|
||||||
|
@ -1603,6 +1690,7 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
|
||||||
Name: name,
|
Name: name,
|
||||||
LowerName: strings.ToLower(name),
|
LowerName: strings.ToLower(name),
|
||||||
Description: desc,
|
Description: desc,
|
||||||
|
DefaultBranch: oldRepo.DefaultBranch,
|
||||||
IsPrivate: oldRepo.IsPrivate,
|
IsPrivate: oldRepo.IsPrivate,
|
||||||
IsFork: true,
|
IsFork: true,
|
||||||
ForkID: oldRepo.ID,
|
ForkID: oldRepo.ID,
|
||||||
|
@ -1621,6 +1709,13 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
|
||||||
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 {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -190,6 +190,41 @@ func RepoRef() macaron.Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
@ -292,32 +327,9 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
|
||||||
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.
|
RetrieveBaseRepo(ctx, repo)
|
||||||
if err = repo.GetBaseRepo(); err != nil {
|
if ctx.Written() {
|
||||||
ctx.Handle(500, "GetBaseRepo", err)
|
|
||||||
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]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -61,7 +61,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.new.repo {
|
&.new.repo {
|
||||||
.selection.dropdown {
|
.ui.form {
|
||||||
|
.selection.dropdown:not(.owner) {
|
||||||
width: 50%!important;
|
width: 50%!important;
|
||||||
}
|
}
|
||||||
#auto-init {
|
#auto-init {
|
||||||
|
@ -69,6 +70,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.new.webhook {
|
.new.webhook {
|
||||||
form {
|
form {
|
||||||
|
|
|
@ -151,7 +151,7 @@ func createRepo(ctx *middleware.Context, owner *models.User, opt api.CreateRepoO
|
||||||
} 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,10 +53,12 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) {
|
||||||
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 {
|
||||||
|
@ -71,6 +73,7 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) {
|
||||||
}
|
}
|
||||||
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.
|
||||||
|
@ -87,12 +90,15 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) {
|
||||||
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
|
||||||
|
@ -152,7 +158,7 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
{{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}}">
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
</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>
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
<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}}
|
||||||
|
@ -138,6 +138,11 @@
|
||||||
<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}}
|
||||||
|
|
Loading…
Reference in New Issue