Search in sources :

Example 6 with Patch

use of io.fabric8.patch.management.Patch in project fabric8 by jboss-fuse.

the class GitPatchManagementServiceImpl method isHfChangeCommit.

/**
 * Checks whether the commit is related to HotFix patch installation.
 * Such patches are P patches that update <strong>only</strong> bundles.
 * @param rc
 * @return patchId of HF patch if one is detected
 */
private String isHfChangeCommit(RevCommit rc) {
    String msg = rc.getShortMessage();
    boolean pPatch = msg != null && msg.startsWith(MARKER_P_PATCH_INSTALLATION_PREFIX);
    if (pPatch) {
        String patchId = msg.length() > MARKER_P_PATCH_INSTALLATION_PREFIX.length() ? msg.substring(MARKER_P_PATCH_INSTALLATION_PREFIX.length()) : null;
        if (patchId != null) {
            Patch p = loadPatch(new PatchDetailsRequest(patchId));
            if (p != null && p.getPatchData() != null) {
                try {
                    boolean hfPatch = p.getPatchData().getBundles().size() > 0;
                    hfPatch &= p.getPatchData().getFeatureFiles().size() == 0;
                    hfPatch &= p.getPatchData().getFiles().size() == 0;
                    hfPatch &= p.getPatchData().getOtherArtifacts().size() == 0;
                    return patchId;
                } catch (Exception e) {
                    return null;
                }
            }
        }
    }
    return null;
}
Also used : ManagedPatch(io.fabric8.patch.management.ManagedPatch) Patch(io.fabric8.patch.management.Patch) PatchDetailsRequest(io.fabric8.patch.management.PatchDetailsRequest) PatchException(io.fabric8.patch.management.PatchException) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException)

Example 7 with Patch

use of io.fabric8.patch.management.Patch in project fabric8 by jboss-fuse.

the class GitPatchManagementServiceImpl method trackBaselinesForChildContainers.

/**
 * Tracks all baselines for child containers that weren't tracked already. These are looked up inside
 * <code>system/org/apache/karaf/admin/org.apache.karaf.admin.core/**</code>
 * @param fork
 */
private void trackBaselinesForChildContainers(Git fork) throws IOException, GitAPIException {
    if (fork.getRepository().getRef("refs/heads/" + gitPatchRepository.getChildBranchName()) == null) {
        // checkout patches-child branch - it'll track baselines for fabric:container-create-child containers
        String startPoint = "patch-management^{commit}";
        if (fork.getRepository().getRef("refs/remotes/origin/" + gitPatchRepository.getChildBranchName()) != null) {
            startPoint = "refs/remotes/origin/" + gitPatchRepository.getChildBranchName();
        }
        gitPatchRepository.checkout(fork).setName(gitPatchRepository.getChildBranchName()).setStartPoint(startPoint).setCreateBranch(true).setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK).call();
    } else {
        gitPatchRepository.checkout(fork).setName(gitPatchRepository.getChildBranchName()).call();
    }
    File systemRepo = getSystemRepository(karafHome, systemContext);
    File[] versionDirs = new File(systemRepo, "org/apache/karaf/admin/org.apache.karaf.admin.core").listFiles();
    Set<Version> versions = new TreeSet<>();
    if (versionDirs != null) {
        for (File version : versionDirs) {
            if (version.isDirectory()) {
                versions.add(Utils.getOsgiVersion(version.getName()));
            }
        }
    }
    for (Version v : versions) {
        String karafVersion = v.toString();
        String tagName = String.format(EnvType.FABRIC_CHILD.getBaselineTagFormat(), karafVersion);
        if (gitPatchRepository.containsTag(fork, tagName)) {
            continue;
        }
        File baselineDistribution = null;
        String location = String.format(systemRepo.getCanonicalPath() + "/org/apache/karaf/admin/org.apache.karaf.admin.core/%1$s/org.apache.karaf.admin.core-%1$s.jar", karafVersion);
        if (new File(location).isFile()) {
            baselineDistribution = new File(location);
            Activator.log(LogService.LOG_INFO, "Found child baseline distribution: " + baselineDistribution.getCanonicalPath());
        }
        if (baselineDistribution != null) {
            try {
                unzipKarafAdminJar(baselineDistribution, fork.getRepository().getWorkTree());
                fork.add().addFilepattern(".").call();
                RevCommit commit = gitPatchRepository.prepareCommit(fork, String.format(MARKER_BASELINE_CHILD_COMMIT_PATTERN, karafVersion)).call();
                // and we'll tag the child baseline
                fork.tag().setName(tagName).setObjectId(commit).call();
            } catch (Exception e) {
                Activator.log(LogService.LOG_ERROR, null, e.getMessage(), e, true);
            }
        }
    }
    gitPatchRepository.push(fork, gitPatchRepository.getChildBranchName());
}
Also used : Version(org.osgi.framework.Version) Artifact.isSameButVersion(io.fabric8.patch.management.Artifact.isSameButVersion) TreeSet(java.util.TreeSet) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) PatchException(io.fabric8.patch.management.PatchException) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 8 with Patch

