Skip to content

Commit 6167187

Browse files
committed
Support git --push-option in order to use copybara with GitLab
1 parent c87115e commit 6167187

File tree

8 files changed

+73
-13
lines changed

8 files changed

+73
-13
lines changed

docs/reference.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2202,7 +2202,7 @@ Name | Type | Description
22022202

22032203
Creates a commit in a git repository using the transformed worktree.<br><br>For GitHub use git.github_destination. For creating Pull Requests in GitHub, use git.github_pr_destination. For creating a Gerrit change use git.gerrit_destination.<br><br>Given that Copybara doesn't ask for user/password in the console when doing the push to remote repos, you have to use ssh protocol, have the credentials cached or use a credential manager.
22042204

2205-
`destination` `git.destination(url, push='master', tag_name=None, tag_msg=None, fetch=None, partial_fetch=False, integrates=None, primary_branch_migration=False, checker=None)`
2205+
`destination` `git.destination(url, push='master', tag_name=None, tag_msg=None, fetch=None, partial_fetch=False, integrates=None, primary_branch_migration=False, checker=None, push_options=None)`
22062206

22072207

22082208
#### Parameters:
@@ -2218,6 +2218,7 @@ partial_fetch | `bool`<br><p>This is an experimental feature that only works for
22182218
integrates | `sequence of git_integrate` or `NoneType`<br><p>Integrate changes from a url present in the migrated change label. Defaults to a semi-fake merge if COPYBARA_INTEGRATE_REVIEW label is present in the message</p>
22192219
primary_branch_migration | `bool`<br><p>When enabled, copybara will ignore the 'push' and 'fetch' params if either is 'master' or 'main' and instead try to establish the default git branch. If this fails, it will fall back to the param's declared value.<br>This is intended to help migrating to the new standard of using 'main' without breaking users relying on the legacy default.</p>
22202220
checker | `checker` or `NoneType`<br><p>A checker that can check leaks or other checks in the commit created. </p>
2221+
push_options | `sequence` or `NoneType`<br><p>A sequence of git push options that can pass into push command. Defaults to none which represents no push options.</p>
22212222

22222223

22232224

java/com/google/copybara/git/GerritDestination.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,8 @@ static GerritDestination newGerritDestination(
615615
gerritSubmit,
616616
primaryBranchMigrationMode),
617617
integrates,
618-
checker),
618+
checker,
619+
ImmutableList.of()),
619620
submit);
620621
}
621622

java/com/google/copybara/git/GitDestination.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ static class MessageInfo {
110110
@Nullable private String resolvedPrimary = null;
111111
private final Iterable<GitIntegrateChanges> integrates;
112112
private final WriteHook writerHook;
113+
private final Iterable<String> pushOptions;
113114
@Nullable private final Checker checker;
114115
private final LazyResourceLoader<GitRepository> localRepo;
115116

@@ -126,7 +127,8 @@ static class MessageInfo {
126127
GeneralOptions generalOptions,
127128
WriteHook writerHook,
128129
Iterable<GitIntegrateChanges> integrates,
129-
@Nullable Checker checker) {
130+
@Nullable Checker checker,
131+
Iterable<String> pushOptions) {
130132
this.repoUrl = checkNotNull(repoUrl);
131133
this.fetch = checkNotNull(fetch);
132134
this.push = checkNotNull(push);
@@ -140,6 +142,7 @@ static class MessageInfo {
140142
this.integrates = checkNotNull(integrates);
141143
this.writerHook = checkNotNull(writerHook);
142144
this.checker = checker;
145+
this.pushOptions = checkNotNull(pushOptions);
143146
this.localRepo = memoized(ignored -> destinationOptions.localGitRepo(repoUrl));
144147
}
145148

@@ -191,7 +194,8 @@ public Writer<GitRevision> newWriter(WriterContext writerContext) throws Validat
191194
destinationOptions.rebaseWhenBaseline(),
192195
gitOptions.visitChangePageSize,
193196
gitOptions.gitTagOverwrite,
194-
checker);
197+
checker,
198+
pushOptions);
195199
}
196200

