Change-Id: Ie206b5340ad2019a1e0bd2bcede2c1e5a279f2d5 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v4.10.0.201712302008-r
@@ -61,36 +61,43 @@ class AlwaysFailUpdate extends RefUpdate { | |||
setCheckConflicting(false); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected RefDatabase getRefDatabase() { | |||
return refdb; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected Repository getRepository() { | |||
return refdb.getRepository(); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected boolean tryLock(boolean deref) throws IOException { | |||
return false; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected void unlock() { | |||
// No locks are held here. | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected Result doUpdate(Result desiredResult) { | |||
return Result.LOCK_FAILURE; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected Result doDelete(Result desiredResult) { | |||
return Result.LOCK_FAILURE; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected Result doLink(String target) { | |||
return Result.LOCK_FAILURE; |
@@ -69,25 +69,31 @@ import org.eclipse.jgit.transport.ReceiveCommand; | |||
import org.eclipse.jgit.transport.ReceiveCommand.Result; | |||
/** | |||
* Command to create, update or delete an entry inside a {@link RefTree}. | |||
* Command to create, update or delete an entry inside a | |||
* {@link org.eclipse.jgit.internal.storage.reftree.RefTree}. | |||
* <p> | |||
* Unlike {@link ReceiveCommand} (which can only update a reference to an | |||
* {@link ObjectId}), a RefTree Command can also create, modify or delete | |||
* symbolic references to a target reference. | |||
* Unlike {@link org.eclipse.jgit.transport.ReceiveCommand} (which can only | |||
* update a reference to an {@link org.eclipse.jgit.lib.ObjectId}), a RefTree | |||
* Command can also create, modify or delete symbolic references to a target | |||
* reference. | |||
* <p> | |||
* RefTree Commands may wrap a {@code ReceiveCommand} to allow callers to | |||
* process an existing ReceiveCommand against a RefTree. | |||
* <p> | |||
* Commands should be passed into {@link RefTree#apply(java.util.Collection)} | |||
* Commands should be passed into | |||
* {@link org.eclipse.jgit.internal.storage.reftree.RefTree#apply(java.util.Collection)} | |||
* for processing. | |||
*/ | |||
public class Command { | |||
/** | |||
* Set unprocessed commands as failed due to transaction aborted. | |||
* <p> | |||
* If a command is still {@link Result#NOT_ATTEMPTED} it will be set to | |||
* {@link Result#REJECTED_OTHER_REASON}. If {@code why} is non-null its | |||
* contents will be used as the message for the first command status. | |||
* If a command is still | |||
* {@link org.eclipse.jgit.transport.ReceiveCommand.Result#NOT_ATTEMPTED} it | |||
* will be set to | |||
* {@link org.eclipse.jgit.transport.ReceiveCommand.Result#REJECTED_OTHER_REASON}. | |||
* If {@code why} is non-null its contents will be used as the message for | |||
* the first command status. | |||
* | |||
* @param commands | |||
* commands to mark as failed. | |||
@@ -147,9 +153,9 @@ public class Command { | |||
* walk instance to peel the {@code newId}. | |||
* @param cmd | |||
* command received from a push client. | |||
* @throws MissingObjectException | |||
* @throws org.eclipse.jgit.errors.MissingObjectException | |||
* {@code oldId} or {@code newId} is missing. | |||
* @throws IOException | |||
* @throws java.io.IOException | |||
* {@code oldId} or {@code newId} cannot be peeled. | |||
*/ | |||
public Command(RevWalk rw, ReceiveCommand cmd) | |||
@@ -186,7 +192,11 @@ public class Command { | |||
} | |||
} | |||
/** @return name of the reference affected by this command. */ | |||
/** | |||
* Get name of the reference affected by this command. | |||
* | |||
* @return name of the reference affected by this command. | |||
*/ | |||
public String getRefName() { | |||
if (cmd != null) { | |||
return cmd.getRefName(); | |||
@@ -222,12 +232,20 @@ public class Command { | |||
} | |||
} | |||
/** @return result of executing this command. */ | |||
/** | |||
* Get result of executing this command. | |||
* | |||
* @return result of executing this command. | |||
*/ | |||
public Result getResult() { | |||
return cmd != null ? cmd.getResult() : result; | |||
} | |||
/** @return optional message explaining command failure. */ | |||
/** | |||
* Get optional message explaining command failure. | |||
* | |||
* @return optional message explaining command failure. | |||
*/ | |||
@Nullable | |||
public String getMessage() { | |||
return cmd != null ? cmd.getMessage() : null; | |||
@@ -253,6 +271,7 @@ public class Command { | |||
return newRef; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public String toString() { | |||
StringBuilder s = new StringBuilder(); |
@@ -74,7 +74,6 @@ import org.eclipse.jgit.errors.DirCacheNameConflictException; | |||
import org.eclipse.jgit.errors.IncorrectObjectTypeException; | |||
import org.eclipse.jgit.errors.MissingObjectException; | |||
import org.eclipse.jgit.internal.JGitText; | |||
import org.eclipse.jgit.lib.FileMode; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectIdRef; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
@@ -92,11 +91,13 @@ import org.eclipse.jgit.util.RawParseUtils; | |||
* default reference {@code "refs/heads/master"} is stored at path | |||
* {@code "heads/master"} in a {@code RefTree}. | |||
* <p> | |||
* Normal references are stored as {@link FileMode#GITLINK} tree entries. The | |||
* ObjectId in the tree entry is the ObjectId the reference refers to. | |||
* Normal references are stored as {@link org.eclipse.jgit.lib.FileMode#GITLINK} | |||
* tree entries. The ObjectId in the tree entry is the ObjectId the reference | |||
* refers to. | |||
* <p> | |||
* Symbolic references are stored as {@link FileMode#SYMLINK} entries, with the | |||
* blob storing the name of the target reference. | |||
* Symbolic references are stored as | |||
* {@link org.eclipse.jgit.lib.FileMode#SYMLINK} entries, with the blob storing | |||
* the name of the target reference. | |||
* <p> | |||
* Annotated tags also store the peeled object using a {@code GITLINK} entry | |||
* with the suffix <code>" ^"</code> (space carrot), for example | |||
@@ -127,13 +128,13 @@ public class RefTree { | |||
* @param tree | |||
* the tree to read. | |||
* @return the ref tree read from the commit. | |||
* @throws IOException | |||
* @throws java.io.IOException | |||
* the repository cannot be accessed through the reader. | |||
* @throws CorruptObjectException | |||
* @throws org.eclipse.jgit.errors.CorruptObjectException | |||
* a tree object is corrupt and cannot be read. | |||
* @throws IncorrectObjectTypeException | |||
* @throws org.eclipse.jgit.errors.IncorrectObjectTypeException | |||
* a tree object wasn't actually a tree. | |||
* @throws MissingObjectException | |||
* @throws org.eclipse.jgit.errors.MissingObjectException | |||
* a reference tree object doesn't exist. | |||
*/ | |||
public static RefTree read(ObjectReader reader, RevTree tree) | |||
@@ -152,9 +153,10 @@ public class RefTree { | |||
/** | |||
* Read one reference. | |||
* <p> | |||
* References are always returned peeled ({@link Ref#isPeeled()} is true). | |||
* If the reference points to an annotated tag, the returned reference will | |||
* be peeled and contain {@link Ref#getPeeledObjectId()}. | |||
* References are always returned peeled | |||
* ({@link org.eclipse.jgit.lib.Ref#isPeeled()} is true). If the reference | |||
* points to an annotated tag, the returned reference will be peeled and | |||
* contain {@link org.eclipse.jgit.lib.Ref#getPeeledObjectId()}. | |||
* <p> | |||
* If the reference is a symbolic reference and the chain depth is less than | |||
* {@link org.eclipse.jgit.lib.RefDatabase#MAX_SYMBOLIC_REF_DEPTH} the | |||
@@ -166,7 +168,7 @@ public class RefTree { | |||
* @param name | |||
* name of the reference to read. | |||
* @return the reference; null if it does not exist. | |||
* @throws IOException | |||
* @throws java.io.IOException | |||
* cannot read a symbolic reference target. | |||
*/ | |||
@Nullable | |||
@@ -378,7 +380,7 @@ public class RefTree { | |||
* Caller is responsible for flushing the inserter before trying | |||
* to read the objects, or exposing them through a reference. | |||
* @return the top level tree. | |||
* @throws IOException | |||
* @throws java.io.IOException | |||
* a tree could not be written. | |||
*/ | |||
public ObjectId writeTree(ObjectInserter inserter) throws IOException { | |||
@@ -391,7 +393,11 @@ public class RefTree { | |||
return contents.writeTree(inserter); | |||
} | |||
/** @return a deep copy of this RefTree. */ | |||
/** | |||
* Create a deep copy of this RefTree. | |||
* | |||
* @return a deep copy of this RefTree. | |||
*/ | |||
public RefTree copy() { | |||
RefTree r = new RefTree(DirCache.newInCore()); | |||
DirCacheBuilder b = r.contents.builder(); |
@@ -87,6 +87,7 @@ class RefTreeBatch extends BatchRefUpdate { | |||
this.refdb = refdb; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public void execute(RevWalk rw, ProgressMonitor monitor) | |||
throws IOException { |
@@ -74,13 +74,15 @@ import org.eclipse.jgit.util.RefList; | |||
import org.eclipse.jgit.util.RefMap; | |||
/** | |||
* Reference database backed by a {@link RefTree}. | |||
* Reference database backed by a | |||
* {@link org.eclipse.jgit.internal.storage.reftree.RefTree}. | |||
* <p> | |||
* The storage for RefTreeDatabase has two parts. The main part is a native Git | |||
* tree object stored under the {@code refs/txn} namespace. To avoid cycles, | |||
* references to {@code refs/txn} are not stored in that tree object, but | |||
* instead in a "bootstrap" layer, which is a separate {@link RefDatabase} such | |||
* as {@link org.eclipse.jgit.internal.storage.file.RefDirectory} using local | |||
* instead in a "bootstrap" layer, which is a separate | |||
* {@link org.eclipse.jgit.lib.RefDatabase} such as | |||
* {@link org.eclipse.jgit.internal.storage.file.RefDirectory} using local | |||
* reference files inside of {@code $GIT_DIR/refs}. | |||
*/ | |||
public class RefTreeDatabase extends RefDatabase { | |||
@@ -99,7 +101,8 @@ public class RefTreeDatabase extends RefDatabase { | |||
* the repository using references in this database. | |||
* @param bootstrap | |||
* bootstrap reference database storing the references that | |||
* anchor the {@link RefTree}. | |||
* anchor the | |||
* {@link org.eclipse.jgit.internal.storage.reftree.RefTree}. | |||
*/ | |||
public RefTreeDatabase(Repository repo, RefDatabase bootstrap) { | |||
Config cfg = repo.getConfig(); | |||
@@ -121,7 +124,8 @@ public class RefTreeDatabase extends RefDatabase { | |||
* the repository using references in this database. | |||
* @param bootstrap | |||
* bootstrap reference database storing the references that | |||
* anchor the {@link RefTree}. | |||
* anchor the | |||
* {@link org.eclipse.jgit.internal.storage.reftree.RefTree}. | |||
* @param txnCommitted | |||
* name of the bootstrap reference holding the committed RefTree. | |||
*/ | |||
@@ -146,6 +150,8 @@ public class RefTreeDatabase extends RefDatabase { | |||
} | |||
/** | |||
* Get the bootstrap reference database | |||
* | |||
* @return the bootstrap reference database, which must be used to access | |||
* {@link #getTxnCommitted()}, {@link #getTxnNamespace()}. | |||
*/ | |||
@@ -153,41 +159,52 @@ public class RefTreeDatabase extends RefDatabase { | |||
return bootstrap; | |||
} | |||
/** @return name of bootstrap reference anchoring committed RefTree. */ | |||
/** | |||
* Get name of bootstrap reference anchoring committed RefTree. | |||
* | |||
* @return name of bootstrap reference anchoring committed RefTree. | |||
*/ | |||
public String getTxnCommitted() { | |||
return txnCommitted; | |||
} | |||
/** | |||
* @return namespace used by bootstrap layer, e.g. {@code refs/txn/}. | |||
* Always ends in {@code '/'}. | |||
* Get namespace used by bootstrap layer. | |||
* | |||
* @return namespace used by bootstrap layer, e.g. {@code refs/txn/}. Always | |||
* ends in {@code '/'}. | |||
*/ | |||
@Nullable | |||
public String getTxnNamespace() { | |||
return txnNamespace; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public void create() throws IOException { | |||
bootstrap.create(); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public boolean performsAtomicTransactions() { | |||
return true; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public void refresh() { | |||
bootstrap.refresh(); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public void close() { | |||
refs = null; | |||
bootstrap.close(); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public Ref getRef(String name) throws IOException { | |||
String[] needle = new String[SEARCH_PATH.length]; | |||
@@ -197,6 +214,7 @@ public class RefTreeDatabase extends RefDatabase { | |||
return firstExactRef(needle); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public Ref exactRef(String name) throws IOException { | |||
if (!repo.isBare() && name.indexOf('/') < 0 && !HEAD.equals(name)) { | |||
@@ -235,6 +253,7 @@ public class RefTreeDatabase extends RefDatabase { | |||
return ""; //$NON-NLS-1$ | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public Map<String, Ref> getRefs(String prefix) throws IOException { | |||
if (!prefix.isEmpty() && prefix.charAt(prefix.length() - 1) != '/') { | |||
@@ -258,6 +277,7 @@ public class RefTreeDatabase extends RefDatabase { | |||
: ObjectId.zeroId(); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public List<Ref> getAdditionalRefs() throws IOException { | |||
Collection<Ref> txnRefs; | |||
@@ -279,6 +299,7 @@ public class RefTreeDatabase extends RefDatabase { | |||
return all; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public Ref peel(Ref ref) throws IOException { | |||
Ref i = ref.getLeaf(); | |||
@@ -306,17 +327,20 @@ public class RefTreeDatabase extends RefDatabase { | |||
return leaf; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public boolean isNameConflicting(String name) throws IOException { | |||
return conflictsWithBootstrap(name) | |||
|| !getConflictingNames(name).isEmpty(); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public BatchRefUpdate newBatchUpdate() { | |||
return new RefTreeBatch(this); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public RefUpdate newUpdate(String name, boolean detach) throws IOException { | |||
if (!repo.isBare() && name.indexOf('/') < 0 && !HEAD.equals(name)) { | |||
@@ -343,6 +367,7 @@ public class RefTreeDatabase extends RefDatabase { | |||
return u; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
public RefRename newRename(String fromName, String toName) | |||
throws IOException { |
@@ -45,7 +45,9 @@ package org.eclipse.jgit.internal.storage.reftree; | |||
import org.eclipse.jgit.lib.RefDatabase; | |||
/** Magic reference name logic for RefTrees. */ | |||
/** | |||
* Magic reference name logic for RefTrees. | |||
*/ | |||
public class RefTreeNames { | |||
/** | |||
* Suffix used on a {@link RefTreeDatabase#getTxnNamespace()} for user data. |
@@ -69,6 +69,7 @@ class RefTreeRename extends RefRename { | |||
this.refdb = refdb; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected Result doRename() throws IOException { | |||
try (RevWalk rw = new RevWalk(refdb.getRepository())) { |
@@ -76,16 +76,19 @@ class RefTreeUpdate extends RefUpdate { | |||
setCheckConflicting(false); // Done automatically by doUpdate. | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected RefDatabase getRefDatabase() { | |||
return refdb; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected Repository getRepository() { | |||
return refdb.getRepository(); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected boolean tryLock(boolean deref) throws IOException { | |||
rw = new RevWalk(getRepository()); | |||
@@ -100,6 +103,7 @@ class RefTreeUpdate extends RefUpdate { | |||
return true; | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected void unlock() { | |||
batch = null; | |||
@@ -109,6 +113,7 @@ class RefTreeUpdate extends RefUpdate { | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected Result doUpdate(Result desiredResult) throws IOException { | |||
return run(newRef(getName(), getNewObjectId()), desiredResult); | |||
@@ -124,11 +129,13 @@ class RefTreeUpdate extends RefUpdate { | |||
return new ObjectIdRef.PeeledNonTag(LOOSE, name, id); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected Result doDelete(Result desiredResult) throws IOException { | |||
return run(null, desiredResult); | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected Result doLink(String target) throws IOException { | |||
Ref dst = new ObjectIdRef.Unpeeled(NEW, target, null); |