Adopt repositories (#12920)
* Don't automatically delete repository files if they are present Prior to this PR Gitea would delete any repository files if they are present during creation or migration. This can in certain circumstances lead to data-loss and is slightly unpleasant. This PR provides a mechanism for Gitea to adopt repositories on creation and otherwise requires an explicit flag for deletion. PushCreate is slightly different - the create will cause adoption if that is allowed otherwise it will delete the data if that is allowed. Signed-off-by: Andrew Thornton <art27@cantab.net> * Update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix tests and migrate overwrite Signed-off-by: Andrew Thornton <art27@cantab.net> * as per @lunny Only offer to adopt or overwrite if the user can do that. Allow the site administrator to adopt or overwrite in all circumstances Signed-off-by: Andrew Thornton <art27@cantab.net> * Use setting.Repository.DefaultBranch for the default branch Signed-off-by: Andrew Thornton <art27@cantab.net> * Always set setting.Repository.DefaultBranch Signed-off-by: Andrew Thornton <art27@cantab.net> * update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * update templates Signed-off-by: Andrew Thornton <art27@cantab.net> * ensure repo closed Signed-off-by: Andrew Thornton <art27@cantab.net> * Rewrite of adoption as per @6543 and @lunny Signed-off-by: Andrew Thornton <art27@cantab.net> * Apply suggestions from code review * update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * missing not Signed-off-by: Andrew Thornton <art27@cantab.net> * add modals and flash reporting Signed-off-by: Andrew Thornton <art27@cantab.net> * Make the unadopted page searchable Signed-off-by: Andrew Thornton <art27@cantab.net> * Add API Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * fix swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * Handle empty and non-master branched repositories Signed-off-by: Andrew Thornton <art27@cantab.net> * placate lint Signed-off-by: Andrew Thornton <art27@cantab.net> * remove commented out code Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
6fa19a8458
commit
7a7f56044a
31 changed files with 1340 additions and 100 deletions
|
@ -743,6 +743,22 @@ func (err ErrRepoAlreadyExist) Error() string {
|
|||
return fmt.Sprintf("repository already exists [uname: %s, name: %s]", err.Uname, err.Name)
|
||||
}
|
||||
|
||||
// ErrRepoFilesAlreadyExist represents a "RepoFilesAlreadyExist" kind of error.
|
||||
type ErrRepoFilesAlreadyExist struct {
|
||||
Uname string
|
||||
Name string
|
||||
}
|
||||
|
||||
// IsErrRepoFilesAlreadyExist checks if an error is a ErrRepoAlreadyExist.
|
||||
func IsErrRepoFilesAlreadyExist(err error) bool {
|
||||
_, ok := err.(ErrRepoFilesAlreadyExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrRepoFilesAlreadyExist) Error() string {
|
||||
return fmt.Sprintf("repository files already exist [uname: %s, name: %s]", err.Uname, err.Name)
|
||||
}
|
||||
|
||||
// ErrForkAlreadyExist represents a "ForkAlreadyExist" kind of error.
|
||||
type ErrForkAlreadyExist struct {
|
||||
Uname string
|
||||
|
|
|
@ -278,7 +278,7 @@ func (repo *Repository) IsBeingCreated() bool {
|
|||
func (repo *Repository) AfterLoad() {
|
||||
// FIXME: use models migration to solve all at once.
|
||||
if len(repo.DefaultBranch) == 0 {
|
||||
repo.DefaultBranch = "master"
|
||||
repo.DefaultBranch = setting.Repository.DefaultBranch
|
||||
}
|
||||
|
||||
repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
|
||||
|
@ -1048,7 +1048,7 @@ func (repo *Repository) CloneLink() (cl *CloneLink) {
|
|||
}
|
||||
|
||||
// CheckCreateRepository check if could created a repository
|
||||
func CheckCreateRepository(doer, u *User, name string) error {
|
||||
func CheckCreateRepository(doer, u *User, name string, overwriteOrAdopt bool) error {
|
||||
if !doer.CanCreateRepo() {
|
||||
return ErrReachLimitOfRepo{u.MaxRepoCreation}
|
||||
}
|
||||
|
@ -1063,6 +1063,10 @@ func CheckCreateRepository(doer, u *User, name string) error {
|
|||
} else if has {
|
||||
return ErrRepoAlreadyExist{u.Name, name}
|
||||
}
|
||||
|
||||
if !overwriteOrAdopt && com.IsExist(RepoPath(u.Name, name)) {
|
||||
return ErrRepoFilesAlreadyExist{u.Name, name}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1116,11 +1120,15 @@ var (
|
|||
|
||||
// IsUsableRepoName returns true when repository is usable
|
||||
func IsUsableRepoName(name string) error {
|
||||
if alphaDashDotPattern.MatchString(name) {
|
||||
// Note: usually this error is normally caught up earlier in the UI
|
||||
return ErrNameCharsNotAllowed{Name: name}
|
||||
}
|
||||
return isUsableName(reservedRepoNames, reservedRepoPatterns, name)
|
||||
}
|
||||
|
||||
// CreateRepository creates a repository for the user/organization.
|
||||
func CreateRepository(ctx DBContext, doer, u *User, repo *Repository) (err error) {
|
||||
func CreateRepository(ctx DBContext, doer, u *User, repo *Repository, overwriteOrAdopt bool) (err error) {
|
||||
if err = IsUsableRepoName(repo.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1132,6 +1140,15 @@ func CreateRepository(ctx DBContext, doer, u *User, repo *Repository) (err error
|
|||
return ErrRepoAlreadyExist{u.Name, repo.Name}
|
||||
}
|
||||
|
||||
repoPath := RepoPath(u.Name, repo.Name)
|
||||
if !overwriteOrAdopt && com.IsExist(repoPath) {
|
||||
log.Error("Files already exist in %s and we are not going to adopt or delete.", repoPath)
|
||||
return ErrRepoFilesAlreadyExist{
|
||||
Uname: u.Name,
|
||||
Name: repo.Name,
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = ctx.e.Insert(repo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1856,6 +1873,10 @@ func GetUserRepositories(opts *SearchRepoOptions) ([]*Repository, int64, error)
|
|||
cond = cond.And(builder.Eq{"is_private": false})
|
||||
}
|
||||
|
||||
if opts.LowerNames != nil && len(opts.LowerNames) > 0 {
|
||||
cond = cond.And(builder.In("lower_name", opts.LowerNames))
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
|
|
|
@ -175,6 +175,8 @@ type SearchRepoOptions struct {
|
|||
// True -> include just has milestones
|
||||
// False -> include just has no milestone
|
||||
HasMilestones util.OptionalBool
|
||||
// LowerNames represents valid lower names to restrict to
|
||||
LowerNames []string
|
||||
}
|
||||
|
||||
//SearchOrderBy is used to sort the result
|
||||
|
|
|
@ -646,8 +646,8 @@ func (u *User) GetOrganizationCount() (int64, error) {
|
|||
}
|
||||
|
||||
// GetRepositories returns repositories that user owns, including private repositories.
|
||||
func (u *User) GetRepositories(listOpts ListOptions) (err error) {
|
||||
u.Repos, _, err = GetUserRepositories(&SearchRepoOptions{Actor: u, Private: true, ListOptions: listOpts})
|
||||
func (u *User) GetRepositories(listOpts ListOptions, names ...string) (err error) {
|
||||
u.Repos, _, err = GetUserRepositories(&SearchRepoOptions{Actor: u, Private: true, ListOptions: listOpts, LowerNames: names})
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue