Skip to content

Commit ae4c487

Browse files
committed
Export of internal change
1 parent bf7649f commit ae4c487

File tree

8 files changed

+446
-124
lines changed

8 files changed

+446
-124
lines changed

docs/reference.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2132,7 +2132,7 @@ version_selector | `latestVersionSelector`<br><p>Select a custom version (tag)to
21322132

21332133
Creates changes in a new pull request in the destination.
21342134

2135-
`gitHubPrDestination git.github_pr_destination(url, destination_ref="master", pr_branch=None, title=None, body=None, integrates=None, api_checker=None, update_description=False)`
2135+
`gitHubPrDestination git.github_pr_destination(url, destination_ref="master", push_to_fork=False, fork_url=None, pr_branch=None, title=None, body=None, integrates=None, api_checker=None, update_description=False)`
21362136

21372137

21382138
#### Parameters:
@@ -2141,6 +2141,8 @@ Parameter | Description
21412141
--------- | -----------
21422142
url | `string`<br><p>Url of the GitHub project. For example "https://github.com/google/copybara'"</p>
21432143
destination_ref | `string`<br><p>Destination reference for the change. By default 'master'</p>
2144+
push_to_fork | `boolean`<br><p>Indicates that the result of the change should be pushed to the current user's personal fork. The PullRequest will still be created on the upstream project.<p>The url of the fork is inferred from `url` and the credentials of the GitHub user (e.g., if `url` is `https://github.com/google/copybara.git` and the workflow is executed by `copybara-bot`, `fork_url` is assumed to be `https://github.com/copybara-bot/copybara.git`).</p><p>If `fork_url` is set, this will be ignored.</p></p>
2145+
fork_url | `string`<br><p>Sets the url of the fork Copybara will push the change to. The PullRequest will still be created on the upstream project.<p>`push_to_fork` is ignored if this is set.</p></p>
21442146
pr_branch | `string`<br><p>Customize the pull request branch. Any variable present in the message in the form of ${CONTEXT_REFERENCE} will be replaced by the corresponding stable reference (head, PR number, Gerrit change number, etc.).</p>
21452147
title | `string`<br><p>When creating (or updating if `update_description` is set) a pull request, use this title. By default it uses the change first line. This field accepts a template with labels. For example: `"Change ${CONTEXT_REFERENCE}"`</p>
21462148
body | `string`<br><p>When creating (or updating if `update_description` is set) a pull request, use this body. By default it uses the change summary. This field accepts a template with labels. For example: `"Change ${CONTEXT_REFERENCE}"`</p>

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

