Search in sources :

Example 1 with CannotResolveRevisionException

use of com.google.copybara.exception.CannotResolveRevisionException in project copybara by google.

the class GerritChange method getGerritPatchSets.

/**
 * Get all the patchsets for a change ordered by the patchset number. Last is the most recent
 * one.
 */
static TreeMap<Integer, GitRevision> getGerritPatchSets(GitRepository repository, String url, int changeNumber) throws RepoException, ValidationException {
    TreeMap<Integer, GitRevision> patchSets = new TreeMap<>();
    String basePath = String.format("refs/changes/%02d/%d", changeNumber % 100, changeNumber);
    Map<String, String> refsToSha1 = repository.lsRemote(url, ImmutableList.of(basePath + "/*"));
    if (refsToSha1.isEmpty()) {
        throw new CannotResolveRevisionException(String.format("Cannot find change number %d in '%s'", changeNumber, url));
    }
    for (Entry<String, String> e : refsToSha1.entrySet()) {
        if (e.getKey().endsWith("/meta") || e.getKey().endsWith("/robot-comments")) {
            continue;
        }
        Preconditions.checkState(e.getKey().startsWith(basePath + "/"), String.format("Unexpected response reference %s for %s", e.getKey(), basePath));
        Matcher matcher = WHOLE_GERRIT_REF.matcher(e.getKey());
        Preconditions.checkArgument(matcher.matches(), "Unexpected format for response reference %s for %s", e.getKey(), basePath);
        int patchSet = Ints.tryParse(matcher.group(2));
        patchSets.put(patchSet, new GitRevision(repository, e.getValue(), gerritPatchSetAsReviewReference(patchSet), e.getKey(), ImmutableListMultimap.of(), url));
    }
    return patchSets;
}
Also used : Matcher(com.google.re2j.Matcher) CharMatcher(com.google.common.base.CharMatcher) CannotResolveRevisionException(com.google.copybara.exception.CannotResolveRevisionException) TreeMap(java.util.TreeMap)

Example 2 with CannotResolveRevisionException

use of com.google.copybara.exception.CannotResolveRevisionException in project copybara by google.

the class GerritChange method resolve.

/**
 * Given a local repository, a repo url and a reference, it tries to do its best to resolve the
 * reference to a Gerrit Change.
 *
 * <p>Note that if the PatchSet is not found in the ref, it will go to Gerrit to get the latest
 * PatchSet number.
 *
 * @return a Gerrit change if it can be resolved. Null otherwise.
 */
@Nullable
public static GerritChange resolve(GitRepository repository, String repoUrl, String ref, GeneralOptions options) throws RepoException, ValidationException {
    if (Strings.isNullOrEmpty(ref)) {
        return null;
    }
    Matcher refMatcher = WHOLE_GERRIT_REF.matcher(ref);
    if (refMatcher.matches()) {
        return new GerritChange(repository, options, repoUrl, Ints.tryParse(refMatcher.group(1)), Ints.tryParse(refMatcher.group(2)), ref);
    }
    // A change number like '23423'
    if (CharMatcher.javaDigit().matchesAllOf(ref)) {
        return resolveLatestPatchSet(repository, options, repoUrl, Ints.tryParse(ref));
    }
    Matcher urlMatcher = URL_PATTERN.matcher(ref);
    if (!urlMatcher.matches()) {
        return null;
    }
    if (!ref.startsWith(repoUrl)) {
        // Assume it is our url. We can make this more strict later
        options.console().warn(String.format("Assuming repository '%s' for looking for review '%s'", repoUrl, ref));
    }
    int change = Ints.tryParse(urlMatcher.group(1));
    Integer patchSet = urlMatcher.group(2) == null ? null : Ints.tryParse(urlMatcher.group(2));
    if (patchSet == null) {
        return resolveLatestPatchSet(repository, options, repoUrl, change);
    }
    Map<Integer, GitRevision> patchSets = getGerritPatchSets(repository, repoUrl, change);
    if (!patchSets.containsKey(patchSet)) {
        throw new CannotResolveRevisionException(String.format("Cannot find patch set %d for change %d in %s. Available Patch sets: %s", patchSet, change, repoUrl, patchSets.keySet()));
    }
    return new GerritChange(repository, options, repoUrl, change, patchSet, patchSets.get(patchSet).contextReference());
}
Also used : Matcher(com.google.re2j.Matcher) CharMatcher(com.google.common.base.CharMatcher) CannotResolveRevisionException(com.google.copybara.exception.CannotResolveRevisionException) Nullable(javax.annotation.Nullable)

