Search in sources :

Example 16 with DestinationEffect

use of com.google.copybara.effect.DestinationEffect in project copybara by google.

the class SubmodulesInDestinationTest method writeWithSubmoduleInDestination.

private void writeWithSubmoduleInDestination() throws Exception {
    fetch = primaryBranch;
    push = primaryBranch;
    Path scratchTree = Files.createTempDirectory("SubmodulesInDestinationTest-scratchTree");
    GitRepository scratchRepo = repo().withWorkTree(scratchTree);
    scratchRepo.simpleCommand("submodule", "add", "file://" + submodule.getGitDir(), "submodule");
    scratchRepo.simpleCommand("commit", "-m", "commit submodule");
    Files.write(workdir.resolve("test42"), new byte[] { 42 });
    WriterContext writerContext = new WriterContext("SubmodulesInDestinationTest", "Test", false, new DummyRevision("test"), Glob.ALL_FILES.roots());
    Destination.Writer<GitRevision> writer = destination().newWriter(writerContext);
    ImmutableList<DestinationEffect> result = writer.write(TransformResults.of(workdir, new DummyRevision("ref1")), destinationFiles, console);
    assertThat(result).hasSize(1);
    assertThat(result.get(0).getErrors()).isEmpty();
    assertThat(result.get(0).getType()).isEqualTo(Type.CREATED);
    assertThat(result.get(0).getDestinationRef().getType()).isEqualTo("commit");
    assertThat(result.get(0).getDestinationRef().getId()).matches("[0-9a-f]{40}");
}
Also used : Path(java.nio.file.Path) WriterContext(com.google.copybara.WriterContext) Destination(com.google.copybara.Destination) DestinationEffect(com.google.copybara.effect.DestinationEffect) DummyRevision(com.google.copybara.testing.DummyRevision)

Example 17 with DestinationEffect

use of com.google.copybara.effect.DestinationEffect in project copybara by google.

the class SubmodulesInDestinationTest method submoduleInSubdirectoryWithSiblingFiles.

@Test
public void submoduleInSubdirectoryWithSiblingFiles() throws Exception {
    destinationFiles = Glob.createGlob(ImmutableList.of("foo/a", "foo/c"));
    fetch = primaryBranch;
    push = primaryBranch;
    Path scratchTree = Files.createTempDirectory("SubmodulesInDestinationTest-scratchTree");
    GitRepository scratchRepo = repo().withWorkTree(scratchTree);
    Files.createDirectories(scratchTree.resolve("foo"));
    Files.write(scratchTree.resolve("foo/a"), new byte[] { 1 });
    scratchRepo.add().files("foo/a").run();
    scratchRepo.simpleCommand("submodule", "add", "file://" + submodule.getGitDir(), "foo/b");
    scratchRepo.simpleCommand("commit", "-m", "commit submodule and foo/a");
    // Create a commit that removes foo/a and adds foo/c
    Files.createDirectories(workdir.resolve("foo"));
    Files.write(workdir.resolve("foo/c"), new byte[] { 1 });
    WriterContext writerContext = new WriterContext("SubmodulesInDestinationTest", "Test", false, new DummyRevision("test"), Glob.ALL_FILES.roots());
    Destination.Writer<GitRevision> writer = destination().newWriter(writerContext);
    ImmutableList<DestinationEffect> result = writer.write(TransformResults.of(workdir, new DummyRevision("ref1")), destinationFiles, console);
    assertThat(result).hasSize(1);
    assertThat(result.get(0).getErrors()).isEmpty();
    assertThat(result.get(0).getType()).isEqualTo(Type.CREATED);
    assertThat(result.get(0).getDestinationRef().getType()).isEqualTo("commit");
    assertThat(result.get(0).getDestinationRef().getId()).matches("[0-9a-f]{40}");
    GitTesting.assertThatCheckout(repo(), primaryBranch).containsFiles("foo/c", "foo/b").containsNoFiles("foo/a");
}
Also used : Path(java.nio.file.Path) WriterContext(com.google.copybara.WriterContext) Destination(com.google.copybara.Destination) DestinationEffect(com.google.copybara.effect.DestinationEffect) DummyRevision(com.google.copybara.testing.DummyRevision) Test(org.junit.Test)

Example 18 with DestinationEffect

use of com.google.copybara.effect.DestinationEffect in project copybara by google.

the class GitHubWriteHook method afterPush.

