| 1261 | } |
| 1262 | |
| 1263 | func mirrorGitRepo(ctx context.Context, srcGitRemote, destGitRemote, srcToken, destToken string) error { |
| 1264 | gitPath, err := os.MkdirTemp(os.TempDir(), "projects") |
| 1265 | if err != nil { |
| 1266 | return err |
| 1267 | } |
| 1268 | defer os.RemoveAll(gitPath) |
| 1269 | |
| 1270 | repo, err := git.PlainCloneContext(ctx, gitPath, false, &git.CloneOptions{ |
| 1271 | URL: srcGitRemote, |
| 1272 | Auth: &githttp.BasicAuth{Username: "x-access-token", Password: srcToken}, |
| 1273 | Mirror: true, |
| 1274 | }) |
| 1275 | if err != nil { |
| 1276 | return fmt.Errorf("failed to clone git repo: %w", err) |
| 1277 | } |
| 1278 | |
| 1279 | _, err = repo.CreateRemote(&config.RemoteConfig{ |
| 1280 | Name: "dest", |
| 1281 | URLs: []string{destGitRemote}, |
| 1282 | }) |
| 1283 | if err != nil { |
| 1284 | return fmt.Errorf("failed to create remote: %w", err) |
| 1285 | } |
| 1286 | |
| 1287 | // Push everything (all refs, like git push --mirror) |
| 1288 | return repo.PushContext(ctx, &git.PushOptions{ |
| 1289 | Auth: &githttp.BasicAuth{Username: "x-access-token", Password: destToken}, |
| 1290 | RemoteName: "dest", |
| 1291 | RefSpecs: []config.RefSpec{ |
| 1292 | "+refs/*:refs/*", // force-push all refs |
| 1293 | }, |
| 1294 | }) |
| 1295 | } |
| 1296 | |
| 1297 | // normalizeGitRemote adds a .git suffix to the Git remote URL if it doesn't already have one. |
| 1298 | // If it's not a Github URL, it returns the string as is. |