private List<CachedPack> cachedPacks = new ArrayList<CachedPack>(2);
+ private Set<ObjectId> tagTargets = Collections.emptySet();
+
private Deflater myDeflater;
private final ObjectReader reader;
ignoreMissingUninteresting = ignore;
}
+ /**
+ * Set the tag targets that should be hoisted earlier during packing.
+ * <p>
+ * Callers may put objects into this set before invoking any of the
+ * preparePack methods to influence where an annotated tag's target is
+ * stored within the resulting pack. Typically these will be clustered
+ * together, and hoisted earlier in the file even if they are ancient
+ * revisions, allowing readers to find tag targets with better locality.
+ *
+ * @param objects
+ * objects that annotated tags point at.
+ */
+ public void setTagTargets(Set<ObjectId> objects) {
+ tagTargets = objects;
+ }
+
/**
* Returns objects number in a pack file that was created by this writer.
*
ArrayList<ObjectToPack> list = (ArrayList<ObjectToPack>) objectsLists[Constants.OBJ_COMMIT];
list.ensureCapacity(list.size() + commits.size());
}
+
+ int commitCnt = 0;
+ boolean putTagTargets = false;
for (RevCommit cmit : commits) {
if (!cmit.has(added)) {
cmit.add(added);
addObject(cmit, 0);
+ commitCnt++;
}
for (int i = 0; i < cmit.getParentCount(); i++) {
if (!p.has(added) && !p.has(RevFlag.UNINTERESTING)) {
p.add(added);
addObject(p, 0);
+ commitCnt++;
+ }
+ }
+
+ if (!putTagTargets && 4096 < commitCnt) {
+ for (ObjectId id : tagTargets) {
+ RevObject obj = walker.lookupOrNull(id);
+ if (obj instanceof RevCommit
+ && obj.has(include)
+ && !obj.has(RevFlag.UNINTERESTING)
+ && !obj.has(added)) {
+ obj.add(added);
+ addObject(obj, 0);
+ }
}
+ putTagTargets = true;
}
}
commits = null;
private final Set<RevCommit> assume;
+ private final Set<ObjectId> tagTargets;
+
private PackConfig packConfig;
/**
db = repo;
include = new TreeMap<String, ObjectId>();
assume = new HashSet<RevCommit>();
+ tagTargets = new HashSet<ObjectId>();
}
/**
*/
public void include(final Ref r) {
include(r.getName(), r.getObjectId());
+
+ if (r.getPeeledObjectId() != null)
+ tagTargets.add(r.getPeeledObjectId());
+
+ else if (r.getObjectId() != null
+ && r.getName().startsWith(Constants.R_HEADS))
+ tagTargets.add(r.getObjectId());
}
/**
exc.add(r.getId());
packWriter.setDeltaBaseAsOffset(true);
packWriter.setThin(exc.size() > 0);
+ if (exc.size() == 0)
+ packWriter.setTagTargets(tagTargets);
packWriter.preparePack(monitor, inc, exc);
final Writer w = new OutputStreamWriter(os, Constants.CHARSET);
pw.setDeltaBaseAsOffset(options.contains(OPTION_OFS_DELTA));
pw.setThin(options.contains(OPTION_THIN_PACK));
+ if (commonBase.isEmpty()) {
+ Set<ObjectId> tagTargets = new HashSet<ObjectId>();
+ for (Ref ref : refs.values()) {
+ if (ref.getPeeledObjectId() != null)
+ tagTargets.add(ref.getPeeledObjectId());
+ else if (ref.getObjectId() == null)
+ continue;
+ else if (ref.getName().startsWith(Constants.R_HEADS))
+ tagTargets.add(ref.getObjectId());
+ }
+ pw.setTagTargets(tagTargets);
+ }
+
RevWalk rw = walk;
if (wantAll.isEmpty()) {
pw.preparePack(pm, wantIds, commonBase);