git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Shawn O. Pearce" <spearce@spearce.org>
To: Robin Rosenberg <robin.rosenberg@dewire.com>
Cc: git@vger.kernel.org
Subject: Re: [EGIT PATCH 2/6] Add ref rename support to JGit
Date: Wed, 20 May 2009 15:16:51 -0700	[thread overview]
Message-ID: <20090520221651.GR30527@spearce.org> (raw)
In-Reply-To: <1242774798-23639-3-git-send-email-robin.rosenberg@dewire.com>

Robin Rosenberg <robin.rosenberg@dewire.com> wrote:
> Now refs can be renamed. The intent is that should be safe. Only the named
> refs and associated logs are updated. Any symbolic refs referring to the renames
> branches are unaffected, except HEAD.
...
> diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefLogWriter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefLogWriter.java
> index a077051..2efa12d 100644
> --- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefLogWriter.java
> +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefLogWriter.java
> @@ -58,6 +58,24 @@ static void append(final RefUpdate u, final String msg) throws IOException {
>  		appendOneRecord(oldId, newId, ident, msg, db, u.getName());
>  	}
>  
> +	static void renameTo(final Repository db, final RefUpdate from,
> +			final RefUpdate to) throws IOException {
> +		final File logdir = new File(db.getDirectory(), Constants.LOGS);
> +		final File reflogFrom = new File(logdir, from.getName());
> +		if (!reflogFrom.exists())
> +			return;
> +		final File reflogTo = new File(logdir, to.getName());
> +		final File refdirTo = reflogTo.getParentFile();
> +		if (!refdirTo.exists() && !refdirTo.mkdirs()) {
> +			throw new IOException("Cannot create directory " + refdirTo);
> +		}
> +		if (!reflogFrom.renameTo(reflogTo)) {

What happens if from = "refs/heads/a" and to = "refs/heads/a/b" ?

> diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefRename.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefRename.java
> new file mode 100644
> index 0000000..4ea9cfa
> --- /dev/null
> +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefRename.java
> @@ -0,0 +1,101 @@
> +package org.spearce.jgit.lib;

Copyright header?

> +
> +import java.io.File;
> +import java.io.IOException;
> +import java.util.ArrayList;
> +import java.util.List;
> +
> +import org.spearce.jgit.lib.RefUpdate.DeleteStore;
> +import org.spearce.jgit.lib.RefUpdate.Result;
> +import org.spearce.jgit.lib.RefUpdate.UpdateStore;
> +
> +/**
> + * A RefUpdate combination for renaming a ref
> + */
> +public class RefRename {
> +	private RefUpdate newToUpdate;
> +
> +	private RefUpdate oldFromDelete;
> +
> +	private Result renameResult;
> +
> +	RefRename(final RefUpdate toUpdate, final RefUpdate fromUpdate) {
> +		newToUpdate = toUpdate;
> +		oldFromDelete = fromUpdate;
> +	}
> +
> +	/**
> +	 * @return result of rename operation
> +	 */
> +	public Result getResult() {
> +		return renameResult;
> +	}
> +
> +	/**
> +	 * @return the result of the new ref update
> +	 * @throws IOException
> +	 */
> +	public Result rename() throws IOException {
> +		List<LockFile> lockFiles = new ArrayList<LockFile>();
> +		LockFile lockFileFrom = new LockFile(oldFromDelete.looseFile);
> +		LockFile lockFileTo = new LockFile(newToUpdate.looseFile);
> +		LockFile lockFileHEAD = new LockFile(new File(oldFromDelete.db
> +				.getRepository().getDirectory(), Constants.HEAD));
> +		lockFiles.add(lockFileTo);
> +		lockFiles.add(lockFileFrom);
> +		lockFiles.add(lockFileHEAD);
> +		try {
> +			for (LockFile l : lockFiles) {
> +				if (!l.lock()) {
> +					unlock(lockFiles);
> +					return Result.LOCK_FAILURE;
> +				}
> +			}
> +		} catch (RuntimeException e) {
> +			unlock(lockFiles);
> +			throw e;
> +		} catch (IOException e) {
> +			unlock(lockFiles);
> +			throw e;
> +		}
> +		boolean renameHEADtoo = oldFromDelete.db.readRef(Constants.HEAD)
> +				.getName().equals(oldFromDelete.getName());
> +		try {
> +			UpdateStore toStore = newToUpdate.newUpdateStore();
> +			RefLogWriter.renameTo(oldFromDelete.getRepository(), oldFromDelete,
> +					newToUpdate);
> +			newToUpdate.setNewObjectId(oldFromDelete.getOldObjectId());
> +			newToUpdate.setExpectedOldObjectId(oldFromDelete.getOldObjectId());

The dst ref can't expect its current value to be the src ref's
current value, the dst ref shouldn't exist, right?  So I'm not sure
how your code is working with this particular assignment occurring
in it.  Shouldn't the update store be failing over the compare on
expected old id?

I think we always want

  newToUpdate.setExpectedOldObjectId(ObjectId.zeroId())

as the JavaDoc for that method says zeroId should be used if the
ref isn't supposed to exist, which should be the case for the
destination side of a rename.

Ooooh.  I see.  Here UpdateStore is bypassing the CAS check, as
it runs inside of the RefUpdate.update() method, before the Store
instance is constructed.

Post taking the LockFile successfully we need to validate that

  ObjectId.zeroId().equals(db.idOf(newToUpdate.getName()))

is still true, otherwise it means someone else created the
destination ref and we're about to overwrite it.

> +			newToUpdate.setRefLogMessage("jgit branch: renamed "
> +					+ oldFromDelete.getName() + " to "
> +					+ oldFromDelete.getName(), false);

Typo, you meant newToUpdate here in the 2nd case.

-- 
Shawn.

  parent reply	other threads:[~2009-05-20 22:16 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-06 23:32 [EGIT PATCH 0/3] Rename refs Robin Rosenberg
2009-05-06 23:32 ` [EGIT PATCH 1/3] Add ref rename support to JGit Robin Rosenberg
2009-05-06 23:33   ` [EGIT PATCH 2/3] Use Constants.R_* in Branch dialog Robin Rosenberg
2009-05-06 23:33     ` [EGIT PATCH 3/3] Add ref rename support to the branch dialog Robin Rosenberg
2009-05-07 15:51   ` [EGIT PATCH 1/3] Add ref rename support to JGit Shawn O. Pearce
2009-05-19 23:13     ` [EGIT PATCH 0/6] Ref rename Robin Rosenberg
2009-05-19 23:13       ` [EGIT PATCH 1/6] Make sure we get the right storage for loose/pack/loose and packed refs Robin Rosenberg
2009-05-19 23:13         ` [EGIT PATCH 2/6] Add ref rename support to JGit Robin Rosenberg
2009-05-19 23:13           ` [EGIT PATCH 3/6] Add ref rename support to the branch dialog Robin Rosenberg
2009-05-19 23:13             ` [EGIT PATCH 4/6] Allow non-ASCII ref names when writing the packed-refs file Robin Rosenberg
2009-05-19 23:13               ` [EGIT PATCH 5/6] Use Constants.PACKED_REFS in RefWriter Robin Rosenberg
2009-05-19 23:13                 ` [EGIT PATCH 6/6] Improve error reporting in the branch dialog Robin Rosenberg
2009-05-20 22:16           ` Shawn O. Pearce [this message]
2009-05-27 22:08             ` [EGIT PATCH 00/10] Rename support Robin Rosenberg
2009-05-27 22:08               ` [EGIT PATCH 01/10] Make sure we get the right storage for loose/pack/loose and packed refs Robin Rosenberg
2009-05-27 22:08                 ` [EGIT PATCH 02/10] Add a toString for debugging to RemoteRefUpdate Robin Rosenberg
2009-05-27 22:08                   ` [EGIT PATCH 03/10] Add a toString to LockFile Robin Rosenberg
2009-05-27 22:08                     ` [EGIT PATCH 04/10] Add more tests for RefUpdate Robin Rosenberg
2009-05-27 22:08                       ` [EGIT PATCH 05/10] Do not write to the reflog unless the refupdate logmessage is set Robin Rosenberg
2009-05-27 22:08                         ` [EGIT PATCH 06/10] Add a utility method for shortening long ref names to short ones Robin Rosenberg
2009-05-27 22:08                           ` [EGIT PATCH 07/10] Set a nice reflog message in the branch command Robin Rosenberg
2009-05-27 22:08                             ` [EGIT PATCH 08/10] Add ref rename support to JGit Robin Rosenberg
2009-05-27 22:08                               ` [EGIT PATCH 09/10] Add ref rename support to the branch dialog Robin Rosenberg
2009-05-27 22:08                                 ` [EGIT PATCH 10/10] Improve error reporting in " Robin Rosenberg
2009-06-03 16:43                               ` [EGIT PATCH 08/10] Add ref rename support to JGit Shawn O. Pearce
2009-06-03 15:41                         ` [EGIT PATCH 05/10] Do not write to the reflog unless the refupdate logmessage is set Shawn O. Pearce
2009-06-07 22:27                           ` Robin Rosenberg
2009-06-07 22:44                             ` Shawn O. Pearce
2009-05-20 21:43         ` [EGIT PATCH 1/6] Make sure we get the right storage for loose/pack/loose and packed refs Shawn O. Pearce
2009-05-21 15:22           ` Robin Rosenberg
2009-05-21 15:48             ` Shawn O. Pearce
2009-06-10 21:22 ` [EGIT PATCH v5 0/7] Ref rename support again Robin Rosenberg
2009-06-10 21:22   ` [EGIT PATCH v5 1/7] Add methods to RawParseUtils for scanning backwards Robin Rosenberg
2009-06-10 21:22     ` [EGIT PATCH v5 2/7] Add a ref log reader class Robin Rosenberg
2009-06-10 21:22       ` [EGIT PATCH v5 3/7] Do not write to the reflog unless the refupdate logmessage is set Robin Rosenberg
2009-06-10 21:22         ` [EGIT PATCH v5 4/7] Add ref rename support to JGit Robin Rosenberg
2009-06-10 21:22           ` [EGIT PATCH v5 5/7] Add ref rename support to the branch dialog Robin Rosenberg
2009-06-10 21:22             ` [EGIT PATCH v5 6/7] Improve error reporting in " Robin Rosenberg
2009-06-10 21:22               ` [EGIT PATCH v5 7/7] Remove a TAB from the message Egit generates into the reflog on commit Robin Rosenberg
2009-06-12 20:02             ` [EGIT PATCH v5 5/7] Add ref rename support to the branch dialog Shawn O. Pearce
2009-06-14 19:47               ` [EGIT PATCH v6 5a/7] Warn for unlocalized string literals in ui plugin Robin Rosenberg
2009-06-14 19:47                 ` [EGIT PATCH v6 5b/6] Add ref rename support to the branch dialog Robin Rosenberg
2009-06-14 19:47                   ` [EGIT PATCH v6 6/7] Improve error reporting in " Robin Rosenberg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090520221651.GR30527@spearce.org \
    --to=spearce@spearce.org \
    --cc=git@vger.kernel.org \
    --cc=robin.rosenberg@dewire.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).