@Override
public ImmutableList<DestinationEffect> afterPush(String serverResponse, MessageInfo messageInfo, GitRevision pushedRevision, List<? extends Change<?>> originChanges) throws ValidationException, RepoException {
    ImmutableList.Builder<DestinationEffect> baseEffects = ImmutableList.<DestinationEffect>builder().addAll(super.afterPush(serverResponse, messageInfo, pushedRevision, originChanges));
    if (prBranchToUpdate == null || !deletePrBranch) {
        return baseEffects.build();
    }
    String projectId = ghHost.getProjectNameFromUrl(repoUrl);
    GitHubApi api = gitHubOptions.newGitHubApi(projectId);
    for (Change<?> change : originChanges) {
        Dict<String, String> labelDict = change.getLabelsForSkylark();
        String updatedPrBranchName = getUpdatedPrBranch(labelDict);
        checkCondition(!Objects.equals(updatedPrBranchName, "master"), "Cannot delete 'master' branch from GitHub");
        String completeRef = String.format("refs/heads/%s", updatedPrBranchName);
        try {
            api.deleteReference(projectId, completeRef);
            baseEffects.add(new DestinationEffect(Type.UPDATED, String.format("Reference '%s' deleted", completeRef), ImmutableList.of(change), new DestinationRef(completeRef, "ref_deleted", "https://github.com/" + projectId + "/tree/" + updatedPrBranchName)));
        } catch (GitHubApiException e) {
            if (e.getResponseCode() == ResponseCode.NOT_FOUND || e.getResponseCode() == ResponseCode.UNPROCESSABLE_ENTITY) {
                console.infoFmt("Branch %s does not exist", updatedPrBranchName);
                logger.atInfo().log("Branch %s does not exist", updatedPrBranchName);
                continue;
            }
            throw e;
        }
    }
    return baseEffects.build();
}
Also used : GitHubApi(com.google.copybara.git.github.api.GitHubApi) DestinationRef(com.google.copybara.effect.DestinationEffect.DestinationRef) DestinationEffect(com.google.copybara.effect.DestinationEffect) ImmutableList(com.google.common.collect.ImmutableList) GitHubApiException(com.google.copybara.git.github.api.GitHubApiException)

Example 19 with DestinationEffect

use of com.google.copybara.effect.DestinationEffect in project copybara by google.

the class GitHubPrDestination method newWriter.

