{"thread":{"id":"36507","subject":"[PATCH v1 2/4] replace: use OPT_CMDMODE to handle modes","startedAt":"2014-04-26T20:00:53Z","lastAt":"2014-04-29T21:43:54Z","messageCount":7,"participants":["Christian Couder","Jeff King","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"239780","messageId":"20140426194404.21546.82305.chriscool@tuxfamily.org","threadId":"36507","inReplyTo":null,"subject":"[PATCH v1 0/4] replace: add option to edit a Git object","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2014-04-26T20:00:53Z","receivedAt":"2014-04-26T20:00:53Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This patch series comes from what Peff sent in the following thread:\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/243361/focus=243528\n\nI added the following fixes:\n\n- add \"strbuf_release(&result);\" in import_object(); this was suggested\n  by Eric Sunshine\n- use MODE_LIST instead of MODE_DELETE if no arguments are passed; this\n  makes the test suite pass\n- add \"--no-replace-objects\" when calling \"git cat-file\" in export_object();\n  so that we edit the original object if an object is already replaced\n\nI am not happy with the fact that if the user doesn't modify the object when\nediting it, then a replace ref can still be created that points to the\noriginal object. I think something should be done to avoid that.\n\nOnce that is fixed, I plan to add some tests and documentation, but I wanted\nfirst to let you know that I am looking at this.\n\nJeff King (4):\n  replace: refactor command-mode determination\n  replace: use OPT_CMDMODE to handle modes\n  replace: factor object resolution out of replace_object\n  replace: add --edit option\n\n builtin/replace.c | 189 ++++++++++++++++++++++++++++++++++++++++++++----------\n 1 file changed, 154 insertions(+), 35 deletions(-)\n\n-- \n1.9.1.636.g20d5f34\n"},{"id":"239781","messageId":"20140426200058.21546.78905.chriscool@tuxfamily.org","threadId":"36507","inReplyTo":"20140426194404.21546.82305.chriscool@tuxfamily.org","subject":"[PATCH v1 1/4] replace: refactor command-mode determination","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2014-04-26T20:00:54Z","receivedAt":"2014-04-26T20:00:54Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"From: Jeff King <peff@peff.net>\n\nThe git-replace command has three modes: listing, deleting,\nand replacing. The first two are selected explicitly. If\nnone is selected, we fallback to listing when there are no\narguments, and replacing otherwise.\n\nLet's figure out up front which operation we are going to\ndo, before getting into the application logic. That lets us\nsimplify our option checks (e.g., we currently have to check\nwhether a useless \"--force\" is given both along with an\nexplicit list, as well as with an implicit one).\n\nThis saves some lines, makes the logic easier to follow, and\nwill facilitate further cleanups.\n\nSigned-off-by: Jeff King <peff@peff.net>\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/replace.c | 14 ++++++--------\n 1 file changed, 6 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex b62420a..28db96f 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -182,12 +182,16 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\n \n \targc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);\n \n+\tif (!list && !delete)\n+\t\tif (!argc)\n+\t\t\tlist = 1;\n+\n \tif (list && delete)\n \t\tusage_msg_opt(\"-l and -d cannot be used together\",\n \t\t\t      git_replace_usage, options);\n \n-\tif (format && delete)\n-\t\tusage_msg_opt(\"--format and -d cannot be used together\",\n+\tif (format && !list)\n+\t\tusage_msg_opt(\"--format cannot be used when not listing\",\n \t\t\t      git_replace_usage, options);\n \n \tif (force && (list || delete))\n@@ -207,9 +211,6 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\n \t\tif (argc != 2)\n \t\t\tusage_msg_opt(\"bad number of arguments\",\n \t\t\t\t      git_replace_usage, options);\n-\t\tif (format)\n-\t\t\tusage_msg_opt(\"--format cannot be used when not listing\",\n-\t\t\t\t      git_replace_usage, options);\n \t\treturn replace_object(argv[0], argv[1], force);\n \t}\n \n@@ -217,9 +218,6 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\n \tif (argc > 1)\n \t\tusage_msg_opt(\"only one pattern can be given with -l\",\n \t\t\t      git_replace_usage, options);\n-\tif (force)\n-\t\tusage_msg_opt(\"-f needs some arguments\",\n-\t\t\t      git_replace_usage, options);\n \n \treturn list_replace_refs(argv[0], format);\n }\n-- \n1.9.1.636.g20d5f34\n"},{"id":"239777","messageId":"20140426200058.21546.25686.chriscool@tuxfamily.org","threadId":"36507","inReplyTo":"20140426194404.21546.82305.chriscool@tuxfamily.org","subject":"[PATCH v1 2/4] replace: use OPT_CMDMODE to handle modes","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2014-04-26T20:00:55Z","receivedAt":"2014-04-26T20:00:55Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"From: Jeff King <peff@peff.net>\n\nBy using OPT_CMDMODE, the mutual exclusion between modes is\ntaken care of for us. It also makes it easy for us to\nmaintain a single variable with the mode, which makes its\nintent more clear. We can use a single switch() to make sure\nwe have covered all of the modes.\n\nThis ends up breaking even in code size, but the win will be\nmuch bigger when we start adding more modes.\n\nSigned-off-by: Jeff King <peff@peff.net>\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/replace.c | 49 +++++++++++++++++++++++++------------------------\n 1 file changed, 25 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 28db96f..29cf699 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -168,11 +168,17 @@ static int replace_object(const char *object_ref, const char *replace_ref,\n \n int cmd_replace(int argc, const char **argv, const char *prefix)\n {\n-\tint list = 0, delete = 0, force = 0;\n+\tint force = 0;\n \tconst char *format = NULL;\n+\tenum {\n+\t\tMODE_UNSPECIFIED = 0,\n+\t\tMODE_LIST,\n+\t\tMODE_DELETE,\n+\t\tMODE_REPLACE\n+\t} cmdmode = MODE_UNSPECIFIED;\n \tstruct option options[] = {\n-\t\tOPT_BOOL('l', \"list\", &list, N_(\"list replace refs\")),\n-\t\tOPT_BOOL('d', \"delete\", &delete, N_(\"delete replace refs\")),\n+\t\tOPT_CMDMODE('l', \"list\", &cmdmode, N_(\"list replace refs\"), MODE_LIST),\n+\t\tOPT_CMDMODE('d', \"delete\", &cmdmode, N_(\"delete replace refs\"), MODE_DELETE),\n \t\tOPT_BOOL('f', \"force\", &force, N_(\"replace the ref if it exists\")),\n \t\tOPT_STRING(0, \"format\", &format, N_(\"format\"), N_(\"use this format\")),\n \t\tOPT_END()\n@@ -182,42 +188,37 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\n \n \targc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);\n \n-\tif (!list && !delete)\n-\t\tif (!argc)\n-\t\t\tlist = 1;\n+\tif (!cmdmode)\n+\t\tcmdmode = argc ? MODE_REPLACE : MODE_LIST;\n \n-\tif (list && delete)\n-\t\tusage_msg_opt(\"-l and -d cannot be used together\",\n-\t\t\t      git_replace_usage, options);\n-\n-\tif (format && !list)\n+\tif (format && cmdmode != MODE_LIST)\n \t\tusage_msg_opt(\"--format cannot be used when not listing\",\n \t\t\t      git_replace_usage, options);\n \n-\tif (force && (list || delete))\n-\t\tusage_msg_opt(\"-f cannot be used with -d or -l\",\n+\tif (force && cmdmode != MODE_REPLACE)\n+\t\tusage_msg_opt(\"-f only makes sense when writing a replacement\",\n \t\t\t      git_replace_usage, options);\n \n-\t/* Delete refs */\n-\tif (delete) {\n+\tswitch (cmdmode) {\n+\tcase MODE_DELETE:\n \t\tif (argc < 1)\n \t\t\tusage_msg_opt(\"-d needs at least one argument\",\n \t\t\t\t      git_replace_usage, options);\n \t\treturn for_each_replace_name(argv, delete_replace_ref);\n-\t}\n \n-\t/* Replace object */\n-\tif (!list && argc) {\n+\tcase MODE_REPLACE:\n \t\tif (argc != 2)\n \t\t\tusage_msg_opt(\"bad number of arguments\",\n \t\t\t\t      git_replace_usage, options);\n \t\treturn replace_object(argv[0], argv[1], force);\n-\t}\n \n-\t/* List refs, even if \"list\" is not set */\n-\tif (argc > 1)\n-\t\tusage_msg_opt(\"only one pattern can be given with -l\",\n-\t\t\t      git_replace_usage, options);\n+\tcase MODE_LIST:\n+\t\tif (argc > 1)\n+\t\t\tusage_msg_opt(\"only one pattern can be given with -l\",\n+\t\t\t\t      git_replace_usage, options);\n+\t\treturn list_replace_refs(argv[0], format);\n \n-\treturn list_replace_refs(argv[0], format);\n+\tdefault:\n+\t\tdie(\"BUG: invalid cmdmode %d\", (int)cmdmode);\n+\t}\n }\n-- \n1.9.1.636.g20d5f34\n"},{"id":"239778","messageId":"20140426200058.21546.63153.chriscool@tuxfamily.org","threadId":"36507","inReplyTo":"20140426194404.21546.82305.chriscool@tuxfamily.org","subject":"[PATCH v1 3/4] replace: factor object resolution out of replace_object","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2014-04-26T20:00:56Z","receivedAt":"2014-04-26T20:00:56Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"From: Jeff King <peff@peff.net>\n\nAs we add new options that operate on objects before\nreplacing them, we'll want to be able to feed raw sha1s\nstraight into replace_object. Split replace_object into the\nobject-resolution part and the actual replacement.\n\nSigned-off-by: Jeff King <peff@peff.net>\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/replace.c | 26 ++++++++++++++++++--------\n 1 file changed, 18 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 29cf699..af40129 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -123,19 +123,17 @@ static int delete_replace_ref(const char *name, const char *ref,\n \treturn 0;\n }\n \n-static int replace_object(const char *object_ref, const char *replace_ref,\n-\t\t\t  int force)\n+static int replace_object_sha1(const char *object_ref,\n+\t\t\t       unsigned char object[20],\n+\t\t\t       const char *replace_ref,\n+\t\t\t       unsigned char repl[20],\n+\t\t\t       int force)\n {\n-\tunsigned char object[20], prev[20], repl[20];\n+\tunsigned char prev[20];\n \tenum object_type obj_type, repl_type;\n \tchar ref[PATH_MAX];\n \tstruct ref_lock *lock;\n \n-\tif (get_sha1(object_ref, object))\n-\t\tdie(\"Failed to resolve '%s' as a valid ref.\", object_ref);\n-\tif (get_sha1(replace_ref, repl))\n-\t\tdie(\"Failed to resolve '%s' as a valid ref.\", replace_ref);\n-\n \tif (snprintf(ref, sizeof(ref),\n \t\t     \"refs/replace/%s\",\n \t\t     sha1_to_hex(object)) > sizeof(ref) - 1)\n@@ -166,6 +164,18 @@ static int replace_object(const char *object_ref, const char *replace_ref,\n \treturn 0;\n }\n \n+static int replace_object(const char *object_ref, const char *replace_ref, int force)\n+{\n+\tunsigned char object[20], repl[20];\n+\n+\tif (get_sha1(object_ref, object))\n+\t\tdie(\"Failed to resolve '%s' as a valid ref.\", object_ref);\n+\tif (get_sha1(replace_ref, repl))\n+\t\tdie(\"Failed to resolve '%s' as a valid ref.\", replace_ref);\n+\n+\treturn replace_object_sha1(object_ref, object, replace_ref, repl, force);\n+}\n+\n int cmd_replace(int argc, const char **argv, const char *prefix)\n {\n \tint force = 0;\n-- \n1.9.1.636.g20d5f34\n"},{"id":"239779","messageId":"20140426200058.21546.28299.chriscool@tuxfamily.org","threadId":"36507","inReplyTo":"20140426194404.21546.82305.chriscool@tuxfamily.org","subject":"[PATCH v1 4/4] replace: add --edit option","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2014-04-26T20:00:57Z","receivedAt":"2014-04-26T20:00:57Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"From: Jeff King <peff@peff.net>\n\nThis allows you to run:\n\n    git replace --edit SHA1\n\nto get dumped in an editor with the contents of the object\nfor SHA1. The result is then read back in and used as a\n\"replace\" object for SHA1. The writing/reading is\ntype-aware, so you get to edit \"ls-tree\" output rather than\nthe binary tree format.\n\nMissing documentation and tests.\n\nSigned-off-by: Jeff King <peff@peff.net>\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/replace.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 111 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex af40129..3da1bae 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -12,6 +12,7 @@\n #include \"builtin.h\"\n #include \"refs.h\"\n #include \"parse-options.h\"\n+#include \"run-command.h\"\n \n static const char * const git_replace_usage[] = {\n \tN_(\"git replace [-f] <object> <replacement>\"),\n@@ -176,6 +177,107 @@ static int replace_object(const char *object_ref, const char *replace_ref, int f\n \treturn replace_object_sha1(object_ref, object, replace_ref, repl, force);\n }\n \n+/*\n+ * Write the contents of the object named by \"sha1\" to the file \"filename\",\n+ * pretty-printed for human editing based on its type.\n+ */\n+static void export_object(const unsigned char *sha1, const char *filename)\n+{\n+\tconst char *argv[] = { \"--no-replace-objects\", \"cat-file\", \"-p\", NULL, NULL };\n+\tstruct child_process cmd = { argv };\n+\tint fd;\n+\n+\tfd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);\n+\tif (fd < 0)\n+\t\tdie_errno(\"unable to open %s for writing\", filename);\n+\n+\targv[3] = sha1_to_hex(sha1);\n+\tcmd.git_cmd = 1;\n+\tcmd.out = fd;\n+\n+\tif (run_command(&cmd))\n+\t\tdie(\"cat-file reported failure\");\n+\n+\tclose(fd);\n+}\n+\n+/*\n+ * Read a previously-exported (and possibly edited) object back from \"filename\",\n+ * interpreting it as \"type\", and writing the result to the object database.\n+ * The sha1 of the written object is returned via sha1.\n+ */\n+static void import_object(unsigned char *sha1, enum object_type type,\n+\t\t\t  const char *filename)\n+{\n+\tint fd;\n+\n+\tfd = open(filename, O_RDONLY);\n+\tif (fd < 0)\n+\t\tdie_errno(\"unable to open %s for reading\", filename);\n+\n+\tif (type == OBJ_TREE) {\n+\t\tconst char *argv[] = { \"mktree\", NULL };\n+\t\tstruct child_process cmd = { argv };\n+\t\tstruct strbuf result = STRBUF_INIT;\n+\n+\t\tcmd.argv = argv;\n+\t\tcmd.git_cmd = 1;\n+\t\tcmd.in = fd;\n+\t\tcmd.out = -1;\n+\n+\t\tif (start_command(&cmd))\n+\t\t\tdie(\"unable to spawn mktree\");\n+\n+\t\tif (strbuf_read(&result, cmd.out, 41) < 0)\n+\t\t\tdie_errno(\"unable to read from mktree\");\n+\t\tclose(cmd.out);\n+\n+\t\tif (finish_command(&cmd))\n+\t\t\tdie(\"mktree reported failure\");\n+\t\tif (get_sha1_hex(result.buf, sha1) < 0)\n+\t\t\tdie(\"mktree did not return an object name\");\n+\n+\t\tstrbuf_release(&result);\n+\t} else {\n+\t\tstruct stat st;\n+\t\tint flags = HASH_FORMAT_CHECK | HASH_WRITE_OBJECT;\n+\n+\t\tif (fstat(fd, &st) < 0)\n+\t\t\tdie_errno(\"unable to fstat %s\", filename);\n+\t\tif (index_fd(sha1, fd, &st, type, NULL, flags) < 0)\n+\t\t\tdie(\"unable to write object to database\");\n+\t\t/* index_fd close()s fd for us */\n+\t}\n+\n+\t/*\n+\t * No need to close(fd) here; both run-command and index-fd\n+\t * will have done it for us.\n+\t */\n+}\n+\n+static int edit_and_replace(const char *object_ref, int force)\n+{\n+\tchar *tmpfile = git_pathdup(\"REPLACE_EDITOBJ\");\n+\tenum object_type type;\n+\tunsigned char old[20], new[20];\n+\n+\tif (get_sha1(object_ref, old) < 0)\n+\t\tdie(\"Not a valid object name: '%s'\", object_ref);\n+\n+\ttype = sha1_object_info(old, NULL);\n+\tif (type < 0)\n+\t\tdie(\"unable to get object type for %s\", sha1_to_hex(old));\n+\n+\texport_object(old, tmpfile);\n+\tif (launch_editor(tmpfile, NULL, NULL) < 0)\n+\t\tdie(\"editing object file failed\");\n+\timport_object(new, type, tmpfile);\n+\n+\tfree(tmpfile);\n+\n+\treturn replace_object_sha1(object_ref, old, \"replacement\", new, force);\n+}\n+\n int cmd_replace(int argc, const char **argv, const char *prefix)\n {\n \tint force = 0;\n@@ -184,11 +286,13 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\n \t\tMODE_UNSPECIFIED = 0,\n \t\tMODE_LIST,\n \t\tMODE_DELETE,\n+\t\tMODE_EDIT,\n \t\tMODE_REPLACE\n \t} cmdmode = MODE_UNSPECIFIED;\n \tstruct option options[] = {\n \t\tOPT_CMDMODE('l', \"list\", &cmdmode, N_(\"list replace refs\"), MODE_LIST),\n \t\tOPT_CMDMODE('d', \"delete\", &cmdmode, N_(\"delete replace refs\"), MODE_DELETE),\n+\t\tOPT_CMDMODE('e', \"edit\", &cmdmode, N_(\"edit existing object\"), MODE_EDIT),\n \t\tOPT_BOOL('f', \"force\", &force, N_(\"replace the ref if it exists\")),\n \t\tOPT_STRING(0, \"format\", &format, N_(\"format\"), N_(\"use this format\")),\n \t\tOPT_END()\n@@ -205,7 +309,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\n \t\tusage_msg_opt(\"--format cannot be used when not listing\",\n \t\t\t      git_replace_usage, options);\n \n-\tif (force && cmdmode != MODE_REPLACE)\n+\tif (force && cmdmode != MODE_REPLACE && cmdmode != MODE_EDIT)\n \t\tusage_msg_opt(\"-f only makes sense when writing a replacement\",\n \t\t\t      git_replace_usage, options);\n \n@@ -222,6 +326,12 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\n \t\t\t\t      git_replace_usage, options);\n \t\treturn replace_object(argv[0], argv[1], force);\n \n+\tcase MODE_EDIT:\n+\t\tif (argc != 1)\n+\t\t\tusage_msg_opt(\"-e needs exactly one argument\",\n+\t\t\t\t      git_replace_usage, options);\n+\t\treturn edit_and_replace(argv[0], force);\n+\n \tcase MODE_LIST:\n \t\tif (argc > 1)\n \t\t\tusage_msg_opt(\"only one pattern can be given with -l\",\n-- \n1.9.1.636.g20d5f34\n"},{"id":"240104","messageId":"20140429023629.GB11730@sigill.intra.peff.net","threadId":"36507","inReplyTo":"20140426194404.21546.82305.chriscool@tuxfamily.org","subject":"Re: [PATCH v1 0/4] replace: add option to edit a Git object","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-04-29T02:36:29Z","receivedAt":"2014-04-29T02:36:29Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Apr 26, 2014 at 10:00:53PM +0200, Christian Couder wrote:\n\n> This patch series comes from what Peff sent in the following thread:\n> \n> http://thread.gmane.org/gmane.comp.version-control.git/243361/focus=243528\n\nThanks. As I recall, these were in pretty good shape, and I just read\nover them again and didn't see anything wrong.\n\n> I added the following fixes:\n> \n> - add \"strbuf_release(&result);\" in import_object(); this was suggested\n>   by Eric Sunshine\n> - use MODE_LIST instead of MODE_DELETE if no arguments are passed; this\n>   makes the test suite pass\n> - add \"--no-replace-objects\" when calling \"git cat-file\" in export_object();\n>   so that we edit the original object if an object is already replaced\n\nAll sensible, I think.\n\n> I am not happy with the fact that if the user doesn't modify the object when\n> editing it, then a replace ref can still be created that points to the\n> original object. I think something should be done to avoid that.\n\nYeah, it should be easy to just hashcmp the sha1s after calling\nimport_object. In fact, I think we can just erase any existing replace\nref in that case (the user might have started with a replace ref and\nconverted it _back_ to the original object, for example).\n\n> Once that is fixed, I plan to add some tests and documentation, but I wanted\n> first to let you know that I am looking at this.\n\nGreat. Thanks for working on this.\n\n-Peff\n"},{"id":"240205","messageId":"xmqqvbtrizfp.fsf@gitster.dls.corp.google.com","threadId":"36507","inReplyTo":"20140429023629.GB11730@sigill.intra.peff.net","subject":"Re: [PATCH v1 0/4] replace: add option to edit a Git object","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-04-29T21:43:54Z","receivedAt":"2014-04-29T21:43:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Sat, Apr 26, 2014 at 10:00:53PM +0200, Christian Couder wrote:\n>\n>> This patch series comes from what Peff sent in the following thread:\n>> \n>> http://thread.gmane.org/gmane.comp.version-control.git/243361/focus=243528\n>\n> Thanks. As I recall, these were in pretty good shape, and I just read\n> over them again and didn't see anything wrong.\n>\n>> I added the following fixes:\n>> \n>> - add \"strbuf_release(&result);\" in import_object(); this was suggested\n>>   by Eric Sunshine\n>> - use MODE_LIST instead of MODE_DELETE if no arguments are passed; this\n>>   makes the test suite pass\n>> - add \"--no-replace-objects\" when calling \"git cat-file\" in export_object();\n>>   so that we edit the original object if an object is already replaced\n>\n> All sensible, I think.\n>\n>> I am not happy with the fact that if the user doesn't modify the object when\n>> editing it, then a replace ref can still be created that points to the\n>> original object. I think something should be done to avoid that.\n>\n> Yeah, it should be easy to just hashcmp the sha1s after calling\n> import_object. In fact, I think we can just erase any existing replace\n> ref in that case (the user might have started with a replace ref and\n> converted it _back_ to the original object, for example).\n>\n>> Once that is fixed, I plan to add some tests and documentation, but I wanted\n>> first to let you know that I am looking at this.\n>\n> Great. Thanks for working on this.\n>\n> -Peff\n\nThanks.  In the meantime, I'll queue these as-is and push the result\nout.\n"}]}