From: Shawn Pearce Date: Sat, 9 Jan 2016 20:51:14 +0000 (-0800) Subject: FileRepository: Support extensions.refsBackendType = RefTree X-Git-Tag: v4.2.0.201601211800-r~4^2~15 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=088c2fc6e33737a406e69a99d75f06d3fbb05e30;p=jgit.git FileRepository: Support extensions.refsBackendType = RefTree This experimental code can be enabled in $GIT_DIR/config: [core] repositoryformatversion = 1 [extensions] refsBackendType = RefTree When these are set the repository will read references from the RefTree rooted by the $GIT_DIR/refs/txn/committed reference. Update debug-rebuild-ref-tree to rebuild refs/txn/committed only from the bootstrap layer. This avoids misuse by rebuilding using packed-refs and $GIT_DIR/refs tree. Change-Id: Icf600e4a36b2f7867822a7ab1f1617d73c710a4b --- diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildRefTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildRefTree.java index 6af4ce1dd1..78ca1a7128 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildRefTree.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildRefTree.java @@ -48,6 +48,7 @@ import java.util.List; import java.util.Map; import org.eclipse.jgit.internal.storage.reftree.RefTree; +import org.eclipse.jgit.internal.storage.reftree.RefTreeDatabase; import org.eclipse.jgit.lib.CommitBuilder; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; @@ -59,12 +60,11 @@ import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.pgm.Command; import org.eclipse.jgit.pgm.TextBuiltin; import org.eclipse.jgit.revwalk.RevWalk; -import org.kohsuke.args4j.Argument; @Command(usage = "usage_RebuildRefTree") class RebuildRefTree extends TextBuiltin { - @Argument(index = 0, required = true, metaVar = "metaVar_ref", usage = "usage_updateRef") - String refName; + private String txnNamespace; + private String txnCommitted; @Override protected void run() throws Exception { @@ -72,10 +72,25 @@ class RebuildRefTree extends TextBuiltin { RevWalk rw = new RevWalk(reader); ObjectInserter inserter = db.newObjectInserter()) { RefDatabase refDb = db.getRefDatabase(); + if (refDb instanceof RefTreeDatabase) { + RefTreeDatabase d = (RefTreeDatabase) refDb; + refDb = d.getBootstrap(); + txnNamespace = d.getTxnNamespace(); + txnCommitted = d.getTxnCommitted(); + } else { + RefTreeDatabase d = new RefTreeDatabase(db, refDb); + txnNamespace = d.getTxnNamespace(); + txnCommitted = d.getTxnCommitted(); + } + + errw.format("Rebuilding %s from %s", //$NON-NLS-1$ + txnCommitted, refDb.getClass().getSimpleName()); + errw.println(); + errw.flush(); CommitBuilder b = new CommitBuilder(); - Ref ref = db.getRefDatabase().exactRef(refName); - RefUpdate update = db.updateRef(refName); + Ref ref = refDb.exactRef(txnCommitted); + RefUpdate update = refDb.newUpdate(txnCommitted, true); ObjectId oldTreeId; if (ref != null && ref.getObjectId() != null) { @@ -116,10 +131,10 @@ class RebuildRefTree extends TextBuiltin { = new ArrayList<>(); for (Ref r : refMap.values()) { - if (refName.equals(r.getName())) { + if (r.getName().equals(txnCommitted) + || r.getName().startsWith(txnNamespace)) { continue; } - cmds.add(new org.eclipse.jgit.internal.storage.reftree.Command( null, db.peel(r))); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileRepositoryBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileRepositoryBuilderTest.java index 280d6040cc..6c8ee737d2 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileRepositoryBuilderTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileRepositoryBuilderTest.java @@ -104,7 +104,7 @@ public class FileRepositoryBuilderTest extends LocalDiskRepositoryTestCase { Repository r = createWorkRepository(); StoredConfig config = r.getConfig(); config.setLong(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION, 1); + ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION, 999999); config.save(); try { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java index 490cbcaa81..4f45cbee5c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java @@ -63,6 +63,7 @@ import org.eclipse.jgit.events.ConfigChangedEvent; import org.eclipse.jgit.events.ConfigChangedListener; import org.eclipse.jgit.events.IndexChangedEvent; import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.internal.storage.reftree.RefTreeDatabase; import org.eclipse.jgit.internal.storage.file.ObjectDirectory.AlternateHandle; import org.eclipse.jgit.internal.storage.file.ObjectDirectory.AlternateRepository; import org.eclipse.jgit.lib.BaseRepositoryBuilder; @@ -201,7 +202,22 @@ public class FileRepository extends Repository { } }); - refs = new RefDirectory(this); + final long repositoryFormatVersion = getConfig().getLong( + ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION, 0); + + String reftype = repoConfig.getString( + "extensions", null, "refsBackendType"); //$NON-NLS-1$ //$NON-NLS-2$ + if (repositoryFormatVersion >= 1 && reftype != null) { + if (StringUtils.equalsIgnoreCase(reftype, "reftree")) { //$NON-NLS-1$ + refs = new RefTreeDatabase(this, new RefDirectory(this)); + } else { + throw new IOException(JGitText.get().unknownRepositoryFormat); + } + } else { + refs = new RefDirectory(this); + } + objectDatabase = new ObjectDirectory(repoConfig, // options.getObjectDirectory(), // options.getAlternateObjectDirectories(), // @@ -209,10 +225,7 @@ public class FileRepository extends Repository { new File(getDirectory(), Constants.SHALLOW)); if (objectDatabase.exists()) { - final long repositoryFormatVersion = getConfig().getLong( - ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION, 0); - if (repositoryFormatVersion > 0) + if (repositoryFormatVersion > 1) throw new IOException(MessageFormat.format( JGitText.get().unknownRepositoryFormat2, Long.valueOf(repositoryFormatVersion))); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabase.java index 983216e304..dc60311102 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabase.java @@ -54,6 +54,7 @@ import java.util.Map; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.lib.BatchRefUpdate; +import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdRef; import org.eclipse.jgit.lib.Ref; @@ -88,6 +89,28 @@ public class RefTreeDatabase extends RefDatabase { private final String txnNamespace; private volatile Scanner.Result refs; + /** + * Create a RefTreeDb for a repository. + * + * @param repo + * the repository using references in this database. + * @param bootstrap + * bootstrap reference database storing the references that + * anchor the {@link RefTree}. + */ + public RefTreeDatabase(Repository repo, RefDatabase bootstrap) { + Config cfg = repo.getConfig(); + String committed = cfg.getString("reftree", null, "committedRef"); //$NON-NLS-1$ //$NON-NLS-2$ + if (committed == null || committed.isEmpty()) { + committed = "refs/txn/committed"; //$NON-NLS-1$ + } + + this.repo = repo; + this.bootstrap = bootstrap; + this.txnNamespace = initNamespace(committed); + this.txnCommitted = committed; + } + /** * Create a RefTreeDb for a repository. *