@ -6,7 +6,6 @@
package models
import (
"bytes"
"context"
"crypto/md5"
"errors"
@ -38,7 +37,6 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"github.com/mcuadros/go-version"
"github.com/unknwon/com"
"xorm.io/builder"
)
@ -149,9 +147,9 @@ const (
// Repository represents a git repository.
type Repository struct {
ID int64 ` xorm:"pk autoincr" `
OwnerID int64 ` xorm:"UNIQUE(s) index" `
OwnerName string ` xorm:"-" `
ID int64 ` xorm:"pk autoincr" `
OwnerID int64 ` xorm:"UNIQUE(s) index" `
OwnerName string
Owner * User ` xorm:"-" `
LowerName string ` xorm:"UNIQUE(s) INDEX NOT NULL" `
Name string ` xorm:"INDEX NOT NULL" `
@ -252,17 +250,9 @@ func (repo *Repository) MustOwner() *User {
return repo . mustOwner ( x )
}
// MustOwnerName always returns valid owner name to avoid
// conceptually impossible error handling.
// It returns "error" and logs error details when error
// occurs.
func ( repo * Repository ) MustOwnerName ( ) string {
return repo . mustOwnerName ( x )
}
// FullName returns the repository full name
func ( repo * Repository ) FullName ( ) string {
return repo . MustOwnerName ( ) + "/" + repo . Name
return repo . OwnerName + "/" + repo . Name
}
// HTMLURL returns the repository HTML URL
@ -294,7 +284,7 @@ func (repo *Repository) GetCommitsCountCacheKey(contextName string, isRef bool)
func ( repo * Repository ) innerAPIFormat ( e Engine , mode AccessMode , isParent bool ) * api . Repository {
var parent * api . Repository
cloneLink := repo . cloneLink ( e , false )
cloneLink := repo . cloneLink ( false )
permission := & api . Permission {
Admin : mode >= AccessModeAdmin ,
Push : mode >= AccessModeWrite ,
@ -356,6 +346,8 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool)
allowSquash = config . AllowSquash
}
repo . mustOwner ( e )
return & api . Repository {
ID : repo . ID ,
Owner : repo . Owner . APIFormat ( ) ,
@ -533,46 +525,11 @@ func (repo *Repository) mustOwner(e Engine) *User {
return repo . Owner
}
func ( repo * Repository ) getOwnerName ( e Engine ) error {
if len ( repo . OwnerName ) > 0 {
return nil
}
if repo . Owner != nil {
repo . OwnerName = repo . Owner . Name
return nil
}
u := new ( User )
has , err := e . ID ( repo . OwnerID ) . Cols ( "name" ) . Get ( u )
if err != nil {
return err
} else if ! has {
return ErrUserNotExist { repo . OwnerID , "" , 0 }
}
repo . OwnerName = u . Name
return nil
}
// GetOwnerName returns the repository owner name
func ( repo * Repository ) GetOwnerName ( ) error {
return repo . getOwnerName ( x )
}
func ( repo * Repository ) mustOwnerName ( e Engine ) string {
if err := repo . getOwnerName ( e ) ; err != nil {
log . Error ( "Error loading repository owner name: %v" , err )
return "error"
}
return repo . OwnerName
}
// ComposeMetas composes a map of metas for properly rendering issue links and external issue trackers.
func ( repo * Repository ) ComposeMetas ( ) map [ string ] string {
if repo . RenderingMetas == nil {
metas := map [ string ] string {
"user" : repo . MustOwner ( ) . Name ,
"user" : repo . OwnerName ,
"repo" : repo . Name ,
"repoPath" : repo . RepoPath ( ) ,
}
@ -588,6 +545,7 @@ func (repo *Repository) ComposeMetas() map[string]string {
}
}
repo . MustOwner ( )
if repo . Owner . IsOrganization ( ) {
teams := make ( [ ] string , 0 , 5 )
_ = x . Table ( "team_repo" ) .
@ -597,7 +555,7 @@ func (repo *Repository) ComposeMetas() map[string]string {
OrderBy ( "team.lower_name" ) .
Find ( & teams )
metas [ "teams" ] = "," + strings . Join ( teams , "," ) + ","
metas [ "org" ] = repo . Owner . LowerName
metas [ "org" ] = strings . ToLower ( repo . OwnerName )
}
repo . RenderingMetas = metas
@ -711,13 +669,9 @@ func (repo *Repository) getTemplateRepo(e Engine) (err error) {
return err
}
func ( repo * Repository ) repoPath ( e Engine ) string {
return RepoPath ( repo . mustOwnerName ( e ) , repo . Name )
}
// RepoPath returns the repository path
func ( repo * Repository ) RepoPath ( ) string {
return repo . repoPath ( x )
return RepoPath ( repo . OwnerName , repo . Name )
}
// GitConfigPath returns the path to a repository's git config/ directory
@ -742,7 +696,7 @@ func (repo *Repository) Link() string {
// ComposeCompareURL returns the repository comparison URL
func ( repo * Repository ) ComposeCompareURL ( oldCommitID , newCommitID string ) string {
return fmt . Sprintf ( "%s/%s/ compare/%s...%s" , repo . MustOwner ( ) . Name , repo . Name , oldCommitID , newCommitID )
return fmt . Sprintf ( "%s/compare/%s...%s" , repo . FullName ( ) , oldCommitID , newCommitID )
}
// UpdateDefaultBranch updates the default branch
@ -757,9 +711,9 @@ func (repo *Repository) IsOwnedBy(userID int64) bool {
}
func ( repo * Repository ) updateSize ( e Engine ) error {
size , err := util . GetDirectorySize ( repo . repoPath ( e ) )
size , err := util . GetDirectorySize ( repo . RepoPath ( ) )
if err != nil {
return fmt . Errorf ( "U pdateSize: %v" , err )
return fmt . Errorf ( "u pdateSize: %v" , err )
}
repo . Size = size
@ -768,8 +722,8 @@ func (repo *Repository) updateSize(e Engine) error {
}
// UpdateSize updates the repository size, calculating it using util.GetDirectorySize
func ( repo * Repository ) UpdateSize ( ) error {
return repo . updateSize ( x )
func ( repo * Repository ) UpdateSize ( ctx DBContext ) error {
return repo . updateSize ( ct x. e )
}
// CanUserFork returns true if specified user can fork repository.
@ -912,7 +866,7 @@ func ComposeHTTPSCloneURL(owner, repo string) string {
return fmt . Sprintf ( "%s%s/%s.git" , setting . AppURL , url . PathEscape ( owner ) , url . PathEscape ( repo ) )
}
func ( repo * Repository ) cloneLink ( e Engine , isWiki bool ) * CloneLink {
func ( repo * Repository ) cloneLink ( isWiki bool ) * CloneLink {
repoName := repo . Name
if isWiki {
repoName += ".wiki"
@ -923,22 +877,21 @@ func (repo *Repository) cloneLink(e Engine, isWiki bool) *CloneLink {
sshUser = setting . SSH . BuiltinServerUser
}
repo . Owner = repo . mustOwner ( e )
cl := new ( CloneLink )
if setting . SSH . Port != 22 {
cl . SSH = fmt . Sprintf ( "ssh://%s@%s:%d/%s/%s.git" , sshUser , setting . SSH . Domain , setting . SSH . Port , repo . Owner . Name , repoName )
cl . SSH = fmt . Sprintf ( "ssh://%s@%s:%d/%s/%s.git" , sshUser , setting . SSH . Domain , setting . SSH . Port , repo . OwnerName , repoName )
} else if setting . Repository . UseCompatSSHURI {
cl . SSH = fmt . Sprintf ( "ssh://%s@%s/%s/%s.git" , sshUser , setting . SSH . Domain , repo . Owner . Name , repoName )
cl . SSH = fmt . Sprintf ( "ssh://%s@%s/%s/%s.git" , sshUser , setting . SSH . Domain , repo . OwnerName , repoName )
} else {
cl . SSH = fmt . Sprintf ( "%s@%s:%s/%s.git" , sshUser , setting . SSH . Domain , repo . Owner . Name , repoName )
cl . SSH = fmt . Sprintf ( "%s@%s:%s/%s.git" , sshUser , setting . SSH . Domain , repo . OwnerName , repoName )
}
cl . HTTPS = ComposeHTTPSCloneURL ( repo . Owner . Name , repoName )
cl . HTTPS = ComposeHTTPSCloneURL ( repo . OwnerName , repoName )
return cl
}
// CloneLink returns clone URLs of repository.
func ( repo * Repository ) CloneLink ( ) ( cl * CloneLink ) {
return repo . cloneLink ( x , false )
return repo . cloneLink ( false )
}
// CheckCreateRepository check if could created a repository
@ -1011,64 +964,6 @@ func createDelegateHooks(repoPath string) (err error) {
return nil
}
// initRepoCommit temporarily changes with work directory.
func initRepoCommit ( tmpPath string , repo * Repository , u * User ) ( err error ) {
commitTimeStr := time . Now ( ) . Format ( time . RFC3339 )
sig := u . NewGitSig ( )
// Because this may call hooks we should pass in the environment
env := append ( os . Environ ( ) ,
"GIT_AUTHOR_NAME=" + sig . Name ,
"GIT_AUTHOR_EMAIL=" + sig . Email ,
"GIT_AUTHOR_DATE=" + commitTimeStr ,
"GIT_COMMITTER_NAME=" + sig . Name ,
"GIT_COMMITTER_EMAIL=" + sig . Email ,
"GIT_COMMITTER_DATE=" + commitTimeStr ,
)
if stdout , err := git . NewCommand ( "add" , "--all" ) .
SetDescription ( fmt . Sprintf ( "initRepoCommit (git add): %s" , tmpPath ) ) .
RunInDir ( tmpPath ) ; err != nil {
log . Error ( "git add --all failed: Stdout: %s\nError: %v" , stdout , err )
return fmt . Errorf ( "git add --all: %v" , err )
}
binVersion , err := git . BinVersion ( )
if err != nil {
return fmt . Errorf ( "Unable to get git version: %v" , err )
}
args := [ ] string {
"commit" , fmt . Sprintf ( "--author='%s <%s>'" , sig . Name , sig . Email ) ,
"-m" , "Initial commit" ,
}
if version . Compare ( binVersion , "1.7.9" , ">=" ) {
sign , keyID := SignInitialCommit ( tmpPath , u )
if sign {
args = append ( args , "-S" + keyID )
} else if version . Compare ( binVersion , "2.0.0" , ">=" ) {
args = append ( args , "--no-gpg-sign" )
}
}
if stdout , err := git . NewCommand ( args ... ) .
SetDescription ( fmt . Sprintf ( "initRepoCommit (git commit): %s" , tmpPath ) ) .
RunInDirWithEnv ( tmpPath , env ) ; err != nil {
log . Error ( "Failed to commit: %v: Stdout: %s\nError: %v" , args , stdout , err )
return fmt . Errorf ( "git commit: %v" , err )
}
if stdout , err := git . NewCommand ( "push" , "origin" , "master" ) .
SetDescription ( fmt . Sprintf ( "initRepoCommit (git push): %s" , tmpPath ) ) .
RunInDirWithEnv ( tmpPath , InternalPushingEnvironment ( u , repo ) ) ; err != nil {
log . Error ( "Failed to push back to master: Stdout: %s\nError: %v" , stdout , err )
return fmt . Errorf ( "git push: %v" , err )
}
return nil
}
// CreateRepoOptions contains the create repository options
type CreateRepoOptions struct {
Name string
@ -1085,7 +980,8 @@ type CreateRepoOptions struct {
Status RepositoryStatus
}
func getRepoInitFile ( tp , name string ) ( [ ] byte , error ) {
// GetRepoInitFile returns repository init files
func GetRepoInitFile ( tp , name string ) ( [ ] byte , error ) {
cleanedName := strings . TrimLeft ( path . Clean ( "/" + name ) , "/" )
relPath := path . Join ( "options" , tp , cleanedName )
@ -1109,140 +1005,6 @@ func getRepoInitFile(tp, name string) ([]byte, error) {
}
}
func prepareRepoCommit ( e Engine , repo * Repository , tmpDir , repoPath string , opts CreateRepoOptions ) error {
commitTimeStr := time . Now ( ) . Format ( time . RFC3339 )
authorSig := repo . Owner . NewGitSig ( )
// Because this may call hooks we should pass in the environment
env := append ( os . Environ ( ) ,
"GIT_AUTHOR_NAME=" + authorSig . Name ,
"GIT_AUTHOR_EMAIL=" + authorSig . Email ,
"GIT_AUTHOR_DATE=" + commitTimeStr ,
"GIT_COMMITTER_NAME=" + authorSig . Name ,
"GIT_COMMITTER_EMAIL=" + authorSig . Email ,
"GIT_COMMITTER_DATE=" + commitTimeStr ,
)
// Clone to temporary path and do the init commit.
if stdout , err := git . NewCommand ( "clone" , repoPath , tmpDir ) .
SetDescription ( fmt . Sprintf ( "initRepository (git clone): %s to %s" , repoPath , tmpDir ) ) .
RunInDirWithEnv ( "" , env ) ; err != nil {
log . Error ( "Failed to clone from %v into %s: stdout: %s\nError: %v" , repo , tmpDir , stdout , err )
return fmt . Errorf ( "git clone: %v" , err )
}
// README
data , err := getRepoInitFile ( "readme" , opts . Readme )
if err != nil {
return fmt . Errorf ( "getRepoInitFile[%s]: %v" , opts . Readme , err )
}
cloneLink := repo . cloneLink ( e , false )
match := map [ string ] string {
"Name" : repo . Name ,
"Description" : repo . Description ,
"CloneURL.SSH" : cloneLink . SSH ,
"CloneURL.HTTPS" : cloneLink . HTTPS ,
}
if err = ioutil . WriteFile ( filepath . Join ( tmpDir , "README.md" ) ,
[ ] byte ( com . Expand ( string ( data ) , match ) ) , 0644 ) ; err != nil {
return fmt . Errorf ( "write README.md: %v" , err )
}
// .gitignore
if len ( opts . Gitignores ) > 0 {
var buf bytes . Buffer
names := strings . Split ( opts . Gitignores , "," )
for _ , name := range names {
data , err = getRepoInitFile ( "gitignore" , name )
if err != nil {
return fmt . Errorf ( "getRepoInitFile[%s]: %v" , name , err )
}
buf . WriteString ( "# ---> " + name + "\n" )
buf . Write ( data )
buf . WriteString ( "\n" )
}
if buf . Len ( ) > 0 {
if err = ioutil . WriteFile ( filepath . Join ( tmpDir , ".gitignore" ) , buf . Bytes ( ) , 0644 ) ; err != nil {
return fmt . Errorf ( "write .gitignore: %v" , err )
}
}
}
// LICENSE
if len ( opts . License ) > 0 {
data , err = getRepoInitFile ( "license" , opts . License )
if err != nil {
return fmt . Errorf ( "getRepoInitFile[%s]: %v" , opts . License , err )
}
if err = ioutil . WriteFile ( filepath . Join ( tmpDir , "LICENSE" ) , data , 0644 ) ; err != nil {
return fmt . Errorf ( "write LICENSE: %v" , err )
}
}
return nil
}
func checkInitRepository ( repoPath string ) ( err error ) {
// Somehow the directory could exist.
if com . IsExist ( repoPath ) {
return fmt . Errorf ( "initRepository: path already exists: %s" , repoPath )
}
// Init git bare new repository.
if err = git . InitRepository ( repoPath , true ) ; err != nil {
return fmt . Errorf ( "InitRepository: %v" , err )
} else if err = createDelegateHooks ( repoPath ) ; err != nil {
return fmt . Errorf ( "createDelegateHooks: %v" , err )
}
return nil
}
// InitRepository initializes README and .gitignore if needed.
func initRepository ( e Engine , repoPath string , u * User , repo * Repository , opts CreateRepoOptions ) ( err error ) {
if err = checkInitRepository ( repoPath ) ; err != nil {
return err
}
// Initialize repository according to user's choice.
if opts . AutoInit {
tmpDir , err := ioutil . TempDir ( os . TempDir ( ) , "gitea-" + repo . Name )
if err != nil {
return fmt . Errorf ( "Failed to create temp dir for repository %s: %v" , repo . repoPath ( e ) , err )
}
defer os . RemoveAll ( tmpDir )
if err = prepareRepoCommit ( e , repo , tmpDir , repoPath , opts ) ; err != nil {
return fmt . Errorf ( "prepareRepoCommit: %v" , err )
}
// Apply changes and commit.
if err = initRepoCommit ( tmpDir , repo , u ) ; err != nil {
return fmt . Errorf ( "initRepoCommit: %v" , err )
}
}
// Re-fetch the repository from database before updating it (else it would
// override changes that were done earlier with sql)
if repo , err = getRepositoryByID ( e , repo . ID ) ; err != nil {
return fmt . Errorf ( "getRepositoryByID: %v" , err )
}
if ! opts . AutoInit {
repo . IsEmpty = true
}
repo . DefaultBranch = "master"
if err = updateRepository ( e , repo , false ) ; err != nil {
return fmt . Errorf ( "updateRepository: %v" , err )
}
return nil
}
var (
reservedRepoNames = [ ] string { "." , ".." }
reservedRepoPatterns = [ ] string { "*.git" , "*.wiki" }
@ -1253,22 +1015,23 @@ func IsUsableRepoName(name string) error {
return isUsableName ( reservedRepoNames , reservedRepoPatterns , name )
}
func createRepository ( e Engine , doer , u * User , repo * Repository ) ( err error ) {
// CreateRepository creates a repository for the user/organization.
func CreateRepository ( ctx DBContext , doer , u * User , repo * Repository ) ( err error ) {
if err = IsUsableRepoName ( repo . Name ) ; err != nil {
return err
}
has , err := isRepositoryExist ( e , u , repo . Name )
has , err := isRepositoryExist ( ctx . e , u , repo . Name )
if err != nil {
return fmt . Errorf ( "IsRepositoryExist: %v" , err )
} else if has {
return ErrRepoAlreadyExist { u . Name , repo . Name }
}
if _ , err = e . Insert ( repo ) ; err != nil {
if _ , err = ctx . e . Insert ( repo ) ; err != nil {
return err
}
if err = deleteRepoRedirect ( e , u . ID , repo . Name ) ; err != nil {
if err = deleteRepoRedirect ( ctx . e , u . ID , repo . Name ) ; err != nil {
return err
}
@ -1297,20 +1060,19 @@ func createRepository(e Engine, doer, u *User, repo *Repository) (err error) {
Type : tp ,
} )
}
}
if _ , err = e . Insert ( & units ) ; err != nil {
if _ , err = ctx . e . Insert ( & units ) ; err != nil {
return err
}
// Remember visibility preference.
u . LastRepoVisibility = repo . IsPrivate
if err = updateUserCols ( e , u , "last_repo_visibility" ) ; err != nil {
if err = updateUserCols ( ctx . e , u , "last_repo_visibility" ) ; err != nil {
return fmt . Errorf ( "updateUser: %v" , err )
}
if _ , err = e . Incr ( "num_repos" ) . ID ( u . ID ) . Update ( new ( User ) ) ; err != nil {
if _ , err = ctx . e . Incr ( "num_repos" ) . ID ( u . ID ) . Update ( new ( User ) ) ; err != nil {
return fmt . Errorf ( "increment user total_repos: %v" , err )
}
u . NumRepos ++
@ -1322,106 +1084,41 @@ func createRepository(e Engine, doer, u *User, repo *Repository) (err error) {
}
for _ , t := range u . Teams {
if t . IncludesAllRepositories {
if err := t . addRepository ( e , repo ) ; err != nil {
if err := t . addRepository ( ctx . e , repo ) ; err != nil {
return fmt . Errorf ( "addRepository: %v" , err )
}
}
}
if isAdmin , err := isUserRepoAdmin ( e , repo , doer ) ; err != nil {
if isAdmin , err := isUserRepoAdmin ( ctx . e , repo , doer ) ; err != nil {
return fmt . Errorf ( "isUserRepoAdmin: %v" , err )
} else if ! isAdmin {
// Make creator repo admin if it wan't assigned automatically
if err = repo . addCollaborator ( e , doer ) ; err != nil {
if err = repo . addCollaborator ( ctx . e , doer ) ; err != nil {
return fmt . Errorf ( "AddCollaborator: %v" , err )
}
if err = repo . changeCollaborationAccessMode ( e , doer . ID , AccessModeAdmin ) ; err != nil {
if err = repo . changeCollaborationAccessMode ( ctx . e , doer . ID , AccessModeAdmin ) ; err != nil {
return fmt . Errorf ( "ChangeCollaborationAccessMode: %v" , err )
}
}
} else if err = repo . recalculateAccesses ( e ) ; err != nil {
} else if err = repo . recalculateAccesses ( ctx . e ) ; err != nil {
// Organization automatically called this in addRepository method.
return fmt . Errorf ( "recalculateAccesses: %v" , err )
}
if setting . Service . AutoWatchNewRepos {
if err = watchRepo ( e , doer . ID , repo . ID , true ) ; err != nil {
if err = watchRepo ( ctx . e , doer . ID , repo . ID , true ) ; err != nil {
return fmt . Errorf ( "watchRepo: %v" , err )
}
}
if err = copyDefaultWebhooksToRepo ( e , repo . ID ) ; err != nil {
if err = copyDefaultWebhooksToRepo ( ctx . e , repo . ID ) ; err != nil {
return fmt . Errorf ( "copyDefaultWebhooksToRepo: %v" , err )
}
return nil
}
// CreateRepository creates a repository for the user/organization.
func CreateRepository ( doer , u * User , opts CreateRepoOptions ) ( _ * Repository , err error ) {
if ! doer . IsAdmin && ! u . CanCreateRepo ( ) {
return nil , ErrReachLimitOfRepo { u . MaxRepoCreation }
}
repo := & Repository {
OwnerID : u . ID ,
Owner : u ,
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 ,
}
sess := x . NewSession ( )
defer sess . Close ( )
if err = sess . Begin ( ) ; err != nil {
return nil , err
}
if err = createRepository ( sess , doer , u , repo ) ; err != nil {
return nil , err
}
// No need for init mirror.
if ! opts . IsMirror {
repoPath := RepoPath ( u . Name , repo . Name )
if err = initRepository ( sess , repoPath , u , repo , opts ) ; err != nil {
if err2 := os . RemoveAll ( repoPath ) ; err2 != nil {
log . Error ( "initRepository: %v" , err )
return nil , fmt . Errorf (
"delete repo directory %s/%s failed(2): %v" , u . Name , repo . Name , err2 )
}
return nil , fmt . Errorf ( "initRepository: %v" , err )
}
// Initialize Issue Labels if selected
if len ( opts . IssueLabels ) > 0 {
if err = initalizeLabels ( sess , repo . ID , opts . IssueLabels ) ; err != nil {
return nil , fmt . Errorf ( "initalizeLabels: %v" , err )
}
}
if stdout , err := git . NewCommand ( "update-server-info" ) .
SetDescription ( fmt . Sprintf ( "CreateRepository(git update-server-info): %s" , repoPath ) ) .
RunInDir ( repoPath ) ; err != nil {
log . Error ( "CreateRepitory(git update-server-info) in %v: Stdout: %s\nError: %v" , repo , stdout , err )
return nil , fmt . Errorf ( "CreateRepository(git update-server-info): %v" , err )
}
}
if err = sess . Commit ( ) ; err != nil {
return nil , err
}
return repo , err
}
func countRepositories ( userID int64 , private bool ) int64 {
sess := x . Where ( "id > 0" )
@ -1458,6 +1155,12 @@ func RepoPath(userName, repoName string) string {
return filepath . Join ( UserPath ( userName ) , strings . ToLower ( repoName ) + ".git" )
}
// IncrementRepoForkNum increment repository fork number
func IncrementRepoForkNum ( ctx DBContext , repoID int64 ) error {
_ , err := ctx . e . Exec ( "UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?" , repoID )
return err
}
// TransferOwnership transfers all corresponding setting from old user to new one.
func TransferOwnership ( doer * User , newOwnerName string , repo * Repository ) error {
newOwner , err := GetUserByName ( newOwnerName )
@ -1485,6 +1188,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
// new owner.
repo . OwnerID = newOwner . ID
repo . Owner = newOwner
repo . OwnerName = newOwner . Name
// Update repository.
if _ , err := sess . ID ( repo . ID ) . Update ( repo ) ; err != nil {
@ -1683,7 +1387,7 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e
}
// Create/Remove git-daemon-export-ok for git-daemon...
daemonExportFile := path . Join ( repo . repoPath ( e ) , ` git-daemon-export-ok ` )
daemonExportFile := path . Join ( repo . RepoPath ( ) , ` git-daemon-export-ok ` )
if repo . IsPrivate && com . IsExist ( daemonExportFile ) {
if err = os . Remove ( daemonExportFile ) ; err != nil {
log . Error ( "Failed to remove %s: %v" , daemonExportFile , err )
@ -1715,6 +1419,11 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e
return nil
}
// UpdateRepositoryCtx updates a repository with db context
func UpdateRepositoryCtx ( ctx DBContext , repo * Repository , visibilityChanged bool ) error {
return updateRepository ( ctx . e , repo , visibilityChanged )
}
// UpdateRepository updates a repository
func UpdateRepository ( repo * Repository , visibilityChanged bool ) ( err error ) {
sess := x . NewSession ( )
@ -1905,7 +1614,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
}
// FIXME: Remove repository files should be executed after transaction succeed.
repoPath := repo . repoPath ( sess )
repoPath := repo . RepoPath ( )
removeAllWithNotice ( sess , "Delete repository files" , repoPath )
err = repo . deleteWiki ( sess )
@ -2030,6 +1739,11 @@ func GetRepositoryByID(id int64) (*Repository, error) {
return getRepositoryByID ( x , id )
}
// GetRepositoryByIDCtx returns the repository by given id if exists.
func GetRepositoryByIDCtx ( ctx DBContext , id int64 ) ( * Repository , error ) {
return getRepositoryByID ( ctx . e , id )
}
// GetRepositoriesMapByIDs returns the repositories by given id slice.
func GetRepositoriesMapByIDs ( ids [ ] int64 ) ( map [ int64 ] * Repository , error ) {
var repos = make ( map [ int64 ] * Repository , len ( ids ) )
@ -2290,7 +2004,7 @@ func GitGcRepos() error {
SetDescription ( fmt . Sprintf ( "Repository Garbage Collection: %s" , repo . FullName ( ) ) ) .
RunInDirTimeout (
time . Duration ( setting . Git . Timeout . GC ) * time . Second ,
RepoPath ( repo . Owner . Name , repo . Name ) ) ; err != nil {
repo . RepoPath ( ) ) ; err != nil {
log . Error ( "Repository garbage collection failed for %v. Stdout: %s\nError: %v" , repo , stdout , err )
return fmt . Errorf ( "Repository garbage collection failed: Error: %v" , err )
}
@ -2479,20 +2193,16 @@ func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) {
}
// CopyLFS copies LFS data from one repo to another
func CopyLFS ( newRepo , oldRepo * Repository ) error {
return copyLFS ( x , newRepo , oldRepo )
}
func copyLFS ( e Engine , newRepo , oldRepo * Repository ) error {
func CopyLFS ( ctx DBContext , newRepo , oldRepo * Repository ) error {
var lfsObjects [ ] * LFSMetaObject
if err := e . Where ( "repository_id=?" , oldRepo . ID ) . Find ( & lfsObjects ) ; err != nil {
if err := ctx . e . Where ( "repository_id=?" , oldRepo . ID ) . Find ( & lfsObjects ) ; err != nil {
return err
}
for _ , v := range lfsObjects {
v . ID = 0
v . RepositoryID = newRepo . ID
if _ , err := e . Insert ( v ) ; err != nil {
if _ , err := ctx . e . Insert ( v ) ; err != nil {
return err
}
}
@ -2500,80 +2210,6 @@ func copyLFS(e Engine, newRepo, oldRepo *Repository) error {
return nil
}
// ForkRepository forks a repository
func ForkRepository ( doer , owner * User , oldRepo * Repository , name , desc string ) ( _ * Repository , err error ) {
forkedRepo , err := oldRepo . GetUserFork ( owner . ID )
if err != nil {
return nil , err
}
if forkedRepo != nil {
return nil , ErrForkAlreadyExist {
Uname : owner . Name ,
RepoName : oldRepo . FullName ( ) ,
ForkName : forkedRepo . FullName ( ) ,
}
}
repo := & Repository {
OwnerID : owner . ID ,
Owner : owner ,
Name : name ,
LowerName : strings . ToLower ( name ) ,
Description : desc ,
DefaultBranch : oldRepo . DefaultBranch ,
IsPrivate : oldRepo . IsPrivate ,
IsEmpty : oldRepo . IsEmpty ,
IsFork : true ,
ForkID : oldRepo . ID ,
}
sess := x . NewSession ( )
defer sess . Close ( )
if err = sess . Begin ( ) ; err != nil {
return nil , err
}
if err = createRepository ( sess , doer , owner , repo ) ; err != nil {
return nil , err
}
if _ , err = sess . Exec ( "UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?" , oldRepo . ID ) ; err != nil {
return nil , err
}
repoPath := RepoPath ( owner . Name , repo . Name )
if stdout , err := git . NewCommand (
"clone" , "--bare" , oldRepo . repoPath ( sess ) , repoPath ) .
SetDescription ( fmt . Sprintf ( "ForkRepository(git clone): %s to %s" , oldRepo . FullName ( ) , repo . FullName ( ) ) ) .
RunInDirTimeout ( 10 * time . Minute , "" ) ; err != nil {
log . Error ( "Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v" , repo , oldRepo , stdout , err )
return nil , fmt . Errorf ( "git clone: %v" , err )
}
if stdout , err := git . NewCommand ( "update-server-info" ) .
SetDescription ( fmt . Sprintf ( "ForkRepository(git update-server-info): %s" , repo . FullName ( ) ) ) .
RunInDir ( repoPath ) ; err != nil {
log . Error ( "Fork Repository (git update-server-info) failed for %v:\nStdout: %s\nError: %v" , repo , stdout , err )
return nil , fmt . Errorf ( "git update-server-info: %v" , err )
}
if err = createDelegateHooks ( repoPath ) ; err != nil {
return nil , fmt . Errorf ( "createDelegateHooks: %v" , err )
}
//Commit repo to get Fork ID
err = sess . Commit ( )
if err != nil {
return nil , err
}
if err = repo . UpdateSize ( ) ; err != nil {
log . Error ( "Failed to update size for repository: %v" , err )
}
return repo , CopyLFS ( repo , oldRepo )
}
// GetForks returns all the forks of the repository
func ( repo * Repository ) GetForks ( ) ( [ ] * Repository , error ) {
forks := make ( [ ] * Repository , 0 , repo . NumForks )