forked from forgejo/forgejo
Use the type RefName for all the needed places and fix pull mirror sync bugs (#24634)
This PR replaces all string refName as a type `git.RefName` to make the code more maintainable. Fix #15367 Replaces #23070 It also fixed a bug that tags are not sync because `git remote --prune origin` will not remove local tags if remote removed. We in fact should use `git fetch --prune --tags origin` but not `git remote update origin` to do the sync. Some answer from ChatGPT as ref. > If the git fetch --prune --tags command is not working as expected, there could be a few reasons why. Here are a few things to check: > >Make sure that you have the latest version of Git installed on your system. You can check the version by running git --version in your terminal. If you have an outdated version, try updating Git and see if that resolves the issue. > >Check that your Git repository is properly configured to track the remote repository's tags. You can check this by running git config --get-all remote.origin.fetch and verifying that it includes +refs/tags/*:refs/tags/*. If it does not, you can add it by running git config --add remote.origin.fetch "+refs/tags/*:refs/tags/*". > >Verify that the tags you are trying to prune actually exist on the remote repository. You can do this by running git ls-remote --tags origin to list all the tags on the remote repository. > >Check if any local tags have been created that match the names of tags on the remote repository. If so, these local tags may be preventing the git fetch --prune --tags command from working properly. You can delete local tags using the git tag -d command. --------- Co-authored-by: delvh <dev.lh@web.de>
This commit is contained in:
parent
26fa94bc25
commit
f9cfd6ce5b
41 changed files with 415 additions and 355 deletions
|
@ -78,13 +78,23 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
|
|||
// If the oldCommitID is "0000000", it means a new reference, the value of newCommitID is empty.
|
||||
// If the newCommitID is "0000000", it means the reference is deleted, the value of oldCommitID is empty.
|
||||
type mirrorSyncResult struct {
|
||||
refName string
|
||||
refName git.RefName
|
||||
oldCommitID string
|
||||
newCommitID string
|
||||
}
|
||||
|
||||
// parseRemoteUpdateOutput detects create, update and delete operations of references from upstream.
|
||||
func parseRemoteUpdateOutput(output string) []*mirrorSyncResult {
|
||||
// possible output example:
|
||||
/*
|
||||
// * [new tag] v0.1.8 -> v0.1.8
|
||||
// * [new branch] master -> origin/master
|
||||
// - [deleted] (none) -> origin/test // delete a branch
|
||||
// - [deleted] (none) -> 1 // delete a tag
|
||||
// 957a993..a87ba5f test -> origin/test
|
||||
// + f895a1e...957a993 test -> origin/test (forced update)
|
||||
*/
|
||||
// TODO: return whether it's a force update
|
||||
func parseRemoteUpdateOutput(output, remoteName string) []*mirrorSyncResult {
|
||||
results := make([]*mirrorSyncResult, 0, 3)
|
||||
lines := strings.Split(output, "\n")
|
||||
for i := range lines {
|
||||
|
@ -94,22 +104,30 @@ func parseRemoteUpdateOutput(output string) []*mirrorSyncResult {
|
|||
continue
|
||||
}
|
||||
|
||||
refName := lines[i][idx+3:]
|
||||
refName := strings.TrimSpace(lines[i][idx+3:])
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(lines[i], " * "): // New reference
|
||||
if strings.HasPrefix(lines[i], " * [new tag]") {
|
||||
refName = git.TagPrefix + refName
|
||||
} else if strings.HasPrefix(lines[i], " * [new branch]") {
|
||||
refName = git.BranchPrefix + refName
|
||||
}
|
||||
case strings.HasPrefix(lines[i], " * [new tag]"): // new tag
|
||||
results = append(results, &mirrorSyncResult{
|
||||
refName: refName,
|
||||
refName: git.RefNameFromTag(refName),
|
||||
oldCommitID: gitShortEmptySha,
|
||||
})
|
||||
case strings.HasPrefix(lines[i], " * [new branch]"): // new branch
|
||||
refName = strings.TrimPrefix(refName, remoteName+"/")
|
||||
results = append(results, &mirrorSyncResult{
|
||||
refName: git.RefNameFromBranch(refName),
|
||||
oldCommitID: gitShortEmptySha,
|
||||
})
|
||||
case strings.HasPrefix(lines[i], " - "): // Delete reference
|
||||
isTag := !strings.HasPrefix(refName, remoteName+"/")
|
||||
var refFullName git.RefName
|
||||
if isTag {
|
||||
refFullName = git.RefNameFromTag(refName)
|
||||
} else {
|
||||
refFullName = git.RefNameFromBranch(strings.TrimPrefix(refName, remoteName+"/"))
|
||||
}
|
||||
results = append(results, &mirrorSyncResult{
|
||||
refName: refName,
|
||||
refName: refFullName,
|
||||
newCommitID: gitShortEmptySha,
|
||||
})
|
||||
case strings.HasPrefix(lines[i], " + "): // Force update
|
||||
|
@ -127,7 +145,7 @@ func parseRemoteUpdateOutput(output string) []*mirrorSyncResult {
|
|||
continue
|
||||
}
|
||||
results = append(results, &mirrorSyncResult{
|
||||
refName: refName,
|
||||
refName: git.RefNameFromBranch(strings.TrimPrefix(refName, remoteName+"/")),
|
||||
oldCommitID: shas[0],
|
||||
newCommitID: shas[1],
|
||||
})
|
||||
|
@ -143,7 +161,7 @@ func parseRemoteUpdateOutput(output string) []*mirrorSyncResult {
|
|||
continue
|
||||
}
|
||||
results = append(results, &mirrorSyncResult{
|
||||
refName: refName,
|
||||
refName: git.RefNameFromBranch(strings.TrimPrefix(refName, remoteName+"/")),
|
||||
oldCommitID: shas[0],
|
||||
newCommitID: shas[1],
|
||||
})
|
||||
|
@ -204,11 +222,12 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
|
|||
|
||||
log.Trace("SyncMirrors [repo: %-v]: running git remote update...", m.Repo)
|
||||
|
||||
cmd := git.NewCommand(ctx, "remote", "update")
|
||||
// use fetch but not remote update because git fetch support --tags but remote update doesn't
|
||||
cmd := git.NewCommand(ctx, "fetch")
|
||||
if m.EnablePrune {
|
||||
cmd.AddArguments("--prune")
|
||||
}
|
||||
cmd.AddDynamicArguments(m.GetRemoteName())
|
||||
cmd.AddArguments("--tags").AddDynamicArguments(m.GetRemoteName())
|
||||
|
||||
remoteURL, remoteErr := git.GetRemoteURL(ctx, repoPath, m.GetRemoteName())
|
||||
if remoteErr != nil {
|
||||
|
@ -384,7 +403,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
|
|||
}
|
||||
|
||||
m.UpdatedUnix = timeutil.TimeStampNow()
|
||||
return parseRemoteUpdateOutput(output), true
|
||||
return parseRemoteUpdateOutput(output, m.GetRemoteName()), true
|
||||
}
|
||||
|
||||
// SyncPullMirror starts the sync of the pull mirror and schedules the next run.
|
||||
|
@ -444,20 +463,13 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
|
|||
|
||||
for _, result := range results {
|
||||
// Discard GitHub pull requests, i.e. refs/pull/*
|
||||
if strings.HasPrefix(result.refName, git.PullPrefix) {
|
||||
if result.refName.IsPull() {
|
||||
continue
|
||||
}
|
||||
|
||||
tp, _ := git.SplitRefName(result.refName)
|
||||
|
||||
// Create reference
|
||||
if result.oldCommitID == gitShortEmptySha {
|
||||
if tp == git.TagPrefix {
|
||||
tp = "tag"
|
||||
} else if tp == git.BranchPrefix {
|
||||
tp = "branch"
|
||||
}
|
||||
commitID, err := gitRepo.GetRefCommitID(result.refName)
|
||||
commitID, err := gitRepo.GetRefCommitID(result.refName.String())
|
||||
if err != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: unable to GetRefCommitID [ref_name: %s]: %v", m.Repo, result.refName, err)
|
||||
continue
|
||||
|
@ -467,13 +479,13 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
|
|||
OldCommitID: git.EmptySHA,
|
||||
NewCommitID: commitID,
|
||||
}, repo_module.NewPushCommits())
|
||||
notification.NotifySyncCreateRef(ctx, m.Repo.MustOwner(ctx), m.Repo, tp, result.refName, commitID)
|
||||
notification.NotifySyncCreateRef(ctx, m.Repo.MustOwner(ctx), m.Repo, result.refName, commitID)
|
||||
continue
|
||||
}
|
||||
|
||||
// Delete reference
|
||||
if result.newCommitID == gitShortEmptySha {
|
||||
notification.NotifySyncDeleteRef(ctx, m.Repo.MustOwner(ctx), m.Repo, tp, result.refName)
|
||||
notification.NotifySyncDeleteRef(ctx, m.Repo.MustOwner(ctx), m.Repo, result.refName)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -547,13 +559,11 @@ func checkAndUpdateEmptyRepository(m *repo_model.Mirror, gitRepo *git.Repository
|
|||
}
|
||||
firstName := ""
|
||||
for _, result := range results {
|
||||
if strings.HasPrefix(result.refName, git.PullPrefix) {
|
||||
continue
|
||||
}
|
||||
tp, name := git.SplitRefName(result.refName)
|
||||
if len(tp) > 0 && tp != git.BranchPrefix {
|
||||
if !result.refName.IsBranch() {
|
||||
continue
|
||||
}
|
||||
|
||||
name := result.refName.BranchName()
|
||||
if len(firstName) == 0 {
|
||||
firstName = name
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue