Search in sources :

Example 1 with PatchData

use of org.jboss.fuse.patch.management.PatchData in project fuse-karaf by jboss-fuse.

the class GitConflictResolutionIT method cherryPickConflict.

@Test
public void cherryPickConflict() throws Exception {
    prepareChanges2();
    RevWalk rw = new RevWalk(git.getRepository());
    git.checkout().setName("custom").setCreateBranch(false).call();
    ObjectId commit = git.getRepository().resolve("patched");
    CherryPickResult result = git.cherryPick().include(commit).call();
    RevCommit cMaster = rw.parseCommit(git.getRepository().resolve("master"));
    RevCommit cCustom = rw.parseCommit(git.getRepository().resolve("custom"));
    RevCommit cPatched = rw.parseCommit(git.getRepository().resolve("patched"));
    assertThat(result.getStatus(), equalTo(CherryPickResult.CherryPickStatus.CONFLICTING));
    Map<String, IndexDiff.StageState> conflicts = git.status().call().getConflictingStageState();
    assertThat(conflicts.size(), equalTo(2));
    assertThat(conflicts.get("etc/org.ops4j.pax.logging.cfg"), equalTo(IndexDiff.StageState.BOTH_MODIFIED));
    assertThat(conflicts.get("etc/file.properties"), equalTo(IndexDiff.StageState.BOTH_MODIFIED));
    new GitPatchManagementServiceImpl().handleCherryPickConflict(null, git, result, git.getRepository().parseCommit(commit), true, PatchKind.NON_ROLLUP, "x", false, false);
    RevCommit cMerged = git.commit().setMessage("resolved").call();
    // we have 4 commits (7349224 is a custom change that's conflicting with "patched" branch):
    /*
           * 92a9ad8 - (HEAD -> custom) resolved
           * 7349224 - custom etc/org.ops4j.pax.logging.cfg
           | * 5777547 - (patched) patched etc/org.ops4j.pax.logging.cfg
           |/
           * 306f328 - (master) original etc/org.ops4j.pax.logging.cfg
         */
    FileWriter writer = new FileWriter("target/report.html");
    PatchData pd = new PatchData("my-patch-id2");
    PatchResult patchResult = PatchResult.load(pd, getClass().getResourceAsStream("/conflicts/example1/fuse-karaf-7.0.0.fuse-000160.patch.result"));
    DiffUtils.generateDiffReport(new Patch(pd, null), patchResult, git, new HashSet<>(), cMaster, cCustom, cPatched, cMerged, writer);
    writer.close();
}
Also used : PatchData(org.jboss.fuse.patch.management.PatchData) ObjectId(org.eclipse.jgit.lib.ObjectId) AbbreviatedObjectId(org.eclipse.jgit.lib.AbbreviatedObjectId) FileWriter(java.io.FileWriter) RevWalk(org.eclipse.jgit.revwalk.RevWalk) CherryPickResult(org.eclipse.jgit.api.CherryPickResult) GitPatchManagementServiceImpl(org.jboss.fuse.patch.management.impl.GitPatchManagementServiceImpl) PatchResult(org.jboss.fuse.patch.management.PatchResult) Patch(org.jboss.fuse.patch.management.Patch) RevCommit(org.eclipse.jgit.revwalk.RevCommit) Test(org.junit.Test)

Example 2 with PatchData

use of org.jboss.fuse.patch.management.PatchData in project fuse-karaf by jboss-fuse.

the class PatchServiceImplTest method testLoadWithPrereqs.

@Test
public void testLoadWithPrereqs() throws IOException {
    PatchServiceImpl service = createMockServiceImpl();
    PatchData pd = PatchData.load(getClass().getClassLoader().getResourceAsStream("test-with-prereq.patch"));
    assertEquals(2, pd.getBundles().size());
    assertEquals(1, pd.getRequirements().size());
    assertTrue(pd.getRequirements().contains("prereq1"));
    assertNull(pd.getVersionRange("mvn:io.fabric8.test/test2/1.0.0"));
}
Also used : PatchData(org.jboss.fuse.patch.management.PatchData) Test(org.junit.Test)

