Browse Source

Teach mergers to use ObjectInserter.newReader()

This allows the RecursiveMerger to iteratively create new merge bases
without necessarily flushing packs to storage in the DFS case;
flushing only need happen at the end of the whole merge process.

Since Merger's walk now depends on its inserter, we need to construct
an inserter at Merger construction time.  This should not be a
significant increase in overhead since unused inserters don't use any
resources (beyond a reference to the Repository).

We also must release and recreate the walk whenever setObjectInserter
is called, which can break usages where setObjectInserter is called in
the middle of stateful operations on the walk.  No usages of this
method within JGit currently do this; the inserter is only ever set
before any stateful walk operations happen.

Change-Id: I9682a6aa4a2c37dccef8e163f132ddb791d79103
stable-3.5
Dave Borowitz 12 years ago committed by Shawn Pearce
parent
commit
0ab3f43c85
  1. 31
      org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java

31
org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java

@ -72,10 +72,10 @@ public abstract class Merger {
protected final Repository db; protected final Repository db;
/** Reader to support {@link #walk} and other object loading. */ /** Reader to support {@link #walk} and other object loading. */
protected final ObjectReader reader; protected ObjectReader reader;
/** A RevWalk for computing merge bases, or listing incoming commits. */ /** A RevWalk for computing merge bases, or listing incoming commits. */
protected final RevWalk walk; protected RevWalk walk;
private ObjectInserter inserter; private ObjectInserter inserter;
@ -96,7 +96,8 @@ public abstract class Merger {
*/ */
protected Merger(final Repository local) { protected Merger(final Repository local) {
db = local; db = local;
reader = db.newObjectReader(); inserter = db.newObjectInserter();
reader = inserter.newReader();
walk = new RevWalk(reader); walk = new RevWalk(reader);
} }
@ -107,14 +108,8 @@ public abstract class Merger {
return db; return db;
} }
/** /** @return an object writer to create objects in {@link #getRepository()}. */
* @return an object writer to create objects in {@link #getRepository()}.
* If no inserter has been set on this instance, one will be created
* and returned by all future calls.
*/
public ObjectInserter getObjectInserter() { public ObjectInserter getObjectInserter() {
if (inserter == null)
inserter = getRepository().newObjectInserter();
return inserter; return inserter;
} }
@ -122,17 +117,20 @@ public abstract class Merger {
* Set the inserter this merger will use to create objects. * Set the inserter this merger will use to create objects.
* <p> * <p>
* If an inserter was already set on this instance (such as by a prior set, * If an inserter was already set on this instance (such as by a prior set,
* or a prior call to {@link #getObjectInserter()}), the prior inserter will * or a prior call to {@link #getObjectInserter()}), the prior inserter as
* be released first. * well as the in-progress walk will be released.
* *
* @param oi * @param oi
* the inserter instance to use. Must be associated with the * the inserter instance to use. Must be associated with the
* repository instance returned by {@link #getRepository()}. * repository instance returned by {@link #getRepository()}.
*/ */
public void setObjectInserter(ObjectInserter oi) { public void setObjectInserter(ObjectInserter oi) {
if (inserter != null) walk.release();
inserter.release(); reader.release();
inserter.release();
inserter = oi; inserter = oi;
reader = oi.newReader();
walk = new RevWalk(reader);
} }
/** /**
@ -174,12 +172,11 @@ public abstract class Merger {
try { try {
boolean ok = mergeImpl(); boolean ok = mergeImpl();
if (ok && inserter != null) if (ok)
inserter.flush(); inserter.flush();
return ok; return ok;
} finally { } finally {
if (inserter != null) inserter.release();
inserter.release();
reader.release(); reader.release();
} }
} }

Loading…
Cancel
Save