diff options
Diffstat (limited to 'models/repo.go')
-rw-r--r-- | models/repo.go | 197 |
1 files changed, 139 insertions, 58 deletions
diff --git a/models/repo.go b/models/repo.go index 197415c6..b628e752 100644 --- a/models/repo.go +++ b/models/repo.go @@ -17,12 +17,14 @@ import ( "regexp" "sort" "strings" + "sync" "time" "unicode/utf8" "github.com/Unknwon/cae/zip" "github.com/Unknwon/com" "github.com/go-xorm/xorm" + "gopkg.in/ini.v1" "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/bindata" @@ -48,7 +50,7 @@ var ( Gitignores, Licenses, Readmes []string // Maximum items per page in forks, watchers and stars of a repo - ItemsPerPage = 54 + ItemsPerPage = 40 ) func LoadRepoConfig() { @@ -319,7 +321,7 @@ func (repo *Repository) UpdateLocalCopy() error { } } else { _, stderr, err := process.ExecDir(-1, localPath, - fmt.Sprintf("UpdateLocalCopy(git pull): %s", repoPath), "git", "pull") + fmt.Sprintf("UpdateLocalCopy(git pull --all): %s", repoPath), "git", "pull", "--all") if err != nil { return fmt.Errorf("git pull: %v - %s", err, stderr) } @@ -379,11 +381,11 @@ func (repo *Repository) CloneLink() (cl CloneLink, err error) { } if setting.SSHPort != 22 { - cl.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.SSHDomain, setting.SSHPort, repo.Owner.LowerName, repo.LowerName) + cl.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.SSHDomain, setting.SSHPort, repo.Owner.Name, repo.Name) } else { - cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.SSHDomain, repo.Owner.LowerName, repo.LowerName) + cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.SSHDomain, repo.Owner.Name, repo.Name) } - cl.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, repo.Owner.LowerName, repo.LowerName) + cl.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, repo.Owner.Name, repo.Name) return cl, nil } @@ -537,6 +539,17 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) { return repo, fmt.Errorf("create update hook: %v", err) } + // Clean up mirror info which prevents "push --all". + configPath := filepath.Join(repoPath, "/config") + cfg, err := ini.Load(configPath) + if err != nil { + return repo, fmt.Errorf("open config file: %v", err) + } + cfg.DeleteSection("remote \"origin\"") + if err = cfg.SaveToIndent(configPath, "\t"); err != nil { + return repo, fmt.Errorf("save config file: %v", err) + } + // Check if repository is empty. _, stderr, err = com.ExecCmdDir(repoPath, "git", "log", "-1") if err != nil { @@ -563,20 +576,20 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) { func initRepoCommit(tmpPath string, sig *git.Signature) (err error) { var stderr string if _, stderr, err = process.ExecDir(-1, - tmpPath, fmt.Sprintf("initRepoCommit(git add): %s", tmpPath), + tmpPath, fmt.Sprintf("initRepoCommit (git add): %s", tmpPath), "git", "add", "--all"); err != nil { return fmt.Errorf("git add: %s", stderr) } if _, stderr, err = process.ExecDir(-1, - tmpPath, fmt.Sprintf("initRepoCommit(git commit): %s", tmpPath), + tmpPath, fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath), "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", "initial commit"); err != nil { return fmt.Errorf("git commit: %s", stderr) } if _, stderr, err = process.ExecDir(-1, - tmpPath, fmt.Sprintf("initRepoCommit(git push): %s", tmpPath), + tmpPath, fmt.Sprintf("initRepoCommit (git push): %s", tmpPath), "git", "push", "origin", "master"); err != nil { return fmt.Errorf("git push: %s", stderr) } @@ -587,7 +600,7 @@ func createUpdateHook(repoPath string) error { hookPath := path.Join(repoPath, "hooks/update") os.MkdirAll(path.Dir(hookPath), os.ModePerm) return ioutil.WriteFile(hookPath, - []byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+appPath+"\"", setting.CustomConf)), 0777) + []byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+setting.AppPath+"\"", setting.CustomConf)), 0777) } type CreateRepoOptions struct { @@ -687,7 +700,7 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C // Init bare new repository. os.MkdirAll(repoPath, os.ModePerm) _, stderr, err := process.ExecDir(-1, repoPath, - fmt.Sprintf("initRepository(git init --bare): %s", repoPath), "git", "init", "--bare") + fmt.Sprintf("initRepository (git init --bare): %s", repoPath), "git", "init", "--bare") if err != nil { return fmt.Errorf("git init --bare: %v - %s", err, stderr) } @@ -898,9 +911,9 @@ func TransferOwnership(u *User, newOwnerName string, repo *Repository) error { } // Remove redundant collaborators. - collaborators, err := repo.GetCollaborators() + collaborators, err := repo.getCollaborators(sess) if err != nil { - return fmt.Errorf("GetCollaborators: %v", err) + return fmt.Errorf("getCollaborators: %v", err) } // Dummy object. @@ -936,9 +949,9 @@ func TransferOwnership(u *User, newOwnerName string, repo *Repository) error { } if newOwner.IsOrganization() { - t, err := newOwner.GetOwnerTeam() + t, err := newOwner.getOwnerTeam(sess) if err != nil { - return fmt.Errorf("GetOwnerTeam: %v", err) + return fmt.Errorf("getOwnerTeam: %v", err) } else if err = t.addRepository(sess, repo); err != nil { return fmt.Errorf("add to owner team: %v", err) } @@ -1104,7 +1117,7 @@ func DeleteRepository(uid, repoID int64) error { return err } else if _, err = sess.Delete(&Milestone{RepoID: repoID}); err != nil { return err - } else if _, err = sess.Delete(&Release{RepoId: repoID}); err != nil { + } else if _, err = sess.Delete(&Release{RepoID: repoID}); err != nil { return err } else if _, err = sess.Delete(&Collaboration{RepoID: repoID}); err != nil { return err @@ -1304,7 +1317,7 @@ func DeleteRepositoryArchives() error { repo := bean.(*Repository) repoPath, err := repo.RepoPath() if err != nil { - if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepositoryArchives[%d]: %v", repo.ID, err)); err2 != nil { + if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepositoryArchives.RepoPath [%d]: %v", repo.ID, err)); err2 != nil { log.Error(4, "CreateRepositoryNotice: %v", err2) } return nil @@ -1313,32 +1326,110 @@ func DeleteRepositoryArchives() error { }) } +// DeleteMissingRepositories deletes all repository records that lost Git files. +func DeleteMissingRepositories() error { + repos := make([]*Repository, 0, 5) + if err := x.Where("id > 0").Iterate(new(Repository), + func(idx int, bean interface{}) error { + repo := bean.(*Repository) + repoPath, err := repo.RepoPath() + if err != nil { + if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepositoryArchives.RepoPath [%d]: %v", repo.ID, err)); err2 != nil { + log.Error(4, "CreateRepositoryNotice: %v", err2) + } + return nil + } + + if !com.IsDir(repoPath) { + repos = append(repos, repo) + } + return nil + }); err != nil { + if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteMissingRepositories: %v", err)); err2 != nil { + log.Error(4, "CreateRepositoryNotice: %v", err2) + } + return nil + } + + if len(repos) == 0 { + return nil + } + + for _, repo := range repos { + log.Trace("Deleting %d/%d...", repo.OwnerID, repo.ID) + if err := DeleteRepository(repo.OwnerID, repo.ID); err != nil { + if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepository [%d]: %v", repo.ID, err)); err2 != nil { + log.Error(4, "CreateRepositoryNotice: %v", err2) + } + } + } + return nil +} + // RewriteRepositoryUpdateHook rewrites all repositories' update hook. func RewriteRepositoryUpdateHook() error { return x.Where("id > 0").Iterate(new(Repository), func(idx int, bean interface{}) error { repo := bean.(*Repository) - if err := repo.GetOwner(); err != nil { - return err + repoPath, err := repo.RepoPath() + if err != nil { + if err2 := CreateRepositoryNotice(fmt.Sprintf("RewriteRepositoryUpdateHook[%d]: %v", repo.ID, err)); err2 != nil { + log.Error(4, "CreateRepositoryNotice: %v", err2) + } + return nil } - return createUpdateHook(RepoPath(repo.Owner.Name, repo.Name)) + return createUpdateHook(repoPath) }) } -var ( - // Prevent duplicate running tasks. - isMirrorUpdating = false - isGitFscking = false - isCheckingRepos = false +// statusPool represents a pool of status with true/false. +type statusPool struct { + lock sync.RWMutex + pool map[string]bool +} + +// Start sets value of given name to true in the pool. +func (p *statusPool) Start(name string) { + p.lock.Lock() + defer p.lock.Unlock() + + p.pool[name] = true +} + +// Stop sets value of given name to false in the pool. +func (p *statusPool) Stop(name string) { + p.lock.Lock() + defer p.lock.Unlock() + + p.pool[name] = false +} + +// IsRunning checks if value of given name is set to true in the pool. +func (p *statusPool) IsRunning(name string) bool { + p.lock.RLock() + defer p.lock.RUnlock() + + return p.pool[name] +} + +// Prevent duplicate running tasks. +var taskStatusPool = &statusPool{ + pool: make(map[string]bool), +} + +const ( + _MIRROR_UPDATE = "mirror_update" + _GIT_FSCK = "git_fsck" + _CHECK_REPOs = "check_repos" ) // MirrorUpdate checks and updates mirror repositories. func MirrorUpdate() { - if isMirrorUpdating { + if taskStatusPool.IsRunning(_MIRROR_UPDATE) { return } - isMirrorUpdating = true - defer func() { isMirrorUpdating = false }() + taskStatusPool.Start(_MIRROR_UPDATE) + defer taskStatusPool.Stop(_MIRROR_UPDATE) log.Trace("Doing: MirrorUpdate") @@ -1386,11 +1477,11 @@ func MirrorUpdate() { // GitFsck calls 'git fsck' to check repository health. func GitFsck() { - if isGitFscking { + if taskStatusPool.IsRunning(_GIT_FSCK) { return } - isGitFscking = true - defer func() { isGitFscking = false }() + taskStatusPool.Start(_GIT_FSCK) + defer taskStatusPool.Stop(_GIT_FSCK) log.Trace("Doing: GitFsck") @@ -1455,11 +1546,11 @@ func repoStatsCheck(checker *repoChecker) { } func CheckRepoStats() { - if isCheckingRepos { + if taskStatusPool.IsRunning(_CHECK_REPOs) { return } - isCheckingRepos = true - defer func() { isCheckingRepos = false }() + taskStatusPool.Start(_CHECK_REPOs) + defer taskStatusPool.Stop(_CHECK_REPOs) log.Trace("Doing: CheckRepoStats") @@ -1680,25 +1771,21 @@ func WatchRepo(uid, repoId int64, watch bool) (err error) { return watchRepo(x, uid, repoId, watch) } -func getWatchers(e Engine, rid int64) ([]*Watch, error) { +func getWatchers(e Engine, repoID int64) ([]*Watch, error) { watches := make([]*Watch, 0, 10) - err := e.Find(&watches, &Watch{RepoID: rid}) - return watches, err + return watches, e.Find(&watches, &Watch{RepoID: repoID}) } // GetWatchers returns all watchers of given repository. -func GetWatchers(rid int64) ([]*Watch, error) { - return getWatchers(x, rid) +func GetWatchers(repoID int64) ([]*Watch, error) { + return getWatchers(x, repoID) } -// Repository.GetWatchers returns all users watching given repository. -func (repo *Repository) GetWatchers(offset int) ([]*User, error) { - users := make([]*User, 0, 10) - offset = (offset - 1) * ItemsPerPage - - err := x.Limit(ItemsPerPage, offset).Where("repo_id=?", repo.ID).Join("LEFT", "watch", "user.id=watch.user_id").Find(&users) - - return users, err +// Repository.GetWatchers returns range of users watching given repository. +func (repo *Repository) GetWatchers(page int) ([]*User, error) { + users := make([]*User, 0, ItemsPerPage) + return users, x.Limit(ItemsPerPage, (page-1)*ItemsPerPage). + Where("repo_id=?", repo.ID).Join("LEFT", "watch", "user.id=watch.user_id").Find(&users) } func notifyWatchers(e Engine, act *Action) error { @@ -1778,13 +1865,10 @@ func IsStaring(uid, repoId int64) bool { return has } -func (repo *Repository) GetStars(offset int) ([]*User, error) { - users := make([]*User, 0, 10) - offset = (offset - 1) * ItemsPerPage - - err := x.Limit(ItemsPerPage, offset).Where("repo_id=?", repo.ID).Join("LEFT", "star", "user.id=star.uid").Find(&users) - - return users, err +func (repo *Repository) GetStargazers(page int) ([]*User, error) { + users := make([]*User, 0, ItemsPerPage) + return users, x.Limit(ItemsPerPage, (page-1)*ItemsPerPage). + Where("repo_id=?", repo.ID).Join("LEFT", "star", "user.id=star.uid").Find(&users) } // ___________ __ @@ -1856,9 +1940,6 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit } func (repo *Repository) GetForks() ([]*Repository, error) { - forks := make([]*Repository, 0, 10) - - err := x.Find(&forks, &Repository{ForkID: repo.ID}) - - return forks, err + forks := make([]*Repository, 0, repo.NumForks) + return forks, x.Find(&forks, &Repository{ForkID: repo.ID}) } |