use of io.fabric8.patch.management.Patch in project fabric8 by jboss-fuse.

the class GitPatchManagementServiceImpl method gatherOverrides.

/**
 * Returns list of bundle updates (maven coordinates) from HF/P patch that should be preserved during
 * installation of R patch
 * @param hfPatchId ID of patch that was detected to be HF patch
 * @param patch currently installed R patch
 * @return
 */
private List<String> gatherOverrides(String hfPatchId, Patch patch) {
    Patch hf = loadPatch(new PatchDetailsRequest(hfPatchId));
    List<String> result = new LinkedList<>();
    if (hf != null && hf.getPatchData() != null) {
        result.addAll(hf.getPatchData().getBundles());
        // leave only these artifacts that are in newer version than in R patch being installed
        if (patch != null && patch.getPatchData() != null) {
            Map<String, Artifact> cache = new HashMap<>();
            for (String bu : patch.getPatchData().getBundles()) {
                Artifact rPatchArtifact = Utils.mvnurlToArtifact(bu, true);
                if (rPatchArtifact != null) {
                    cache.put(String.format("%s:%s", rPatchArtifact.getGroupId(), rPatchArtifact.getArtifactId()), rPatchArtifact);
                }
            }
            for (String bu : hf.getPatchData().getBundles()) {
                Artifact hfPatchArtifact = Utils.mvnurlToArtifact(bu, true);
                String key = String.format("%s:%s", hfPatchArtifact.getGroupId(), hfPatchArtifact.getArtifactId());
                if (cache.containsKey(key)) {
                    Version hfVersion = Utils.getOsgiVersion(hfPatchArtifact.getVersion());
                    Version rVersion = Utils.getOsgiVersion(cache.get(key).getVersion());
                    if (rVersion.compareTo(hfVersion) >= 0) {
                        result.remove(bu);
                    }
                }
            }
        }
    }
    return result;
}
Also used : HashMap(java.util.HashMap) Version(org.osgi.framework.Version) Artifact.isSameButVersion(io.fabric8.patch.management.Artifact.isSameButVersion) ManagedPatch(io.fabric8.patch.management.ManagedPatch) Patch(io.fabric8.patch.management.Patch) PatchDetailsRequest(io.fabric8.patch.management.PatchDetailsRequest) LinkedList(java.util.LinkedList) Artifact(io.fabric8.patch.management.Artifact)

Example 9 with Patch

use of io.fabric8.patch.management.Patch in project fabric8 by jboss-fuse.

the class GitPatchManagementServiceImpl method listPatches.

@Override
public List<Patch> listPatches(boolean details) throws PatchException {
    List<Patch> patches = new LinkedList<>();
    File[] patchDescriptors = patchesDir.listFiles(new FilenameFilter() {

        @Override
        public boolean accept(File dir, String name) {
            return name.endsWith(".patch") && new File(dir, name).isFile();
        }
    });
    try {
        for (File pd : patchDescriptors) {
            Patch p = loadPatch(pd, details);
            patches.add(p);
        }
    } catch (IOException e) {
        throw new PatchException(e.getMessage(), e);
    }
    return patches;
}
Also used : FilenameFilter(java.io.FilenameFilter) IOException(java.io.IOException) PatchException(io.fabric8.patch.management.PatchException) ManagedPatch(io.fabric8.patch.management.ManagedPatch) Patch(io.fabric8.patch.management.Patch) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) LinkedList(java.util.LinkedList)

Example 10 with Patch

use of io.fabric8.patch.management.Patch in project fabric8 by jboss-fuse.

the class GitPatchManagementServiceImpl method trackPatch.

/**
 * <p>This method turns static information about a patch into managed patch - i.e., patch added to git
 * repository.</p>
 *
 * <p>Such patch has its own branch ready to be merged (when patch is installed). Before installation we can verify
 * the patch,
 * examine the content, check the differences, conflicts and perform simulation (merge to temporary branch created
 * from main patch branch)</p>
 *
 * <p>The strategy is as follows:<ul>
 *     <li><em>main patch branch</em> in git repository tracks all changes (from baselines, patch-management
 *     system, patches and user changes)</li>
 *     <li>Initially there are 3 commits: baseline, patch-management bundle installation in etc/startup.properties,
 *     initial user changes</li>
 *     <li>We always <strong>tag the baseline commit</strong></li>
 *     <li>User changes may be applied each time Framework is restarted</li>
 *     <li>When we add a patch, we create <em>named branch</em> from the <strong>latest baseline</strong></li>
 *     <li>When we install a patch, we <strong>merge</strong> the patch branch with the <em>main patch branch</em>
 *     (that may contain additional user changes)</li>
 *     <li>When patch ZIP contains new baseline distribution, after merging patch branch, we tag the merge commit
 *     in <em>main patch branch</em> branch as new baseline</li>
 *     <li>Branches for new patches will then be created from new baseline commit</li>
 * </ul></p>
 * @param patchData
 * @return
 */