@Override
public Writer<GitRevision> newWriter(WriterContext writerContext) throws ValidationException {
    String prBranch = getPullRequestBranchName(writerContext.getOriginalRevision(), writerContext.getWorkflowName(), writerContext.getWorkflowIdentityUser());
    GitHubPrWriteHook gitHubPrWriteHook = writeHook.withUpdatedPrBranch(prBranch);
    GitHubWriterState state = new GitHubWriterState(localRepo, destinationOptions.localRepoPath != null ? prBranch : "copybara/push-" + UUID.randomUUID() + (writerContext.isDryRun() ? "-dryrun" : ""));
    return new WriterImpl<GitHubWriterState>(writerContext.isDryRun(), url, getDestinationRef(), prBranch, partialFetch, /*tagName*/
    null, /*tagMsg*/
    null, generalOptions, gitHubPrWriteHook, state, /*nonFastForwardPush=*/
    true, integrates, destinationOptions.lastRevFirstParent, destinationOptions.ignoreIntegrationErrors, destinationOptions.localRepoPath, destinationOptions.committerName, destinationOptions.committerEmail, destinationOptions.rebaseWhenBaseline(), gitOptions.visitChangePageSize, gitOptions.gitTagOverwrite, checker) {

        @Override
        public ImmutableList<DestinationEffect> write(TransformResult transformResult, Glob destinationFiles, Console console) throws ValidationException, RepoException, IOException {
            ImmutableList.Builder<DestinationEffect> result = ImmutableList.<DestinationEffect>builder().addAll(super.write(transformResult, destinationFiles, console));
            if (writerContext.isDryRun() || state.pullRequestNumber != null) {
                return result.build();
            }
            if (!gitHubDestinationOptions.createPullRequest) {
                console.infoFmt("Please create a PR manually following this link: %s/compare/%s...%s" + " (Only needed once)", asHttpsUrl(), getDestinationRef(), prBranch);
                state.pullRequestNumber = -1L;
                return result.build();
            }
            GitHubApi api = gitHubOptions.newGitHubApi(getProjectName());
            ImmutableList<PullRequest> pullRequests = api.getPullRequests(getProjectName(), PullRequestListParams.DEFAULT.withHead(String.format("%s:%s", ghHost.getUserNameFromUrl(url), prBranch)));
            ChangeMessage msg = ChangeMessage.parseMessage(transformResult.getSummary().trim());
            String title = GitHubPrDestination.this.title == null ? msg.firstLine() : SkylarkUtil.mapLabels(transformResult.getLabelFinder(), GitHubPrDestination.this.title, "title");
            String prBody = GitHubPrDestination.this.body == null ? msg.toString() : SkylarkUtil.mapLabels(transformResult.getLabelFinder(), GitHubPrDestination.this.body, "body");
            for (PullRequest pr : pullRequests) {
                if (pr.getHead().getRef().equals(prBranch)) {
                    if (!pr.isOpen()) {
                        console.warnFmt("Pull request for branch %s already exists as %s/pull/%s, but is closed - " + "reopening.", prBranch, asHttpsUrl(), pr.getNumber());
                        api.updatePullRequest(getProjectName(), pr.getNumber(), new UpdatePullRequest(null, null, OPEN));
                    } else {
                        console.infoFmt("Pull request for branch %s already exists as %s/pull/%s", prBranch, asHttpsUrl(), pr.getNumber());
                    }
                    if (!pr.getBase().getRef().equals(getDestinationRef())) {
                        // TODO(malcon): Update PR or create a new one?
                        console.warnFmt("Current base branch '%s' is different from the PR base branch '%s'", getDestinationRef(), pr.getBase().getRef());
                    }
                    if (updateDescription) {
                        checkCondition(!Strings.isNullOrEmpty(title), "Pull Request title cannot be empty. Either use 'title' field in" + " git.github_pr_destination or modify the message to not be empty");
                        api.updatePullRequest(getProjectName(), pr.getNumber(), new UpdatePullRequest(title, prBody, /*state=*/
                        null));
                    }
                    result.add(new DestinationEffect(DestinationEffect.Type.UPDATED, String.format("Pull Request %s updated", pr.getHtmlUrl()), transformResult.getChanges().getCurrent(), new DestinationEffect.DestinationRef(Long.toString(pr.getNumber()), "pull_request", pr.getHtmlUrl())));
                    return result.build();
                }
            }
            checkCondition(!Strings.isNullOrEmpty(title), "Pull Request title cannot be empty. Either use 'title' field in" + " git.github_pr_destination or modify the message to not be empty");
            PullRequest pr = api.createPullRequest(getProjectName(), new CreatePullRequest(title, prBody, prBranch, getDestinationRef()));
            console.infoFmt("Pull Request %s/pull/%s created using branch '%s'.", asHttpsUrl(), pr.getNumber(), prBranch);
            state.pullRequestNumber = pr.getNumber();
            result.add(new DestinationEffect(DestinationEffect.Type.CREATED, String.format("Pull Request %s created", pr.getHtmlUrl()), transformResult.getChanges().getCurrent(), new DestinationEffect.DestinationRef(Long.toString(pr.getNumber()), "pull_request", pr.getHtmlUrl())));
            return result.build();
        }

        @Override
        public Endpoint getFeedbackEndPoint(Console console) throws ValidationException {
            gitHubOptions.validateEndpointChecker(endpointChecker);
            return new GitHubEndPoint(gitHubOptions.newGitHubApiSupplier(url, endpointChecker, ghHost), url, console, ghHost);
        }
    };
}
Also used : TransformResult(com.google.copybara.TransformResult) ImmutableList(com.google.common.collect.ImmutableList) CreatePullRequest(com.google.copybara.git.github.api.CreatePullRequest) UpdatePullRequest(com.google.copybara.git.github.api.UpdatePullRequest) PullRequest(com.google.copybara.git.github.api.PullRequest) CreatePullRequest(com.google.copybara.git.github.api.CreatePullRequest) WriterImpl(com.google.copybara.git.GitDestination.WriterImpl) GitHubApi(com.google.copybara.git.github.api.GitHubApi) DestinationEffect(com.google.copybara.effect.DestinationEffect) Console(com.google.copybara.util.console.Console) ChangeMessage(com.google.copybara.ChangeMessage) UpdatePullRequest(com.google.copybara.git.github.api.UpdatePullRequest) Glob(com.google.copybara.util.Glob)

Example 20 with DestinationEffect

use of com.google.copybara.effect.DestinationEffect in project copybara by google.

the class Mirror method run.

