|
|
|
@ -659,47 +659,21 @@ type MigrateRepoOptions struct {
|
|
|
|
|
RemoteAddr string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func isGitRepoURL(repoURL string, timeout time.Duration) bool { |
|
|
|
|
cmd := git.NewCommand("ls-remote") |
|
|
|
|
cmd.AddArguments("-q", "-h", repoURL, "HEAD") |
|
|
|
|
res, err := cmd.RunTimeout(timeout) |
|
|
|
|
if err != nil { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
if strings.Contains(res, "fatal") || strings.Contains(res, "not found") { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func wikiRemoteURL(remote string, timeout time.Duration) string { |
|
|
|
|
wikiRemoteStd := remote |
|
|
|
|
wikiRemoteBitBucket := remote |
|
|
|
|
/* |
|
|
|
|
GitHub, GitLab, Gogs: NAME.wiki.git |
|
|
|
|
BitBucket: NAME.git/wiki |
|
|
|
|
*/ |
|
|
|
|
gitSuffixed := strings.HasSuffix(remote, ".git") |
|
|
|
|
if gitSuffixed { |
|
|
|
|
wikiRemoteStd = wikiRemoteStd[:len(wikiRemoteStd)-4] |
|
|
|
|
wikiRemoteBitBucket += "/wiki" |
|
|
|
|
} else { |
|
|
|
|
wikiRemoteBitBucket += ".git/wiki" |
|
|
|
|
} |
|
|
|
|
wikiRemoteStd += ".wiki.git" |
|
|
|
|
isBB := strings.Contains(remote, "bitbucket") |
|
|
|
|
if isBB { |
|
|
|
|
if isGitRepoURL(wikiRemoteBitBucket, timeout) { |
|
|
|
|
return wikiRemoteBitBucket |
|
|
|
|
} else if isGitRepoURL(wikiRemoteStd, timeout) { |
|
|
|
|
return wikiRemoteStd |
|
|
|
|
/* |
|
|
|
|
GitHub, GitLab, Gogs: *.wiki.git |
|
|
|
|
BitBucket: *.git/wiki |
|
|
|
|
*/ |
|
|
|
|
var commonWikiURLSuffixes = []string{".wiki.git", ".git/wiki"} |
|
|
|
|
|
|
|
|
|
// wikiRemoteURL returns accessible repository URL for wiki if exists.
|
|
|
|
|
// Otherwise, it returns an empty string.
|
|
|
|
|
func wikiRemoteURL(remote string) string { |
|
|
|
|
remote = strings.TrimSuffix(remote, ".git") |
|
|
|
|
for _, suffix := range commonWikiURLSuffixes { |
|
|
|
|
wikiURL := remote + suffix |
|
|
|
|
if git.IsRepoURLAccessible(wikiURL) { |
|
|
|
|
return wikiURL |
|
|
|
|
} |
|
|
|
|
return "" |
|
|
|
|
} |
|
|
|
|
if isGitRepoURL(wikiRemoteStd, timeout) { |
|
|
|
|
return wikiRemoteStd |
|
|
|
|
} else if isGitRepoURL(wikiRemoteBitBucket, timeout) { |
|
|
|
|
return wikiRemoteBitBucket |
|
|
|
|
} |
|
|
|
|
return "" |
|
|
|
|
} |
|
|
|
@ -733,25 +707,26 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
|
|
|
|
repo.NumWatches = 1 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gitTimeout := time.Duration(setting.Git.Timeout.Migrate) * time.Second |
|
|
|
|
migrateTimeout := time.Duration(setting.Git.Timeout.Migrate) * time.Second |
|
|
|
|
|
|
|
|
|
os.RemoveAll(repoPath) |
|
|
|
|
if err = git.Clone(opts.RemoteAddr, repoPath, git.CloneRepoOptions{ |
|
|
|
|
Mirror: true, |
|
|
|
|
Quiet: true, |
|
|
|
|
Timeout: gitTimeout, |
|
|
|
|
Timeout: migrateTimeout, |
|
|
|
|
}); err != nil { |
|
|
|
|
return repo, fmt.Errorf("Clone: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
wikiRemotePath := wikiRemoteURL(opts.RemoteAddr, gitTimeout) |
|
|
|
|
if wikiRemotePath != "" { |
|
|
|
|
wikiRemotePath := wikiRemoteURL(opts.RemoteAddr) |
|
|
|
|
if len(wikiRemotePath) > 0 { |
|
|
|
|
os.RemoveAll(wikiPath) |
|
|
|
|
if err = git.Clone(wikiRemotePath, wikiPath, git.CloneRepoOptions{ |
|
|
|
|
Mirror: true, |
|
|
|
|
Quiet: true, |
|
|
|
|
Timeout: gitTimeout, |
|
|
|
|
Timeout: migrateTimeout, |
|
|
|
|
}); err != nil { |
|
|
|
|
log.Info("Clone wiki failed: %v", err) |
|
|
|
|
log.Info("Clone wiki: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -797,40 +772,38 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
|
|
|
|
return CleanUpMigrateInfo(repo) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Finish migrating repository with things that don't need to be done for mirrors.
|
|
|
|
|
// cleanUpMigrateGitConfig removes mirror info which prevents "push --all".
|
|
|
|
|
// This also removes possible user credentials.
|
|
|
|
|
func cleanUpMigrateGitConfig(configPath string) error { |
|
|
|
|
cfg, err := ini.Load(configPath) |
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("open config file: %v", err) |
|
|
|
|
} |
|
|
|
|
cfg.DeleteSection("remote \"origin\"") |
|
|
|
|
if err = cfg.SaveToIndent(configPath, "\t"); err != nil { |
|
|
|
|
return fmt.Errorf("save config file: %v", err) |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Finish migrating repository and/or wiki with things that don't need to be done for mirrors.
|
|
|
|
|
func CleanUpMigrateInfo(repo *Repository) (*Repository, error) { |
|
|
|
|
repoPath := repo.RepoPath() |
|
|
|
|
hasWiki := repo.HasWiki() |
|
|
|
|
|
|
|
|
|
if err := createUpdateHook(repoPath); err != nil { |
|
|
|
|
return repo, fmt.Errorf("createUpdateHook: %v", err) |
|
|
|
|
} |
|
|
|
|
if hasWiki { |
|
|
|
|
if err := createUpdateHook(repoPath); err != nil { |
|
|
|
|
return repo, fmt.Errorf("createUpdateHook: %v", err) |
|
|
|
|
if repo.HasWiki() { |
|
|
|
|
if err := createUpdateHook(repo.WikiPath()); err != nil { |
|
|
|
|
return repo, fmt.Errorf("createUpdateHook (wiki): %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Clean up mirror info which prevents "push --all".
|
|
|
|
|
// 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) |
|
|
|
|
} |
|
|
|
|
cfg.DeleteSection("remote \"origin\"") |
|
|
|
|
if err = cfg.SaveToIndent(configPath, "\t"); err != nil { |
|
|
|
|
return repo, fmt.Errorf("save config file: %v", err) |
|
|
|
|
if err := cleanUpMigrateGitConfig(repo.GitConfigPath()); err != nil { |
|
|
|
|
return repo, fmt.Errorf("cleanUpMigrateGitConfig: %v", err) |
|
|
|
|
} |
|
|
|
|
if hasWiki { |
|
|
|
|
wikiConfigPath := filepath.Join(repo.WikiPath(), "config") |
|
|
|
|
cfg, err = ini.Load(wikiConfigPath) |
|
|
|
|
if err != nil { |
|
|
|
|
return repo, fmt.Errorf("open wiki config file: %v", err) |
|
|
|
|
} |
|
|
|
|
cfg.DeleteSection("remote \"origin\"") |
|
|
|
|
if err = cfg.SaveToIndent(wikiConfigPath, "\t"); err != nil { |
|
|
|
|
return repo, fmt.Errorf("save wiki config file: %v", err) |
|
|
|
|
if repo.HasWiki() { |
|
|
|
|
if err := cleanUpMigrateGitConfig(path.Join(repo.WikiPath(), "config")); err != nil { |
|
|
|
|
return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|