use of com.google.copybara.exception.ValidationException in project copybara by google.
the class PatchingOptionsTest method applyExcludedWithForcePatch.
@Test
public void applyExcludedWithForcePatch() throws Exception {
forceUseGnuPatch();
ValidationException e = assertThrows(ValidationException.class, () -> checkApplyExcluded());
assertThat(e).hasMessageThat().contains("--patch-skip-version-check is incompatible with patch transformations that uses" + " excluded paths");
}
use of com.google.copybara.exception.ValidationException 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) {
/**
* 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 = startRevision.associatedLabels().get(GITHUB_BASE_BRANCH_SHA1);
Preconditions.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() {
return new GitHubEndPoint(githubOptions, url);
}
/**
* 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 {
if (!useMerge) {
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);
}
}
@Nullable
@Override
public String getGroupIdentity(GitRevision rev) throws RepoException {
return rev.associatedLabels().get(GITHUB_PR_NUMBER_LABEL);
}
};
}
use of com.google.copybara.exception.ValidationException in project copybara by google.
the class WorkflowRunHelper method doMigrate.
private ImmutableList<DestinationEffect> doMigrate(O rev, @Nullable O lastRev, Console processConsole, Metadata metadata, Changes changes, @Nullable String destinationBaseline, @Nullable O changeIdentityRevision) throws IOException, RepoException, ValidationException {
Path checkoutDir = workdir.resolve("checkout");
try (ProfilerTask ignored = profiler().start("prepare_workdir")) {
processConsole.progress("Cleaning working directory");
if (Files.exists(workdir)) {
FileUtil.deleteRecursively(workdir);
}
Files.createDirectories(checkoutDir);
}
processConsole.progress("Checking out the change");
try (ProfilerTask ignored = profiler().start("origin.checkout", profiler().taskType(workflow.getOrigin().getType()))) {
originReader.checkout(rev, checkoutDir);
}
// Remove excluded origin files.
PathMatcher originFiles = workflow.getOriginFiles().relativeTo(checkoutDir);
processConsole.progress("Removing excluded origin files");
int deleted = FileUtil.deleteFilesRecursively(checkoutDir, FileUtil.notPathMatcher(originFiles));
if (deleted != 0) {
processConsole.info(String.format("Removed %d files from workdir that do not match origin_files", deleted));
}
Path originCopy = null;
if (workflow.getReverseTransformForCheck() != null) {
try (ProfilerTask ignored = profiler().start("reverse_copy")) {
workflow.getConsole().progress("Making a copy or the workdir for reverse checking");
originCopy = Files.createDirectories(workdir.resolve("origin"));
FileUtil.copyFilesRecursively(checkoutDir, originCopy, FAIL_OUTSIDE_SYMLINKS);
}
}
TransformWork transformWork = new TransformWork(checkoutDir, metadata, changes, workflow.getConsole(), new MigrationInfo(getOriginLabelName(), writer), resolvedRef).withLastRev(lastRev).withCurrentRev(rev);
try (ProfilerTask ignored = profiler().start("transforms")) {
workflow.getTransformation().transform(transformWork);
}
if (workflow.getReverseTransformForCheck() != null) {
workflow.getConsole().progress("Checking that the transformations can be reverted");
Path reverse;
try (ProfilerTask ignored = profiler().start("reverse_copy")) {
reverse = Files.createDirectories(workdir.resolve("reverse"));
FileUtil.copyFilesRecursively(checkoutDir, reverse, FAIL_OUTSIDE_SYMLINKS);
}
try (ProfilerTask ignored = profiler().start("reverse_transform")) {
workflow.getReverseTransformForCheck().transform(new TransformWork(reverse, new Metadata(transformWork.getMessage(), transformWork.getAuthor()), changes, workflow.getConsole(), new MigrationInfo(/*originLabel=*/
null, null), resolvedRef));
}
String diff;
try {
diff = new String(DiffUtil.diff(originCopy, reverse, workflow.isVerbose(), workflow.getGeneralOptions().getEnvironment()), StandardCharsets.UTF_8);
} catch (InsideGitDirException e) {
throw new ValidationException("Cannot use 'reversible_check = True' because Copybara temporary directory (%s) is" + " inside a git directory (%s). Please remove the git repository or use %s flag.", e.getPath(), e.getGitDirPath(), OUTPUT_ROOT_FLAG);
}
if (!diff.trim().isEmpty()) {
workflow.getConsole().error("Non reversible transformations:\n" + DiffUtil.colorize(workflow.getConsole(), diff));
throw new ValidationException("Workflow '%s' is not reversible", workflow.getName());
}
}
workflow.getConsole().progress("Checking that destination_files covers all files in transform result");
new ValidateDestinationFilesVisitor(workflow.getDestinationFiles(), checkoutDir).verifyFilesToWrite();
// TODO(malcon): Pass metadata object instead
TransformResult transformResult = new TransformResult(checkoutDir, rev, transformWork.getAuthor(), transformWork.getMessage(), resolvedRef, workflow.getName(), changes, rawSourceRef);
if (destinationBaseline != null) {
transformResult = transformResult.withBaseline(destinationBaseline);
}
transformResult = transformResult.withAskForConfirmation(workflow.isAskForConfirmation()).withIdentity(workflow.getMigrationIdentity(changeIdentityRevision, transformWork));
ImmutableList<DestinationEffect> result;
try (ProfilerTask ignored = profiler().start("destination.write", profiler().taskType(workflow.getDestination().getType()))) {
result = writer.write(transformResult, processConsole);
}
Verify.verifyNotNull(result, "Destination returned a null result.");
Verify.verify(!result.isEmpty(), "Destination " + writer + " returned an empty set of effects");
return result;
}
use of com.google.copybara.exception.ValidationException in project copybara by google.
the class WorkflowRunHelper method migrate.
/**
* Performs a full migration, including checking out files from the origin, deleting excluded
* files, transforming the code, and writing to the destination. This writes to the destination
* exactly once.
*
* @param rev revision to the version which will be written to the destination
* @param lastRev last revision that was migrated
* @param processConsole console to use to print progress messages
* @param metadata metadata of the change to be migrated
* @param changes changes included in this migration
* @param destinationBaseline it not null, use this baseline in the destination
* @param changeIdentityRevision the revision to be used for computing the change identity
*/
ImmutableList<DestinationEffect> migrate(O rev, @Nullable O lastRev, Console processConsole, Metadata metadata, Changes changes, @Nullable String destinationBaseline, @Nullable O changeIdentityRevision) throws IOException, RepoException, ValidationException {
ImmutableList<DestinationEffect> effects = ImmutableList.of();
boolean callPerMigrationHook = true;
try {
eventMonitor().onChangeMigrationStarted(new ChangeMigrationStartedEvent());
effects = doMigrate(rev, lastRev, processConsole, metadata, changes, destinationBaseline, changeIdentityRevision);
return effects;
} catch (EmptyChangeException empty) {
effects = ImmutableList.of(new DestinationEffect(Type.NOOP, empty.getMessage(), changes.getCurrent(), /*destinationRef=*/
null, ImmutableList.of()));
throw empty;
} catch (ValidationException | IOException | RepoException | RuntimeException e) {
effects = ImmutableList.of(new DestinationEffect(Type.ERROR, "Errors happened during the migration", changes.getCurrent(), /*destinationRef=*/
null, ImmutableList.of(e.getMessage() != null ? e.getMessage() : e.toString())));
callPerMigrationHook = e instanceof ValidationException;
throw e;
} finally {
eventMonitor().onChangeMigrationFinished(new ChangeMigrationFinishedEvent(effects));
if (callPerMigrationHook) {
FinishHookContext finishHookContext = new FinishHookContext(getOriginReader().getFeedbackEndPoint(), getDestinationWriter().getFeedbackEndPoint(), effects, resolvedRef, new SkylarkConsole(getConsole()));
try (ProfilerTask ignored = profiler().start("finish_hooks")) {
for (Action action : workflow.getAfterMigrationActions()) {
try (ProfilerTask ignored2 = profiler().start(action.getName())) {
logger.log(Level.INFO, "Running after migration hook: " + action.getName());
action.run(finishHookContext);
}
}
}
}
}
}
use of com.google.copybara.exception.ValidationException in project copybara by google.
the class Copybara method validate.
/**
* Validates that the configuration is correct and that there is a valid migration specified by
* {@code migrationName}.
*
* <p>Note that, besides validating the specific migration, all the configuration will be
* validated syntactically.
*/
public boolean validate(Options options, ConfigLoader<?> configLoader, String migrationName) throws IOException {
Console console = options.get(GeneralOptions.class).console();
ArrayList<Message> messages = new ArrayList<>();
try {
Config config = configLoader.loadConfig(options, console);
messages.addAll(validateConfig(config, migrationName));
} catch (ValidationException e) {
// The validate subcommand should not throw Validation exceptions but log a result
StringBuilder error = new StringBuilder(e.getMessage()).append("\n");
Throwable cause = e.getCause();
while (cause != null) {
error.append(" CAUSED BY: ").append(cause.getMessage()).append("\n");
cause = cause.getCause();
}
messages.add(Message.error(error.toString()));
}
messages.forEach(message -> message.printTo(console));
boolean hasNoErrors = messages.stream().noneMatch(message -> message.getType() == MessageType.ERROR);
if (hasNoErrors) {
console.info(String.format("Configuration '%s' is valid.", configLoader.location()));
} else {
console.error(String.format("Configuration '%s' is invalid.", configLoader.location()));
}
return hasNoErrors;
}
Aggregations