You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by to...@apache.org on 2017/10/06 14:38:46 UTC

svn commit: r1811337 - in /jackrabbit/oak/trunk/oak-upgrade/src: main/java/org/apache/jackrabbit/oak/upgrade/ main/java/org/apache/jackrabbit/oak/upgrade/version/ test/java/org/apache/jackrabbit/oak/upgrade/

Author: tomekr
Date: Fri Oct  6 14:38:46 2017
New Revision: 1811337

URL: http://svn.apache.org/viewvc?rev=1811337&view=rev
Log:
OAK-6633: Overwriting a versionable node with the copy-versions=false doesn't remove versionable properties

Modified:
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionablePropertiesEditor.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistoryTest.java

Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java?rev=1811337&r1=1811336&r2=1811337&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositorySidegrade.java Fri Oct  6 14:38:46 2017
@@ -29,14 +29,17 @@ import javax.jcr.RepositoryException;
 
 import com.google.common.collect.Lists;
 import org.apache.commons.lang.StringUtils;
+import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.plugins.migration.FilteringNodeState;
 import org.apache.jackrabbit.oak.plugins.migration.NameFilteringNodeState;
 import org.apache.jackrabbit.oak.plugins.migration.NodeStateCopier;
 import org.apache.jackrabbit.oak.plugins.migration.report.LoggingReporter;
 import org.apache.jackrabbit.oak.plugins.migration.report.ReportingNodeState;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
 import org.apache.jackrabbit.oak.segment.SegmentNodeState;
 import org.apache.jackrabbit.oak.segment.file.FileStore;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
@@ -470,6 +473,18 @@ public class RepositorySidegrade {
                 createIndexEditorProvider()
         )));
         target.merge(targetRoot, new LoggingCompositeHook(hooks, null, false), CommitInfo.EMPTY);
