aboutsummaryrefslogtreecommitdiffstats
path: root/models/repo.go
diff options
context:
space:
mode:
authorUnknwon <u@gogs.io>2015-12-08 20:06:12 -0500
committerUnknwon <u@gogs.io>2015-12-08 20:06:12 -0500
commit120cd4e4716d11f79a7e8c41c066383e579d480a (patch)
treeb25ae1b31ecf5437250c388d55ee940e294a4187 /models/repo.go
parent1cbd4c01fbfd4e15e36a722c9e2cc19366be3df8 (diff)
downloadgitea-120cd4e4716d11f79a7e8c41c066383e579d480a.tar.gz
gitea-120cd4e4716d11f79a7e8c41c066383e579d480a.zip
#1984 Better mirror repo management
Diffstat (limited to 'models/repo.go')
-rw-r--r--models/repo.go118
1 files changed, 83 insertions, 35 deletions
diff --git a/models/repo.go b/models/repo.go
index 25f66600ab..2a45bdc0b2 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -301,6 +301,10 @@ func (repo *Repository) RepoPath() string {
return repo.repoPath(x)
}
+func (repo *Repository) GitConfigPath() string {
+ return filepath.Join(repo.RepoPath(), "config")
+}
+
func (repo *Repository) RepoLink() string {
return setting.AppSubUrl + "/" + repo.MustOwner().Name + "/" + repo.Name
}
@@ -345,7 +349,7 @@ func (repo *Repository) LocalCopyPath() string {
func updateLocalCopy(repoPath, localPath string) error {
if !com.IsExist(localPath) {
- if err := git.Clone(repoPath, localPath); err != nil {
+ if err := git.Clone(repoPath, localPath, git.CloneRepoOptions{}); err != nil {
return fmt.Errorf("Clone: %v", err)
}
} else {
@@ -484,6 +488,8 @@ type Mirror struct {
Interval int // Hour.
Updated time.Time `xorm:"UPDATED"`
NextUpdate time.Time
+
+ address string `xorm:"-"`
}
func (m *Mirror) AfterSet(colName string, _ xorm.Cell) {
@@ -497,6 +503,61 @@ func (m *Mirror) AfterSet(colName string, _ xorm.Cell) {
}
}
+func (m *Mirror) readAddress() {
+ if len(m.address) > 0 {
+ return
+ }
+
+ cfg, err := ini.Load(m.Repo.GitConfigPath())
+ if err != nil {
+ log.Error(4, "Load: %v", err)
+ return
+ }
+ m.address = cfg.Section("remote \"origin\"").Key("url").Value()
+}
+
+// HandleCloneUserCredentials replaces user credentials from HTTP/HTTPS URL
+// with placeholder <credentials>.
+// It will fail for any other forms of clone addresses.
+func HandleCloneUserCredentials(url string, mosaics bool) string {
+ i := strings.Index(url, "@")
+ if i == -1 {
+ return url
+ }
+ start := strings.Index(url, "://")
+ if start == -1 {
+ return url
+ }
+ if mosaics {
+ return url[:start+3] + "<credentials>" + url[i:]
+ }
+ return url[:start+3] + url[i+1:]
+}
+
+// Address returns mirror address from Git repository config without credentials.
+func (m *Mirror) Address() string {
+ m.readAddress()
+ return HandleCloneUserCredentials(m.address, false)
+}
+
+// FullAddress returns mirror address from Git repository config.
+func (m *Mirror) FullAddress() string {
+ m.readAddress()
+ return m.address
+}
+
+// SaveAddress writes new address to Git repository config.
+func (m *Mirror) SaveAddress(addr string) error {
+ configPath := m.Repo.GitConfigPath()
+ cfg, err := ini.Load(configPath)
+ if err != nil {
+ return fmt.Errorf("Load: %v", err)
+ }
+
+ cfg.Section("remote \"origin\"").Key("url").SetValue(addr)
+ return cfg.SaveToIndent(configPath, "\t")
+}
+
func getMirror(e Engine, repoId int64) (*Mirror, error) {
m := &Mirror{RepoID: repoId}
has, err := e.Get(m)
@@ -527,25 +588,6 @@ func createUpdateHook(repoPath string) error {
fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+setting.AppPath+"\"", setting.CustomConf))
}
-// MirrorRepository creates a mirror repository from source.
-func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error {
- _, stderr, err := process.ExecTimeout(10*time.Minute,
- fmt.Sprintf("MirrorRepository: %s/%s", userName, repoName),
- "git", "clone", "--mirror", url, repoPath)
- if err != nil {
- return errors.New("git clone --mirror: " + stderr)
- }
-
- if _, err = x.InsertOne(&Mirror{
- RepoID: repoId,
- Interval: 24,
- NextUpdate: time.Now().Add(24 * time.Hour),
- }); err != nil {
- return err
- }
- return nil
-}
-
type MigrateRepoOptions struct {
Name string
Description string
@@ -582,29 +624,35 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
repo.NumWatches = 1
}
- repo.IsBare = false
+ os.RemoveAll(repoPath)
+ if err = git.Clone(opts.RemoteAddr, repoPath, git.CloneRepoOptions{
+ Mirror: true,
+ Quiet: true,
+ Timeout: 10 * time.Minute,
+ }); err != nil {
+ return repo, fmt.Errorf("Clone: %v", err)
+ }
+
if opts.IsMirror {
- if err = MirrorRepository(repo.ID, u.Name, repo.Name, repoPath, opts.RemoteAddr); err != nil {
- return repo, err
+ if _, err = x.InsertOne(&Mirror{
+ RepoID: repo.ID,
+ Interval: 24,
+ NextUpdate: time.Now().Add(24 * time.Hour),
+ }); err != nil {
+ return repo, fmt.Errorf("InsertOne: %v", err)
}
+
repo.IsMirror = true
return repo, UpdateRepository(repo, false)
- } else {
- os.RemoveAll(repoPath)
}
- // FIXME: this command could for both migrate and mirror
- _, stderr, err := process.ExecTimeout(10*time.Minute,
- fmt.Sprintf("MigrateRepository: %s", repoPath),
- "git", "clone", "--mirror", "--bare", "--quiet", opts.RemoteAddr, repoPath)
- if err != nil {
- return repo, fmt.Errorf("git clone --mirror --bare --quiet: %v", stderr)
- } else if err = createUpdateHook(repoPath); err != nil {
- return repo, fmt.Errorf("create update hook: %v", err)
+ if err = createUpdateHook(repoPath); err != nil {
+ return repo, fmt.Errorf("createUpdateHook: %v", err)
}
// Clean up mirror info which prevents "push --all".
- configPath := filepath.Join(repoPath, "/config")
+ // This also removes possible user credentials.
+ configPath := repo.GitConfigPath()
cfg, err := ini.Load(configPath)
if err != nil {
return repo, fmt.Errorf("open config file: %v", err)
@@ -615,7 +663,7 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
}
// Check if repository is empty.
- _, stderr, err = com.ExecCmdDir(repoPath, "git", "log", "-1")
+ _, stderr, err := com.ExecCmdDir(repoPath, "git", "log", "-1")
if err != nil {
if strings.Contains(stderr, "fatal: bad default revision 'HEAD'") {
repo.IsBare = true