diff options
Diffstat (limited to 'org.eclipse.jgit')
6 files changed, 104 insertions, 52 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java index 22d0c1ad3b..21e7041b32 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java @@ -114,19 +114,6 @@ public abstract class RefDatabase { public abstract boolean isNameConflicting(String name) throws IOException; /** - * Create a symbolic reference from one name to another. - * - * @param name - * the name of the reference. Should be {@link Constants#HEAD} or - * starting with {@link Constants#R_REFS}. - * @param target - * the target of the reference. - * @throws IOException - * the reference could not be created or overwritten. - */ - public abstract void link(String name, String target) throws IOException; - - /** * Create a new update command to create, modify or delete a reference. * * @param name diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectory.java index 9fdb48fe83..90ac0bf47e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectory.java @@ -439,24 +439,11 @@ public class RefDirectory extends RefDatabase { return leaf; } - @Override - public void link(String name, String target) throws IOException { - LockFile lck = new LockFile(fileFor(name)); - if (!lck.lock()) - throw new IOException("Cannot lock " + name); - lck.setNeedStatInformation(true); - try { - lck.write(encode(SYMREF + target + '\n')); - if (!lck.commit()) - throw new IOException("Cannot write " + name); - } finally { - lck.unlock(); - } - putLooseRef(newSymbolicRef(lck.getCommitLastModified(), name, target)); + void storedSymbolicRef(RefDirectoryUpdate u, long modified, String target) { + putLooseRef(newSymbolicRef(modified, u.getRef().getName(), target)); fireRefsChanged(); } - @Override public RefDirectoryUpdate newUpdate(String name, boolean detach) throws IOException { final RefList<Ref> packed = getPackedRefs(); @@ -536,7 +523,8 @@ public class RefDirectory extends RefDatabase { fireRefsChanged(); } - void log(final RefUpdate update, final String msg) throws IOException { + void log(final RefUpdate update, final String msg, final boolean deref) + throws IOException { final ObjectId oldId = update.getOldObjectId(); final ObjectId newId = update.getNewObjectId(); final Ref ref = update.getRef(); @@ -558,9 +546,12 @@ public class RefDirectory extends RefDatabase { r.append('\n'); final byte[] rec = encode(r.toString()); - if (ref.isSymbolic()) + if (deref && ref.isSymbolic()) { + log(ref.getName(), rec); + log(ref.getLeaf().getName(), rec); + } else { log(ref.getName(), rec); - log(ref.getLeaf().getName(), rec); + } } private void log(final String refName, final byte[] rec) throws IOException { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryRename.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryRename.java index e43d2a5617..fec00d9325 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryRename.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryRename.java @@ -208,8 +208,16 @@ class RefDirectoryRename extends RefRename { private boolean linkHEAD(RefUpdate target) { try { - refdb.link(Constants.HEAD, target.getName()); - return true; + RefUpdate u = refdb.newUpdate(Constants.HEAD, false); + u.disableRefLog(); + switch (u.link(target.getName())) { + case NEW: + case FORCED: + case NO_CHANGE: + return true; + default: + return false; + } } catch (IOException e) { return false; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryUpdate.java index 113b74b44e..447be104ab 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDirectoryUpdate.java @@ -44,6 +44,8 @@ package org.eclipse.jgit.lib; +import static org.eclipse.jgit.lib.Constants.encode; + import java.io.IOException; /** Updates any reference stored by {@link RefDirectory}. */ @@ -68,8 +70,10 @@ class RefDirectoryUpdate extends RefUpdate { } @Override - protected boolean tryLock() throws IOException { - Ref dst = getRef().getLeaf(); + protected boolean tryLock(boolean deref) throws IOException { + Ref dst = getRef(); + if (deref) + dst = dst.getLeaf(); String name = dst.getName(); lock = new LockFile(database.fileFor(name)); if (lock.lock()) { @@ -105,7 +109,7 @@ class RefDirectoryUpdate extends RefUpdate { msg = strResult; } } - database.log(this, msg); + database.log(this, msg, true); } if (!lock.commit()) return Result.LOCK_FAILURE; @@ -132,4 +136,21 @@ class RefDirectoryUpdate extends RefUpdate { database.delete(this); return status; } + + @Override + protected Result doLink(final String target) throws IOException { + lock.setNeedStatInformation(true); + lock.write(encode(RefDirectory.SYMREF + target + '\n')); + + String msg = getRefLogMessage(); + if (msg != null) + database.log(this, msg, false); + if (!lock.commit()) + return Result.LOCK_FAILURE; + database.storedSymbolicRef(this, lock.getCommitLastModified(), target); + + if (getRef().getStorage() == Ref.Storage.NEW) + return Result.NEW; + return Result.FORCED; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java index 33e12a110d..553266284b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java @@ -183,13 +183,17 @@ public abstract class RefUpdate { * If the locking was successful the implementor must set the current * identity value by calling {@link #setOldObjectId(ObjectId)}. * + * @param deref + * true if the lock should be taken against the leaf level + * reference; false if it should be taken exactly against the + * current reference. * @return true if the lock was acquired and the reference is likely * protected from concurrent modification; false if it failed. * @throws IOException * the lock couldn't be taken due to an unexpected storage * failure, and not because of a concurrent update. */ - protected abstract boolean tryLock() throws IOException; + protected abstract boolean tryLock(boolean deref) throws IOException; /** Releases the lock taken by {@link #tryLock} if it succeeded. */ protected abstract void unlock(); @@ -209,6 +213,13 @@ public abstract class RefUpdate { protected abstract Result doDelete(Result desiredResult) throws IOException; /** + * @param target + * @return {@link Result#NEW} on success. + * @throws IOException + */ + protected abstract Result doLink(String target) throws IOException; + + /** * Get the name of the ref this update will operate on. * * @return name of underlying ref. @@ -499,6 +510,50 @@ public abstract class RefUpdate { } } + /** + * Replace this reference with a symbolic reference to another reference. + * <p> + * This exact reference (not its traversed leaf) is replaced with a symbolic + * reference to the requested name. + * + * @param target + * name of the new target for this reference. The new target name + * must be absolute, so it must begin with {@code refs/}. + * @return {@link Result#NEW} or {@link Result#FORCED} on success. + * @throws IOException + */ + public Result link(String target) throws IOException { + if (!target.startsWith(Constants.R_REFS)) + throw new IllegalArgumentException("Not " + Constants.R_REFS); + if (getRefDatabase().isNameConflicting(getName())) + return Result.LOCK_FAILURE; + try { + if (!tryLock(false)) + return Result.LOCK_FAILURE; + + final Ref old = getRefDatabase().getRef(getName()); + if (old != null && old.isSymbolic()) { + final Ref dst = old.getTarget(); + if (target.equals(dst.getName())) + return result = Result.NO_CHANGE; + } + + if (old != null && old.getObjectId() != null) + setOldObjectId(old.getObjectId()); + + final Ref dst = getRefDatabase().getRef(target); + if (dst != null && dst.getObjectId() != null) + setNewObjectId(dst.getObjectId()); + + return result = doLink(target); + } catch (IOException x) { + result = Result.IO_FAILURE; + throw x; + } finally { + unlock(); + } + } + private Result updateImpl(final RevWalk walk, final Store store) throws IOException { RevObject newObj; @@ -507,7 +562,7 @@ public abstract class RefUpdate { if (getRefDatabase().isNameConflicting(getName())) return Result.LOCK_FAILURE; try { - if (!tryLock()) + if (!tryLock(true)) return Result.LOCK_FAILURE; if (expValue != null) { final ObjectId o; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java index ecae243a41..ca86e36a47 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java @@ -276,8 +276,10 @@ public class Repository { objectDatabase.create(); new File(gitDir, "branches").mkdir(); - final String master = Constants.R_HEADS + Constants.MASTER; - refs.link(Constants.HEAD, master); + + RefUpdate head = updateRef(Constants.HEAD); + head.disableRefLog(); + head.link(Constants.R_HEADS + Constants.MASTER); cfg.setInt("core", null, "repositoryformatversion", 0); cfg.setBoolean("core", null, "filemode", true); @@ -899,18 +901,6 @@ public class Repository { objectDatabase.openPack(pack, idx); } - /** - * Writes a symref (e.g. HEAD) to disk - * - * @param name symref name - * @param target pointed to ref - * @throws IOException - */ - public void writeSymref(final String name, final String target) - throws IOException { - refs.link(name, target); - } - public String toString() { return "Repository[" + getDirectory() + "]"; } |