Example 3 with PatchData

use of org.jboss.fuse.patch.management.PatchData in project fuse-karaf by jboss-fuse.

the class GitPatchManagementServiceImpl method updateOverrides.

/**
 * <p>Updates existing <code>etc/org.apache.karaf.features.xml</code> after installing single {@link PatchKind#NON_ROLLUP}
 * patch. Both bundle and feature replacements are taken into account.</p>
 * @param workTree
 * @param patches
 */
private void updateOverrides(File workTree, List<PatchData> patches) throws IOException {
    File overrides = new File(workTree, "etc/" + featureProcessing);
    File versions = new File(workTree, "etc/" + featureProcessingVersions);
    // we need two different versions to detect whether the version is externalized in etc/versions.properties
    FeaturesProcessing fp1;
    FeaturesProcessing fp2;
    if (overrides.isFile()) {
        fp1 = InternalUtils.loadFeatureProcessing(overrides, versions);
        fp2 = InternalUtils.loadFeatureProcessing(overrides, null);
    } else {
        fp1 = fp2 = new FeaturesProcessing();
    }
    List<BundleReplacements.OverrideBundle> br1 = fp1.getBundleReplacements().getOverrideBundles();
    List<BundleReplacements.OverrideBundle> br2 = fp2.getBundleReplacements().getOverrideBundles();
    org.apache.felix.utils.properties.Properties props = null;
    boolean propertyChanged = false;
    if (versions.isFile()) {
        props = new org.apache.felix.utils.properties.Properties(versions);
    }
    for (PatchData patchData : patches) {
        for (String bundle : patchData.getBundles()) {
            Artifact artifact = mvnurlToArtifact(bundle, true);
            if (artifact == null) {
                continue;
            }
            // Compute patch bundle version and range
            Version oVer = Utils.getOsgiVersion(artifact.getVersion());
            String vr = patchData.getVersionRange(bundle);
            if (vr != null && !vr.isEmpty()) {
                artifact.setVersion(vr);
            } else {
                Version v1 = new Version(oVer.getMajor(), oVer.getMinor(), 0);
                Version v2 = new Version(oVer.getMajor(), oVer.getMinor() + 1, 0);
                artifact.setVersion(new VersionRange(VersionRange.LEFT_CLOSED, v1, v2, VersionRange.RIGHT_OPEN).toString());
            }
            // features processing file may contain e.g.,:
            // <bundle originalUri="mvn:org.jboss.fuse/fuse-zen/[1,2)/war"
            // replacement="mvn:org.jboss.fuse/fuse-zen/${version.test2}/war" mode="maven" />
            // patch descriptor contains e.g.,:
            // bundle.0 = mvn:org.jboss.fuse/fuse-zen/1.2.0/war
            // bundle.0.range = [1.1,1.2)
            // 
            // we will always match by replacement attribute, ignoring originalUri - the patch descriptor must be
            // prepared correctly
            int idx = 0;
            BundleReplacements.OverrideBundle existing = null;
            // we'll examine model with resolved property placeholders, but modify the other one
            for (BundleReplacements.OverrideBundle override : br1) {
                LocationPattern lp = new LocationPattern(artifact.getCanonicalUri());
                if (lp.matches(override.getReplacement())) {
                    // we've found existing override in current etc/org.apache.karaf.features.xml
                    existing = br2.get(idx);
                    break;
                }
                idx++;
            }
            if (existing == null) {
                existing = new BundleReplacements.OverrideBundle();
                br2.add(existing);
            }
            // either update existing override or configure a new one
            existing.setMode(BundleReplacements.BundleOverrideMode.MAVEN);
            existing.setOriginalUri(artifact.getCanonicalUri());
            String replacement = existing.getReplacement();
            if (replacement != null && replacement.contains("${")) {
                // assume that we have existing replacement="mvn:org.jboss.fuse/fuse-zen/${version.test2}/war"
                // so we can't change the replacement and instead we have to update properties
                String property = null;
                String value = null;
                if (replacement.startsWith("mvn:")) {
                    LocationPattern existingReplacement = new LocationPattern(replacement);
                    property = existingReplacement.getVersionString().substring(existingReplacement.getVersionString().indexOf("${") + 2);
                    if (property.contains("}")) {
                        // it should...
                        property = property.substring(0, property.indexOf("}"));
                    }
                    LocationPattern newReplacement = new LocationPattern(bundle);
                    value = newReplacement.getVersionString();
                } else {
                // non-mvn? then we can't determine the version from non-mvn: URI...
                }
                // we are not changing replacement - we'll have to update properties
                if (props != null && property != null) {
                    props.setProperty(property, value);
                    propertyChanged = true;
                }
            } else {
                existing.setReplacement(bundle);
            }
        }
        // feature overrides
        File featureOverridesLocation = new File(patchData.getPatchDirectory(), "org.apache.karaf.features.xml");
        if (featureOverridesLocation.isFile()) {
            FeaturesProcessing featureOverrides = InternalUtils.loadFeatureProcessing(featureOverridesLocation, null);
            Map<String, FeatureReplacements.OverrideFeature> patchedFeatures = new LinkedHashMap<>();
            List<FeatureReplacements.OverrideFeature> mergedOverrides = new LinkedList<>();
            featureOverrides.getFeatureReplacements().getReplacements().forEach(of -> patchedFeatures.put(of.getFeature().getId(), of));
            fp2.getFeatureReplacements().getReplacements().forEach(of -> {
                FeatureReplacements.OverrideFeature override = patchedFeatures.remove(of.getFeature().getId());
                mergedOverrides.add(override == null ? of : override);
            });
            // add remaining
            mergedOverrides.addAll(patchedFeatures.values());
            fp2.getFeatureReplacements().getReplacements().clear();
            fp2.getFeatureReplacements().getReplacements().addAll(mergedOverrides);
        }
    }
    if (propertyChanged) {
        props.save();
    }
    InternalUtils.saveFeatureProcessing(fp2, overrides, versions);
}
Also used : BundleReplacements(org.apache.karaf.features.internal.model.processing.BundleReplacements) VersionRange(org.osgi.framework.VersionRange) FeatureReplacements(org.apache.karaf.features.internal.model.processing.FeatureReplacements) FeaturesProcessing(org.apache.karaf.features.internal.model.processing.FeaturesProcessing) LinkedHashMap(java.util.LinkedHashMap) Version(org.osgi.framework.Version) PatchData(org.jboss.fuse.patch.management.PatchData) Artifact(org.jboss.fuse.patch.management.Artifact) LinkedList(java.util.LinkedList) LocationPattern(org.apache.karaf.features.LocationPattern) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File)

