Skip to content

Commit 2da63a4

Browse files
committed
as per wxiaoguang
Signed-off-by: Andrew Thornton <[email protected]>
1 parent 2d2f32d commit 2da63a4

File tree

1 file changed

+67
-53
lines changed

1 file changed

+67
-53
lines changed

services/mirror/mirror_pull.go

Lines changed: 67 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,43 @@ func parseRemoteUpdateOutput(output string) []*mirrorSyncResult {
140140
return results
141141
}
142142

143+
func pruneBrokenReferences(ctx context.Context,
144+
m *models.Mirror,
145+
repoPath string,
146+
timeout time.Duration,
147+
stdoutBuilder, stderrBuilder *strings.Builder,
148+
sanitizer *strings.Replacer,
149+
isWiki bool) error {
150+
151+
wiki := ""
152+
if isWiki {
153+
wiki = "Wiki "
154+
}
155+
156+
stderrBuilder.Reset()
157+
stdoutBuilder.Reset()
158+
pruneErr := git.NewCommandContext(ctx, "remote", "prune", m.GetRemoteName()).
159+
SetDescription(fmt.Sprintf("Mirror.runSync %ssPrune references: %s ", wiki, m.Repo.FullName())).
160+
RunInDirTimeoutPipeline(timeout, repoPath, stdoutBuilder, stderrBuilder)
161+
if pruneErr != nil {
162+
stdout := stdoutBuilder.String()
163+
stderr := stderrBuilder.String()
164+
165+
// sanitize the output, since it may contain the remote address, which may
166+
// contain a password
167+
stderrMessage := sanitizer.Replace(stderr)
168+
stdoutMessage := sanitizer.Replace(stdout)
169+
170+
log.Error("Failed to prune mirror repository %s%-v references:\nStdout: %s\nStderr: %s\nErr: %v", wiki, m.Repo, stdoutMessage, stderrMessage, pruneErr)
171+
desc := fmt.Sprintf("Failed to prune mirror repository %s'%s' references: %s", wiki, repoPath, stderrMessage)
172+
if err := models.CreateRepositoryNotice(desc); err != nil {
173+
log.Error("CreateRepositoryNotice: %v", err)
174+
}
175+
// this if will only be reached on a successful prune so try to get the mirror again
176+
}
177+
return pruneErr
178+
}
179+
143180
// runSync returns true if sync finished without error.
144181
func runSync(ctx context.Context, m *models.Mirror) ([]*mirrorSyncResult, bool) {
145182
repoPath := m.Repo.RepoPath()
@@ -160,7 +197,7 @@ func runSync(ctx context.Context, m *models.Mirror) ([]*mirrorSyncResult, bool)
160197

161198
stdoutBuilder := strings.Builder{}
162199
stderrBuilder := strings.Builder{}
163-
if err := git.NewCommand(gitArgs...).
200+
if err := git.NewCommandContext(ctx, gitArgs...).
164201
SetDescription(fmt.Sprintf("Mirror.runSync: %s", m.Repo.FullName())).
165202
RunInDirTimeoutPipeline(timeout, repoPath, &stdoutBuilder, &stderrBuilder); err != nil {
166203
stdout := stdoutBuilder.String()
@@ -178,35 +215,22 @@ func runSync(ctx context.Context, m *models.Mirror) ([]*mirrorSyncResult, bool)
178215
err = nil
179216

180217
// Attempt prune
181-
stderrBuilder.Reset()
182-
stdoutBuilder.Reset()
183-
if pruneErr := git.NewCommand("remote", "prune", m.GetRemoteName()).
184-
SetDescription(fmt.Sprintf("Mirror.runSync Prune references: %s ", m.Repo.FullName())).
185-
RunInDirTimeoutPipeline(timeout, repoPath, &stdoutBuilder, &stderrBuilder); pruneErr != nil {
186-
stdout := stdoutBuilder.String()
187-
stderr := stderrBuilder.String()
188-
189-
// sanitize the output, since it may contain the remote address, which may
190-
// contain a password
191-
stderrMessage := sanitizer.Replace(stderr)
192-
stdoutMessage := sanitizer.Replace(stdout)
193-
194-
log.Error("Failed to prune mirror repository %-v references:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, pruneErr)
195-
desc := fmt.Sprintf("Failed to prune mirror repository '%s' references: %s", repoPath, stderrMessage)
196-
if err := models.CreateRepositoryNotice(desc); err != nil {
197-
log.Error("CreateRepositoryNotice: %v", err)
218+
pruneErr := pruneBrokenReferences(ctx, m, repoPath, timeout, &stdoutBuilder, &stderrBuilder, sanitizer, false)
219+
if pruneErr == nil {
220+
// Successful prune - reattempt mirror
221+
stderrBuilder.Reset()
222+
stdoutBuilder.Reset()
223+
if err = git.NewCommandContext(ctx, gitArgs...).
224+
SetDescription(fmt.Sprintf("Mirror.runSync: %s", m.Repo.FullName())).
225+
RunInDirTimeoutPipeline(timeout, repoPath, &stdoutBuilder, &stderrBuilder); err != nil {
226+
stdout := stdoutBuilder.String()
227+
stderr := stderrBuilder.String()
228+
229+
// sanitize the output, since it may contain the remote address, which may
230+
// contain a password
231+
stderrMessage = sanitizer.Replace(stderr)
232+
stdoutMessage = sanitizer.Replace(stdout)
198233
}
199-
// this if will only be reached on a successful prune so try to get the mirror again
200-
} else if err = git.NewCommand(gitArgs...).
201-
SetDescription(fmt.Sprintf("Mirror.runSync: %s", m.Repo.FullName())).
202-
RunInDirTimeoutPipeline(timeout, repoPath, &stdoutBuilder, &stderrBuilder); err != nil {
203-
stdout := stdoutBuilder.String()
204-
stderr := stderrBuilder.String()
205-
206-
// sanitize the output, since it may contain the remote address, which may
207-
// contain a password
208-
stderrMessage = sanitizer.Replace(stderr)
209-
stdoutMessage = sanitizer.Replace(stdout)
210234
}
211235
}
212236

@@ -251,7 +275,7 @@ func runSync(ctx context.Context, m *models.Mirror) ([]*mirrorSyncResult, bool)
251275
log.Trace("SyncMirrors [repo: %-v Wiki]: running git remote update...", m.Repo)
252276
stderrBuilder.Reset()
253277
stdoutBuilder.Reset()
254-
if err := git.NewCommand("remote", "update", "--prune", m.GetRemoteName()).
278+
if err := git.NewCommandContext(ctx, "remote", "update", "--prune", m.GetRemoteName()).
255279
SetDescription(fmt.Sprintf("Mirror.runSync Wiki: %s ", m.Repo.FullName())).
256280
RunInDirTimeoutPipeline(timeout, wikiPath, &stdoutBuilder, &stderrBuilder); err != nil {
257281
stdout := stdoutBuilder.String()
@@ -277,30 +301,20 @@ func runSync(ctx context.Context, m *models.Mirror) ([]*mirrorSyncResult, bool)
277301
err = nil
278302

279303
// Attempt prune
280-
stderrBuilder.Reset()
281-
stdoutBuilder.Reset()
282-
if err := git.NewCommand("remote", "prune", m.GetRemoteName()).
283-
SetDescription(fmt.Sprintf("Mirror.runSync Prune Wiki references: %s ", m.Repo.FullName())).
284-
RunInDirTimeoutPipeline(timeout, wikiPath, &stdoutBuilder, &stderrBuilder); err != nil {
285-
stdout := stdoutBuilder.String()
286-
stderr := stderrBuilder.String()
287-
288-
stderrMessage := sanitizer.Replace(stderr)
289-
stdoutMessage := sanitizer.Replace(stdout)
290-
291-
log.Error("Failed to prune mirror repository wiki %-v references:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err)
292-
desc := fmt.Sprintf("Failed to prune mirror repository wiki '%s' references: %s", wikiPath, stderrMessage)
293-
if err = models.CreateRepositoryNotice(desc); err != nil {
294-
log.Error("CreateRepositoryNotice: %v", err)
304+
pruneErr := pruneBrokenReferences(ctx, m, repoPath, timeout, &stdoutBuilder, &stderrBuilder, sanitizer, true)
305+
if pruneErr == nil {
306+
// Successful prune - reattempt mirror
307+
stderrBuilder.Reset()
308+
stdoutBuilder.Reset()
309+
310+
if err = git.NewCommandContext(ctx, "remote", "update", "--prune", m.GetRemoteName()).
311+
SetDescription(fmt.Sprintf("Mirror.runSync Wiki: %s ", m.Repo.FullName())).
312+
RunInDirTimeoutPipeline(timeout, wikiPath, &stdoutBuilder, &stderrBuilder); err != nil {
313+
stdout := stdoutBuilder.String()
314+
stderr := stderrBuilder.String()
315+
stderrMessage = sanitizer.Replace(stderr)
316+
stdoutMessage = sanitizer.Replace(stdout)
295317
}
296-
// this if will only be reached on a successful prune so try to get the mirror again
297-
} else if err = git.NewCommand("remote", "update", "--prune", m.GetRemoteName()).
298-
SetDescription(fmt.Sprintf("Mirror.runSync Wiki: %s ", m.Repo.FullName())).
299-
RunInDirTimeoutPipeline(timeout, wikiPath, &stdoutBuilder, &stderrBuilder); err != nil {
300-
stdout := stdoutBuilder.String()
301-
stderr := stderrBuilder.String()
302-
stderrMessage = sanitizer.Replace(stderr)
303-
stdoutMessage = sanitizer.Replace(stdout)
304318
}
305319
}
306320

0 commit comments

Comments
 (0)