+        removeVersions();
+    }
+
+    private void removeVersions() throws CommitFailedException {
+        NodeState root = target.getRoot();
+        NodeState wrappedRoot = FilteringNodeState.wrap(PathUtils.ROOT_PATH, root, includePaths, excludePaths, fragmentPaths, excludeFragments);
+        List<String> versionablesToStrip = VersionHistoryUtil.getVersionableNodes(wrappedRoot, new TypePredicate(root, JcrConstants.MIX_VERSIONABLE), versionCopyConfiguration.getVersionsMinDate());
+        if (!versionablesToStrip.isEmpty()) {
+            LOG.info("Removing version histories for included paths");
+            NodeBuilder newRoot = VersionHistoryUtil.removeVersions(root, versionablesToStrip);
+            target.merge(newRoot, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        }
     }
 
     private boolean isCompleteMigration() {

Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java?rev=1811337&r1=1811336&r2=1811337&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java Fri Oct  6 14:38:46 2017
@@ -66,6 +66,7 @@ import com.google.common.collect.HashBiM
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
+import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
 import org.apache.jackrabbit.core.IndexAccessor;
 import org.apache.jackrabbit.core.RepositoryContext;
@@ -82,6 +83,7 @@ import org.apache.jackrabbit.core.securi
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.index.CompositeIndexEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
@@ -89,10 +91,13 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.IndexUpdateCallback;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceEditorProvider;
+import org.apache.jackrabbit.oak.plugins.migration.FilteringNodeState;
 import org.apache.jackrabbit.oak.plugins.migration.NameFilteringNodeState;
 import org.apache.jackrabbit.oak.plugins.migration.NodeStateCopier;
 import org.apache.jackrabbit.oak.plugins.migration.report.LoggingReporter;
 import org.apache.jackrabbit.oak.plugins.migration.report.ReportingNodeState;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.namespace.NamespaceConstants;
 import org.apache.jackrabbit.oak.plugins.name.Namespaces;
 import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
@@ -578,12 +583,26 @@ public class RepositoryUpgrade {
 
             target.merge(targetBuilder, new LoggingCompositeHook(hooks, source, overrideEarlyShutdown()), CommitInfo.EMPTY);
             logger.info("Processing commit hooks completed in {}s ({})", watch.elapsed(TimeUnit.SECONDS), watch);
+
+            removeVersions();
+
             logger.debug("Repository upgrade completed.");
         } catch (Exception e) {
             throw new RepositoryException("Failed to copy content", e);
         }
     }
 
+    private void removeVersions() throws CommitFailedException {
+        NodeState root = target.getRoot();
+        NodeState wrappedRoot = FilteringNodeState.wrap(PathUtils.ROOT_PATH, root, includePaths, excludePaths, fragmentPaths, excludeFragments);
+        List<String> versionablesToStrip = VersionHistoryUtil.getVersionableNodes(wrappedRoot, new TypePredicate(root, JcrConstants.MIX_VERSIONABLE), versionCopyConfiguration.getVersionsMinDate());
+        if (!versionablesToStrip.isEmpty()) {
+            logger.info("Removing version histories for included paths");
+            NodeBuilder newRoot = VersionHistoryUtil.removeVersions(root, versionablesToStrip);
+            target.merge(newRoot, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        }
+    }
+
     private boolean overrideEarlyShutdown() {
         if (earlyShutdown == false) {
             return false;
@@ -599,6 +618,10 @@ public class RepositoryUpgrade {
             logger.info("Overriding early shutdown to false because of the copy versions settings");
             return false;
         }
+        if (c.isCopyVersions() && target.getRoot().hasChildNode(JcrConstants.JCR_SYSTEM)) {
+            logger.info("Overriding early shutdown to false because the target exists");
+            return false;
+        }
         return true;
     }
 

Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java?rev=1811337&r1=1811336&r2=1811337&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionCopier.java Fri Oct  6 14:38:46 2017
@@ -16,24 +16,21 @@
  */
 package org.apache.jackrabbit.oak.upgrade.version;
 
-import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
 import static org.apache.jackrabbit.JcrConstants.NT_VERSION;
 
 import java.util.Calendar;
 import java.util.Iterator;
 
-import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.migration.NodeStateCopier;
 import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
-import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.upgrade.DescendantsIterator;
-import org.apache.jackrabbit.util.ISO8601;
 
 import static org.apache.jackrabbit.oak.spi.version.VersionConstants.VERSION_STORE_PATH;
 
 import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getRelativeVersionHistoryPath;
+import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getVersionHistoryLastModified;
 import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getVersionHistoryNodeState;
 
 /**
@@ -94,21 +91,4 @@ public class VersionCopier {
         return false;
     }
 
-    private Calendar getVersionHistoryLastModified(final NodeState versionHistory) {
-        Calendar youngest = Calendar.getInstance();
-        youngest.setTimeInMillis(0);
-        for (final ChildNodeEntry entry : versionHistory.getChildNodeEntries()) {
-            final NodeState version = entry.getNodeState();
-            if (!isVersion.apply(version)) {
-                continue;
-            }
-            if (version.hasProperty(JCR_CREATED)) {
-                final Calendar created = ISO8601.parse(version.getProperty(JCR_CREATED).getValue(Type.DATE));
-                if (created.after(youngest)) {
-                    youngest = created;
-                }
-            }
-        }
-        return youngest;
-    }
 }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java?rev=1811337&r1=1811336&r2=1811337&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionHistoryUtil.java Fri Oct  6 14:38:46 2017
@@ -16,24 +16,46 @@
  */
 package org.apache.jackrabbit.oak.upgrade.version;
 
+import static com.google.common.collect.ImmutableSet.of;
 import static com.google.common.collect.Iterables.concat;
+import static com.google.common.collect.Sets.newHashSet;
 import static java.util.Collections.singleton;
+import static org.apache.jackrabbit.JcrConstants.JCR_BASEVERSION;
+import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
+import static org.apache.jackrabbit.JcrConstants.JCR_ISCHECKEDOUT;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_PREDECESSORS;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
+import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
+import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONHISTORY;
 import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONSTORAGE;
+import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE;
+import static org.apache.jackrabbit.JcrConstants.MIX_VERSIONABLE;
+import static org.apache.jackrabbit.oak.plugins.memory.MultiGenericPropertyState.nameProperty;
 import static org.apache.jackrabbit.oak.spi.version.VersionConstants.REP_VERSIONSTORAGE;
 
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
 import com.google.common.base.Joiner;
+import org.apache.jackrabbit.util.ISO8601;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class VersionHistoryUtil {
 
+    private static final Logger LOG = LoggerFactory.getLogger(VersionHistoryUtil.class);
+
     public static String getRelativeVersionHistoryPath(String versionableUuid) {
         return Joiner.on('/').join(concat(
                 singleton(""),
@@ -44,7 +66,7 @@ public class VersionHistoryUtil {
     /**
      * Constructs the version history path based on the versionable's UUID.
      *
-     * @param root The root NodeState below which to look for the version.
+     * @param versionStorage below which to look for the version.
      * @param versionableUuid The String representation of the versionable's UUID.
      * @return The NodeState corresponding to the version history, or {@code null}
      *         if it does not exist.
@@ -57,7 +79,7 @@ public class VersionHistoryUtil {
         return historyParent.getChildNode(versionableUuid);
     }
 
-    static NodeBuilder getVersionHistoryBuilder(NodeBuilder versionStorage, String versionableUuid) {
+    public static NodeBuilder getVersionHistoryBuilder(NodeBuilder versionStorage, String versionableUuid) {
         NodeBuilder history = versionStorage;
         for (String segment : getRelativeVersionHistoryPathSegments(versionableUuid)) {
             history = history.getChildNode(segment);
@@ -89,4 +111,108 @@ public class VersionHistoryUtil {
         return vs;
     }
 
+    public static List<String> getVersionableNodes(NodeState root, TypePredicate isVersionable, Calendar olderThan) {
+        List<String> paths = new ArrayList<>();
+        NodeState versionStorage = getVersionStorage(root);
+        getVersionableNodes(root, versionStorage, isVersionable, olderThan, PathUtils.ROOT_PATH, paths);
+        return paths;
+    }
+
+
+    private static void getVersionableNodes(NodeState node, NodeState versionStorage, TypePredicate isVersionable, Calendar olderThan, String path, List<String> paths) {
+        if (isVersionable.apply(node)) {
+            if (olderThan == null) {
+                paths.add(path);
+            } else {
+                NodeState versionHistory = getVersionHistoryNodeState(versionStorage, node.getString(JCR_UUID));
+                Calendar lastModified = getVersionHistoryLastModified(versionHistory);
+                if (lastModified.before(olderThan)) {
+                    paths.add(path);
+                }
+            }
+        }
+        for (ChildNodeEntry c : node.getChildNodeEntries()) {
+            getVersionableNodes(c.getNodeState(), versionStorage, isVersionable, olderThan, PathUtils.concat(path, c.getName()), paths);
+        }
+    }
+
+    public static Calendar getVersionHistoryLastModified(NodeState versionHistory) {
+        Calendar youngest = Calendar.getInstance();
+        youngest.setTimeInMillis(0);
+        for (final ChildNodeEntry entry : versionHistory.getChildNodeEntries()) {
+            final NodeState version = entry.getNodeState();
+            if (version.hasProperty(JCR_CREATED)) {
+                final Calendar created = ISO8601.parse(version.getProperty(JCR_CREATED).getValue(Type.DATE));
+                if (created.after(youngest)) {
+                    youngest = created;
+                }
+            }
+        }
+        return youngest;
+    }
+
+    public static void removeVersionProperties(NodeBuilder versionableBuilder, TypePredicate isReferenceable) {
+        assert versionableBuilder.exists();
+
+        removeMixin(versionableBuilder, MIX_VERSIONABLE);
+
+        // we don't know if the UUID is otherwise referenced,
+        // so make sure the node remains referencable
+        if (!isReferenceable.apply(versionableBuilder.getNodeState())) {
+            addMixin(versionableBuilder, MIX_REFERENCEABLE);
+        }
+
+        versionableBuilder.removeProperty(JCR_VERSIONHISTORY);
+        versionableBuilder.removeProperty(JCR_PREDECESSORS);
+        versionableBuilder.removeProperty(JCR_BASEVERSION);
+        versionableBuilder.removeProperty(JCR_ISCHECKEDOUT);
+    }
+
+    static void addMixin(NodeBuilder builder, String name) {
+        if (builder.hasProperty(JCR_MIXINTYPES)) {
+            final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
+            if (mixins.add(name)) {
+                builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
+            }
+        } else {
+            builder.setProperty(nameProperty(JCR_MIXINTYPES, of(name)));
+        }
+    }
+
+    private static void removeMixin(NodeBuilder builder, String name) {
+        if (builder.hasProperty(JCR_MIXINTYPES)) {
+            final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
+            if (mixins.remove(name)) {
+                if (mixins.isEmpty()) {
+                    builder.removeProperty(JCR_MIXINTYPES);
+                } else {
+                    builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
+                }
+            }
+        }
+    }
+
+    public static NodeBuilder removeVersions(NodeState root,
+                               List<String> toRemove) {
+        NodeBuilder rootBuilder = root.builder();
+        TypePredicate isReferenceable = new TypePredicate(root, MIX_REFERENCEABLE);
+        NodeBuilder versionStorage = getVersionStorage(rootBuilder);
+        for (String p : toRemove) {
+            LOG.info("Removing version history for {}", p);
+            NodeBuilder b = getBuilder(rootBuilder, p);
+            String uuid = b.getString(JCR_UUID);
+            VersionHistoryUtil.removeVersionProperties(b, isReferenceable);
+            getVersionHistoryBuilder(versionStorage, uuid).remove();
+        }
+        return rootBuilder;
+    }
+
+    private static NodeBuilder getBuilder(NodeBuilder root, String path) {
+        NodeBuilder builder = root;
+        for (String e : PathUtils.elements(path)) {
+            builder = builder.child(e);
+        }
+        return builder;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java?rev=1811337&r1=1811336&r2=1811337&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionableEditor.java Fri Oct  6 14:38:46 2017
@@ -34,19 +34,14 @@ import java.util.Collections;
 import java.util.Set;
 
 import static com.google.common.collect.ImmutableSet.of;
-import static com.google.common.collect.Sets.newHashSet;
-import static org.apache.jackrabbit.JcrConstants.JCR_BASEVERSION;
-import static org.apache.jackrabbit.JcrConstants.JCR_ISCHECKEDOUT;
-import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
-import static org.apache.jackrabbit.JcrConstants.JCR_PREDECESSORS;
 import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
-import static org.apache.jackrabbit.JcrConstants.JCR_VERSIONHISTORY;
 import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE;
 import static org.apache.jackrabbit.JcrConstants.MIX_VERSIONABLE;
-import static org.apache.jackrabbit.oak.plugins.memory.MultiGenericPropertyState.nameProperty;
 import static org.apache.jackrabbit.oak.spi.version.VersionConstants.MIX_REP_VERSIONABLE_PATHS;
+import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.addMixin;
 import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getVersionHistoryBuilder;
 import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.getVersionStorage;
+import static org.apache.jackrabbit.oak.upgrade.version.VersionHistoryUtil.removeVersionProperties;
 
 /**
  * The VersionableEditor provides two possible ways to handle
@@ -56,7 +51,7 @@ import static org.apache.jackrabbit.oak.
  *     <li>
  *         it can skip copying version histories and remove the
  *         {@code mix:versionable} mixin together with any related
- *         properties (see {@link #removeVersionProperties(NodeBuilder)}).
+ *         properties (see {@link VersionHistoryUtil#removeVersionProperties(NodeBuilder, TypePredicate)}).
  *     </li>
  * </ul>
  */
@@ -143,7 +138,7 @@ public class VersionableEditor extends D
                 setVersionablePath(versionableUuid);
             } else {
                 NodeBuilder versionableBuilder = getNodeBuilder(rootBuilder, this.path);
-                removeVersionProperties(versionableBuilder);
+                removeVersionProperties(versionableBuilder, isReferenceable);
                 if (isVersionable.apply(versionableBuilder.getNodeState())) {
                     logger.warn("Node {} is still versionable. Creating empty version history.", path);
                     createEmptyHistory(versionableBuilder);
@@ -173,23 +168,6 @@ public class VersionableEditor extends D
         return getVersionHistoryBuilder(versionStorage, versionableUuid).exists();
     }
 
-    private void removeVersionProperties(final NodeBuilder versionableBuilder) {
-        assert versionableBuilder.exists();
-
-        removeMixin(versionableBuilder, MIX_VERSIONABLE);
-
-        // we don't know if the UUID is otherwise referenced,
-        // so make sure the node remains referencable
-        if (!isReferenceable.apply(versionableBuilder.getNodeState())) {
-            addMixin(versionableBuilder, MIX_REFERENCEABLE);
-        }
-
-        versionableBuilder.removeProperty(JCR_VERSIONHISTORY);
-        versionableBuilder.removeProperty(JCR_PREDECESSORS);
-        versionableBuilder.removeProperty(JCR_BASEVERSION);
-        versionableBuilder.removeProperty(JCR_ISCHECKEDOUT);
-    }
-
     private void createEmptyHistory(NodeBuilder versionable) throws CommitFailedException {
         vMgr.getOrCreateVersionHistory(versionable, Collections.<String,Object>emptyMap());
     }
@@ -224,27 +202,5 @@ public class VersionableEditor extends D
         return builder;
     }
 
-    private static void addMixin(NodeBuilder builder, String name) {
-        if (builder.hasProperty(JCR_MIXINTYPES)) {
-            final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
-            if (mixins.add(name)) {
-                builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
-            }
-        } else {
-            builder.setProperty(nameProperty(JCR_MIXINTYPES, of(name)));
-        }
-    }
 
-    private static void removeMixin(NodeBuilder builder, String name) {
-        if (builder.hasProperty(JCR_MIXINTYPES)) {
-            final Set<String> mixins = newHashSet(builder.getProperty(JCR_MIXINTYPES).getValue(Type.NAMES));
-            if (mixins.remove(name)) {
-                if (mixins.isEmpty()) {
-                    builder.removeProperty(JCR_MIXINTYPES);
-                } else {
-                    builder.setProperty(nameProperty(JCR_MIXINTYPES, mixins));
-                }
-            }
-        }
-    }
 }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionablePropertiesEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionablePropertiesEditor.java?rev=1811337&r1=1811336&r2=1811337&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionablePropertiesEditor.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/version/VersionablePropertiesEditor.java Fri Oct  6 14:38:46 2017
@@ -69,8 +69,6 @@ public final class VersionableProperties
 
     private final TypePredicate isVersionable;
 
-    private final TypePredicate isSimpleVersionable;
-
     private final TypePredicate isNtVersion;
 
     private final TypePredicate isFrozenNode;
@@ -80,7 +78,6 @@ public final class VersionableProperties
         this.rootBuilder = rootBuilder;
         this.versionStorage = getVersionStorage(rootBuilder);
         this.isVersionable = new TypePredicate(rootBuilder.getNodeState(), MIX_VERSIONABLE);
-        this.isSimpleVersionable = new TypePredicate(rootBuilder.getNodeState(), MIX_SIMPLE_VERSIONABLE);
         this.isNtVersion = new TypePredicate(rootBuilder.getNodeState(), NT_VERSION);
         this.isFrozenNode = new TypePredicate(rootBuilder.getNodeState(), NT_FROZENNODE);
     }
@@ -90,7 +87,6 @@ public final class VersionableProperties
         this.rootBuilder = parent.rootBuilder;
         this.versionStorage = parent.versionStorage;
         this.isVersionable = parent.isVersionable;
-        this.isSimpleVersionable = parent.isSimpleVersionable;
         this.isNtVersion = parent.isNtVersion;
         this.isFrozenNode = parent.isFrozenNode;
     }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java?rev=1811337&r1=1811336&r2=1811337&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistorySidegradeTest.java Fri Oct  6 14:38:46 2017
@@ -50,15 +50,10 @@ public class CopyVersionHistorySidegrade
     }
 
     @Override
-    protected Session performCopy(VersionCopySetup setup) throws RepositoryException, IOException {
-        final NodeStore targetNodeStore = new MemoryNodeStore();
-        final RepositorySidegrade sidegrade = new RepositorySidegrade(sourceNodeStore, targetNodeStore);
+    protected void migrate(VersionCopySetup setup, NodeStore target, String includePath) throws RepositoryException, IOException {
+        final RepositorySidegrade sidegrade = new RepositorySidegrade(sourceNodeStore, target);
+        sidegrade.setIncludes(includePath);
         setup.setup(sidegrade.versionCopyConfiguration);
         sidegrade.copy();
-
-        repository = (RepositoryImpl) new Jcr(new Oak(targetNodeStore)).createRepository();
-        Session s = repository.login(AbstractRepositoryUpgradeTest.CREDENTIALS);
-        sessions.add(s);
-        return s;
     }
-}
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistoryTest.java?rev=1811337&r1=1811336&r2=1811337&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistoryTest.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/CopyVersionHistoryTest.java Fri Oct  6 14:38:46 2017
@@ -50,6 +50,7 @@ import com.google.common.collect.Maps;
 import org.apache.jackrabbit.core.RepositoryContext;
 import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.jcr.Jcr;
 import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl;
 import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
@@ -256,23 +257,50 @@ public class CopyVersionHistoryTest exte
                 .getPrimaryNodeType());
     }
 
+    @Test
+    public void removeVersionHistory() throws RepositoryException, IOException {
+        final NodeStore targetNodeStore = SegmentNodeStoreBuilders.builder(new MemoryStore()).build();
+        migrate(new VersionCopySetup() {
+            @Override
+            public void setup(VersionCopyConfiguration config) {
+            }
+        }, targetNodeStore, PathUtils.ROOT_PATH);
+        migrate(new VersionCopySetup() {
+            @Override
+            public void setup(VersionCopyConfiguration config) {
+                config.setCopyVersions(null);
+                config.setCopyOrphanedVersions(null);
+            }
+        }, targetNodeStore, "/versionables");
+        repository = (RepositoryImpl) new Jcr(new Oak(targetNodeStore)).createRepository();
+        Session s = repository.login(AbstractRepositoryUpgradeTest.CREDENTIALS);
+        sessions.add(s);
+        assertMissingHistories(s, VERSIONABLES_OLD, VERSIONABLES_YOUNG);
+        assertNonVersionablePaths(s, VERSIONABLES_OLD, VERSIONABLES_YOUNG);
+
+    }
+
     protected Session performCopy(VersionCopySetup setup) throws RepositoryException, IOException {
+        final NodeStore targetNodeStore = SegmentNodeStoreBuilders.builder(new MemoryStore()).build();
+        migrate(setup, targetNodeStore, PathUtils.ROOT_PATH);
+        repository = (RepositoryImpl) new Jcr(new Oak(targetNodeStore)).createRepository();
+        Session s = repository.login(AbstractRepositoryUpgradeTest.CREDENTIALS);
+        sessions.add(s);
+        return s;
+    }
+
+    protected void migrate(VersionCopySetup setup, NodeStore target, String includePath) throws RepositoryException, IOException {
         final RepositoryConfig sourceConfig = RepositoryConfig.create(source);
         final RepositoryContext sourceContext = RepositoryContext.create(sourceConfig);
-        final NodeStore targetNodeStore = SegmentNodeStoreBuilders.builder(new MemoryStore()).build();
         try {
-            final RepositoryUpgrade upgrade = new RepositoryUpgrade(sourceContext, targetNodeStore);
+            final RepositoryUpgrade upgrade = new RepositoryUpgrade(sourceContext, target);
+            upgrade.setIncludes(includePath);
             setup.setup(upgrade.versionCopyConfiguration);
-            upgrade.setEarlyShutdown(true);
+            upgrade.setEarlyShutdown(false);
             upgrade.copy(null);
         } finally {
             sourceContext.getRepository().shutdown();
         }
-
-        repository = (RepositoryImpl) new Jcr(new Oak(targetNodeStore)).createRepository();
-        Session s = repository.login(AbstractRepositoryUpgradeTest.CREDENTIALS);
-        sessions.add(s);
-        return s;
     }
 
     @After
@@ -358,6 +386,18 @@ public class CopyVersionHistoryTest exte
             }
         }
     }
+
+    private static void assertNonVersionablePaths(final Session session, final String... names)
+            throws RepositoryException {
+        for (final String mixin : MIXINS) {
+            final String pathPrefix = VERSIONABLES_PATH_PREFIX + mixin + "/";
+            for (final String name : names) {
+                final String path = pathPrefix + name;
+                final Node node = session.getNode(path);
+                assertFalse("Node " + path + " shouldn't have mix:versionable mixin", node.isNodeType(MIX_VERSIONABLE));
+            }
+        }
+    }
 
     private static void assertVersionablePath(final VersionHistory history, final String versionablePath)
             throws RepositoryException {