-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
Add safe pull mirror option to avoid original repository deletion by force-push #19165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5c01fc0
571ef30
4bdb918
1dc838e
a9cd187
a8066a5
d46a5de
93c5f50
724030a
ed8b20f
f602aab
f02d5b3
44e4912
9b40dee
5e16d8a
aaaac62
a7eb9cf
6801ef1
e324609
fff683b
061b46a
e3b10d2
ad9a062
8b7479a
b703f0a
a1cb58f
e68e5c6
0ec287c
8f78236
bf243ee
0bf7a7c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||
| // Use of this source code is governed by a MIT-style | ||
| // license that can be found in the LICENSE file. | ||
|
|
||
| package migrations | ||
|
|
||
| import ( | ||
| "fmt" | ||
|
|
||
| "xorm.io/xorm" | ||
| ) | ||
|
|
||
| func addEnableSafeMirrorColToMirror(x *xorm.Engine) error { | ||
| type Mirror struct { | ||
| EnableSafeMirror bool `xorm:"NOT NULL DEFAULT false"` | ||
| } | ||
|
|
||
| if err := x.Sync2(new(Mirror)); err != nil { | ||
| return fmt.Errorf("Sync2: %v", err) | ||
| } | ||
| return nil | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -695,8 +695,8 @@ last_used=上次使用在 | |
| no_activity=没有最近活动 | ||
| can_read_info=读取 | ||
| can_write_info=写入 | ||
| key_state_desc=7 天内使用过该密钥 | ||
| token_state_desc=7 天内使用过该密钥 | ||
| key_state_desc=7 天内使用过该密钥 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please revert changes to translation file |
||
| token_state_desc=7 天内使用过该密钥 | ||
| principal_state_desc=7 天内使用过该规则 | ||
| show_openid=在个人信息上显示 | ||
| hide_openid=在个人信息上隐藏 | ||
|
|
@@ -878,7 +878,7 @@ watchers=关注者 | |
| stargazers=称赞者 | ||
| forks=派生仓库 | ||
| pick_reaction=选择你的表情 | ||
| reactions_more=再加载 %d | ||
| reactions_more=再加载 %d | ||
| unit_disabled=站点管理员已禁用此仓库单元。 | ||
| language_other=其它 | ||
| adopt_search=输入用户名以搜索未被收录的仓库... (留空以查找全部) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -215,6 +215,19 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo | |
| log.Error("SyncMirrors [repo: %-v]: GetRemoteAddress Error %v", m.Repo, remoteErr) | ||
| } | ||
|
|
||
| if m.EnableSafeMirror { | ||
| // detect can safe mirror | ||
| canUpdate, err := detectCanUpdateMirror(ctx, m, gitArgs) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will be resource intense on huge repos .. e.g. Linux kernel
|
||
| if err != nil { | ||
| log.Error("CheckRepositoryCanSafeMirrorError: %v", err) | ||
| } | ||
| // can not safe mirror | ||
| if !canUpdate { | ||
| log.Error("CheckSyncMirrors [repo: %-v]: cannot sync safe mirror...", m.Repo) | ||
| return nil, false | ||
| } | ||
| } | ||
|
|
||
| stdoutBuilder := strings.Builder{} | ||
| stderrBuilder := strings.Builder{} | ||
| if err := git.NewCommand(ctx, gitArgs...). | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,203 @@ | ||||||||||||||||||||||||||||||||||||||||||
| // Copyright 2019 The Gitea Authors. All rights reserved. | ||||||||||||||||||||||||||||||||||||||||||
| // Use of this source code is governed by a MIT-style | ||||||||||||||||||||||||||||||||||||||||||
| // license that can be found in the LICENSE file. | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| package mirror | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||
| "strconv" | ||||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| admin_model "code.gitea.io/gitea/models/admin" | ||||||||||||||||||||||||||||||||||||||||||
| repo_model "code.gitea.io/gitea/models/repo" | ||||||||||||||||||||||||||||||||||||||||||
| "code.gitea.io/gitea/modules/git" | ||||||||||||||||||||||||||||||||||||||||||
| "code.gitea.io/gitea/modules/log" | ||||||||||||||||||||||||||||||||||||||||||
| "code.gitea.io/gitea/modules/setting" | ||||||||||||||||||||||||||||||||||||||||||
| "code.gitea.io/gitea/modules/util" | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // get git command running stdout and stderr | ||||||||||||||||||||||||||||||||||||||||||
| func getGitCommandStdoutStderr(ctx context.Context, m *repo_model.Mirror, gitArgs []string, newRepoPath string) (string, string, error) { | ||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs a better naming, this sounds like a generic function, but it's specific to a certain action.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And also a better comment, please. |
||||||||||||||||||||||||||||||||||||||||||
| stdoutBuilder := strings.Builder{} | ||||||||||||||||||||||||||||||||||||||||||
| stderrBuilder := strings.Builder{} | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+24
to
+25
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How big can these become? If they can become quite big, it's better to use buffered I/O.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to https://github.com/go-gitea/gitea/pull/19165/files#r833702091 I'd say large. |
||||||||||||||||||||||||||||||||||||||||||
| timeout := time.Duration(setting.Git.Timeout.Mirror) * time.Second | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| remoteAddr, remoteErr := git.GetRemoteAddress(ctx, newRepoPath, m.GetRemoteName()) | ||||||||||||||||||||||||||||||||||||||||||
| if remoteErr != nil { | ||||||||||||||||||||||||||||||||||||||||||
| log.Error("GetMirrorCanUpdate [repo: %-v]: GetRemoteAddress Error %v", m.Repo, remoteErr) | ||||||||||||||||||||||||||||||||||||||||||
| return "", "", remoteErr | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+28
to
+32
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if err := git.NewCommand(ctx, gitArgs...). | ||||||||||||||||||||||||||||||||||||||||||
| SetDescription(fmt.Sprintf("Mirror.getMirrorCanUpdate: %s", m.Repo.FullName())). | ||||||||||||||||||||||||||||||||||||||||||
| RunWithContext(&git.RunContext{ | ||||||||||||||||||||||||||||||||||||||||||
| Timeout: timeout, | ||||||||||||||||||||||||||||||||||||||||||
| Dir: newRepoPath, | ||||||||||||||||||||||||||||||||||||||||||
| Stdout: &stdoutBuilder, | ||||||||||||||||||||||||||||||||||||||||||
| Stderr: &stderrBuilder, | ||||||||||||||||||||||||||||||||||||||||||
| }); err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| stdout := stdoutBuilder.String() | ||||||||||||||||||||||||||||||||||||||||||
| stderr := stderrBuilder.String() | ||||||||||||||||||||||||||||||||||||||||||
| sanitizer := util.NewURLSanitizer(remoteAddr, true) | ||||||||||||||||||||||||||||||||||||||||||
| stderrMessage := sanitizer.Replace(stderr) | ||||||||||||||||||||||||||||||||||||||||||
| stdoutMessage := sanitizer.Replace(stdout) | ||||||||||||||||||||||||||||||||||||||||||
| log.Error("CreateRepositoryNotice: %v", err) | ||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems incorrect here. |
||||||||||||||||||||||||||||||||||||||||||
| log.Error("getGitCommandStdoutStderr [repo: %-v]: failed to check if mirror can be updated:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err) | ||||||||||||||||||||||||||||||||||||||||||
| desc := fmt.Sprintf("Failed to check if mirror '%s' can be updated: %s", newRepoPath, stderrMessage) | ||||||||||||||||||||||||||||||||||||||||||
| if err = admin_model.CreateRepositoryNotice(desc); err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| log.Error("CreateRepositoryNotice: %v", err) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to return here with a error. |
||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| stdoutRepoCommitCount := stdoutBuilder.String() | ||||||||||||||||||||||||||||||||||||||||||
| stderrRepoCommitCount := stdoutBuilder.String() | ||||||||||||||||||||||||||||||||||||||||||
| stderrBuilder.Reset() | ||||||||||||||||||||||||||||||||||||||||||
| stdoutBuilder.Reset() | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return stdoutRepoCommitCount, stderrRepoCommitCount, nil | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // sync new repo mirror | ||||||||||||||||||||||||||||||||||||||||||
| func syncRepoMirror(ctx context.Context, m *repo_model.Mirror, gitArgs []string, newRepoPath string) (bool, error) { | ||||||||||||||||||||||||||||||||||||||||||
| timeout := time.Duration(setting.Git.Timeout.Mirror) * time.Second | ||||||||||||||||||||||||||||||||||||||||||
| remoteAddr, remoteErr := git.GetRemoteAddress(ctx, newRepoPath, m.GetRemoteName()) | ||||||||||||||||||||||||||||||||||||||||||
| if remoteErr != nil { | ||||||||||||||||||||||||||||||||||||||||||
| log.Error("GetMirrorCanUpdate [repo: %-v]: GetRemoteAddress Error %v", m.Repo, remoteErr) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+65
to
+67
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| stdoutBuilder := strings.Builder{} | ||||||||||||||||||||||||||||||||||||||||||
| stderrBuilder := strings.Builder{} | ||||||||||||||||||||||||||||||||||||||||||
| err := git.NewCommand(ctx, gitArgs...). | ||||||||||||||||||||||||||||||||||||||||||
| SetDescription(fmt.Sprintf("Mirror.runSync: %s", m.Repo.FullName())). | ||||||||||||||||||||||||||||||||||||||||||
| RunWithContext(&git.RunContext{ | ||||||||||||||||||||||||||||||||||||||||||
| Timeout: timeout, | ||||||||||||||||||||||||||||||||||||||||||
| Dir: newRepoPath, | ||||||||||||||||||||||||||||||||||||||||||
| Stdout: &stdoutBuilder, | ||||||||||||||||||||||||||||||||||||||||||
| Stderr: &stderrBuilder, | ||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||
| sanitizer := util.NewURLSanitizer(remoteAddr, true) | ||||||||||||||||||||||||||||||||||||||||||
| var stdout, stderr string | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| stdout = stdoutBuilder.String() | ||||||||||||||||||||||||||||||||||||||||||
| stderr = stderrBuilder.String() | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // sanitize the output, since it may contain the remote address, which may | ||||||||||||||||||||||||||||||||||||||||||
| // contain a password | ||||||||||||||||||||||||||||||||||||||||||
| stderrMessage := sanitizer.Replace(stderr) | ||||||||||||||||||||||||||||||||||||||||||
| stdoutMessage := sanitizer.Replace(stdout) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Now check if the error is a resolve reference due to broken reference | ||||||||||||||||||||||||||||||||||||||||||
| if strings.Contains(stderr, "unable to resolve reference") && strings.Contains(stderr, "reference broken") { | ||||||||||||||||||||||||||||||||||||||||||
| log.Warn("SyncMirrors [repo: %-v]: failed to update mirror repository due to broken references:\nStdout: %s\nStderr: %s\nErr: %v\nAttempting Prune", m.Repo, stdoutMessage, stderrMessage, err) | ||||||||||||||||||||||||||||||||||||||||||
| err = nil | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Attempt prune | ||||||||||||||||||||||||||||||||||||||||||
| pruneErr := pruneBrokenReferences(ctx, m, newRepoPath, timeout, &stdoutBuilder, &stderrBuilder, sanitizer, false) | ||||||||||||||||||||||||||||||||||||||||||
| if pruneErr == nil { | ||||||||||||||||||||||||||||||||||||||||||
| // Successful prune - reattempt mirror | ||||||||||||||||||||||||||||||||||||||||||
| stderrBuilder.Reset() | ||||||||||||||||||||||||||||||||||||||||||
| stdoutBuilder.Reset() | ||||||||||||||||||||||||||||||||||||||||||
| if err = git.NewCommand(ctx, gitArgs...). | ||||||||||||||||||||||||||||||||||||||||||
| SetDescription(fmt.Sprintf("Mirror.runSync: %s", m.Repo.FullName())). | ||||||||||||||||||||||||||||||||||||||||||
| RunWithContext(&git.RunContext{ | ||||||||||||||||||||||||||||||||||||||||||
| Timeout: timeout, | ||||||||||||||||||||||||||||||||||||||||||
| Dir: newRepoPath, | ||||||||||||||||||||||||||||||||||||||||||
| Stdout: &stdoutBuilder, | ||||||||||||||||||||||||||||||||||||||||||
| Stderr: &stderrBuilder, | ||||||||||||||||||||||||||||||||||||||||||
| }); err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| stdout := stdoutBuilder.String() | ||||||||||||||||||||||||||||||||||||||||||
| stderr := stderrBuilder.String() | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // sanitize the output, since it may contain the remote address, which may | ||||||||||||||||||||||||||||||||||||||||||
| // contain a password | ||||||||||||||||||||||||||||||||||||||||||
| stderrMessage = sanitizer.Replace(stderr) | ||||||||||||||||||||||||||||||||||||||||||
| stdoutMessage = sanitizer.Replace(stdout) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // If there is still an error (or there always was an error) | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| log.Error("SyncMirrors [repo: %-v]: failed to update mirror repository:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err) | ||||||||||||||||||||||||||||||||||||||||||
| desc := fmt.Sprintf("Failed to update mirror repository '%s': %s", newRepoPath, stderrMessage) | ||||||||||||||||||||||||||||||||||||||||||
| if err = admin_model.CreateRepositoryNotice(desc); err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| log.Error("CreateRepositoryNotice: %v", err) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| return false, nil | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| return false, nil | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // detect user can update the mirror | ||||||||||||||||||||||||||||||||||||||||||
| func detectCanUpdateMirror(ctx context.Context, m *repo_model.Mirror, gitArgs []string) (bool, error) { | ||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function needs some more comments in order to not have a 10 minutes hard time understanding how this function is achieving it's "detection method". |
||||||||||||||||||||||||||||||||||||||||||
| repoPath := m.Repo.RepoPath() | ||||||||||||||||||||||||||||||||||||||||||
| newRepoPath := fmt.Sprintf("%s_update", repoPath) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // do copy directory recursive | ||||||||||||||||||||||||||||||||||||||||||
| err := util.CopyDir(repoPath, newRepoPath) | ||||||||||||||||||||||||||||||||||||||||||
| defer func() { | ||||||||||||||||||||||||||||||||||||||||||
| // delete the temp directory | ||||||||||||||||||||||||||||||||||||||||||
| errDelete := util.RemoveAll(newRepoPath) | ||||||||||||||||||||||||||||||||||||||||||
| if errDelete != nil { | ||||||||||||||||||||||||||||||||||||||||||
| log.Error("DeleteRepositoryTempDirectoryError: %v", errDelete) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| }() | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| log.Error("GetMirrorCanUpdate [repo: %-v]: CopyDirectory Error %v", m.Repo, err) | ||||||||||||||||||||||||||||||||||||||||||
| return false, err | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| syncStatus, err := syncRepoMirror(ctx, m, gitArgs, newRepoPath) | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| return false, err | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| if !syncStatus { | ||||||||||||||||||||||||||||||||||||||||||
| return false, nil | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| gitCommitCountArgs := []string{"rev-list", "HEAD", "--count"} | ||||||||||||||||||||||||||||||||||||||||||
| stdoutNewRepoCommitCount, _, err := getGitCommandStdoutStderr(ctx, m, gitCommitCountArgs, newRepoPath) | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| return false, err | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| stdoutNewRepoCommitCount = strings.TrimSpace(stdoutNewRepoCommitCount) | ||||||||||||||||||||||||||||||||||||||||||
| stdoutRepoCommitCount, _, err := getGitCommandStdoutStderr(ctx, m, gitCommitCountArgs, repoPath) | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| return false, err | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| stdoutRepoCommitCount = strings.TrimSpace(stdoutRepoCommitCount) | ||||||||||||||||||||||||||||||||||||||||||
| var repoCommitCount, newRepoCommitCount int64 | ||||||||||||||||||||||||||||||||||||||||||
| if i, err := strconv.ParseInt(stdoutRepoCommitCount, 10, 64); err == nil { | ||||||||||||||||||||||||||||||||||||||||||
| repoCommitCount = i | ||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||
| return false, err | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| if i, err := strconv.ParseInt(stdoutNewRepoCommitCount, 10, 64); err == nil { | ||||||||||||||||||||||||||||||||||||||||||
| newRepoCommitCount = i | ||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||
| return false, err | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| if repoCommitCount > newRepoCommitCount { | ||||||||||||||||||||||||||||||||||||||||||
| return false, nil | ||||||||||||||||||||||||||||||||||||||||||
| } else if repoCommitCount == newRepoCommitCount { | ||||||||||||||||||||||||||||||||||||||||||
| // noting to happen | ||||||||||||||||||||||||||||||||||||||||||
| return true, nil | ||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||
| // compare commit id | ||||||||||||||||||||||||||||||||||||||||||
| skipcout := newRepoCommitCount - repoCommitCount | ||||||||||||||||||||||||||||||||||||||||||
| gitNewRepoLastCommitIDArgs := []string{"log", "-1", fmt.Sprintf("--skip=%d", skipcout), "--format='%H'"} | ||||||||||||||||||||||||||||||||||||||||||
| stdoutNewRepoCommitID, _, err := getGitCommandStdoutStderr(ctx, m, gitNewRepoLastCommitIDArgs, newRepoPath) | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| return false, err | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| gitRepoLastCommitIDArgs := []string{"log", "--format='%H'", "-n", "1"} | ||||||||||||||||||||||||||||||||||||||||||
| stdoutRepoCommitID, _, err := getGitCommandStdoutStderr(ctx, m, gitRepoLastCommitIDArgs, repoPath) | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| return false, err | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| if stdoutNewRepoCommitID != stdoutRepoCommitID { | ||||||||||||||||||||||||||||||||||||||||||
| return false, fmt.Errorf("Old repo commit id: %s not match new repo id: %s", stdoutRepoCommitID, stdoutNewRepoCommitID) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| return true, nil | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+180
to
+202
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just for the sake of understanding here, it's more or less trying to detect if a force-push has happen on the upstream's repo?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is the purpose. However, I think copying the repo again and again is not ideal. A better solution could be: track all branches locally, fetch remote, compare the merge-base, if the merge-base is not the locally tracked one, then there is a force-push. And there might be other better solutions, but copying the repo is not the proper way.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep, I'm also looking for an ideal solution to figure out this sitution.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you seem my option with the reference-transaction hook ? #14076 (comment) |
||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.