197201
/**
@@ -242,6 +246,7 @@ public static class WriterImpl<S extends WriterState>
242246
private final int visitChangePageSize;
243247
private final boolean gitTagOverwrite;
244248
@Nullable private final Checker checker;
249+
private final Iterable<String> pushOptions;
245250

246251
/** Create a new git.destination writer */
247252
WriterImpl(
@@ -265,7 +270,8 @@ public static class WriterImpl<S extends WriterState>
265270
boolean rebase,
266271
int visitChangePageSize,
267272
boolean gitTagOverwrite,
268-
Checker checker) {
273+
Checker checker,
274+
Iterable<String> pushOptions) {
269275
this.skipPush = skipPush;
270276
this.repoUrl = checkNotNull(repoUrl);
271277
this.remoteFetch = checkNotNull(remoteFetch);
@@ -289,6 +295,7 @@ public static class WriterImpl<S extends WriterState>
289295
this.visitChangePageSize = visitChangePageSize;
290296
this.gitTagOverwrite = gitTagOverwrite;
291297
this.checker = checker;
298+
this.pushOptions = pushOptions;
292299
}
293300

294301
@Override
@@ -659,6 +666,7 @@ public ImmutableList<DestinationEffect> write(TransformResult transformResult,
659666
String serverResponse = generalOptions.repoTask(
660667
"push",
661668
() -> scratchClone.push()
669+
.pushOptions(pushOptions)
662670
.withRefspecs(repoUrl,
663671
tagName != null
664672
? ImmutableList.of(scratchClone.createRefSpec(

java/com/google/copybara/git/GitHubPrDestination.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ public Writer<GitRevision> newWriter(WriterContext writerContext) throws Validat
191191
destinationOptions.rebaseWhenBaseline(),
192192
gitOptions.visitChangePageSize,
193193
gitOptions.gitTagOverwrite,
194-
checker) {
194+
checker,
195+
ImmutableList.of()) {
195196
@Override
196197
public ImmutableList<DestinationEffect> write(
197198
TransformResult transformResult, Glob destinationFiles, Console console)

java/com/google/copybara/git/GitModule.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,16 @@ private boolean convertDescribeVersion(Object describeVersion) {
13391339
doc = "A checker that can check leaks or other checks in the commit created. ",
13401340
named = true,
13411341
positional = false),
1342+
@Param(
1343+
name = "push_options",
1344+
allowedTypes = {
1345+
@ParamType(type = Sequence.class),
1346+
@ParamType(type = NoneType.class),
1347+
},
1348+
defaultValue = "None",
1349+
doc = "A sequence of git push options that can pass into push command. Defaults to none which represents no push options.",
1350+
named = true,
1351+
positional = false),
13421352
},
13431353
useStarlarkThread = true)
13441354
@UsesFlags(GitDestinationOptions.class)
@@ -1352,6 +1362,7 @@ public GitDestination destination(
13521362
Object integrates,
13531363
Boolean primaryBranchMigration,
13541364
Object checker,
1365+
Object pushOptions,
13551366
StarlarkThread thread)
13561367
throws EvalException {
13571368
GitDestinationOptions destinationOptions = options.get(GitDestinationOptions.class);
@@ -1365,6 +1376,9 @@ public GitDestination destination(
13651376
"Skipping git checker for git.destination. Note that this could"
13661377
+ " cause leaks or other problems");
13671378
}
1379+
Iterable<String> resolvedPushOptions = Starlark.isNullOrNone(pushOptions)
1380+
? ImmutableList.of()
1381+
: Sequence.cast(pushOptions, String.class, "push_options");
13681382
return new GitDestination(
13691383
fixHttp(
13701384
checkNotEmpty(firstNotNull(destinationOptions.url, url), "url"),
@@ -1384,7 +1398,8 @@ public GitDestination destination(
13841398
Starlark.isNullOrNone(integrates)
13851399
? defaultGitIntegrate
13861400
: Sequence.cast(integrates, GitIntegrateChanges.class, "integrates"),
1387-
maybeChecker);
1401+
maybeChecker,
1402+
resolvedPushOptions);
13881403
}
13891404

13901405
@SuppressWarnings("unused")
@@ -1612,7 +1627,8 @@ public GitDestination gitHubDestination(
16121627
Starlark.isNullOrNone(integrates)
16131628
? defaultGitIntegrate
16141629
: Sequence.cast(integrates, GitIntegrateChanges.class, "integrates"),
1615-
checkerObj);
1630+
checkerObj,
1631+
ImmutableList.of());
16161632
}
16171633

16181634
@SuppressWarnings("unused")

java/com/google/copybara/git/GitRepository.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ public LogCmd log(String referenceExpr) {
442442

443443
@CheckReturnValue
444444
public PushCmd push() {
445-
return new PushCmd(this, /*url=*/null, ImmutableList.of(), /*prune=*/false);
445+
return new PushCmd(this, /*url=*/null, ImmutableList.of(), /*prune=*/false, ImmutableList.of());
446446
}
447447

448448
@CheckReturnValue
@@ -678,6 +678,12 @@ protected String runPush(PushCmd pushCmd) throws RepoException, ValidationExcept
678678
cmd.add("--no-verify");
679679
}
680680

681+
if(!pushCmd.pushOptions.isEmpty()) {
682+
for(String option : pushCmd.pushOptions) {
683+
cmd.add("--push-option=" + option);
684+
}
685+
}
686+
681687
if (pushCmd.url != null) {
682688
cmd.add(validateUrl(pushCmd.url));
683689
for (Refspec refspec : pushCmd.refspecs) {
@@ -1887,6 +1893,8 @@ public static class PushCmd {
18871893
private final ImmutableList<Refspec> refspecs;
18881894
private final boolean prune;
18891895

1896+
private final ImmutableList<String> pushOptions;
1897+
18901898
@Nullable
18911899
public String getUrl() {
18921900
return url;
@@ -1903,24 +1911,30 @@ public boolean isPrune() {
19031911

19041912
@CheckReturnValue
19051913
public PushCmd(GitRepository repo, @Nullable String url, ImmutableList<Refspec> refspecs,
1906-
boolean prune) {
1914+
boolean prune, ImmutableList<String> pushOptions) {
19071915
this.repo = checkNotNull(repo);
19081916
this.url = url;
19091917
this.refspecs = checkNotNull(refspecs);
19101918
Preconditions.checkArgument(refspecs.isEmpty() || url != null, "refspec can only be"
19111919
+ " used when a url is passed");
19121920
this.prune = prune;
1921+
this.pushOptions = pushOptions;
19131922
}
19141923

19151924
@CheckReturnValue
19161925
public PushCmd withRefspecs(String url, Iterable<Refspec> refspecs) {
19171926
return new PushCmd(repo, checkNotNull(url), ImmutableList.copyOf(refspecs),
1918-
prune);
1927+
prune, pushOptions);
19191928
}
19201929

19211930
@CheckReturnValue
19221931
public PushCmd prune(boolean prune) {
1923-
return new PushCmd(repo, url, this.refspecs, prune);
1932+
return new PushCmd(repo, url, this.refspecs, prune, pushOptions);
1933+
}
1934+
1935+
@CheckReturnValue
1936+
public PushCmd pushOptions(Iterable<String> pushOptions) {
1937+
return new PushCmd(repo, url, refspecs, prune, ImmutableList.copyOf(pushOptions));
19241938
}
19251939

19261940
/**

javatests/com/google/copybara/git/GitDestinationIntegrateTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,25 @@ public void testIncludeFiles() throws ValidationException, IOException, RepoExce
351351
.isEqualTo(Lists.newArrayList(previous.getCommit().getSha1()));
352352
}
353353

354+
@Test
355+
public void testPushOptionsTrigger() throws Exception {
356+
RepoException e = assertThrows(RepoException.class, () -> migrateOriginChange(
357+
destination(
358+
"url = '" + url + "'",
359+
String.format("fetch = '%s'", primaryBranch),
360+
String.format("push = '%s'", primaryBranch),
361+
"integrates = []",
362+
"push_options = ['ci.skip']"),
363+
"Test change\n\n"
364+
+ GitModule.DEFAULT_INTEGRATE_LABEL + "=http://should_not_be_used\n", "some content"));
365+
assertThat(e)
366+
.hasMessageThat()
367+
.contains("--push-option=ci.skip");
368+
assertThat(e)
369+
.hasMessageThat()
370+
.contains("the receiving end does not support push options");
371+
}
372+
354373
@Test
355374
public void testIncludeFilesOutdatedBranch() throws Exception {
356375
Path repoPath = Files.createTempDirectory("test");

javatests/com/google/copybara/git/GitRepositoryTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ public void doPushWithHook(GitRepository origin) throws Exception {
10941094
origin,
10951095
"file://" + remote.getGitDir(),
10961096
ImmutableList.of(repository.createRefSpec("+" + defaultBranch + ":" + defaultBranch)),
1097-
false).run();
1097+
false, ImmutableList.of()).run();
10981098
}
10991099

11001100

0 commit comments

Comments
 (0)