Example 4 with PatchData

use of org.jboss.fuse.patch.management.PatchData in project fuse-karaf by jboss-fuse.

the class GitPatchManagementServiceImpl method loadPatch.

/**
 * Retrieves patch information from existing file
 * @param patchDescriptor existing file with patch descriptor (<code>*.patch</code> file)
 * @param details whether the returned {@link Patch} should contain {@link ManagedPatch} information
 * @return
 * @throws IOException
 */
private Patch loadPatch(File patchDescriptor, boolean details) throws IOException {
    Patch p = new Patch();
    if (!patchDescriptor.exists() || !patchDescriptor.isFile()) {
        return null;
    }
    PatchData data = PatchData.load(new FileInputStream(patchDescriptor));
    p.setPatchData(data);
    File patchDirectory = new File(patchesDir, FilenameUtils.getBaseName(patchDescriptor.getName()));
    if (patchDirectory.exists() && patchDirectory.isDirectory()) {
        // not every descriptor downloaded may be a ZIP file, not every patch has content
        data.setPatchDirectory(patchDirectory);
        File featureOverridesLocation = new File(patchDirectory, "org.apache.karaf.features.xml");
        if (featureOverridesLocation.isFile()) {
            // them available during all patch operations
            try {
                FeaturesProcessing featureOverrides = InternalUtils.loadFeatureProcessing(featureOverridesLocation, null);
                List<String> overrides = new LinkedList<>();
                if (featureOverrides.getFeatureReplacements().getReplacements() != null) {
                    featureOverrides.getFeatureReplacements().getReplacements().forEach(of -> overrides.add(of.getFeature().getId()));
                }
                data.setFeatureOverrides(overrides);
            } catch (Exception e) {
                Activator.log(LogService.LOG_WARNING, "Problem loading org.apache.karaf.features.xml from patch " + data.getId() + ": " + e.getMessage());
            }
        }
    }
    data.setPatchLocation(patchesDir);
    File resultFile = new File(patchesDir, FilenameUtils.getBaseName(patchDescriptor.getName()) + ".patch.result");
    if (resultFile.exists() && resultFile.isFile()) {
        PatchResult result = PatchResult.load(data, new FileInputStream(resultFile));
        p.setResult(result);
    }
    if (details) {
        ManagedPatch mp = gitPatchRepository.getManagedPatch(data.getId());
        p.setManagedPatch(mp);
    }
    return p;
}
Also used : ManagedPatch(org.jboss.fuse.patch.management.ManagedPatch) PatchData(org.jboss.fuse.patch.management.PatchData) PatchResult(org.jboss.fuse.patch.management.PatchResult) Patch(org.jboss.fuse.patch.management.Patch) ManagedPatch(org.jboss.fuse.patch.management.ManagedPatch) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) FileInputStream(java.io.FileInputStream) FeaturesProcessing(org.apache.karaf.features.internal.model.processing.FeaturesProcessing) LinkedList(java.util.LinkedList) PatchException(org.jboss.fuse.patch.management.PatchException) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) IOException(java.io.IOException)

