mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 01:58:56 +00:00 
			
		
		
		
	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:
		| @@ -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 | ||||
| 		} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user