@Override
public void run(Path workdir, ImmutableList<String> sourceRefs) throws RepoException, IOException, ValidationException {
    try (ProfilerTask ignore = generalOptions.profiler().start("run/" + name)) {
        GitRepository repo = gitOptions.cachedBareRepoForUrl(origin);
        if (!Strings.isNullOrEmpty(gitDestinationOptions.committerName)) {
            repo.simpleCommand("config", "user.name", gitDestinationOptions.committerName);
        }
        if (!Strings.isNullOrEmpty(gitDestinationOptions.committerEmail)) {
            repo.simpleCommand("config", "user.email", gitDestinationOptions.committerEmail);
        }
        if (Iterables.isEmpty(actions)) {
            defaultMirror(repo);
        } else {
            ImmutableList.Builder<ActionResult> allResultsBuilder = ImmutableList.builder();
            for (Action action : actions) {
                GitMirrorContext context = new GitMirrorContext(action, new SkylarkConsole(generalOptions.console()), sourceRefs, refspec, origin, destination, generalOptions.isForced(), repo, generalOptions.getDirFactory(), Dict.empty());
                try {
                    action.run(context);
                    ActionResult actionResult = context.getActionResult();
                    allResultsBuilder.add(actionResult);
                    // First error aborts the execution of the other actions unless --force is used
                    ValidationException.checkCondition(generalOptions.isForced() || actionResult.getResult() != Result.ERROR, "Feedback migration '%s' action '%s' returned error: %s. Aborting execution.", name, action.getName(), actionResult.getMsg());
                } catch (NonFastForwardRepositoryException e) {
                    allResultsBuilder.add(ActionResult.error(action.getName() + ": " + e.getMessage()));
                    if (!generalOptions.isForced()) {
                        throw e;
                    }
                    logger.atWarning().withCause(e).log();
                } finally {
                    generalOptions.eventMonitors().dispatchEvent(m -> m.onChangeMigrationFinished(new ChangeMigrationFinishedEvent(ImmutableList.copyOf(context.getNewDestinationEffects()), getOriginDescription(), getDestinationDescription())));
                }
            }
            ImmutableList<ActionResult> allResults = allResultsBuilder.build();
            if (allResults.stream().anyMatch(a -> a.getResult() == Result.ERROR)) {
                String errors = allResults.stream().filter(a -> a.getResult() == Result.ERROR).map(ActionResult::getMsg).collect(Collectors.joining("\n - "));
                throw new ValidationException("One or more errors happened during the migration:\n" + " - " + errors);
            }
            // This check also returns true if there are no actions
            if (allResults.stream().allMatch(a -> a.getResult() == Result.NO_OP)) {
                String detailedMessage = allResults.isEmpty() ? "actions field is empty" : allResults.stream().map(ActionResult::getMsg).collect(ImmutableList.toImmutableList()).toString();
                throw new EmptyChangeException(String.format("git.mirror migration '%s' was noop. Detailed messages: %s", name, detailedMessage));
            }
        }
    }
    // More fine grain events based on the references created/updated/deleted:
    ChangeMigrationFinishedEvent event = new ChangeMigrationFinishedEvent(ImmutableList.of(new DestinationEffect(generalOptions.dryRunMode ? DestinationEffect.Type.NOOP : DestinationEffect.Type.UPDATED, generalOptions.dryRunMode ? "Refspecs " + refspec + " can be mirrored" : "Refspecs " + refspec + " mirrored successfully", // TODO(danielromero): Populate OriginRef here
    ImmutableList.of(), new DestinationRef(getOriginDestinationRef(destination), "mirror", /*url=*/
    null))), getOriginDescription(), getDestinationDescription());
    generalOptions.eventMonitors().dispatchEvent(m -> m.onChangeMigrationFinished(event));
}
Also used : Action(com.google.copybara.action.Action) ValidationException(com.google.copybara.exception.ValidationException) ChangeMigrationFinishedEvent(com.google.copybara.monitor.EventMonitor.ChangeMigrationFinishedEvent) ImmutableList(com.google.common.collect.ImmutableList) SkylarkConsole(com.google.copybara.transform.SkylarkConsole) ActionResult(com.google.copybara.action.ActionResult) DestinationRef(com.google.copybara.effect.DestinationEffect.DestinationRef) ProfilerTask(com.google.copybara.profiler.Profiler.ProfilerTask) DestinationEffect(com.google.copybara.effect.DestinationEffect) EmptyChangeException(com.google.copybara.exception.EmptyChangeException)

Aggregations

DestinationEffect (com.google.copybara.effect.DestinationEffect)39 DummyRevision (com.google.copybara.testing.DummyRevision)26 Test (org.junit.Test)22 WriterContext (com.google.copybara.WriterContext)19 Author (com.google.copybara.authoring.Author)13 Glob (com.google.copybara.util.Glob)13 ImmutableList (com.google.common.collect.ImmutableList)11 Changes (com.google.copybara.revision.Changes)10 Path (java.nio.file.Path)10 ValidationException (com.google.copybara.exception.ValidationException)9 RepoException (com.google.copybara.exception.RepoException)8 IOException (java.io.IOException)8 ImmutableSetMultimap (com.google.common.collect.ImmutableSetMultimap)7 ChangeMessage (com.google.copybara.ChangeMessage)7 Writer (com.google.copybara.Destination.Writer)7 Metadata (com.google.copybara.Metadata)7 MigrationInfo (com.google.copybara.MigrationInfo)7 TransformWork (com.google.copybara.TransformWork)7 CheckerException (com.google.copybara.checks.CheckerException)7 LowLevelHttpRequest (com.google.api.client.http.LowLevelHttpRequest)6