diff --git a/src/main/java/org/wildfly/installationmanager/CandidateType.java b/src/main/java/org/wildfly/installationmanager/CandidateType.java new file mode 100644 index 0000000..9f478ff --- /dev/null +++ b/src/main/java/org/wildfly/installationmanager/CandidateType.java @@ -0,0 +1,8 @@ +package org.wildfly.installationmanager; + +/** + * Supported candidate types + */ +public enum CandidateType { + UPDATE, REVERT +} diff --git a/src/main/java/org/wildfly/installationmanager/FileConflict.java b/src/main/java/org/wildfly/installationmanager/FileConflict.java new file mode 100644 index 0000000..5d76ba1 --- /dev/null +++ b/src/main/java/org/wildfly/installationmanager/FileConflict.java @@ -0,0 +1,101 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2024 Red Hat, Inc., and individual contributors + * as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.wildfly.installationmanager; + +import java.nio.file.Path; +import java.util.Objects; + +/** + * Represents a file modified by both the update and by the user. Such files cause a conflict and are resolved using + * a backup file to preserve either user or update changes. + */ +public class FileConflict { + + /** + * Describes the change to the file - it can be modified, removed, added, or not-existing (e.g. when a new file was added by user + * and doesn't exist in the update). + */ + public enum Status { + MODIFIED, + REMOVED, + ADDED, + NONE } + private Path relativePath; + private Status userChanges; + private Status updateChanges; + private boolean overwritten; + + public FileConflict(Path relativePath, Status userChanges, Status updateChanges, boolean overwritten) { + this.relativePath = relativePath; + this.userChanges = userChanges; + this.updateChanges = updateChanges; + this.overwritten = overwritten; + } + + /** + * File's Relative path to the server root + */ + public Path getRelativePath() { + return relativePath; + } + + /** + * The change to the current copy of the file, i.e. compared to previous installation/update state. + */ + public Status getUserChanges() { + return userChanges; + } + + /** + * The change performed in the update compared to the previous installation/update state. + */ + public Status getUpdateChanges() { + return updateChanges; + } + + /** + * Whether the user or update changes have been used to resolve conflict. Set to true if the update state overrides user changes, false otherwise. + */ + public boolean isOverwritten() { + return overwritten; + } + + @Override + public String toString() { + return "FileConflict{" + + "relativePath=" + relativePath + + ", userChanges=" + userChanges + + ", updateChanges=" + updateChanges + + ", overwritten=" + overwritten + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FileConflict that = (FileConflict) o; + return overwritten == that.overwritten && Objects.equals(relativePath, that.relativePath) && userChanges == that.userChanges && updateChanges == that.updateChanges; + } + + @Override + public int hashCode() { + return Objects.hash(relativePath, userChanges, updateChanges, overwritten); + } +} diff --git a/src/main/java/org/wildfly/installationmanager/spi/InstallationManager.java b/src/main/java/org/wildfly/installationmanager/spi/InstallationManager.java index 594f392..3049d53 100644 --- a/src/main/java/org/wildfly/installationmanager/spi/InstallationManager.java +++ b/src/main/java/org/wildfly/installationmanager/spi/InstallationManager.java @@ -18,6 +18,8 @@ package org.wildfly.installationmanager.spi; +import org.wildfly.installationmanager.CandidateType; +import org.wildfly.installationmanager.FileConflict; import org.wildfly.installationmanager.InstallationChanges; import org.wildfly.installationmanager.Channel; import org.wildfly.installationmanager.HistoryResult; @@ -29,7 +31,6 @@ import java.nio.file.Path; import java.util.Collection; import java.util.List; -import java.util.Optional; public interface InstallationManager { /** @@ -161,6 +162,7 @@ public interface InstallationManager { * @return a CLI command. * @throws OperationNotAvailableException - if the installation manager CLI support is not installed */ + @Deprecated String generateApplyUpdateCommand(Path scriptHome, Path candidatePath, OsShell shell) throws OperationNotAvailableException; /** @@ -173,12 +175,49 @@ public interface InstallationManager { * @return a CLI command. * @throws OperationNotAvailableException - if the installation manager CLI support is not installed */ + @Deprecated String generateApplyRevertCommand(Path scriptHome, Path candidatePath, OsShell shell) throws OperationNotAvailableException; + /** + * Generate an apply update CLI command. + * The generated command can be run in separate process to apply changes. + * + * @param candidatePath - Specify the directory path of the candidate installation to apply. + * @param scriptHome - Specify the directory path containing the script used to execute the apply command. + * @param shell - Specify what shell should the script be runnable in + * @param noConflictsOnly - Specify whether the command should fail if file conflicts are present + * @return a CLI command. + * @throws OperationNotAvailableException - if the installation manager CLI support is not installed + */ + String generateApplyUpdateCommand(Path scriptHome, Path candidatePath, OsShell shell, boolean noConflictsOnly) throws OperationNotAvailableException; + + /** + * Generate an apply rollback CLI command. + * The generated command can be run in separate process to apply changes. + * + * @param candidatePath - Specify the directory path of the candidate installation to apply. + * @param scriptHome - Specify the directory path containing the script used to execute the apply command. + * @param shell - Specify what shell should the script be runnable in + * @param noConflictsOnly - Specify whether the command should fail if file conflicts are present + * @return a CLI command. + * @throws OperationNotAvailableException - if the installation manager CLI support is not installed + */ + String generateApplyRevertCommand(Path scriptHome, Path candidatePath, OsShell shell, boolean noConflictsOnly) throws OperationNotAvailableException; + /** * Reports latest versions of manifests used in latest update/install operation for each registered channels. * @return list of {@link ManifestVersion}s * @throws Exception if there was an error reading the version information */ Collection getInstalledVersions() throws Exception; + + /** + * Checks a candidate for update or revert at {@code candidatePath} and generates a list of potential file conflicts. + * + * @param candidatePath - location of the candidate server + * @param candidateType - the type of the candidate server + * @return collection of the {@code FileConflicts} or an empty collection if no conflicts were found. + * @throws Exception - if there was an exception accessing the server information or if the candidate is invalid + */ + Collection verifyCandidate(Path candidatePath, CandidateType candidateType) throws Exception; }