Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Export of internal change
Browse files Browse the repository at this point in the history
Yannic committed Mar 20, 2020

Verified

This commit was signed with the committer’s verified signature.
gsherwood Greg Sherwood
1 parent bf7649f commit ae4c487
Showing 8 changed files with 446 additions and 124 deletions.
4 changes: 3 additions & 1 deletion docs/reference.md
Original file line number Diff line number Diff line change
@@ -2132,7 +2132,7 @@ version_selector | `latestVersionSelector`<br><p>Select a custom version (tag)to

Creates changes in a new pull request in the destination.

`gitHubPrDestination git.github_pr_destination(url, destination_ref="master", pr_branch=None, title=None, body=None, integrates=None, api_checker=None, update_description=False)`
`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)`


#### Parameters:
@@ -2141,6 +2141,8 @@ Parameter | Description
--------- | -----------
url | `string`<br><p>Url of the GitHub project. For example "https://github.com/google/copybara'"</p>
destination_ref | `string`<br><p>Destination reference for the change. By default 'master'</p>
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>
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>
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>
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>
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>
166 changes: 123 additions & 43 deletions java/com/google/copybara/git/GitDestination.java
Original file line number Diff line number Diff line change
@@ -195,7 +195,8 @@ public static class WriterImpl<S extends WriterState>
implements Writer<GitRevision> {

final boolean skipPush;
private final String repoUrl;
private final String fetchRepoUrl;
private final String pushRepoUrl;
private final String remoteFetch;
private final String remotePush;
@Nullable private final String tagNameTemplate;
@@ -218,18 +219,75 @@ public static class WriterImpl<S extends WriterState>
private final int visitChangePageSize;
private final boolean gitTagOverwrite;

/**
* Create a new git.destination writer
*/
WriterImpl(boolean skipPush, String repoUrl, String remoteFetch,
String remotePush, String tagNameTemplate, String tagMsgTemplate,
GeneralOptions generalOptions, WriteHook writeHook, S state,
boolean nonFastForwardPush, Iterable<GitIntegrateChanges> integrates,
boolean lastRevFirstParent, boolean ignoreIntegrationErrors, String localRepoPath,
String committerName, String committerEmail, boolean rebase, int visitChangePageSize,
@Deprecated
WriterImpl(
boolean skipPush,
String repoUrl,
String remoteFetch,
String remotePush,
String tagNameTemplate,
String tagMsgTemplate,
GeneralOptions generalOptions,
WriteHook writeHook,
S state,
boolean nonFastForwardPush,
Iterable<GitIntegrateChanges> integrates,
boolean lastRevFirstParent,
boolean ignoreIntegrationErrors,
String localRepoPath,
String committerName,
String committerEmail,
boolean rebase,
int visitChangePageSize,
boolean gitTagOverwrite) {
this(
skipPush,
repoUrl,
repoUrl,
remoteFetch,
remotePush,
tagNameTemplate,
tagMsgTemplate,
generalOptions,
writeHook,
state,
nonFastForwardPush,
integrates,
lastRevFirstParent,
ignoreIntegrationErrors,
localRepoPath,
committerName,
committerEmail,
rebase,
visitChangePageSize,
gitTagOverwrite);
}

/** Create a new git.destination writer */
WriterImpl(
boolean skipPush,
String fetchRepoUrl,
String pushRepoUrl,
String remoteFetch,
String remotePush,
String tagNameTemplate,
String tagMsgTemplate,
GeneralOptions generalOptions,
WriteHook writeHook,
S state,
boolean nonFastForwardPush,
Iterable<GitIntegrateChanges> integrates,
boolean lastRevFirstParent,
boolean ignoreIntegrationErrors,
String localRepoPath,
String committerName,
String committerEmail,
boolean rebase,
int visitChangePageSize,
boolean gitTagOverwrite) {
this.skipPush = skipPush;
this.repoUrl = checkNotNull(repoUrl);
this.fetchRepoUrl = checkNotNull(fetchRepoUrl);
this.pushRepoUrl = checkNotNull(pushRepoUrl);
this.remoteFetch = checkNotNull(remoteFetch);
this.remotePush = checkNotNull(remotePush);
this.tagNameTemplate = tagNameTemplate;
@@ -251,6 +309,16 @@ public static class WriterImpl<S extends WriterState>
this.gitTagOverwrite = gitTagOverwrite;
}

@VisibleForTesting
String getFetchRepoUrl() {
return fetchRepoUrl;
}

@VisibleForTesting
String getPushRepoUrl() {
return pushRepoUrl;
}

@Override
public void visitChanges(@Nullable GitRevision start, ChangesVisitor visitor)
throws RepoException, ValidationException {
@@ -284,7 +352,7 @@ public void visitChanges(@Nullable GitRevision start, ChangesVisitor visitor)
private void fetchIfNeeded(GitRepository repo, Console console)
throws RepoException, ValidationException {
if (!state.alreadyFetched) {
GitRevision revision = fetchFromRemote(console, repo, repoUrl, remoteFetch);
GitRevision revision = fetchFromRemote(console, repo, getFetchRepoUrl(), remoteFetch);
if (revision != null) {
repo.simpleCommand("branch", state.localBranch, revision.getSha1());
}
@@ -343,8 +411,10 @@ private GitRevision getLocalBranchRevision(GitRepository gitRepository) throws R
if (force) {
return null;
}
throw new RepoException(String.format("Could not find %s in %s and '%s' was not used",
remoteFetch, repoUrl, GeneralOptions.FORCE));
throw new RepoException(
String.format(
"Could not find %s in %s and '%s' was not used",
remoteFetch, getFetchRepoUrl(), GeneralOptions.FORCE));
}
}

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

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

if (state.firstWrite) {
String reference = baseline != null ? baseline : state.localBranch;
configForPush(getRepository(console), repoUrl, remotePush);
configForPush(getRepository(console), getPushRepoUrl(), remotePush);
if (!force && localBranchRevision == null) {
throw new RepoException(String.format(
"Cannot checkout '%s' from '%s'. Use '%s' if the destination is a new git repo or"
+ " you don't care about the destination current status", reference,
repoUrl,
GeneralOptions.FORCE));
throw new RepoException(
String.format(
"Cannot checkout '%s' from '%s'. Use '%s' if the destination is a new git repo or"
+ " you don't care about the destination current status",
reference, getPushRepoUrl(), GeneralOptions.FORCE));
}
if (localBranchRevision != null) {
scratchClone.simpleCommand("checkout", "-f", "-q", reference);
@@ -468,7 +539,7 @@ public ImmutableList<DestinationEffect> write(TransformResult transformResult,
} else if (!skipPush) {
// Should be a no-op, but an iterative migration could take several minutes between
// migrations so lets fetch the latest first.
fetchFromRemote(console, scratchClone, repoUrl, remoteFetch);
fetchFromRemote(console, scratchClone, getFetchRepoUrl(), remoteFetch);
}

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

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

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

String serverResponse = generalOptions.repoTask(
"push",
() -> scratchClone.push()
.withRefspecs(repoUrl,
tagName != null
? ImmutableList.of(scratchClone.createRefSpec(
(nonFastForwardPush ? "+" : "") + "HEAD:" + push),
scratchClone.createRefSpec((gitTagOverwrite ? "+" : "")
+ tagName))
: ImmutableList.of(scratchClone.createRefSpec(
(nonFastForwardPush ? "+" : "") + "HEAD:" + push)))
.run()
);
String serverResponse =
generalOptions.repoTask(
"push",
() ->
scratchClone
.push()
.withRefspecs(
getPushRepoUrl(),
tagName != null
? ImmutableList.of(
scratchClone.createRefSpec(
(nonFastForwardPush ? "+" : "") + "HEAD:" + push),
scratchClone.createRefSpec(
(gitTagOverwrite ? "+" : "") + tagName))
: ImmutableList.of(
scratchClone.createRefSpec(
(nonFastForwardPush ? "+" : "") + "HEAD:" + push)))
.run());
return writeHook.afterPush(serverResponse, messageInfo, head, originChanges);
}

@@ -661,11 +737,15 @@ public GitRepository getRepository(Console console) throws RepoException, Valida
private void updateLocalBranchToBaseline(GitRepository repo, String baseline)
throws RepoException {
if (baseline != null && !repo.refExists(baseline)) {
throw new RepoException("Cannot find baseline '" + baseline
+ (getLocalBranchRevision(repo) != null
? "' from fetch reference '" + remoteFetch + "'"
: "' and fetch reference '" + remoteFetch + "' itself")
+ " in " + repoUrl + ".");
throw new RepoException(
"Cannot find baseline '"
+ baseline
+ (getLocalBranchRevision(repo) != null
? "' from fetch reference '" + remoteFetch + "'"
: "' and fetch reference '" + remoteFetch + "' itself")
+ " in "
+ getFetchRepoUrl()
+ ".");
} else if (baseline != null) {
// Update the local branch to use the baseline
repo.simpleCommand("update-ref", state.localBranch, baseline);
Loading

0 comments on commit ae4c487

Please sign in to comment.