Example 3 with CannotResolveRevisionException

use of com.google.copybara.exception.CannotResolveRevisionException in project copybara by google.

the class GitHubPrOrigin method getRevisionForPR.

private GitRevision getRevisionForPR(String project, PullRequest prData) throws RepoException, ValidationException {
    GitHubApi api = gitHubOptions.newGitHubApi(project);
    int prNumber = (int) prData.getNumber();
    boolean actuallyUseMerge = this.useMerge;
    ImmutableListMultimap.Builder<String, String> labels = ImmutableListMultimap.builder();
    checkPrState(prData);
    checkPrBranch(project, prData);
    checkRequiredLabels(api, project, prData);
    checkRequiredStatusContextNames(api, project, prData);
    checkRequiredCheckRuns(api, project, prData);
    checkReviewApprovers(api, project, prData, labels);
    // Fetch also the baseline branch. It is almost free and doing a roundtrip later would hurt
    // latency.
    console.progressFmt("Fetching Pull Request %d and branch '%s'", prNumber, prData.getBase().getRef());
    ImmutableList.Builder<String> refSpecBuilder = ImmutableList.<String>builder().add(String.format("%s:%s", asHeadRef(prNumber), LOCAL_PR_HEAD_REF)).add(String.format("refs/heads/%s:" + LOCAL_PR_BASE_BRANCH, prData.getBase().getRef()));
    if (actuallyUseMerge) {
        if (!Boolean.FALSE.equals(prData.isMergeable())) {
            refSpecBuilder.add(String.format("%s:%s", asMergeRef(prNumber), LOCAL_PR_MERGE_REF));
        } else if (forceImport()) {
            console.warnFmt("PR %d is not mergeable, but continuing with PR Head instead because of %s", prNumber, GeneralOptions.FORCE);
            actuallyUseMerge = false;
        } else {
            throw new CannotResolveRevisionException(String.format("Cannot find a merge reference for Pull Request %d." + " It might have a conflict with head.", prNumber));
        }
    }
    ImmutableList<String> refspec = refSpecBuilder.build();
    try (ProfilerTask ignore = generalOptions.profiler().start("fetch")) {
        getRepository().fetch(ghHost.projectAsUrl(project), /*prune=*/
        false, /*force=*/
        true, refspec, partialFetch);
    } catch (CannotResolveRevisionException e) {
        if (actuallyUseMerge && prData.isMergeable() == null && forceImport()) {
            // We can perhaps recover by fetching without the merge ref
            actuallyUseMerge = false;
            refspec = refspec.subList(0, refspec.size() - 1);
            try (ProfilerTask ignore = generalOptions.profiler().start("fetch")) {
                getRepository().fetch(ghHost.projectAsUrl(project), /*prune=*/
                false, /*force=*/
                true, refspec, partialFetch);
                e = null;
            } catch (CannotResolveRevisionException e2) {
                // Report the error from the second fetch instead of the original fetch
                e = e2;
            }
        }
        if (e != null) {
            if (actuallyUseMerge) {
                String msg = String.format("Cannot find a merge reference for Pull Request %d.", prNumber);
                if (Boolean.TRUE.equals(prData.isMergeable())) {
                    msg += " GitHub reported that this merge reference should exist.";
                }
                throw new CannotResolveRevisionException(msg, e);
            } else {
                throw new CannotResolveRevisionException(String.format("Cannot find Pull Request %d.", prNumber), e);
            }
        }
    }
    String refForMigration = actuallyUseMerge ? LOCAL_PR_MERGE_REF : LOCAL_PR_HEAD_REF;
    GitRevision gitRevision = getRepository().resolveReference(refForMigration);
    String headPrSha1 = getRepository().resolveReference(LOCAL_PR_HEAD_REF).getSha1();
    String integrateLabel = new GitHubPrIntegrateLabel(getRepository(), generalOptions, project, prNumber, prData.getHead().getLabel(), // The integrate SHA has to be HEAD of the PR not the merge ref, even if use_merge = True
    headPrSha1).toString();
    labels.putAll(GITHUB_PR_REQUESTED_REVIEWER, prData.getRequestedReviewers().stream().map(User::getLogin).collect(toImmutableList()));
    labels.put(GITHUB_PR_NUMBER_LABEL, Integer.toString(prNumber));
    labels.put(GitModule.DEFAULT_INTEGRATE_LABEL, integrateLabel);
    labels.put(GITHUB_BASE_BRANCH, prData.getBase().getRef());
    labels.put(GITHUB_PR_HEAD_SHA, headPrSha1);
    labels.put(GITHUB_PR_USE_MERGE, Boolean.toString(actuallyUseMerge));
    String mergeBase = getRepository().mergeBase(refForMigration, LOCAL_PR_BASE_BRANCH);
    labels.put(GITHUB_BASE_BRANCH_SHA1, mergeBase);
    labels.put(GITHUB_PR_TITLE, prData.getTitle());
    labels.put(GITHUB_PR_BODY, prData.getBody());
    labels.put(GITHUB_PR_URL, prData.getHtmlUrl());
    labels.put(GITHUB_PR_USER, prData.getUser().getLogin());
    labels.putAll(GITHUB_PR_ASSIGNEE, prData.getAssignees().stream().map(User::getLogin).collect(Collectors.toList()));
    GitRevision result = new GitRevision(getRepository(), gitRevision.getSha1(), /*reviewReference=*/
    null, actuallyUseMerge ? asMergeRef(prNumber) : asHeadRef(prNumber), labels.build(), url);
    return describeVersion ? getRepository().addDescribeVersion(result) : result;
}
Also used : User(com.google.copybara.git.github.api.User) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) Endpoint(com.google.copybara.Endpoint) GitHubApi(com.google.copybara.git.github.api.GitHubApi) ProfilerTask(com.google.copybara.profiler.Profiler.ProfilerTask) ImmutableListMultimap.toImmutableListMultimap(com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) CannotResolveRevisionException(com.google.copybara.exception.CannotResolveRevisionException)