@Override
public Patch trackPatch(PatchData patchData) throws PatchException {
    try {
        awaitInitialization();
    } catch (InterruptedException e) {
        throw new PatchException("Patch management system is not ready yet");
    }
    Git fork = null;
    try {
        Git mainRepository = gitPatchRepository.findOrCreateMainGitRepository();
        // prepare single fork for all the below operations
        fork = gitPatchRepository.cloneRepository(mainRepository, true);
        // 1. find current baseline
        RevTag latestBaseline = gitPatchRepository.findCurrentBaseline(fork);
        if (latestBaseline == null) {
            throw new PatchException("Can't find baseline distribution tracked in patch management. Is patch management initialized?");
        }
        // the commit from the patch should be available from main patch branch
        RevCommit commit = new RevWalk(fork.getRepository()).parseCommit(latestBaseline.getObject());
        // create dedicated branch for this patch. We'll immediately add patch content there so we can examine the
        // changes from the latest baseline
        gitPatchRepository.checkout(fork).setCreateBranch(true).setName("patch-" + patchData.getId()).setStartPoint(commit).call();
        // copy patch resources (but not maven artifacts from system/ or repository/) to working copy
        if (patchData.getPatchDirectory() != null) {
            boolean removeTargetDir = patchData.isRollupPatch();
            copyManagedDirectories(patchData.getPatchDirectory(), fork.getRepository().getWorkTree(), removeTargetDir, false, false);
        }
        // add the changes
        fork.add().addFilepattern(".").call();
        // remove the deletes (without touching specially-managed etc/overrides.properties)
        for (String missing : fork.status().call().getMissing()) {
            if (!"etc/overrides.properties".equals(missing)) {
                fork.rm().addFilepattern(missing).call();
            }
        }
        // record information about other "patches" included in added patch (e.g., Fuse patch
        // may contain patches to admin:create based containers in standalone mode)
        StringWriter sw = new StringWriter();
        sw.append("# tags for patches included in \"").append(patchData.getId()).append("\"\n");
        for (String bundle : patchData.getBundles()) {
            // containers that want to patch:install patches added in root containers
            if (bundle.contains("mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/")) {
                Artifact a = Utils.mvnurlToArtifact(bundle, true);
                if (a != null) {
                    sw.append(String.format(EnvType.STANDALONE_CHILD.getBaselineTagFormat(), a.getVersion())).append("\n");
                }
                break;
            }
        }
        FileUtils.write(new File(fork.getRepository().getWorkTree(), "patch-info.txt"), sw.toString());
        fork.add().addFilepattern(".").call();
        // commit the changes (patch vs. baseline) to patch branch
        gitPatchRepository.prepareCommit(fork, String.format("[PATCH] Tracking patch %s", patchData.getId())).call();
        // push the patch branch
        gitPatchRepository.push(fork, "patch-" + patchData.getId());
        // track other kinds of baselines found in the patch
        if (env.isFabric()) {
            trackBaselinesForRootContainer(fork);
            trackBaselinesForChildContainers(fork);
            trackBaselinesForSSHContainers(fork);
        } else {
            // for admin:create child containers
            trackBaselinesForChildContainers(fork);
        }
        return new Patch(patchData, gitPatchRepository.getManagedPatch(patchData.getId()));
    } catch (IOException | GitAPIException e) {
        throw new PatchException(e.getMessage(), e);
    } finally {
        if (fork != null) {
            gitPatchRepository.closeRepository(fork, true);
        }
    }
}
Also used : RevTag(org.eclipse.jgit.revwalk.RevTag) IOException(java.io.IOException) RevWalk(org.eclipse.jgit.revwalk.RevWalk) Artifact(io.fabric8.patch.management.Artifact) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) Git(org.eclipse.jgit.api.Git) StringWriter(java.io.StringWriter) PatchException(io.fabric8.patch.management.PatchException) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) ManagedPatch(io.fabric8.patch.management.ManagedPatch) Patch(io.fabric8.patch.management.Patch) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Aggregations

File (java.io.File)54 Test (org.junit.Test)43 Git (org.eclipse.jgit.api.Git)35 PatchException (io.fabric8.patch.management.PatchException)34 Patch (io.fabric8.patch.management.Patch)30 IOException (java.io.IOException)28 GitPatchManagementServiceImpl (io.fabric8.patch.management.impl.GitPatchManagementServiceImpl)27 GitPatchRepository (io.fabric8.patch.management.impl.GitPatchRepository)26 HashMap (java.util.HashMap)18 RevCommit (org.eclipse.jgit.revwalk.RevCommit)18 LinkedList (java.util.LinkedList)17 ZipFile (org.apache.commons.compress.archivers.zip.ZipFile)17 GitAPIException (org.eclipse.jgit.api.errors.GitAPIException)17 ObjectId (org.eclipse.jgit.lib.ObjectId)17 Bundle (org.osgi.framework.Bundle)17 Version (org.osgi.framework.Version)15 PatchResult (io.fabric8.patch.management.PatchResult)13 BundleUpdate (io.fabric8.patch.management.BundleUpdate)11 PatchData (io.fabric8.patch.management.PatchData)11 ArrayList (java.util.ArrayList)11