{"thread":{"id":"35581","subject":"[PATCH v4 01/10] Rename READ_SHA1_FILE_REPLACE flag to LOOKUP_REPLACE_OBJECT","startedAt":"2013-12-28T11:00:05Z","lastAt":"2013-12-31T06:23:58Z","messageCount":13,"participants":["Christian Couder","Junio C Hamano"],"isPatch":true,"patchVersion":4,"patchTotal":10},"messages":[{"id":"232477","messageId":"20131228105505.2272.58873.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":null,"subject":"[PATCH v4 00/10] teach replace objects to sha1_object_info_extended()","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:05Z","receivedAt":"2013-12-28T11:00:05Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Here is version 4 of a patch series to improve the way\nsha1_object_info_extended() behaves when it is passed a\nreplaced object. The idea is to add a flags argument to it\nin the same way as what has been done to read_sha1_file().\n\nThis patch series was inspired by a sub thread in this\ndiscussion:\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/238118\n\nThe only changes compared to version 3 are the following:\n\n\t- the name of the 'full' format is now 'long'\n\n\t- the names of the replace_format enum fields\n\thave been prepended with 'REPLACE_FORMAT_'. This\n\tavoids a compilation conflict on Windows where\n\tSHORT is predefined. Thanks to Karsten for\n\treporting this problem.\n\nThese changes only affect patches 7/10, 8/10, 9/10 and 10/10\nthat add a new --format option to list replace refs.\n\nChristian Couder (10):\n  Rename READ_SHA1_FILE_REPLACE flag to LOOKUP_REPLACE_OBJECT\n  replace_object: don't check read_replace_refs twice\n  Introduce lookup_replace_object_extended() to pass flags\n  Add an \"unsigned flags\" parameter to sha1_object_info_extended()\n  t6050: show that git cat-file --batch fails with replace objects\n  sha1_file: perform object replacement in sha1_object_info_extended()\n  builtin/replace: teach listing using short, medium or long formats\n  t6050: add tests for listing with --format\n  builtin/replace: unset read_replace_refs\n  Documentation/git-replace: describe --format option\n\n Documentation/git-replace.txt | 19 +++++++++++-\n builtin/cat-file.c            |  2 +-\n builtin/replace.c             | 67 ++++++++++++++++++++++++++++++++++++++-----\n cache.h                       | 12 ++++++--\n replace_object.c              |  3 --\n sha1_file.c                   | 20 ++++++-------\n streaming.c                   |  2 +-\n t/t6050-replace.sh            | 42 +++++++++++++++++++++++++++\n 8 files changed, 141 insertions(+), 26 deletions(-)\n\n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232476","messageId":"20131228110016.2272.85613.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 01/10] Rename READ_SHA1_FILE_REPLACE flag to LOOKUP_REPLACE_OBJECT","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:06Z","receivedAt":"2013-12-28T11:00:06Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"The READ_SHA1_FILE_REPLACE flag is more related to using the\nlookup_replace_object() function rather than the\nread_sha1_file() function.\n\nWe also need such a flag to be used with sha1_object_info()\ninstead of read_sha1_file().\n\nThe name LOOKUP_REPLACE_OBJECT is therefore better for this\nflag.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n cache.h     | 4 ++--\n sha1_file.c | 2 +-\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex ce377e1..873a6b5 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -760,11 +760,11 @@ int daemon_avoid_alias(const char *path);\n int offset_1st_component(const char *path);\n \n /* object replacement */\n-#define READ_SHA1_FILE_REPLACE 1\n+#define LOOKUP_REPLACE_OBJECT 1\n extern void *read_sha1_file_extended(const unsigned char *sha1, enum object_type *type, unsigned long *size, unsigned flag);\n static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)\n {\n-\treturn read_sha1_file_extended(sha1, type, size, READ_SHA1_FILE_REPLACE);\n+\treturn read_sha1_file_extended(sha1, type, size, LOOKUP_REPLACE_OBJECT);\n }\n extern const unsigned char *do_lookup_replace_object(const unsigned char *sha1);\n static inline const unsigned char *lookup_replace_object(const unsigned char *sha1)\ndiff --git a/sha1_file.c b/sha1_file.c\nindex daacc0c..76e9f32 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -2591,7 +2591,7 @@ void *read_sha1_file_extended(const unsigned char *sha1,\n \tvoid *data;\n \tchar *path;\n \tconst struct packed_git *p;\n-\tconst unsigned char *repl = (flag & READ_SHA1_FILE_REPLACE)\n+\tconst unsigned char *repl = (flag & LOOKUP_REPLACE_OBJECT)\n \t\t? lookup_replace_object(sha1) : sha1;\n \n \terrno = 0;\n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232483","messageId":"20131228110016.2272.63916.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 02/10] replace_object: don't check read_replace_refs twice","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:07Z","receivedAt":"2013-12-28T11:00:07Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Since e1111cef (inline lookup_replace_object() calls,\nMay 15 2011) the read_replace_refs global variable is\nchecked twice, once in lookup_replace_object() and\nonce again in do_lookup_replace_object().\n\nAs do_lookup_replace_object() is called only from\nlookup_replace_object(), we can remove the check in\ndo_lookup_replace_object().\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n replace_object.c | 3 ---\n 1 file changed, 3 deletions(-)\n\ndiff --git a/replace_object.c b/replace_object.c\nindex d0b1548..cdcaf8c 100644\n--- a/replace_object.c\n+++ b/replace_object.c\n@@ -97,9 +97,6 @@ const unsigned char *do_lookup_replace_object(const unsigned char *sha1)\n \tint pos, depth = MAXREPLACEDEPTH;\n \tconst unsigned char *cur = sha1;\n \n-\tif (!read_replace_refs)\n-\t\treturn sha1;\n-\n \tprepare_replace_object();\n \n \t/* Try to recursively replace the object */\n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232484","messageId":"20131228110016.2272.47632.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 03/10] Introduce lookup_replace_object_extended() to pass flags","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:08Z","receivedAt":"2013-12-28T11:00:08Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Currently, there is only one caller to lookup_replace_object()\nthat can benefit from passing it some flags, but we expect\nthat there could be more.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n cache.h     | 6 ++++++\n sha1_file.c | 3 +--\n 2 files changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 873a6b5..563f85f 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -773,6 +773,12 @@ static inline const unsigned char *lookup_replace_object(const unsigned char *sh\n \t\treturn sha1;\n \treturn do_lookup_replace_object(sha1);\n }\n+static inline const unsigned char *lookup_replace_object_extended(const unsigned char *sha1, unsigned flag)\n+{\n+\tif (! (flag & LOOKUP_REPLACE_OBJECT))\n+\t\treturn sha1;\n+\treturn lookup_replace_object(sha1);\n+}\n \n /* Read and unpack a sha1 file into memory, write memory to a sha1 file */\n extern int sha1_object_info(const unsigned char *, unsigned long *);\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 76e9f32..4fb2f17 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -2591,8 +2591,7 @@ void *read_sha1_file_extended(const unsigned char *sha1,\n \tvoid *data;\n \tchar *path;\n \tconst struct packed_git *p;\n-\tconst unsigned char *repl = (flag & LOOKUP_REPLACE_OBJECT)\n-\t\t? lookup_replace_object(sha1) : sha1;\n+\tconst unsigned char *repl = lookup_replace_object_extended(sha1, flag);\n \n \terrno = 0;\n \tdata = read_object(repl, type, size);\n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232482","messageId":"20131228110016.2272.20738.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 04/10] Add an \"unsigned flags\" parameter to sha1_object_info_extended()","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:09Z","receivedAt":"2013-12-28T11:00:09Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This parameter is not used yet, but it will be used to tell\nsha1_object_info_extended() if it should perform object\nreplacement or not.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/cat-file.c | 2 +-\n cache.h            | 2 +-\n sha1_file.c        | 6 +++---\n streaming.c        | 2 +-\n 4 files changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex b2ca775..b15c064 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -238,7 +238,7 @@ static int batch_one_object(const char *obj_name, struct batch_options *opt,\n \t\treturn 0;\n \t}\n \n-\tif (sha1_object_info_extended(data->sha1, &data->info) < 0) {\n+\tif (sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) {\n \t\tprintf(\"%s missing\\n\", obj_name);\n \t\tfflush(stdout);\n \t\treturn 0;\ndiff --git a/cache.h b/cache.h\nindex 563f85f..701e42c 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1104,7 +1104,7 @@ struct object_info {\n \t\t} packed;\n \t} u;\n };\n-extern int sha1_object_info_extended(const unsigned char *, struct object_info *);\n+extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags);\n \n /* Dumb servers support */\n extern int update_server_info(int);\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 4fb2f17..482037e 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -2443,7 +2443,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,\n \treturn 0;\n }\n \n-int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)\n+int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags)\n {\n \tstruct cached_object *co;\n \tstruct pack_entry e;\n@@ -2477,7 +2477,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)\n \trtype = packed_object_info(e.p, e.offset, oi);\n \tif (rtype < 0) {\n \t\tmark_bad_packed_object(e.p, sha1);\n-\t\treturn sha1_object_info_extended(sha1, oi);\n+\t\treturn sha1_object_info_extended(sha1, oi, 0);\n \t} else if (in_delta_base_cache(e.p, e.offset)) {\n \t\toi->whence = OI_DBCACHED;\n \t} else {\n@@ -2499,7 +2499,7 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)\n \n \toi.typep = &type;\n \toi.sizep = sizep;\n-\tif (sha1_object_info_extended(sha1, &oi) < 0)\n+\tif (sha1_object_info_extended(sha1, &oi, LOOKUP_REPLACE_OBJECT) < 0)\n \t\treturn -1;\n \treturn type;\n }\ndiff --git a/streaming.c b/streaming.c\nindex debe904..9659f18 100644\n--- a/streaming.c\n+++ b/streaming.c\n@@ -113,7 +113,7 @@ static enum input_source istream_source(const unsigned char *sha1,\n \n \toi->typep = type;\n \toi->sizep = &size;\n-\tstatus = sha1_object_info_extended(sha1, oi);\n+\tstatus = sha1_object_info_extended(sha1, oi, 0);\n \tif (status < 0)\n \t\treturn stream_error;\n \n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232478","messageId":"20131228110016.2272.70512.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 05/10] t6050: show that git cat-file --batch fails with replace objects","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:10Z","receivedAt":"2013-12-28T11:00:10Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"When --batch is passed to git cat-file, the sha1_object_info_extended()\nfunction is used to get information about the objects passed to\ngit cat-file.\n\nUnfortunately sha1_object_info_extended() doesn't take care of\nobject replacement properly, so it will often fail with a\nmessage like this:\n\n$ echo a3fb2e1845a1aaf129b7975048973414dc172173 | git cat-file --batch\na3fb2e1845a1aaf129b7975048973414dc172173 commit 231\nfatal: object a3fb2e1845a1aaf129b7975048973414dc172173 change size!?\n\nThe goal of this patch is to show this breakage.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n t/t6050-replace.sh | 5 +++++\n 1 file changed, 5 insertions(+)\n\ndiff --git a/t/t6050-replace.sh b/t/t6050-replace.sh\nindex 7d47984..b90dbdc 100755\n--- a/t/t6050-replace.sh\n+++ b/t/t6050-replace.sh\n@@ -276,6 +276,11 @@ test_expect_success '-f option bypasses the type check' '\n \tgit replace -f HEAD^ $BLOB\n '\n \n+test_expect_failure 'git cat-file --batch works on replace objects' '\n+\tgit replace | grep $PARA3 &&\n+\techo $PARA3 | git cat-file --batch\n+'\n+\n test_expect_success 'replace ref cleanup' '\n \ttest -n \"$(git replace)\" &&\n \tgit replace -d $(git replace) &&\n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232486","messageId":"20131228110016.2272.86549.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 06/10] sha1_file: perform object replacement in sha1_object_info_extended()","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:11Z","receivedAt":"2013-12-28T11:00:11Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"sha1_object_info_extended() should perform object replacement\nif it is needed.\n\nThe simplest way to do that is to make it call\nlookup_replace_object_extended().\n\nAnd now its \"unsigned flags\" parameter is used as it is passed\nto lookup_replace_object_extended().\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n sha1_file.c        | 13 +++++++------\n t/t6050-replace.sh |  2 +-\n 2 files changed, 8 insertions(+), 7 deletions(-)\n\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 482037e..ee224e4 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -2448,8 +2448,9 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,\n \tstruct cached_object *co;\n \tstruct pack_entry e;\n \tint rtype;\n+\tconst unsigned char *real = lookup_replace_object_extended(sha1, flags);\n \n-\tco = find_cached_object(sha1);\n+\tco = find_cached_object(real);\n \tif (co) {\n \t\tif (oi->typep)\n \t\t\t*(oi->typep) = co->type;\n@@ -2461,23 +2462,23 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,\n \t\treturn 0;\n \t}\n \n-\tif (!find_pack_entry(sha1, &e)) {\n+\tif (!find_pack_entry(real, &e)) {\n \t\t/* Most likely it's a loose object. */\n-\t\tif (!sha1_loose_object_info(sha1, oi)) {\n+\t\tif (!sha1_loose_object_info(real, oi)) {\n \t\t\toi->whence = OI_LOOSE;\n \t\t\treturn 0;\n \t\t}\n \n \t\t/* Not a loose object; someone else may have just packed it. */\n \t\treprepare_packed_git();\n-\t\tif (!find_pack_entry(sha1, &e))\n+\t\tif (!find_pack_entry(real, &e))\n \t\t\treturn -1;\n \t}\n \n \trtype = packed_object_info(e.p, e.offset, oi);\n \tif (rtype < 0) {\n-\t\tmark_bad_packed_object(e.p, sha1);\n-\t\treturn sha1_object_info_extended(sha1, oi, 0);\n+\t\tmark_bad_packed_object(e.p, real);\n+\t\treturn sha1_object_info_extended(real, oi, 0);\n \t} else if (in_delta_base_cache(e.p, e.offset)) {\n \t\toi->whence = OI_DBCACHED;\n \t} else {\ndiff --git a/t/t6050-replace.sh b/t/t6050-replace.sh\nindex b90dbdc..bb785ec 100755\n--- a/t/t6050-replace.sh\n+++ b/t/t6050-replace.sh\n@@ -276,7 +276,7 @@ test_expect_success '-f option bypasses the type check' '\n \tgit replace -f HEAD^ $BLOB\n '\n \n-test_expect_failure 'git cat-file --batch works on replace objects' '\n+test_expect_success 'git cat-file --batch works on replace objects' '\n \tgit replace | grep $PARA3 &&\n \techo $PARA3 | git cat-file --batch\n '\n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232479","messageId":"20131228110016.2272.37189.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 07/10] builtin/replace: teach listing using short, medium or long formats","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:12Z","receivedAt":"2013-12-28T11:00:12Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"By default when listing replace refs, only the sha1 of the\nreplaced objects are shown.\n\nIn many cases, it is much nicer to be able to list all the\nsha1 of the replaced objects along with the sha1 of the\nreplacment objects.\n\nAnd in other cases it might be interesting to also show the\ntypes of the replaced and replacement objects.\n\nThis patch introduce a new --format=<fmt> option where\n<fmt> can be any of the following:\n\n\t'short': this is the same as when no --format\n\t\toption is used, that is only the sha1 of\n\t\tthe replaced objects are shown\n\t'medium': this also lists the sha1 of the\n\t\treplacement objects\n\t'long': this shows the sha1 and the type of both\n\t\tthe replaced and the replacement objects\n\nSome documentation and some tests will follow.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/replace.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++------\n 1 file changed, 58 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex b1bd3ef..b93d204 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -16,27 +16,69 @@\n static const char * const git_replace_usage[] = {\n \tN_(\"git replace [-f] <object> <replacement>\"),\n \tN_(\"git replace -d <object>...\"),\n-\tN_(\"git replace -l [<pattern>]\"),\n+\tN_(\"git replace [--format=<format>] [-l [<pattern>]]\"),\n \tNULL\n };\n \n+enum replace_format {\n+      REPLACE_FORMAT_SHORT,\n+      REPLACE_FORMAT_MEDIUM,\n+      REPLACE_FORMAT_LONG\n+};\n+\n+struct show_data {\n+\tconst char *pattern;\n+\tenum replace_format format;\n+};\n+\n static int show_reference(const char *refname, const unsigned char *sha1,\n \t\t\t  int flag, void *cb_data)\n {\n-\tconst char *pattern = cb_data;\n+\tstruct show_data *data = cb_data;\n+\n+\tif (!fnmatch(data->pattern, refname, 0)) {\n+\t\tif (data->format == REPLACE_FORMAT_SHORT)\n+\t\t\tprintf(\"%s\\n\", refname);\n+\t\telse if (data->format == REPLACE_FORMAT_MEDIUM)\n+\t\t\tprintf(\"%s -> %s\\n\", refname, sha1_to_hex(sha1));\n+\t\telse { /* data->format == REPLACE_FORMAT_LONG */\n+\t\t\tunsigned char object[20];\n+\t\t\tenum object_type obj_type, repl_type;\n+\n+\t\t\tif (get_sha1(refname, object))\n+\t\t\t\treturn error(\"Failed to resolve '%s' as a valid ref.\", refname);\n+\n+\t\t\tobj_type = sha1_object_info(object, NULL);\n+\t\t\trepl_type = sha1_object_info(sha1, NULL);\n \n-\tif (!fnmatch(pattern, refname, 0))\n-\t\tprintf(\"%s\\n\", refname);\n+\t\t\tprintf(\"%s (%s) -> %s (%s)\\n\", refname, typename(obj_type),\n+\t\t\t       sha1_to_hex(sha1), typename(repl_type));\n+\t\t}\n+\t}\n \n \treturn 0;\n }\n \n-static int list_replace_refs(const char *pattern)\n+static int list_replace_refs(const char *pattern, const char *format)\n {\n+\tstruct show_data data;\n+\n \tif (pattern == NULL)\n \t\tpattern = \"*\";\n+\tdata.pattern = pattern;\n+\n+\tif (format == NULL || *format == '\\0' || !strcmp(format, \"short\"))\n+\t\tdata.format = REPLACE_FORMAT_SHORT;\n+\telse if (!strcmp(format, \"medium\"))\n+\t\tdata.format = REPLACE_FORMAT_MEDIUM;\n+\telse if (!strcmp(format, \"long\"))\n+\t\tdata.format = REPLACE_FORMAT_LONG;\n+\telse\n+\t\tdie(\"invalid replace format '%s'\\n\"\n+\t\t    \"valid formats are 'short', 'medium' and 'long'\\n\",\n+\t\t    format);\n \n-\tfor_each_replace_ref(show_reference, (void *) pattern);\n+\tfor_each_replace_ref(show_reference, (void *) &data);\n \n \treturn 0;\n }\n@@ -127,10 +169,12 @@ static int replace_object(const char *object_ref, const char *replace_ref,\n int cmd_replace(int argc, const char **argv, const char *prefix)\n {\n \tint list = 0, delete = 0, force = 0;\n+\tconst char *format = NULL;\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_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 \t};\n \n@@ -140,6 +184,10 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\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+\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 \t\t\t      git_replace_usage, options);\n@@ -157,6 +205,9 @@ 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@@ -168,5 +219,5 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\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]);\n+\treturn list_replace_refs(argv[0], format);\n }\n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232481","messageId":"20131228110016.2272.66623.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 08/10] t6050: add tests for listing with --format","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:13Z","receivedAt":"2013-12-28T11:00:13Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This patch adds tests for \"git replace -l --format=<fmt>\".\n\n'short', 'medium' and 'long' are the only allowed values\nfor <fmt>.\n\n'short' is the same as with no --format option.\nTests for 'medium' and 'long' are the most needed.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n t/t6050-replace.sh | 37 +++++++++++++++++++++++++++++++++++++\n 1 file changed, 37 insertions(+)\n\ndiff --git a/t/t6050-replace.sh b/t/t6050-replace.sh\nindex bb785ec..9d05101 100755\n--- a/t/t6050-replace.sh\n+++ b/t/t6050-replace.sh\n@@ -281,6 +281,43 @@ test_expect_success 'git cat-file --batch works on replace objects' '\n \techo $PARA3 | git cat-file --batch\n '\n \n+test_expect_success 'test --format bogus' '\n+\ttest_must_fail git replace --format bogus >/dev/null 2>&1\n+'\n+\n+test_expect_success 'test --format short' '\n+\tgit replace --format=short >actual &&\n+\tgit replace >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'test --format medium' '\n+\tH1=$(git --no-replace-objects rev-parse HEAD~1) &&\n+\tHT=$(git --no-replace-objects rev-parse HEAD^{tree}) &&\n+\tMYTAG=$(git --no-replace-objects rev-parse mytag) &&\n+\t{\n+\t\techo \"$H1 -> $BLOB\" &&\n+\t\techo \"$BLOB -> $REPLACED\" &&\n+\t\techo \"$HT -> $H1\" &&\n+\t\techo \"$PARA3 -> $S\" &&\n+\t\techo \"$MYTAG -> $HASH1\"\n+\t} | sort >expected &&\n+\tgit replace -l --format medium | sort > actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_failure 'test --format long' '\n+\t{\n+\t\techo \"$H1 (commit) -> $BLOB (blob)\" &&\n+\t\techo \"$BLOB (blob) -> $REPLACED (blob)\" &&\n+\t\techo \"$HT (tree) -> $H1 (commit)\" &&\n+\t\techo \"$PARA3 (commit) -> $S (commit)\" &&\n+\t\techo \"$MYTAG (tag) -> $HASH1 (commit)\"\n+\t} | sort >expected &&\n+\tgit replace --format=long | sort > actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'replace ref cleanup' '\n \ttest -n \"$(git replace)\" &&\n \tgit replace -d $(git replace) &&\n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232480","messageId":"20131228110016.2272.5575.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 09/10] builtin/replace: unset read_replace_refs","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:14Z","receivedAt":"2013-12-28T11:00:14Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"When checking to see if some objects are of the same type\nand when displaying the type of objects, git replace uses\nthe sha1_object_info() function.\n\nUnfortunately this function by default respects replace\nrefs, so instead of the type of a replaced object, it\ngives the type of the replacement object which might\nbe different.\n\nTo fix this bug, and because git replace should work at a\nlevel before replacement takes place, let's unset the\nread_replace_refs global variable at the beginning of\ncmd_replace().\n\nSuggested-by: Jeff King <peff@peff.net>\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/replace.c  | 2 ++\n t/t6050-replace.sh | 2 +-\n 2 files changed, 3 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex b93d204..2336325 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -178,6 +178,8 @@ int cmd_replace(int argc, const char **argv, const char *prefix)\n \t\tOPT_END()\n \t};\n \n+\tread_replace_refs = 0;\n+\n \targc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);\n \n \tif (list && delete)\ndiff --git a/t/t6050-replace.sh b/t/t6050-replace.sh\nindex 9d05101..719a116 100755\n--- a/t/t6050-replace.sh\n+++ b/t/t6050-replace.sh\n@@ -306,7 +306,7 @@ test_expect_success 'test --format medium' '\n \ttest_cmp expected actual\n '\n \n-test_expect_failure 'test --format long' '\n+test_expect_success 'test --format long' '\n \t{\n \t\techo \"$H1 (commit) -> $BLOB (blob)\" &&\n \t\techo \"$BLOB (blob) -> $REPLACED (blob)\" &&\n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232485","messageId":"20131228110016.2272.77703.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"[PATCH v4 10/10] Documentation/git-replace: describe --format option","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-28T11:00:15Z","receivedAt":"2013-12-28T11:00:15Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Signed-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n Documentation/git-replace.txt | 19 ++++++++++++++++++-\n 1 file changed, 18 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt\nindex f373ab4..0a02f70 100644\n--- a/Documentation/git-replace.txt\n+++ b/Documentation/git-replace.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n [verse]\n 'git replace' [-f] <object> <replacement>\n 'git replace' -d <object>...\n-'git replace' -l [<pattern>]\n+'git replace' [--format=<format>] [-l [<pattern>]]\n \n DESCRIPTION\n -----------\n@@ -70,6 +70,23 @@ OPTIONS\n \tTyping \"git replace\" without arguments, also lists all replace\n \trefs.\n \n+--format=<format>::\n+\tWhen listing, use the specified <format>, which can be one of\n+\t'short', 'medium' and 'long'. When omitted, the format\n+\tdefaults to 'short'.\n+\n+FORMATS\n+-------\n+\n+The following format are available:\n+\n+* 'short':\n+\t<replaced sha1>\n+* 'medium':\n+\t<replaced sha1> -> <replacement sha1>\n+* 'long':\n+\t<replaced sha1> (<replaced type>) -> <replacement sha1> (<replacement type>)\n+\n CREATING REPLACEMENT OBJECTS\n ----------------------------\n \n-- \n1.8.4.1.616.g07f5c81\n"},{"id":"232527","messageId":"xmqqob3yqdup.fsf@gitster.dls.corp.google.com","threadId":"35581","inReplyTo":"20131228105505.2272.58873.chriscool@tuxfamily.org","subject":"Re: [PATCH v4 00/10] teach replace objects to sha1_object_info_extended()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-12-30T20:32:30Z","receivedAt":"2013-12-30T20:32:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Christian Couder <chriscool@tuxfamily.org> writes:\n\n> The only changes compared to version 3 are the following:\n\nI'll queue this instead on top, as the series is already in 'next'.\n\nThanks.\n\n-- >8 --\nFrom: Christian Couder <chriscool@tuxfamily.org>\nDate: Sat, 28 Dec 2013 12:00:05 +0100\nSubject: [PATCH] replace info: rename 'full' to 'long' and clarify in-code symbols\n\nEnum names SHORT/MEDIUM/FULL were too broad to be descriptive.  And\nthey clashed with built-in symbols on platforms like Windows.\nClarify by giving them REPLACE_FORMAT_ prefix.\n\nRename 'full' format in \"git replace --format=<name>\" to 'long', to\nmatch others (i.e. 'short' and 'medium').\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n Documentation/git-replace.txt |  4 ++--\n builtin/replace.c             | 24 ++++++++++++++----------\n t/t6050-replace.sh            |  4 ++--\n 3 files changed, 18 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt\nindex 7a07828..0a02f70 100644\n--- a/Documentation/git-replace.txt\n+++ b/Documentation/git-replace.txt\n@@ -72,7 +72,7 @@ OPTIONS\n \n --format=<format>::\n \tWhen listing, use the specified <format>, which can be one of\n-\t'short', 'medium' and 'full'. When omitted, the format\n+\t'short', 'medium' and 'long'. When omitted, the format\n \tdefaults to 'short'.\n \n FORMATS\n@@ -84,7 +84,7 @@ The following format are available:\n \t<replaced sha1>\n * 'medium':\n \t<replaced sha1> -> <replacement sha1>\n-* 'full'\n+* 'long':\n \t<replaced sha1> (<replaced type>) -> <replacement sha1> (<replacement type>)\n \n CREATING REPLACEMENT OBJECTS\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 1672870..2336325 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -20,11 +20,15 @@ static const char * const git_replace_usage[] = {\n \tNULL\n };\n \n-enum repl_fmt { SHORT, MEDIUM, FULL };\n+enum replace_format {\n+      REPLACE_FORMAT_SHORT,\n+      REPLACE_FORMAT_MEDIUM,\n+      REPLACE_FORMAT_LONG\n+};\n \n struct show_data {\n \tconst char *pattern;\n-\tenum repl_fmt fmt;\n+\tenum replace_format format;\n };\n \n static int show_reference(const char *refname, const unsigned char *sha1,\n@@ -33,11 +37,11 @@ static int show_reference(const char *refname, const unsigned char *sha1,\n \tstruct show_data *data = cb_data;\n \n \tif (!fnmatch(data->pattern, refname, 0)) {\n-\t\tif (data->fmt == SHORT)\n+\t\tif (data->format == REPLACE_FORMAT_SHORT)\n \t\t\tprintf(\"%s\\n\", refname);\n-\t\telse if (data->fmt == MEDIUM)\n+\t\telse if (data->format == REPLACE_FORMAT_MEDIUM)\n \t\t\tprintf(\"%s -> %s\\n\", refname, sha1_to_hex(sha1));\n-\t\telse { /* data->fmt == FULL */\n+\t\telse { /* data->format == REPLACE_FORMAT_LONG */\n \t\t\tunsigned char object[20];\n \t\t\tenum object_type obj_type, repl_type;\n \n@@ -64,14 +68,14 @@ static int list_replace_refs(const char *pattern, const char *format)\n \tdata.pattern = pattern;\n \n \tif (format == NULL || *format == '\\0' || !strcmp(format, \"short\"))\n-\t\tdata.fmt = SHORT;\n+\t\tdata.format = REPLACE_FORMAT_SHORT;\n \telse if (!strcmp(format, \"medium\"))\n-\t\tdata.fmt = MEDIUM;\n-\telse if (!strcmp(format, \"full\"))\n-\t\tdata.fmt = FULL;\n+\t\tdata.format = REPLACE_FORMAT_MEDIUM;\n+\telse if (!strcmp(format, \"long\"))\n+\t\tdata.format = REPLACE_FORMAT_LONG;\n \telse\n \t\tdie(\"invalid replace format '%s'\\n\"\n-\t\t    \"valid formats are 'short', 'medium' and 'full'\\n\",\n+\t\t    \"valid formats are 'short', 'medium' and 'long'\\n\",\n \t\t    format);\n \n \tfor_each_replace_ref(show_reference, (void *) &data);\ndiff --git a/t/t6050-replace.sh b/t/t6050-replace.sh\nindex d0c62f7..719a116 100755\n--- a/t/t6050-replace.sh\n+++ b/t/t6050-replace.sh\n@@ -306,7 +306,7 @@ test_expect_success 'test --format medium' '\n \ttest_cmp expected actual\n '\n \n-test_expect_success 'test --format full' '\n+test_expect_success 'test --format long' '\n \t{\n \t\techo \"$H1 (commit) -> $BLOB (blob)\" &&\n \t\techo \"$BLOB (blob) -> $REPLACED (blob)\" &&\n@@ -314,7 +314,7 @@ test_expect_success 'test --format full' '\n \t\techo \"$PARA3 (commit) -> $S (commit)\" &&\n \t\techo \"$MYTAG (tag) -> $HASH1 (commit)\"\n \t} | sort >expected &&\n-\tgit replace --format=full | sort > actual &&\n+\tgit replace --format=long | sort > actual &&\n \ttest_cmp expected actual\n '\n \n-- \n1.8.5.2-311-g6427a96\n"},{"id":"232536","messageId":"20131231.072358.1765034958065747837.chriscool@tuxfamily.org","threadId":"35581","inReplyTo":"xmqqob3yqdup.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v4 00/10] teach replace objects to sha1_object_info_extended()","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2013-12-31T06:23:58Z","receivedAt":"2013-12-31T06:23:58Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n>\n> Christian Couder <chriscool@tuxfamily.org> writes:\n> \n>> The only changes compared to version 3 are the following:\n> \n> I'll queue this instead on top, as the series is already in 'next'.\n\nGreat!\n\nThanks,\nChristian.\n"}]}