Source:
public void rollbackPatch(Path target, boolean dryRun) throws IOException { List<PatchInfo> installedPatches = getInstalledPatches(target); if (installedPatches.isEmpty()) { throw MSG.patchNoPatchesInstalledToRollback(); } PatchInfo patchInfo = installedPatches.remove(installedPatches.size() - 1); Path backup = getBackupPath(target, patchInfo); for (PatchOperation operation : patchInfo.getOperations()) { switch (operation.getAction()) { case ADD: { Path file = target.resolve(operation.getNewPath()); println(dryRun, MSG.patchRollbackFile(file)); if (!dryRun) { Files.delete(file); } } break; case SOFT_REPLACE: { Path file = target.resolve(operation.getPath()); String sha256 = sha256(file); if (sha256.equals(operation.getDigest())) { println(dryRun, MSG.patchRollbackFile(file)); if (!dryRun) { Files.move(backup.resolve(operation.getPath()), target.resolve(operation.getPath()), StandardCopyOption.REPLACE_EXISTING); } } } case UPGRADE: { Path file = target.resolve(operation.getNewPath()); println(dryRun, MSG.patchRollbackFile(file)); if (!dryRun) { Files.delete(file); } } case REMOVE: case HARD_REPLACE: { Path file = target.resolve(operation.getPath()); println(dryRun, MSG.patchRollbackFile(file)); if (!dryRun) { Files.move(backup.resolve(operation.getPath()), target.resolve(operation.getPath()), StandardCopyOption.REPLACE_EXISTING); } } break; } } if (!dryRun) { writeInstalledPatches(target, installedPatches); } println(dryRun, MSG.patchRollback(patchInfo)); }

Target:
public void rollbackPatch(Path target, boolean dryRun) throws IOException { List<PatchInfo> installedPatches = getInstalledPatches(target); if (installedPatches.isEmpty()) { throw MSG.patchNoPatchesInstalledToRollback(); } PatchInfo patchInfo = installedPatches.remove(installedPatches.size() - 1); Path backup = getBackupPath(target, patchInfo); for (PatchOperation operation : patchInfo.getOperations()) { switch (operation.getAction()) { case ADD: { Path file = target.resolve(operation.getNewPath()); println(dryRun, MSG.patchRollbackFile(file)); if (!dryRun) { Files.delete(file); } } break; case SOFT_REPLACE: { Path file = target.resolve(operation.getPath()); String sha256 = sha256(file); if (sha256 != null && sha256.equals(operation.getNewDigest())) { println(dryRun, MSG.patchRollbackFile(file)); if (!dryRun) { Files.move(backup.resolve(operation.getPath()), target.resolve(operation.getPath()), StandardCopyOption.REPLACE_EXISTING); } } file = target.resolve(operation.getNewPath()); file = file.getParent().resolve(file.getFileName().toString() + "-" + patchInfo.getTargetVersion()); if (Files.exists(file)) { println(dryRun, MSG.patchRollbackFile(file)); if (!dryRun) { Files.delete(file); } } break; } case UPGRADE: { Path file = target.resolve(operation.getNewPath()); if (!dryRun) { Files.delete(file); } } case REMOVE: case HARD_REPLACE: { Path file = target.resolve(operation.getPath()); println(dryRun, MSG.patchRollbackFile(file)); if (!dryRun) { Files.move(backup.resolve(operation.getPath()), target.resolve(operation.getPath()), StandardCopyOption.REPLACE_EXISTING); } } break; } } if (!dryRun) { writeInstalledPatches(target, installedPatches); } println(dryRun, MSG.patchRollback(patchInfo)); }