]> source.dussan.org Git - jgit.git/commitdiff
Add retainOnReset(RevFlag) to RevWalk to simplify reset usage 79/35079/2
authorShawn Pearce <spearce@spearce.org>
Fri, 17 Oct 2014 21:17:23 +0000 (14:17 -0700)
committerShawn Pearce <spearce@spearce.org>
Sun, 19 Oct 2014 18:36:08 +0000 (11:36 -0700)
Applications sometimes use a RevFlag instead of a Set<RevObject>
to track boolean state bits about objects being processed. However
this requires careful use of the resetRetain() methods to avoid an
accidental clearing of the RevFlag bits, effectively clearing the
Set<RevObject> the application wanted to track.

Simplify that use case by offering retainOnReset, a collection of
flags that are never cleared by the RevWalk.

Change-Id: I4c05b89b1398e4a4f371eac3a5d1d5edddec838f

org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java

index 79cc42d17075eb31214b35e64b99583fd2079880..d19e467c1dd2e785225019332f924bd376314aff 100644 (file)
@@ -174,6 +174,7 @@ public class RevWalk implements Iterable<RevCommit> {
 
        private int delayFreeFlags;
 
+       private int retainOnReset;
        int carryFlags = UNINTERESTING;
 
        final ArrayList<RevCommit> roots;
@@ -1092,6 +1093,47 @@ public class RevWalk implements Iterable<RevCommit> {
                        carry(flag);
        }
 
+       /**
+        * Preserve a RevFlag during all {@code reset} methods.
+        * <p>
+        * Calling {@code retainOnReset(flag)} avoids needing to pass the flag
+        * during each {@code resetRetain()} invocation on this instance.
+        * <p>
+        * Clearing flags marked retainOnReset requires disposing of the flag with
+        * {@code #disposeFlag(RevFlag)} or disposing of the entire RevWalk by
+        * {@code #dispose()}.
+        *
+        * @param flag
+        *            the flag to retain during all resets.
+        * @since 3.6
+        */
+       public final void retainOnReset(RevFlag flag) {
+               if ((freeFlags & flag.mask) != 0)
+                       throw new IllegalArgumentException(MessageFormat.format(JGitText.get().flagIsDisposed, flag.name));
+               if (flag.walker != this)
+                       throw new IllegalArgumentException(MessageFormat.format(JGitText.get().flagNotFromThis, flag.name));
+               retainOnReset |= flag.mask;
+       }
+
+       /**
+        * Preserve a set of RevFlags during all {@code reset} methods.
+        * <p>
+        * Calling {@code retainOnReset(set)} avoids needing to pass the flags
+        * during each {@code resetRetain()} invocation on this instance.
+        * <p>
+        * Clearing flags marked retainOnReset requires disposing of the flag with
+        * {@code #disposeFlag(RevFlag)} or disposing of the entire RevWalk by
+        * {@code #dispose()}.
+        *
+        * @param flags
+        *            the flags to retain during all resets.
+        * @since 3.6
+        */
+       public final void retainOnReset(Collection<RevFlag> flags) {
+               for (RevFlag f : flags)
+                       retainOnReset(f);
+       }
+
        /**
         * Allow a flag to be recycled for a different use.
         * <p>
@@ -1110,6 +1152,7 @@ public class RevWalk implements Iterable<RevCommit> {
        }
 
        void freeFlag(final int mask) {
+               retainOnReset &= ~mask;
                if (isNotStarted()) {
                        freeFlags |= mask;
                        carryFlags &= ~mask;
@@ -1158,6 +1201,9 @@ public class RevWalk implements Iterable<RevCommit> {
         * Unlike {@link #dispose()} previously acquired RevObject (and RevCommit)
         * instances are not invalidated. RevFlag instances are not invalidated, but
         * are removed from all RevObjects.
+        * <p>
+        * See {@link #retainOnReset(RevFlag)} for an alternative that does not
+        * require passing the flags during each reset.
         *
         * @param retainFlags
         *            application flags that should <b>not</b> be cleared from
@@ -1183,7 +1229,7 @@ public class RevWalk implements Iterable<RevCommit> {
         */
        protected void reset(int retainFlags) {
                finishDelayedFreeFlags();
-               retainFlags |= PARSED;
+               retainFlags |= PARSED | retainOnReset;
                final int clearFlags = ~retainFlags;
 
                final FIFORevQueue q = new FIFORevQueue();
@@ -1227,6 +1273,7 @@ public class RevWalk implements Iterable<RevCommit> {
                reader.release();
                freeFlags = APP_FLAGS;
                delayFreeFlags = 0;
+               retainOnReset = 0;
                carryFlags = UNINTERESTING;
                objects.clear();
                reader.release();