git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Yann Dirson <dirson@bertin.fr>
Cc: Thomas Rast <trast@inf.ethz.ch>,
	Johannes Sixt <j.sixt@viscovery.net>,
	Junio C Hamano <gitster@pobox.com>,
	Andreas Schwab <schwab@linux-m68k.org>,
	Christian Couder <christian.couder@gmail.com>,
	Thomas Rast <trast@student.ethz.ch>,
	git list <git@vger.kernel.org>
Subject: Re: [BUG] Cannot push some grafted branches
Date: Tue, 18 Dec 2012 11:24:02 -0500	[thread overview]
Message-ID: <20121218162402.GA20122@sigill.intra.peff.net> (raw)
In-Reply-To: <20121218144157.00ccd915@chalon.bertin.fr>

On Tue, Dec 18, 2012 at 02:41:57PM +0100, Yann Dirson wrote:

> > I wouldn't even want a script -- we'd end up inventing a complicated
> > command-line editor for what can simply be done by judicious use of an
> > actual text editor.  How about something like the following?
> 
> Well, while it does the job, it is still hardly as straightforward as the
> old "vi .git/info/grafts", or as a single easily-remembered commandline.

I wouldn't discount coming up with something based around "git commit"
that might be easier to use for specific instances, but it does seem
like an obvious feature to "git replace" to encapsulate Thomas's edit
script, which is the most general form.

I am not really interested in pushing this forward myself, but I worked
up this toy that somebody might find interesting (you can "git replace
HEAD~20" to get dumped in an editor). It should probably handle trees,
and it would probably make sense to do per-object-type sanity checks
(e.g., call verify_tag on tags).

diff --git a/builtin/replace.c b/builtin/replace.c
index 398ccd5..90979b6 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -81,6 +81,57 @@ static int delete_replace_ref(const char *name, const char *ref,
 	return 0;
 }
 
+static void edit_buffer(struct strbuf *out, const char *buf, unsigned long len)
+{
+	char tmpfile[PATH_MAX];
+	int fd;
+
+	fd = git_mkstemp(tmpfile, sizeof(tmpfile), "replace.XXXXXX");
+	if (fd < 0)
+		die_errno("unable to create tempfile");
+	if (write_in_full(fd, buf, len) < 0)
+		die_errno("unable to write to tempfile");
+	if (launch_editor(tmpfile, out, NULL) < 0)
+		die_errno("unable to run editor");
+
+	close(fd);
+	unlink_or_warn(tmpfile);
+}
+
+static void edit_object(unsigned char old[20], unsigned char new[20])
+{
+	enum object_type type;
+	unsigned long size;
+	char *old_buf;
+	struct strbuf new_buf = STRBUF_INIT;
+
+	old_buf = read_sha1_file_extended(old, &type, &size, 0);
+	if (!old_buf)
+		die("unable to read object '%s'", sha1_to_hex(old));
+
+	switch (type) {
+	case OBJ_COMMIT:
+	case OBJ_TAG:
+	case OBJ_BLOB:
+		/* These are OK to edit literally. */
+		edit_buffer(&new_buf, old_buf, size);
+		break;
+	case OBJ_TREE:
+		/*
+		 * XXX we'd probably want to massage this into ls-tree format,
+		 * and then read the result back via mktree.
+		 */
+		die("editing tree objects is not yet supported");
+	default:
+		die("unknown object type for %s", sha1_to_hex(old));
+	}
+
+	if (write_sha1_file(new_buf.buf, new_buf.len, typename(type), new) < 0)
+		die("unable to write replacement object");
+	free(old_buf);
+	strbuf_release(&new_buf);
+}
+
 static int replace_object(const char *object_ref, const char *replace_ref,
 			  int force)
 {
@@ -90,7 +141,7 @@ static int replace_object(const char *object_ref, const char *replace_ref,
 
 	if (get_sha1(object_ref, object))
 		die("Failed to resolve '%s' as a valid ref.", object_ref);
-	if (get_sha1(replace_ref, repl))
+	if (replace_ref && get_sha1(replace_ref, repl))
 		die("Failed to resolve '%s' as a valid ref.", replace_ref);
 
 	if (snprintf(ref, sizeof(ref),
@@ -105,6 +156,9 @@ static int replace_object(const char *object_ref, const char *replace_ref,
 	else if (!force)
 		die("replace ref '%s' already exists", ref);
 
+	if (!replace_ref)
+		edit_object(object, repl);
+
 	lock = lock_any_ref_for_update(ref, prev, 0);
 	if (!lock)
 		die("%s: cannot lock the ref", ref);
@@ -144,7 +198,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
 
 	/* Replace object */
 	if (!list && argc) {
-		if (argc != 2)
+		if (argc < 1 || argc > 2)
 			usage_msg_opt("bad number of arguments",
 				      git_replace_usage, options);
 		return replace_object(argv[0], argv[1], force);

  parent reply	other threads:[~2012-12-18 16:24 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-11 14:39 [BUG] Cannot push some grafted branches Yann Dirson
2012-12-11 18:15 ` Junio C Hamano
2012-12-12  8:44   ` Yann Dirson
2012-12-12 10:54     ` Yann Dirson
2012-12-12 19:57     ` Junio C Hamano
2012-12-17  7:52       ` Yann Dirson
2012-12-17  8:56         ` Junio C Hamano
2012-12-17 10:30           ` Yann Dirson
2012-12-17  8:43       ` Thomas Rast
2012-12-17 10:40         ` Yann Dirson
2012-12-17 13:43           ` Christian Couder
2012-12-17 14:02             ` Yann Dirson
2012-12-17 20:03             ` Andreas Schwab
2012-12-17 21:14               ` Junio C Hamano
2012-12-18 11:00                 ` Yann Dirson
2012-12-18 12:03                   ` Johannes Sixt
2012-12-18 12:49                     ` Thomas Rast
2012-12-18 13:41                       ` Yann Dirson
2012-12-18 14:31                         ` Thomas Rast
2012-12-18 16:24                         ` Jeff King [this message]
2012-12-19  7:13                           ` Johannes Sixt
2012-12-19 13:06                             ` Jeff King
2012-12-18 16:09                   ` Junio C Hamano
2012-12-19  8:29                     ` Yann Dirson
2012-12-19 13:12                     ` Thomas Rast
2012-12-19 20:07                       ` Junio C Hamano
2012-12-21 12:47                         ` Michael J Gruber
2012-12-21 16:58                           ` Junio C Hamano
2012-12-22 16:38                             ` Michael J Gruber

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=20121218162402.GA20122@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=christian.couder@gmail.com \
    --cc=dirson@bertin.fr \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=j.sixt@viscovery.net \
    --cc=schwab@linux-m68k.org \
    --cc=trast@inf.ethz.ch \
    --cc=trast@student.ethz.ch \
    /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).