Example 5 with PatchData

use of org.jboss.fuse.patch.management.PatchData in project fuse-karaf by jboss-fuse.

the class GitPatchManagementServiceImpl method checkPendingPatches.

@Override
public void checkPendingPatches() {
    File[] pendingPatches = patchesDir.listFiles(pathname -> pathname.exists() && pathname.getName().endsWith(".pending"));
    if (pendingPatches == null || pendingPatches.length == 0) {
        return;
    }
    final String dataCache = systemContext.getProperty("org.osgi.framework.storage");
    for (File pending : pendingPatches) {
        try {
            Pending what = Pending.valueOf(FileUtils.readFileToString(pending, "UTF-8"));
            final String prefix = what == Pending.ROLLUP_INSTALLATION ? "install" : "rollback";
            String name = pending.getName().replaceFirst("\\.pending$", "");
            if (isStandaloneChild()) {
                if (name.endsWith("." + System.getProperty("karaf.name") + ".patch")) {
                    name = name.replaceFirst("\\." + System.getProperty("karaf.name"), "");
                } else {
                    continue;
                }
            }
            File patchFile = new File(pending.getParentFile(), name);
            if (!patchFile.isFile()) {
                Activator.log(LogService.LOG_INFO, "Ignoring patch result file: " + patchFile.getName());
                continue;
            }
            PatchData patchData = PatchData.load(new FileInputStream(patchFile));
            Patch patch = loadPatch(new PatchDetailsRequest(patchData.getId()));
            String dataFilesName = patchData.getId() + ".datafiles";
            if (isStandaloneChild()) {
                dataFilesName = patchData.getId() + "." + System.getProperty("karaf.name") + ".datafiles";
            }
            final File dataFilesBackupDir = new File(pending.getParentFile(), dataFilesName);
            final Properties backupProperties = new Properties();
            FileInputStream inStream = new FileInputStream(new File(dataFilesBackupDir, "backup-" + prefix + ".properties"));
            backupProperties.load(inStream);
            Utils.closeQuietly(inStream);
            // maybe one of those bundles has data directory to restore?
            for (Bundle b : systemContext.getBundles()) {
                if (b.getSymbolicName() != null) {
                    String key = String.format("%s$$%s", stripSymbolicName(b.getSymbolicName()), b.getVersion().toString());
                    if (backupProperties.containsKey(key)) {
                        String backupDirName = backupProperties.getProperty(key);
                        File backupDir = new File(dataFilesBackupDir, prefix + "/" + backupDirName + "/data");
                        restoreDataDirectory(dataCache, b, backupDir);
                        // we no longer want to restore this dir
                        backupProperties.remove(key);
                    }
                }
            }
            // 2. We can however have more bundle data backups - we'll restore them after each bundle
            // is INSTALLED and we'll use listener for this
            BundleListener bundleListener = new SynchronousBundleListener() {

                @Override
                public void bundleChanged(BundleEvent event) {
                    Bundle b = event.getBundle();
                    if (event.getType() == BundleEvent.INSTALLED && b.getSymbolicName() != null) {
                        String key = String.format("%s$$%s", stripSymbolicName(b.getSymbolicName()), b.getVersion().toString());
                        if (backupProperties.containsKey(key)) {
                            String backupDirName = backupProperties.getProperty(key);
                            File backupDir = new File(dataFilesBackupDir, prefix + "/" + backupDirName + "/data");
                            restoreDataDirectory(dataCache, b, backupDir);
                        }
                    }
                }
            };
            systemContext.addBundleListener(bundleListener);
            pendingPatchesListeners.put(patchData.getId(), bundleListener);
        } catch (Exception e) {
            Activator.log(LogService.LOG_ERROR, null, e.getMessage(), e, true);
        }
    }
}
Also used : PatchData(org.jboss.fuse.patch.management.PatchData) Bundle(org.osgi.framework.Bundle) Properties(java.util.Properties) PatchDetailsRequest(org.jboss.fuse.patch.management.PatchDetailsRequest) FileInputStream(java.io.FileInputStream) PatchException(org.jboss.fuse.patch.management.PatchException) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) IOException(java.io.IOException) BundleEvent(org.osgi.framework.BundleEvent) BundleListener(org.osgi.framework.BundleListener) SynchronousBundleListener(org.osgi.framework.SynchronousBundleListener) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) Patch(org.jboss.fuse.patch.management.Patch) ManagedPatch(org.jboss.fuse.patch.management.ManagedPatch) Pending(org.jboss.fuse.patch.management.Pending) SynchronousBundleListener(org.osgi.framework.SynchronousBundleListener)

Aggregations

PatchData (org.jboss.fuse.patch.management.PatchData)16 Patch (org.jboss.fuse.patch.management.Patch)9 File (java.io.File)8 Test (org.junit.Test)8 IOException (java.io.IOException)6 LinkedList (java.util.LinkedList)6 PatchResult (org.jboss.fuse.patch.management.PatchResult)6 FileInputStream (java.io.FileInputStream)5 PatchException (org.jboss.fuse.patch.management.PatchException)5 ZipFile (org.apache.commons.compress.archivers.zip.ZipFile)4 BundleUpdate (org.jboss.fuse.patch.management.BundleUpdate)4 GitPatchManagementServiceImpl (org.jboss.fuse.patch.management.impl.GitPatchManagementServiceImpl)4 Bundle (org.osgi.framework.Bundle)4 HashMap (java.util.HashMap)3 LinkedHashMap (java.util.LinkedHashMap)3 Properties (java.util.Properties)3 Artifact (org.jboss.fuse.patch.management.Artifact)3 PatchDetailsRequest (org.jboss.fuse.patch.management.PatchDetailsRequest)3 Version (org.osgi.framework.Version)3 FileWriter (java.io.FileWriter)2