Lines changed: 123 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ public static class WriterImpl<S extends WriterState>
195195
implements Writer<GitRevision> {
196196

197197
final boolean skipPush;
198-
private final String repoUrl;
198+
private final String fetchRepoUrl;
199+
private final String pushRepoUrl;
199200
private final String remoteFetch;
200201
private final String remotePush;
201202
@Nullable private final String tagNameTemplate;
@@ -218,18 +219,75 @@ public static class WriterImpl<S extends WriterState>
218219
private final int visitChangePageSize;
219220
private final boolean gitTagOverwrite;
220221

221-
/**
222-
* Create a new git.destination writer
223-
*/
224-
WriterImpl(boolean skipPush, String repoUrl, String remoteFetch,
225-
String remotePush, String tagNameTemplate, String tagMsgTemplate,
226-
GeneralOptions generalOptions, WriteHook writeHook, S state,
227-
boolean nonFastForwardPush, Iterable<GitIntegrateChanges> integrates,
228-
boolean lastRevFirstParent, boolean ignoreIntegrationErrors, String localRepoPath,
229-
String committerName, String committerEmail, boolean rebase, int visitChangePageSize,
222+
@Deprecated
223+
WriterImpl(
224+
boolean skipPush,
225+
String repoUrl,
226+
String remoteFetch,
227+
String remotePush,
228+
String tagNameTemplate,
229+
String tagMsgTemplate,
230+
GeneralOptions generalOptions,
231+
WriteHook writeHook,
232+
S state,
233+
boolean nonFastForwardPush,
234+
Iterable<GitIntegrateChanges> integrates,
235+
boolean lastRevFirstParent,
236+
boolean ignoreIntegrationErrors,
237+
String localRepoPath,
238+
String committerName,
239+
String committerEmail,
240+
boolean rebase,
241+
int visitChangePageSize,
242+
boolean gitTagOverwrite) {
243+
this(
244+
skipPush,
245+
repoUrl,
246+
repoUrl,
247+
remoteFetch,
248+
remotePush,
249+
tagNameTemplate,
250+
tagMsgTemplate,
251+
generalOptions,
252+
writeHook,
253+
state,
254+
nonFastForwardPush,
255+
integrates,
256+
lastRevFirstParent,
257+
ignoreIntegrationErrors,
258+
localRepoPath,
259+
committerName,
260+
committerEmail,
261+
rebase,
262+
visitChangePageSize,
263+
gitTagOverwrite);
264+
}
265+
266+
/** Create a new git.destination writer */
267+
WriterImpl(
268+
boolean skipPush,
269+
String fetchRepoUrl,
270+
String pushRepoUrl,
271+
String remoteFetch,
272+
String remotePush,
273+
String tagNameTemplate,
274+
String tagMsgTemplate,
275+
GeneralOptions generalOptions,
276+
WriteHook writeHook,
277+
S state,
278+
boolean nonFastForwardPush,
279+
Iterable<GitIntegrateChanges> integrates,
280+
boolean lastRevFirstParent,
281+
boolean ignoreIntegrationErrors,
282+
String localRepoPath,
283+
String committerName,
284+
String committerEmail,
285+
boolean rebase,
286+
int visitChangePageSize,
230287
boolean gitTagOverwrite) {
231288
this.skipPush = skipPush;
232-
this.repoUrl = checkNotNull(repoUrl);
289+
this.fetchRepoUrl = checkNotNull(fetchRepoUrl);
290+
this.pushRepoUrl = checkNotNull(pushRepoUrl);
233291
this.remoteFetch = checkNotNull(remoteFetch);
234292
this.remotePush = checkNotNull(remotePush);
235293
this.tagNameTemplate = tagNameTemplate;
@@ -251,6 +309,16 @@ public static class WriterImpl<S extends WriterState>
251309
this.gitTagOverwrite = gitTagOverwrite;
252310
}
253311

312+
@VisibleForTesting
313+
String getFetchRepoUrl() {
314+
return fetchRepoUrl;
315+
}
316+
317+
@VisibleForTesting
318+
String getPushRepoUrl() {
319+
return pushRepoUrl;
320+
}
321+
254322
@Override
255323
public void visitChanges(@Nullable GitRevision start, ChangesVisitor visitor)
256324
throws RepoException, ValidationException {
@@ -284,7 +352,7 @@ public void visitChanges(@Nullable GitRevision start, ChangesVisitor visitor)
284352
private void fetchIfNeeded(GitRepository repo, Console console)
285353
throws RepoException, ValidationException {
286354
if (!state.alreadyFetched) {
287-
GitRevision revision = fetchFromRemote(console, repo, repoUrl, remoteFetch);
355+
GitRevision revision = fetchFromRemote(console, repo, getFetchRepoUrl(), remoteFetch);
288356
if (revision != null) {
289357
repo.simpleCommand("branch", state.localBranch, revision.getSha1());
290358
}
@@ -343,8 +411,10 @@ private GitRevision getLocalBranchRevision(GitRepository gitRepository) throws R
343411
if (force) {
344412
return null;
345413
}
346-
throw new RepoException(String.format("Could not find %s in %s and '%s' was not used",
347-
remoteFetch, repoUrl, GeneralOptions.FORCE));
414+
throw new RepoException(
415+
String.format(
416+
"Could not find %s in %s and '%s' was not used",
417+
remoteFetch, getFetchRepoUrl(), GeneralOptions.FORCE));
348418
}
349419
}
350420

@@ -436,7 +506,8 @@ public ImmutableList<DestinationEffect> write(TransformResult transformResult,
436506
Glob destinationFiles, Console console)
437507
throws ValidationException, RepoException, IOException {
438508
logger.atInfo().log(
439-
"Exporting from %s to: url=%s ref=%s", transformResult.getPath(), repoUrl, remotePush);
509+
"Exporting from %s to: url=%s ref=%s",
510+
transformResult.getPath(), getPushRepoUrl(), remotePush);
440511
String baseline = transformResult.getBaseline();
441512

442513
GitRepository scratchClone = getRepository(console);
@@ -450,13 +521,13 @@ public ImmutableList<DestinationEffect> write(TransformResult transformResult,
450521

451522
if (state.firstWrite) {
452523
String reference = baseline != null ? baseline : state.localBranch;
453-
configForPush(getRepository(console), repoUrl, remotePush);
524+
configForPush(getRepository(console), getPushRepoUrl(), remotePush);
454525
if (!force && localBranchRevision == null) {
455-
throw new RepoException(String.format(
456-
"Cannot checkout '%s' from '%s'. Use '%s' if the destination is a new git repo or"
457-
+ " you don't care about the destination current status", reference,
458-
repoUrl,
459-
GeneralOptions.FORCE));
526+
throw new RepoException(
527+
String.format(
528+
"Cannot checkout '%s' from '%s'. Use '%s' if the destination is a new git repo or"
529+
+ " you don't care about the destination current status",
530+
reference, getPushRepoUrl(), GeneralOptions.FORCE));
460531
}
461532
if (localBranchRevision != null) {
462533
scratchClone.simpleCommand("checkout", "-f", "-q", reference);
@@ -468,7 +539,7 @@ public ImmutableList<DestinationEffect> write(TransformResult transformResult,
468539
} else if (!skipPush) {
469540
// Should be a no-op, but an iterative migration could take several minutes between
470541
// migrations so lets fetch the latest first.
471-
fetchFromRemote(console, scratchClone, repoUrl, remoteFetch);
542+
fetchFromRemote(console, scratchClone, getFetchRepoUrl(), remoteFetch);
472543
}
473544

474545
PathMatcher pathMatcher = destinationFiles.relativeTo(scratchClone.getWorkTree());
@@ -505,7 +576,7 @@ public ImmutableList<DestinationEffect> write(TransformResult transformResult,
505576
commitMessage);
506577

507578
// Don't remove. Used internally in test
508-
console.verboseFmt("Integrates for %s: %s", repoUrl, Iterables.size(integrates));
579+
console.verboseFmt("Integrates for %s: %s", getPushRepoUrl(), Iterables.size(integrates));
509580

510581
for (GitIntegrateChanges integrate : integrates) {
511582
integrate.run(alternate, generalOptions, messageInfo,
@@ -562,7 +633,7 @@ public ImmutableList<DestinationEffect> write(TransformResult transformResult,
562633
console.info(DiffUtil.colorize(
563634
console, scratchClone.simpleCommand("show", "HEAD").getStdout()));
564635
if (!console.promptConfirmation(
565-
String.format("Proceed with push to %s %s?", repoUrl, remotePush))) {
636+
String.format("Proceed with push to %s %s?", getPushRepoUrl(), remotePush))) {
566637
console.warn("Migration aborted by user.");
567638
throw new ChangeRejectedException(
568639
"User aborted execution: did not confirm diff changes.");
@@ -588,24 +659,29 @@ public ImmutableList<DestinationEffect> write(TransformResult transformResult,
588659
new DestinationEffect.DestinationRef(head.getSha1(), "commit", /*url=*/ null)));
589660
}
590661
String push = writeHook.getPushReference(getCompleteRef(remotePush), transformResult);
591-
console.progress(String.format("Git Destination: Pushing to %s %s", repoUrl, push));
662+
console.progress(String.format("Git Destination: Pushing to %s %s", getPushRepoUrl(), push));
592663
checkCondition(!nonFastForwardPush
593664
|| !Objects.equals(remoteFetch, remotePush), "non fast-forward push is only"
594665
+ " allowed when fetch != push");
595666

596-
String serverResponse = generalOptions.repoTask(
597-
"push",
598-
() -> scratchClone.push()
599-
.withRefspecs(repoUrl,
600-
tagName != null
601-
? ImmutableList.of(scratchClone.createRefSpec(
602-
(nonFastForwardPush ? "+" : "") + "HEAD:" + push),
603-
scratchClone.createRefSpec((gitTagOverwrite ? "+" : "")
604-
+ tagName))
605-
: ImmutableList.of(scratchClone.createRefSpec(
606-
(nonFastForwardPush ? "+" : "") + "HEAD:" + push)))
607-
.run()
608-
);
667+
String serverResponse =
668+
generalOptions.repoTask(
669+
"push",
670+
() ->
671+
scratchClone
672+
.push()
673+
.withRefspecs(
674+
getPushRepoUrl(),
675+
tagName != null
676+
? ImmutableList.of(
677+
scratchClone.createRefSpec(
678+
(nonFastForwardPush ? "+" : "") + "HEAD:" + push),
679+
scratchClone.createRefSpec(
680+
(gitTagOverwrite ? "+" : "") + tagName))
681+
: ImmutableList.of(
682+
scratchClone.createRefSpec(
683+
(nonFastForwardPush ? "+" : "") + "HEAD:" + push)))
684+
.run());
609685
return writeHook.afterPush(serverResponse, messageInfo, head, originChanges);
610686
}
611687

@@ -661,11 +737,15 @@ public GitRepository getRepository(Console console) throws RepoException, Valida
661737
private void updateLocalBranchToBaseline(GitRepository repo, String baseline)
662738
throws RepoException {
663739
if (baseline != null && !repo.refExists(baseline)) {
664-
throw new RepoException("Cannot find baseline '" + baseline
665-
+ (getLocalBranchRevision(repo) != null
666-
? "' from fetch reference '" + remoteFetch + "'"
667-
: "' and fetch reference '" + remoteFetch + "' itself")
668-
+ " in " + repoUrl + ".");
740+
throw new RepoException(
741+
"Cannot find baseline '"
742+
+ baseline
743+
+ (getLocalBranchRevision(repo) != null
744+
? "' from fetch reference '" + remoteFetch + "'"
745+
: "' and fetch reference '" + remoteFetch + "' itself")
746+
+ " in "
747+
+ getFetchRepoUrl()
748+
+ ".");
669749
} else if (baseline != null) {
670750
// Update the local branch to use the baseline
671751
repo.simpleCommand("update-ref", state.localBranch, baseline);

0 commit comments

Comments
 (0)