Example 4 with CannotResolveRevisionException

use of com.google.copybara.exception.CannotResolveRevisionException in project copybara by google.

the class GitHubPrOrigin method resolve.

@Override
public GitRevision resolve(String reference) throws RepoException, ValidationException {
    checkCondition(reference != null, "" + "A pull request reference is expected as argument in the command line." + " Invoke copybara as:\n" + "    copybara copy.bara.sky workflow_name 12345");
    console.progress("GitHub PR Origin: Resolving reference " + reference);
    String configProjectName = ghHost.getProjectNameFromUrl(url);
    // GitHub's commit 'status' webhook provides only the commit SHA
    if (GitRevision.COMPLETE_SHA1_PATTERN.matcher(reference).matches()) {
        PullRequest pr = getPrFromSha(configProjectName, reference);
        return getRevisionForPR(configProjectName, pr);
    }
    // A whole https pull request url
    Optional<GitHubPrUrl> githubPrUrl = ghHost.maybeParseGithubPrUrl(reference);
    if (githubPrUrl.isPresent()) {
        checkCondition(githubPrUrl.get().getProject().equals(configProjectName), "Project name should be '%s' but it is '%s' instead", configProjectName, githubPrUrl.get().getProject());
        return getRevisionForPR(configProjectName, getPrFromNumber(configProjectName, githubPrUrl.get().getPrNumber()));
    }
    // A Pull request number
    if (CharMatcher.digit().matchesAllOf(reference)) {
        return getRevisionForPR(ghHost.getProjectNameFromUrl(url), getPrFromNumber(configProjectName, Integer.parseInt(reference)));
    }
    // refs/pull/12345/head
    Optional<Integer> prNumber = GitHubUtil.maybeParseGithubPrFromHeadRef(reference);
    if (prNumber.isPresent()) {
        return getRevisionForPR(configProjectName, getPrFromNumber(configProjectName, prNumber.get()));
    }
    throw new CannotResolveRevisionException(String.format("'%s' is not a valid reference for a GitHub Pull Request. Valid formats:" + "'https://github.com/project/pull/1234', 'refs/pull/1234/head' or '1234'", reference));
}
Also used : PullRequest(com.google.copybara.git.github.api.PullRequest) CannotResolveRevisionException(com.google.copybara.exception.CannotResolveRevisionException) GitHubPrUrl(com.google.copybara.git.github.util.GitHubHost.GitHubPrUrl)

Example 5 with CannotResolveRevisionException

use of com.google.copybara.exception.CannotResolveRevisionException in project copybara by google.

the class GitHubPrOrigin method newReader.

