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
This commit is contained in:
parent
48e245fc60
commit
088c2fc6e3
|
@ -48,6 +48,7 @@
|
|||
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.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 @@ protected void run() throws Exception {
|
|||
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 @@ private RefTree rebuild(Map<String, Ref> refMap) {
|
|||
= 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)));
|
||||
|
|
|
@ -104,7 +104,7 @@ public void unknownRepositoryFormatVersion() throws Exception {
|
|||
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 {
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
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 void onConfigChanged(ConfigChangedEvent event) {
|
|||
}
|
||||
});
|
||||
|
||||
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 void onConfigChanged(ConfigChangedEvent event) {
|
|||
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)));
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
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.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue