From: Jeff King <peff@peff.net>
To: Michael Haggerty <mhagger@alum.mit.edu>
Cc: Christian Couder <christian.couder@gmail.com>,
Junio C Hamano <gitster@pobox.com>,
git@vger.kernel.org
Subject: [RFC/PATCH 4/4] replace: add --edit option
Date: Thu, 6 Mar 2014 12:51:17 -0500 [thread overview]
Message-ID: <20140306175117.GD30691@sigill.intra.peff.net> (raw)
In-Reply-To: <20140306174803.GA30486@sigill.intra.peff.net>
This allows you to run:
git replace --edit SHA1
to get dumped in an editor with the contents of the object
for SHA1. The result is then read back in and used as a
"replace" object for SHA1. The writing/reading is
type-aware, so you get to edit "ls-tree" output rather than
the binary tree format.
Missing documentation and tests.
Signed-off-by: Jeff King <peff@peff.net>
---
Besides missing docs and tests, we might find that we want to factor the
code a little differently when we start adding other helpers (like
"--graft"). I will probably push this forward at some point, but I'm not
planning on working on it for the rest of the day, so if you want to
pick it up as a base in the meantime and try "--graft", "--env-filter",
or anything else clever on top, please go ahead.
builtin/replace.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 109 insertions(+), 1 deletion(-)
diff --git a/builtin/replace.c b/builtin/replace.c
index a090302..3ed5f75 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -12,6 +12,7 @@
#include "builtin.h"
#include "refs.h"
#include "parse-options.h"
+#include "run-command.h"
static const char * const git_replace_usage[] = {
N_("git replace [-f] <object> <replacement>"),
@@ -176,6 +177,105 @@ static int replace_object(const char *object_ref, const char *replace_ref, int f
return replace_object_sha1(object_ref, object, replace_ref, repl, force);
}
+/*
+ * Write the contents of the object named by "sha1" to the file "filename",
+ * pretty-printed for human editing based on its type.
+ */
+static void export_object(const unsigned char *sha1, const char *filename)
+{
+ const char *argv[] = { "cat-file", "-p", NULL, NULL };
+ struct child_process cmd = { argv };
+ int fd;
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0)
+ die_errno("unable to open %s for writing", filename);
+
+ argv[2] = sha1_to_hex(sha1);
+ cmd.git_cmd = 1;
+ cmd.out = fd;
+
+ if (run_command(&cmd))
+ die("cat-file reported failure");
+
+ close(fd);
+}
+
+/*
+ * Read a previously-exported (and possibly edited) object back from "filename",
+ * interpreting it as "type", and writing the result to the object database.
+ * The sha1 of the written object is returned via sha1.
+ */
+static void import_object(unsigned char *sha1, enum object_type type,
+ const char *filename)
+{
+ int fd;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ die_errno("unable to open %s for reading", filename);
+
+ if (type == OBJ_TREE) {
+ const char *argv[] = { "mktree", NULL };
+ struct child_process cmd = { argv };
+ struct strbuf result = STRBUF_INIT;
+
+ cmd.argv = argv;
+ cmd.git_cmd = 1;
+ cmd.in = fd;
+ cmd.out = -1;
+
+ if (start_command(&cmd))
+ die("unable to spawn mktree");
+
+ if (strbuf_read(&result, cmd.out, 41) < 0)
+ die_errno("unable to read from mktree");
+ close(cmd.out);
+
+ if (finish_command(&cmd))
+ die("mktree reported failure");
+ if (get_sha1_hex(result.buf, sha1) < 0)
+ die("mktree did not return an object name");
+ } else {
+ struct stat st;
+ int flags = HASH_FORMAT_CHECK | HASH_WRITE_OBJECT;
+
+ if (fstat(fd, &st) < 0)
+ die_errno("unable to fstat %s", filename);
+ if (index_fd(sha1, fd, &st, type, NULL, flags) < 0)
+ die("unable to write object to database");
+ /* index_fd close()s fd for us */
+ }
+
+ /*
+ * No need to close(fd) here; both run-command and index-fd
+ * will have done it for us.
+ */
+}
+
+static int edit_and_replace(const char *object_ref, int force)
+{
+ char *tmpfile = git_pathdup("REPLACE_EDITOBJ");
+ enum object_type type;
+ unsigned char old[20], new[20];
+
+ if (get_sha1(object_ref, old) < 0)
+ die("Not a valid object name: '%s'", object_ref);
+
+ type = sha1_object_info(old, NULL);
+ if (type < 0)
+ die("unable to get object type for %s", sha1_to_hex(old));
+
+ export_object(old, tmpfile);
+ if (launch_editor(tmpfile, NULL, NULL) < 0)
+ die("editing object file failed");
+ import_object(new, type, tmpfile);
+
+ free(tmpfile);
+
+ return replace_object_sha1(object_ref, old, "replacement", new, force);
+}
+
int cmd_replace(int argc, const char **argv, const char *prefix)
{
int force = 0;
@@ -184,11 +284,13 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
MODE_UNSPECIFIED = 0,
MODE_LIST,
MODE_DELETE,
+ MODE_EDIT,
MODE_REPLACE
} cmdmode = MODE_UNSPECIFIED;
struct option options[] = {
OPT_CMDMODE('l', "list", &cmdmode, N_("list replace refs"), MODE_LIST),
OPT_CMDMODE('d', "delete", &cmdmode, N_("delete replace refs"), MODE_DELETE),
+ OPT_CMDMODE('e', "edit", &cmdmode, N_("edit existing object"), MODE_EDIT),
OPT_BOOL('f', "force", &force, N_("replace the ref if it exists")),
OPT_STRING(0, "format", &format, N_("format"), N_("use this format")),
OPT_END()
@@ -205,7 +307,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
usage_msg_opt("--format cannot be used when not listing",
git_replace_usage, options);
- if (force && cmdmode != MODE_REPLACE)
+ if (force && cmdmode != MODE_REPLACE && cmdmode != MODE_EDIT)
usage_msg_opt("-f only makes sense when writing a replacement",
git_replace_usage, options);
@@ -222,6 +324,12 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
git_replace_usage, options);
return replace_object(argv[0], argv[1], force);
+ case MODE_EDIT:
+ if (argc != 1)
+ usage_msg_opt("-e needs exactly one argument",
+ git_replace_usage, options);
+ return edit_and_replace(argv[0], force);
+
case MODE_LIST:
if (argc > 1)
usage_msg_opt("only one pattern can be given with -l",
--
1.8.5.2.500.g8060133
next prev parent reply other threads:[~2014-03-06 17:51 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-04 17:48 [PATCH] disable grafts during fetch/push/bundle Jeff King
2014-03-04 20:52 ` Junio C Hamano
2014-03-05 0:56 ` Jeff King
2014-03-05 18:49 ` Junio C Hamano
2014-03-05 18:52 ` Jeff King
2014-03-05 19:18 ` Junio C Hamano
2014-03-05 19:28 ` Jeff King
2014-03-05 20:24 ` Junio C Hamano
2014-03-06 8:42 ` Michael Haggerty
2014-03-06 9:17 ` Christian Couder
2014-03-06 15:56 ` Jeff King
2014-03-06 16:41 ` Michael Haggerty
2014-03-06 17:48 ` Jeff King
2014-03-06 17:49 ` [RFC/PATCH 1/4] replace: refactor command-mode determination Jeff King
2014-03-06 17:49 ` [RFC/PATCH 2/4] replace: use OPT_CMDMODE to handle modes Jeff King
[not found] ` <CAP8UFD2c0UKT8Uyw4j9SzKGx2oLn=o7N-dtvQHPaaBtLT6ggcw@mail.gmail.com>
2014-03-06 18:48 ` Jeff King
2014-03-06 17:49 ` [RFC/PATCH 3/4] replace: factor object resolution out of replace_object Jeff King
2014-03-06 17:51 ` Jeff King [this message]
2014-03-07 1:57 ` [RFC/PATCH 4/4] replace: add --edit option Eric Sunshine
2014-03-07 17:17 ` Jeff King
2014-03-06 19:00 ` [PATCH] disable grafts during fetch/push/bundle Junio C Hamano
2014-03-06 19:07 ` Jeff King
2014-03-06 23:01 ` Philip Oakley
2014-03-06 23:29 ` Michael Haggerty
2014-03-06 23:39 ` Junio C Hamano
2014-03-07 7:08 ` Christian Couder
2014-03-07 17:19 ` Jeff King
2014-03-19 22:39 ` Junio C Hamano
2014-03-21 0:49 ` Jeff King
2014-03-06 23:48 ` Philip Oakley
2014-03-04 23:36 ` Eric Sunshine
2014-03-05 0:37 ` Jeff King
2014-03-05 1:00 ` Eric Sunshine
2014-03-05 1:05 ` Jeff King
2014-03-05 1:07 ` Eric Sunshine
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=20140306175117.GD30691@sigill.intra.peff.net \
--to=peff@peff.net \
--cc=christian.couder@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=mhagger@alum.mit.edu \
/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).