@Override
public Reader<GitRevision> newReader(Glob originFiles, Authoring authoring) throws ValidationException {
    return new ReaderImpl(url, originFiles, authoring, gitOptions, gitOriginOptions, generalOptions, /*includeBranchCommitLogs=*/
    false, submoduleStrategy, firstParent, partialFetch, patchTransformation, describeVersion, /*configPath=*/
    null, /*workflowName=*/
    null) {

        /**
         * Disable rebase since this is controlled by useMerge field.
         */
        @Override
        protected void maybeRebase(GitRepository repo, GitRevision ref, Path workdir) throws RepoException, CannotResolveRevisionException {
        }

        @Override
        public Optional<Baseline<GitRevision>> findBaseline(GitRevision startRevision, String label) throws RepoException, ValidationException {
            if (!baselineFromBranch) {
                return super.findBaseline(startRevision, label);
            }
            return findBaselinesWithoutLabel(startRevision, /*limit=*/
            1).stream().map(e -> new Baseline<>(e.getSha1(), e)).findFirst();
        }

        @Override
        public ImmutableList<GitRevision> findBaselinesWithoutLabel(GitRevision startRevision, int limit) throws RepoException, ValidationException {
            String baseline = Iterables.getLast(startRevision.associatedLabels().get(GITHUB_BASE_BRANCH_SHA1), null);
            checkNotNull(baseline, "%s label should be present in %s", GITHUB_BASE_BRANCH_SHA1, startRevision);
            GitRevision baselineRev = getRepository().resolveReference(baseline);
            // Don't skip the first change as it is already the baseline
            BaselinesWithoutLabelVisitor<GitRevision> visitor = new BaselinesWithoutLabelVisitor<>(originFiles, limit, /*skipFirst=*/
            false);
            visitChanges(baselineRev, visitor);
            return visitor.getResult();
        }

        @Override
        public Endpoint getFeedbackEndPoint(Console console) throws ValidationException {
            gitHubOptions.validateEndpointChecker(endpointChecker);
            return new GitHubEndPoint(gitHubOptions.newGitHubApiSupplier(url, endpointChecker, ghHost), url, console, ghHost);
        }

        /**
         * Deal with the case of useMerge. We have a new commit (the merge) and first-parent from that
         * commit doesn't work for this case.
         */
        @Override
        public ChangesResponse<GitRevision> changes(@Nullable GitRevision fromRef, GitRevision toRef) throws RepoException, ValidationException {
            checkCondition(toRef.associatedLabels().containsKey(GITHUB_PR_USE_MERGE), "Cannot determine whether 'use_merge' was set.");
            if (toRef.associatedLabel(GITHUB_PR_USE_MERGE).contains("false")) {
                return super.changes(fromRef, toRef);
            }
            GitLogEntry merge = Iterables.getOnlyElement(getRepository().log(toRef.getSha1()).withLimit(1).run());
            // Fast-forward merge
            if (merge.getParents().size() == 1) {
                return super.changes(fromRef, toRef);
            }
            // HEAD of the Pull Request
            GitRevision gitRevision = merge.getParents().get(1);
            ChangesResponse<GitRevision> prChanges = super.changes(fromRef, gitRevision);
            // origin_files
            if (prChanges.isEmpty()) {
                return prChanges;
            }
            try {
                return ChangesResponse.forChanges(ImmutableList.<Change<GitRevision>>builder().addAll(prChanges.getChanges()).add(change(merge.getCommit())).build());
            } catch (EmptyChangeException e) {
                throw new RepoException("Error getting the merge commit information: " + merge, e);
            }
        }
    };
}
Also used : Path(java.nio.file.Path) GitHubUtil.asHeadRef(com.google.copybara.git.github.util.GitHubUtil.asHeadRef) Origin(com.google.copybara.Origin) CombinedStatus(com.google.copybara.git.github.api.CombinedStatus) Collections2(com.google.common.collect.Collections2) Review(com.google.copybara.git.github.api.Review) ImmutableListMultimap.toImmutableListMultimap(com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap) Matcher(java.util.regex.Matcher) Change(com.google.copybara.Change) BaselinesWithoutLabelVisitor(com.google.copybara.BaselinesWithoutLabelVisitor) CannotResolveRevisionException(com.google.copybara.exception.CannotResolveRevisionException) Endpoint(com.google.copybara.Endpoint) Splitter(com.google.common.base.Splitter) GeneralOptions(com.google.copybara.GeneralOptions) Path(java.nio.file.Path) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) User(com.google.copybara.git.github.api.User) ProfilerTask(com.google.copybara.profiler.Profiler.ProfilerTask) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Set(java.util.Set) Collectors(java.util.stream.Collectors) Collectors.joining(java.util.stream.Collectors.joining) Sets(com.google.common.collect.Sets) Objects(java.util.Objects) List(java.util.List) GitHubApi(com.google.copybara.git.github.api.GitHubApi) PullRequest(com.google.copybara.git.github.api.PullRequest) GitHubUtil.asMergeRef(com.google.copybara.git.github.util.GitHubUtil.asMergeRef) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) AutoValue(com.google.auto.value.AutoValue) Optional(java.util.Optional) Joiner(com.google.common.base.Joiner) AuthorAssociation(com.google.copybara.git.github.api.AuthorAssociation) Iterables(com.google.common.collect.Iterables) CheckRuns(com.google.copybara.git.github.api.CheckRuns) ValidationException.checkCondition(com.google.copybara.exception.ValidationException.checkCondition) RepoException(com.google.copybara.exception.RepoException) SubmoduleStrategy(com.google.copybara.git.GitOrigin.SubmoduleStrategy) HashSet(java.util.HashSet) GitHubUtil(com.google.copybara.git.github.util.GitHubUtil) Label(com.google.copybara.git.github.api.Label) State(com.google.copybara.git.github.api.Status.State) ImmutableList(com.google.common.collect.ImmutableList) Issue(com.google.copybara.git.github.api.Issue) Nullable(javax.annotation.Nullable) GitLogEntry(com.google.copybara.git.GitRepository.GitLogEntry) Uninterruptibles(com.google.common.util.concurrent.Uninterruptibles) EmptyChangeException(com.google.copybara.exception.EmptyChangeException) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) CharMatcher(com.google.common.base.CharMatcher) ValidationException(com.google.copybara.exception.ValidationException) ReaderImpl(com.google.copybara.git.GitOrigin.ReaderImpl) PatchTransformation(com.google.copybara.transform.patch.PatchTransformation) Console(com.google.copybara.util.console.Console) TimeUnit(java.util.concurrent.TimeUnit) Authoring(com.google.copybara.authoring.Authoring) Checker(com.google.copybara.checks.Checker) Glob(com.google.copybara.util.Glob) CheckRun(com.google.copybara.git.github.api.CheckRun) Preconditions(com.google.common.base.Preconditions) Status(com.google.copybara.git.github.api.Status) GitHubHost(com.google.copybara.git.github.util.GitHubHost) GitHubPrUrl(com.google.copybara.git.github.util.GitHubHost.GitHubPrUrl) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) ReaderImpl(com.google.copybara.git.GitOrigin.ReaderImpl) Change(com.google.copybara.Change) RepoException(com.google.copybara.exception.RepoException) Console(com.google.copybara.util.console.Console) BaselinesWithoutLabelVisitor(com.google.copybara.BaselinesWithoutLabelVisitor) EmptyChangeException(com.google.copybara.exception.EmptyChangeException) Nullable(javax.annotation.Nullable) GitLogEntry(com.google.copybara.git.GitRepository.GitLogEntry)

Aggregations

CannotResolveRevisionException (com.google.copybara.exception.CannotResolveRevisionException)23 Test (org.junit.Test)10 CharMatcher (com.google.common.base.CharMatcher)6 ProfilerTask (com.google.copybara.profiler.Profiler.ProfilerTask)5 ImmutableList (com.google.common.collect.ImmutableList)4 Endpoint (com.google.copybara.Endpoint)4 EmptyChangeException (com.google.copybara.exception.EmptyChangeException)4 RepoException (com.google.copybara.exception.RepoException)4 PullRequest (com.google.copybara.git.github.api.PullRequest)4 Change (com.google.copybara.Change)3 Path (java.nio.file.Path)3 Matcher (java.util.regex.Matcher)3 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 Preconditions (com.google.common.base.Preconditions)2 Splitter (com.google.common.base.Splitter)2 Collections2 (com.google.common.collect.Collections2)2 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)2 ImmutableListMultimap (com.google.common.collect.ImmutableListMultimap)2 ImmutableListMultimap.toImmutableListMultimap (com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap)2 ImmutableMap (com.google.common.collect.ImmutableMap)2