2020-01-12 15:11:17 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repository
import (
"fmt"
"strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
2020-08-11 23:05:34 +03:00
"code.gitea.io/gitea/modules/util"
2020-09-25 07:09:23 +03:00
"github.com/unknwon/com"
2020-01-12 15:11:17 +03:00
)
// CreateRepository creates a repository for the user/organization.
2020-09-25 07:09:23 +03:00
func CreateRepository ( doer , u * models . User , opts models . CreateRepoOptions ) ( * models . Repository , error ) {
2020-01-12 15:11:17 +03:00
if ! doer . IsAdmin && ! u . CanCreateRepo ( ) {
return nil , models . ErrReachLimitOfRepo {
Limit : u . MaxRepoCreation ,
}
}
2020-09-06 23:58:54 +03:00
if len ( opts . DefaultBranch ) == 0 {
opts . DefaultBranch = setting . Repository . DefaultBranch
}
2020-01-12 15:11:17 +03:00
repo := & models . Repository {
OwnerID : u . ID ,
Owner : u ,
OwnerName : u . Name ,
Name : opts . Name ,
LowerName : strings . ToLower ( opts . Name ) ,
Description : opts . Description ,
OriginalURL : opts . OriginalURL ,
OriginalServiceType : opts . GitServiceType ,
IsPrivate : opts . IsPrivate ,
IsFsckEnabled : ! opts . IsMirror ,
CloseIssuesViaCommitInAnyBranch : setting . Repository . DefaultCloseIssuesViaCommitsInAnyBranch ,
Status : opts . Status ,
IsEmpty : ! opts . AutoInit ,
2020-09-19 19:44:55 +03:00
TrustModel : opts . TrustModel ,
2020-01-12 15:11:17 +03:00
}
2020-09-25 07:09:23 +03:00
if err := models . WithTx ( func ( ctx models . DBContext ) error {
if err := models . CreateRepository ( ctx , doer , u , repo , false ) ; err != nil {
2020-01-12 15:11:17 +03:00
return err
}
// No need for init mirror.
2020-09-25 07:09:23 +03:00
if opts . IsMirror {
return nil
}
repoPath := models . RepoPath ( u . Name , repo . Name )
if com . IsExist ( repoPath ) {
// repo already exists - We have two or three options.
// 1. We fail stating that the directory exists
// 2. We create the db repository to go with this data and adopt the git repo
// 3. We delete it and start afresh
//
// Previously Gitea would just delete and start afresh - this was naughty.
// So we will now fail and delegate to other functionality to adopt or delete
log . Error ( "Files already exist in %s and we are not going to adopt or delete." , repoPath )
return models . ErrRepoFilesAlreadyExist {
Uname : u . Name ,
Name : repo . Name ,
}
}
if err := initRepository ( ctx , repoPath , doer , repo , opts ) ; err != nil {
if err2 := util . RemoveAll ( repoPath ) ; err2 != nil {
log . Error ( "initRepository: %v" , err )
return fmt . Errorf (
"delete repo directory %s/%s failed(2): %v" , u . Name , repo . Name , err2 )
2020-01-12 15:11:17 +03:00
}
2020-09-25 07:09:23 +03:00
return fmt . Errorf ( "initRepository: %v" , err )
}
2020-01-12 15:11:17 +03:00
2020-09-25 07:09:23 +03:00
// Initialize Issue Labels if selected
if len ( opts . IssueLabels ) > 0 {
if err := models . InitializeLabels ( ctx , repo . ID , opts . IssueLabels , false ) ; err != nil {
if errDelete := models . DeleteRepository ( doer , u . ID , repo . ID ) ; errDelete != nil {
log . Error ( "Rollback deleteRepository: %v" , errDelete )
2020-01-12 15:11:17 +03:00
}
2020-09-25 07:09:23 +03:00
return fmt . Errorf ( "InitializeLabels: %v" , err )
2020-01-12 15:11:17 +03:00
}
2020-09-25 07:09:23 +03:00
}
2020-01-12 15:11:17 +03:00
2020-09-25 07:09:23 +03:00
if stdout , err := git . NewCommand ( "update-server-info" ) .
SetDescription ( fmt . Sprintf ( "CreateRepository(git update-server-info): %s" , repoPath ) ) .
RunInDir ( repoPath ) ; err != nil {
log . Error ( "CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v" , repo , stdout , err )
if errDelete := models . DeleteRepository ( doer , u . ID , repo . ID ) ; errDelete != nil {
log . Error ( "Rollback deleteRepository: %v" , errDelete )
2020-01-12 15:11:17 +03:00
}
2020-09-25 07:09:23 +03:00
return fmt . Errorf ( "CreateRepository(git update-server-info): %v" , err )
2020-01-12 15:11:17 +03:00
}
return nil
2020-09-25 07:09:23 +03:00
} ) ; err != nil {
return nil , err
}
2020-01-12 15:11:17 +03:00
2020-09-25 07:09:23 +03:00
return repo , nil
2020-01-12 15:11:17 +03:00
}