{"thread":{"id":"12377","subject":"[PATCH 0/5] Builtin \"git remote\"","startedAt":"2008-02-29T01:44:33Z","lastAt":"2008-03-11T16:44:29Z","messageCount":29,"participants":["Johannes Schindelin","Junio C Hamano","Daniel Barkalow","David Kågedal"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"70342","messageId":"alpine.LSU.1.00.0802290144130.22527@racer.site","threadId":"12377","inReplyTo":null,"subject":"[PATCH 0/5] Builtin \"git remote\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:44:33Z","receivedAt":"2008-02-29T01:44:33Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis patch series puts a few building blocks in place (the first three\npatches), builds in \"git remote\", and fixes the current behaviour of\n\"git remote prune\" when the remote was initialized with --mirror.\n\nIt incorporates Hannes Sixt's comments about checking remote_nr.\n\nOh, and in contrast to the earlier series, I removed the DWIM \"git add\nremote\" patch.\n\nIt also demonstrates that format-patch --cover-letter should default to -M\nfor the diffstat (search for \"git-remote.perl\"...).\n\nJohannes Schindelin (5):\n      path-list: add functions to work with unsorted lists\n      parseopt: add flag to stop on first non option\n      Test \"git remote show\" and \"git remote prune\"\n      Make git-remote a builtin\n      builtin-remote: prune remotes correctly that were added with --mirror\n\n Makefile                         |    3 +-\n builtin-remote.c                 |  557 ++++++++++++++++++++++++++++++++++++++\n builtin.h                        |    1 +\n contrib/examples/git-remote.perl |  477 ++++++++++++++++++++++++++++++++\n git-remote.perl                  |  477 --------------------------------\n git.c                            |    1 +\n parse-options.c                  |    2 +\n parse-options.h                  |    1 +\n path-list.c                      |   30 ++\n path-list.h                      |    8 +-\n remote.c                         |    3 +-\n remote.h                         |    1 +\n t/t5505-remote.sh                |   50 ++++\n 13 files changed, 1131 insertions(+), 480 deletions(-)\n create mode 100644 builtin-remote.c\n create mode 100755 contrib/examples/git-remote.perl\n delete mode 100755 git-remote.perl\n\n"},{"id":"70343","messageId":"alpine.LSU.1.00.0802290144410.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0802290144130.22527@racer.site","subject":"[PATCH 1/5] path-list: add functions to work with unsorted lists","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:44:56Z","receivedAt":"2008-02-29T01:44:56Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nUp to now, path-lists were sorted at all times.  But sometimes it\nis much more convenient to build the list and sort it at the end,\nor sort it not at all.\n\nAdd path_list_append() and sort_path_list() to allow that.\n\nAlso, add the unsorted_path_list_has_path() function, to do a linear\nsearch.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tThis is probably useful to a number of existing non-users of\n\tpath_list.\n\n path-list.c |   30 ++++++++++++++++++++++++++++++\n path-list.h |    8 +++++++-\n 2 files changed, 37 insertions(+), 1 deletions(-)\n\ndiff --git a/path-list.c b/path-list.c\nindex 3d83b7b..92e5cf2 100644\n--- a/path-list.c\n+++ b/path-list.c\n@@ -102,3 +102,33 @@ void print_path_list(const char *text, const struct path_list *p)\n \tfor (i = 0; i < p->nr; i++)\n \t\tprintf(\"%s:%p\\n\", p->items[i].path, p->items[i].util);\n }\n+\n+struct path_list_item *path_list_append(const char *path, struct path_list *list)\n+{\n+\tALLOC_GROW(list->items, list->nr + 1, list->alloc);\n+\tlist->items[list->nr].path =\n+\t\tlist->strdup_paths ? xstrdup(path) : (char *)path;\n+\treturn list->items + list->nr++;\n+}\n+\n+static int cmp_items(const void *a, const void *b)\n+{\n+\tconst struct path_list_item *one = a;\n+\tconst struct path_list_item *two = b;\n+\treturn strcmp(one->path, two->path);\n+}\n+\n+void sort_path_list(struct path_list *list)\n+{\n+\tqsort(list->items, list->nr, sizeof(*list->items), cmp_items);\n+}\n+\n+int unsorted_path_list_has_path(struct path_list *list, const char *path)\n+{\n+\tint i;\n+\tfor (i = 0; i < list->nr; i++)\n+\t\tif (!strcmp(path, list->items[i].path))\n+\t\t\treturn 1;\n+\treturn 0;\n+}\n+\ndiff --git a/path-list.h b/path-list.h\nindex 5931e2c..ca2cbba 100644\n--- a/path-list.h\n+++ b/path-list.h\n@@ -13,10 +13,16 @@ struct path_list\n };\n \n void print_path_list(const char *text, const struct path_list *p);\n+void path_list_clear(struct path_list *list, int free_util);\n \n+/* Use these functions only on sorted lists: */\n int path_list_has_path(const struct path_list *list, const char *path);\n-void path_list_clear(struct path_list *list, int free_util);\n struct path_list_item *path_list_insert(const char *path, struct path_list *list);\n struct path_list_item *path_list_lookup(const char *path, struct path_list *list);\n \n+/* Use these functions only on unsorted lists: */\n+struct path_list_item *path_list_append(const char *path, struct path_list *list);\n+void sort_path_list(struct path_list *list);\n+int unsorted_path_list_has_path(struct path_list *list, const char *path);\n+\n #endif /* PATH_LIST_H */\n-- \n1.5.4.3.431.g066fa\n\n\n"},{"id":"70344","messageId":"alpine.LSU.1.00.0802290145020.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0802290144130.22527@racer.site","subject":"[PATCH 2/5] parseopt: add flag to stop on first non option","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:45:09Z","receivedAt":"2008-02-29T01:45:09Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n parse-options.c |    2 ++\n parse-options.h |    1 +\n 2 files changed, 3 insertions(+), 0 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex d9562ba..be35785 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -249,6 +249,8 @@ int parse_options(int argc, const char **argv, const struct option *options,\n \t\tconst char *arg = args.argv[0];\n \n \t\tif (*arg != '-' || !arg[1]) {\n+\t\t\tif (flags & PARSE_OPT_STOP_AT_NON_OPTION)\n+\t\t\t\tbreak;\n \t\t\targv[j++] = args.argv[0];\n \t\t\tcontinue;\n \t\t}\ndiff --git a/parse-options.h b/parse-options.h\nindex 102ac31..0d40cd2 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -18,6 +18,7 @@ enum parse_opt_type {\n \n enum parse_opt_flags {\n \tPARSE_OPT_KEEP_DASHDASH = 1,\n+\tPARSE_OPT_STOP_AT_NON_OPTION = 2,\n };\n \n enum parse_opt_option_flags {\n-- \n1.5.4.3.431.g066fa\n\n\n"},{"id":"70345","messageId":"alpine.LSU.1.00.0802290145160.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0802290144130.22527@racer.site","subject":"[PATCH 3/5] Test \"git remote show\" and \"git remote prune\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:45:24Z","receivedAt":"2008-02-29T01:45:24Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nWhile at it, also fix a few instances where a cd was done outside of a\nsubshell.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n t/t5505-remote.sh |   34 ++++++++++++++++++++++++++++++++++\n 1 files changed, 34 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex 4fc62f5..e1e0a18 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -94,4 +94,38 @@ test_expect_success 'remove remote' '\n )\n '\n \n+cat > test/expect << EOF\n+* remote origin\n+  URL: $(pwd)/one/.git\n+  Remote branch(es) merged with 'git pull' while on branch master\n+    master\n+  New remote branches (next fetch will store in remotes/origin)\n+    master\n+  Tracked remote branches\n+    side master\n+EOF\n+\n+test_expect_success 'show' '\n+\t(cd test &&\n+\t git config --add remote.origin.fetch \\\n+\t\trefs/heads/master:refs/heads/upstream &&\n+\t git fetch &&\n+\t git branch -d -r origin/master &&\n+\t (cd ../one &&\n+\t  echo 1 > file &&\n+\t  git commit -m update file) &&\n+\t git remote show origin > output &&\n+\t git diff expect output)\n+'\n+\n+test_expect_success 'prune' '\n+\t(cd one &&\n+\t git branch -m side side2) &&\n+\t(cd test &&\n+\t git fetch origin &&\n+\t git remote prune origin &&\n+\t git rev-parse refs/remotes/origin/side2 &&\n+\t ! git rev-parse refs/remotes/origin/side)\n+'\n+\n test_done\n-- \n1.5.4.3.431.g066fa\n\n\n"},{"id":"70346","messageId":"alpine.LSU.1.00.0802290145310.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0802290144130.22527@racer.site","subject":"[PATCH 4/5] Make git-remote a builtin","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:45:45Z","receivedAt":"2008-02-29T01:45:45Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tRelative to my patch series of December, this fixes a nasty bug\n\tin \"git remote rm\": do not call anything that invalidates the\n\tcached refs from the callback function passed to for_each_ref().\n\n\tSuch as delete_ref()...\n\n\tInstead, build the list of refs-to-delete, and _then_ delete them.\n\tJunio, this should solve the problems that you encountered (I\n\tvalgrinded it).\n\n\tThis includes the fix to guard remote->url accesses by checking\n\tremote->url_nr, as suggested by Johannes Sixt.\n\n Makefile                                           |    3 +-\n builtin-remote.c                                   |  547 ++++++++++++++++++++\n builtin.h                                          |    1 +\n .../examples/git-remote.perl                       |    0 \n git.c                                              |    1 +\n remote.c                                           |    3 +-\n remote.h                                           |    1 +\n t/t5505-remote.sh                                  |    4 +-\n 8 files changed, 556 insertions(+), 4 deletions(-)\n create mode 100644 builtin-remote.c\n rename git-remote.perl => contrib/examples/git-remote.perl (100%)\n\ndiff --git a/Makefile b/Makefile\nindex 8d8fc17..759074a 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -243,7 +243,7 @@ SCRIPT_SH = \\\n SCRIPT_PERL = \\\n \tgit-add--interactive.perl \\\n \tgit-archimport.perl git-cvsimport.perl git-relink.perl \\\n-\tgit-cvsserver.perl git-remote.perl git-cvsexportcommit.perl \\\n+\tgit-cvsserver.perl git-cvsexportcommit.perl \\\n \tgit-send-email.perl git-svn.perl\n \n SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \\\n@@ -380,6 +380,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-push.o \\\n \tbuiltin-read-tree.o \\\n \tbuiltin-reflog.o \\\n+\tbuiltin-remote.o \\\n \tbuiltin-send-pack.o \\\n \tbuiltin-config.o \\\n \tbuiltin-rerere.o \\\ndiff --git a/builtin-remote.c b/builtin-remote.c\nnew file mode 100644\nindex 0000000..d229919\n--- /dev/null\n+++ b/builtin-remote.c\n@@ -0,0 +1,547 @@\n+#include \"cache.h\"\n+#include \"parse-options.h\"\n+#include \"transport.h\"\n+#include \"remote.h\"\n+#include \"path-list.h\"\n+#include \"strbuf.h\"\n+#include \"run-command.h\"\n+#include \"refs.h\"\n+\n+static const char * const builtin_remote_usage[] = {\n+\t\"git remote\",\n+        \"git remote add <name> <url>\",\n+        \"git remote rm <name>\",\n+        \"git remote show <name>\",\n+        \"git remote prune <name>\",\n+        \"git remote update [group]\",\n+\tNULL\n+};\n+\n+static int verbose;\n+\n+static inline int postfixcmp(const char *string, const char *postfix)\n+{\n+\tint len1 = strlen(string), len2 = strlen(postfix);\n+\tif (len1 < len2)\n+\t\treturn 1;\n+\treturn strcmp(string + len1 - len2, postfix);\n+}\n+\n+static inline const char *skip_prefix(const char *name, const char *prefix)\n+{\n+\treturn !name ? \"\" :\n+\t\tprefixcmp(name, prefix) ?  name : name + strlen(prefix);\n+}\n+\n+static int opt_parse_track(const struct option *opt, const char *arg, int not)\n+{\n+\tstruct path_list *list = opt->value;\n+\tif (not)\n+\t\tpath_list_clear(list, 0);\n+\telse\n+\t\tpath_list_append(arg, list);\n+\treturn 0;\n+}\n+\n+static int fetch_remote(const char *name)\n+{\n+\tconst char *argv[] = { \"fetch\", name, NULL };\n+\tif (run_command_v_opt(argv, RUN_GIT_CMD))\n+\t\treturn error (\"Could not fetch %s\", name);\n+\treturn 0;\n+}\n+\n+static int add(int argc, const char **argv)\n+{\n+\tint fetch = 0, mirror = 0;\n+\tstruct path_list track = { NULL, 0, 0 };\n+\tconst char *master = NULL;\n+\tstruct remote *remote;\n+\tstruct strbuf buf, buf2;\n+\tconst char *name, *url;\n+\tint i;\n+\n+\tstruct option options[] = {\n+\t\tOPT_GROUP(\"add specific options\"),\n+\t\tOPT_BOOLEAN('f', \"fetch\", &fetch, \"fetch the remote branches\"),\n+\t\tOPT_CALLBACK('t', \"track\", &track, \"branch\",\n+\t\t\t\"branch(es) to track\", opt_parse_track),\n+\t\tOPT_STRING('m', \"master\", &master, \"branch\", \"master branch\"),\n+\t\tOPT_BOOLEAN(0, \"mirror\", &mirror, \"no separate remotes\"),\n+\t\tOPT_END()\n+\t};\n+\n+\targc = parse_options(argc, argv, options, builtin_remote_usage, 0);\n+\n+\tif (argc < 2)\n+\t\tusage_with_options(builtin_remote_usage, options);\n+\n+\tname = argv[0];\n+\turl = argv[1];\n+\n+\tremote = remote_get(name);\n+\tif (remote && (remote->url_nr > 1 || strcmp(name, remote->url[0]) ||\n+\t\t\tremote->fetch_refspec_nr))\n+\t\tdie (\"remote %s already exists.\", name);\n+\n+\tstrbuf_init(&buf, 0);\n+\tstrbuf_init(&buf2, 0);\n+\n+\tstrbuf_addf(&buf, \"remote.%s.url\", name);\n+\tif (git_config_set(buf.buf, url))\n+\t\treturn 1;\n+\n+\tif (track.nr == 0)\n+\t\tpath_list_append(\"*\", &track);\n+\tfor (i = 0; i < track.nr; i++) {\n+\t\tstruct path_list_item *item = track.items + i;\n+\n+\t\tstrbuf_reset(&buf);\n+\t\tstrbuf_addf(&buf, \"remote.%s.fetch\", name);\n+\n+\t\tstrbuf_reset(&buf2);\n+\t\tif (mirror)\n+\t\t\tstrbuf_addf(&buf2, \"refs/%s:refs/%s\",\n+\t\t\t\t\titem->path, item->path);\n+\t\telse\n+\t\t\tstrbuf_addf(&buf2, \"refs/heads/%s:refs/remotes/%s/%s\",\n+\t\t\t\t\titem->path, name, item->path);\n+\t\tif (git_config_set_multivar(buf.buf, buf2.buf, \"^$\", 0))\n+\t\t\treturn 1;\n+\t}\n+\n+\tif (fetch && fetch_remote(name))\n+\t\treturn 1;\n+\n+\tif (master) {\n+\t\tstrbuf_reset(&buf);\n+\t\tstrbuf_addf(&buf, \"refs/remotes/%s/HEAD\", name);\n+\n+\t\tstrbuf_reset(&buf2);\n+\t\tstrbuf_addf(&buf2, \"refs/remotes/%s/%s\", name, master);\n+\n+\t\tif (create_symref(buf.buf, buf2.buf, \"remote add\"))\n+\t\t\treturn error (\"Could not setup master '%s'\", master);\n+\t}\n+\n+\tstrbuf_release(&buf);\n+\tstrbuf_release(&buf2);\n+\tpath_list_clear(&track, 0);\n+\n+\treturn 0;\n+}\n+\n+struct branch_info {\n+\tchar *remote;\n+\tstruct path_list merge;\n+};\n+\n+static struct path_list branch_list;\n+\n+static int config_read_branches(const char *key, const char *value)\n+{\n+\tif (!prefixcmp(key, \"branch.\")) {\n+\t\tchar *name;\n+\t\tstruct path_list_item *item;\n+\t\tstruct branch_info *info;\n+\t\tenum { REMOTE, MERGE } type;\n+\n+\t\tkey += 7;\n+\t\tif (!postfixcmp(key, \".remote\")) {\n+\t\t\tname = xstrndup(key, strlen(key) - 7);\n+\t\t\ttype = REMOTE;\n+\t\t} else if (!postfixcmp(key, \".merge\")) {\n+\t\t\tname = xstrndup(key, strlen(key) - 6);\n+\t\t\ttype = MERGE;\n+\t\t} else\n+\t\t\treturn 0;\n+\n+\t\titem = path_list_insert(name, &branch_list);\n+\n+\t\tif (!item->util)\n+\t\t\titem->util = xcalloc(sizeof(struct branch_info), 1);\n+\t\tinfo = item->util;\n+\t\tif (type == REMOTE) {\n+\t\t\tif (info->remote)\n+\t\t\t\twarning (\"more than one branch.%s\", key);\n+\t\t\tinfo->remote = xstrdup(value);\n+\t\t} else {\n+\t\t\tchar *space = strchr(value, ' ');\n+\t\t\tvalue = skip_prefix(value, \"refs/heads/\");\n+\t\t\twhile (space) {\n+\t\t\t\tchar *merge;\n+\t\t\t\tmerge = xstrndup(value, space - value);\n+\t\t\t\tpath_list_append(merge, &info->merge);\n+\t\t\t\tvalue = skip_prefix(space + 1, \"refs/heads/\");\n+\t\t\t\tspace = strchr(value, ' ');\n+\t\t\t}\n+\t\t\tpath_list_append(xstrdup(value), &info->merge);\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static void read_branches()\n+{\n+\tif (branch_list.nr)\n+\t\treturn;\n+\tgit_config(config_read_branches);\n+\tsort_path_list(&branch_list);\n+}\n+\n+struct ref_states {\n+\tstruct remote *remote;\n+\tstruct strbuf remote_prefix;\n+\tstruct path_list new, stale, tracked;\n+};\n+\n+static int handle_one_branch(const char *refname,\n+\tconst unsigned char *sha1, int flags, void *cb_data)\n+{\n+\tstruct ref_states *states = cb_data;\n+\tstruct refspec refspec;\n+\n+\tmemset(&refspec, 0, sizeof(refspec));\n+\trefspec.dst = (char *)refname;\n+\tif (!remote_find_tracking(states->remote, &refspec)) {\n+\t\tstruct path_list_item *item;\n+\t\tconst char *name = skip_prefix(refspec.src, \"refs/heads/\");\n+\t\tif (unsorted_path_list_has_path(&states->tracked, name) ||\n+\t\t\t\tunsorted_path_list_has_path(&states->new,\n+\t\t\t\t\tname))\n+\t\t\treturn 0;\n+\t\titem = path_list_append(name, &states->stale);\n+\t\titem->util = xstrdup(refname);\n+\t}\n+\treturn 0;\n+}\n+\n+static int get_ref_states(const struct ref *ref, struct ref_states *states)\n+{\n+\tstruct ref *fetch_map = NULL, **tail = &fetch_map;\n+\tint i;\n+\n+\tfor (i = 0; i < states->remote->fetch_refspec_nr; i++)\n+\t\tif (get_fetch_map(ref, states->remote->fetch +i, &tail, 1))\n+\t\t\tdie (\"Could not get fetch map for refspec %s\",\n+\t\t\t\tstates->remote->fetch_refspec[i]);\n+\n+\tstates->new.strdup_paths = states->tracked.strdup_paths = 1;\n+\tfor (ref = fetch_map; ref; ref = ref->next) {\n+\t\tstruct path_list *target = &states->tracked;\n+\t\tunsigned char sha1[20];\n+\t\tvoid *util = NULL;\n+\n+\t\tif (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1))\n+\t\t\ttarget = &states->new;\n+\t\telse {\n+\t\t\ttarget = &states->tracked;\n+\t\t\tif (hashcmp(sha1, ref->new_sha1))\n+\t\t\t\tutil = &states;\n+\t\t}\n+\t\tpath_list_append(skip_prefix(ref->name, \"refs/heads/\"),\n+\t\t\t\ttarget)->util = util;\n+\t}\n+\tfree_refs(fetch_map);\n+\n+\tstrbuf_addf(&states->remote_prefix,\n+\t\t\"refs/remotes/%s/\", states->remote->name);\n+\tfor_each_ref(handle_one_branch, states);\n+\tsort_path_list(&states->stale);\n+\n+\treturn 0;\n+}\n+\n+struct branches_for_remote {\n+\tconst char *prefix;\n+\tstruct path_list *branches;\n+};\n+\n+static int add_branch_for_removal(const char *refname,\n+\tconst unsigned char *sha1, int flags, void *cb_data)\n+{\n+\tstruct branches_for_remote *branches = cb_data;\n+\n+\tif (!prefixcmp(refname, branches->prefix)) {\n+\t\tstruct path_list_item *item;\n+\t\titem = path_list_append(refname, branches->branches);\n+\t\titem->util = xmalloc(20);\n+\t\thashcpy(item->util, sha1);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int remove_branches(struct path_list *branches)\n+{\n+\tint i, result = 0;\n+\tfor (i = 0; i < branches->nr; i++) {\n+\t\tstruct path_list_item *item = branches->items + i;\n+\t\tconst char *refname = item->path;\n+\t\tunsigned char *sha1 = item->util;\n+\n+\t\tif (delete_ref(refname, sha1))\n+\t\t\tresult |= error(\"Could not remove branch %s\", refname);\n+\t}\n+\treturn result;\n+}\n+\n+static int rm(int argc, const char **argv)\n+{\n+\tstruct option options[] = {\n+\t\tOPT_END()\n+\t};\n+\tstruct remote *remote;\n+\tstruct strbuf buf;\n+\tstruct path_list branches = { NULL, 0, 0, 1 };\n+\tstruct branches_for_remote cb_data = { NULL, &branches };\n+\tint i;\n+\n+\tif (argc != 2)\n+\t\tusage_with_options(builtin_remote_usage, options);\n+\n+\tremote = remote_get(argv[1]);\n+\tif (!remote)\n+\t\tdie (\"No such remote: %s\", argv[1]);\n+\n+\tstrbuf_init(&buf, 0);\n+\tstrbuf_addf(&buf, \"remote.%s\", remote->name);\n+\tif (git_config_rename_section(buf.buf, NULL) < 1)\n+\t\treturn error(\"Could not remove config section '%s'\", buf.buf);\n+\n+\tread_branches();\n+\tfor (i = 0; i < branch_list.nr; i++) {\n+\t\tstruct path_list_item *item = branch_list.items +i;\n+\t\tstruct branch_info *info = item->util;\n+\t\tif (info->remote && !strcmp(info->remote, remote->name)) {\n+\t\t\tconst char *keys[] = { \"remote\", \"merge\", NULL }, **k;\n+\t\t\tfor (k = keys; *k; k++) {\n+\t\t\t\tstrbuf_reset(&buf);\n+\t\t\t\tstrbuf_addf(&buf, \"branch.%s.%s\",\n+\t\t\t\t\t\titem->path, *k);\n+\t\t\t\tif (git_config_set(buf.buf, NULL)) {\n+\t\t\t\t\tstrbuf_release(&buf);\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * We cannot just pass a function to for_each_ref() which deletes\n+\t * the branches one by one, since for_each_ref() relies on cached\n+\t * refs, which are invalidated when deleting a branch.\n+\t */\n+\tstrbuf_reset(&buf);\n+\tstrbuf_addf(&buf, \"refs/remotes/%s/\", remote->name);\n+\tcb_data.prefix = buf.buf;\n+\ti = for_each_ref(add_branch_for_removal, &cb_data);\n+\tstrbuf_release(&buf);\n+\n+\tif (!i)\n+\t\ti = remove_branches(&branches);\n+\tpath_list_clear(&branches, 1);\n+\n+\treturn i;\n+}\n+\n+static void show_list(const char *title, struct path_list *list)\n+{\n+\tint i;\n+\n+\tif (!list->nr)\n+\t\treturn;\n+\n+\tprintf(title, list->nr > 1 ? \"es\" : \"\");\n+\tprintf(\"\\n    \");\n+\tfor (i = 0; i < list->nr; i++)\n+\t\tprintf(\"%s%s\", i ? \" \" : \"\", list->items[i].path);\n+\tprintf(\"\\n\");\n+}\n+\n+static int show_or_prune(int argc, const char **argv, int prune)\n+{\n+\tint dry_run = 0, result = 0;\n+\tstruct option options[] = {\n+\t\tOPT_GROUP(\"show specific options\"),\n+\t\tOPT__DRY_RUN(&dry_run),\n+\t\tOPT_END()\n+\t};\n+\tstruct ref_states states;\n+\n+\targc = parse_options(argc, argv, options, builtin_remote_usage, 0);\n+\n+\tif (argc < 1)\n+\t\tusage_with_options(builtin_remote_usage, options);\n+\n+\tmemset(&states, 0, sizeof(states));\n+\tfor (; argc; argc--, argv++) {\n+\t\tstruct transport *transport;\n+\t\tconst struct ref *ref;\n+\t\tstruct strbuf buf;\n+\t\tint i, got_states;\n+\n+\t\tstates.remote = remote_get(*argv);\n+\t\tif (!states.remote)\n+\t\t\treturn error(\"No such remote: %s\", *argv);\n+\t\ttransport = transport_get(NULL, states.remote->url_nr > 0 ?\n+\t\t\tstates.remote->url[0] : NULL);\n+\t\tref = transport_get_remote_refs(transport);\n+\n+\t\tread_branches();\n+\t\tgot_states = get_ref_states(ref, &states);\n+\t\tif (got_states)\n+\t\t\tresult = error(\"Error getting local info for '%s'\",\n+\t\t\t\t\tstates.remote->name);\n+\n+\t\tif (prune) {\n+\t\t\tstruct strbuf buf;\n+\n+\t\t\tstrbuf_init(&buf, 0);\n+\t\t\tfor (i = 0; i < states.stale.nr; i++) {\n+\t\t\t\tstrbuf_reset(&buf);\n+\t\t\t\tstrbuf_addf(&buf, \"refs/remotes/%s/%s\", *argv,\n+\t\t\t\t\t\tstates.stale.items[i].path);\n+\t\t\t\tresult |= delete_ref(buf.buf, NULL);\n+\t\t\t}\n+\n+\t\t\tstrbuf_release(&buf);\n+\t\t\tgoto cleanup_states;\n+\t\t}\n+\n+\t\tprintf(\"* remote %s\\n  URL: %s\\n\", *argv,\n+\t\t\tstates.remote->url_nr > 0 ?\n+\t\t\t\tstates.remote->url[0] : \"(no URL)\");\n+\n+\t\tfor (i = 0; i < branch_list.nr; i++) {\n+\t\t\tstruct path_list_item *branch = branch_list.items + i;\n+\t\t\tstruct branch_info *info = branch->util;\n+\t\t\tint j;\n+\n+\t\t\tif (!info->merge.nr || strcmp(*argv, info->remote))\n+\t\t\t\tcontinue;\n+\t\t\tprintf(\"  Remote branch%s merged with 'git pull' \"\n+\t\t\t\t\"while on branch %s\\n   \",\n+\t\t\t\tinfo->merge.nr > 1 ? \"es\" : \"\",\n+\t\t\t\tbranch->path);\n+\t\t\tfor (j = 0; j < info->merge.nr; j++)\n+\t\t\t\tprintf(\" %s\", info->merge.items[j].path);\n+\t\t\tprintf(\"\\n\");\n+\t\t}\n+\n+\t\tif (got_states)\n+\t\t\tcontinue;\n+\t\tstrbuf_init(&buf, 0);\n+\t\tstrbuf_addf(&buf, \"  New remote branch%%s (next fetch will \"\n+\t\t\t\"store in remotes/%s)\", states.remote->name);\n+\t\tshow_list(buf.buf, &states.new);\n+\t\tstrbuf_release(&buf);\n+\t\tshow_list(\"  Stale tracking branch%s (use 'git remote prune')\",\n+\t\t\t\t&states.stale);\n+\t\tshow_list(\"  Tracked remote branch%s\",\n+\t\t\t\t&states.tracked);\n+\n+\t\tif (states.remote->push_refspec_nr) {\n+\t\t\tprintf(\"  Local branch%s pushed with 'git push'\\n   \",\n+\t\t\t\tstates.remote->push_refspec_nr > 1 ?\n+\t\t\t\t\t\"es\" : \"\");\n+\t\t\tfor (i = 0; i < states.remote->push_refspec_nr; i++) {\n+\t\t\t\tstruct refspec *spec = states.remote->push + i;\n+\t\t\t\tprintf(\" %s%s%s%s\", spec->force ? \"+\" : \"\",\n+\t\t\t\t\tskip_prefix(spec->src, \"refs/heads/\"),\n+\t\t\t\t\tspec->dst ? \":\" : \"\",\n+\t\t\t\t\tskip_prefix(spec->dst, \"refs/heads/\"));\n+\t\t\t}\n+\t\t}\n+cleanup_states:\n+\t\t/* NEEDSWORK: free remote */\n+\t\tpath_list_clear(&states.new, 0);\n+\t\tpath_list_clear(&states.stale, 0);\n+\t\tpath_list_clear(&states.tracked, 0);\n+\t}\n+\n+\treturn result;\n+}\n+\n+static int update_one(struct remote *remote, void *priv)\n+{\n+\tif (!remote->skip_default_update)\n+\t\treturn fetch_remote(remote->name);\n+\treturn 0;\n+}\n+\n+static int update(int argc, const char **argv)\n+{\n+\tint i;\n+\n+\tif (argc < 2)\n+\t\treturn for_each_remote(update_one, NULL);\n+\n+\tfor (i = 1; i < argc; i++)\n+\t\tif (fetch_remote(argv[i]))\n+\t\t\treturn 1;\n+\treturn 0;\n+}\n+\n+static int get_one_entry(struct remote *remote, void *priv)\n+{\n+\tstruct path_list *list = priv;\n+\n+\tpath_list_append(remote->name, list)->util = remote->url_nr ?\n+\t\t(void *)remote->url[0] : NULL;\n+\tif (remote->url_nr > 1)\n+\t\twarning (\"Remote %s has more than one URL\", remote->name);\n+\n+\treturn 0;\n+}\n+\n+static int show_all()\n+{\n+\tstruct path_list list = { NULL, 0, 0 };\n+\tint result = for_each_remote(get_one_entry, &list);\n+\n+\tif (!result) {\n+\t\tint i;\n+\n+\t\tsort_path_list(&list);\n+\t\tfor (i = 0; i < list.nr; i++) {\n+\t\t\tstruct path_list_item *item = list.items + i;\n+\t\t\tprintf(\"%s%s%s\\n\", item->path,\n+\t\t\t\tverbose ? \"\\t\" : \"\",\n+\t\t\t\tverbose && item->util ?\n+\t\t\t\t\t(const char *)item->util : \"\");\n+\t\t}\n+\t}\n+\treturn result;\n+}\n+\n+int cmd_remote(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct option options[] = {\n+\t\tOPT__VERBOSE(&verbose),\n+\t\tOPT_END()\n+\t};\n+\tint result;\n+\n+\targc = parse_options(argc, argv, options, builtin_remote_usage,\n+\t\tPARSE_OPT_STOP_AT_NON_OPTION);\n+\n+\tif (argc < 1)\n+\t\tresult = show_all();\n+\telse if (!strcmp(argv[0], \"add\"))\n+\t\tresult = add(argc, argv);\n+\telse if (!strcmp(argv[0], \"rm\"))\n+\t\tresult = rm(argc, argv);\n+\telse if (!strcmp(argv[0], \"show\"))\n+\t\tresult = show_or_prune(argc, argv, 0);\n+\telse if (!strcmp(argv[0], \"prune\"))\n+\t\tresult = show_or_prune(argc, argv, 1);\n+\telse if (!strcmp(argv[0], \"update\"))\n+\t\tresult = update(argc, argv);\n+\telse {\n+\t\terror (\"Unknown subcommand: %s\", argv[0]);\n+\t\tusage_with_options(builtin_remote_usage, options);\n+\t}\n+\n+\treturn result ? 1 : 0;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex 674c8a1..95126fd 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -67,6 +67,7 @@ extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);\n extern int cmd_push(int argc, const char **argv, const char *prefix);\n extern int cmd_read_tree(int argc, const char **argv, const char *prefix);\n extern int cmd_reflog(int argc, const char **argv, const char *prefix);\n+extern int cmd_remote(int argc, const char **argv, const char *prefix);\n extern int cmd_config(int argc, const char **argv, const char *prefix);\n extern int cmd_rerere(int argc, const char **argv, const char *prefix);\n extern int cmd_reset(int argc, const char **argv, const char *prefix);\ndiff --git a/git-remote.perl b/contrib/examples/git-remote.perl\nsimilarity index 100%\nrename from git-remote.perl\nrename to contrib/examples/git-remote.perl\ndiff --git a/git.c b/git.c\nindex 9cca81a..1e3eb10 100644\n--- a/git.c\n+++ b/git.c\n@@ -334,6 +334,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"push\", cmd_push, RUN_SETUP },\n \t\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n \t\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n+\t\t{ \"remote\", cmd_remote, RUN_SETUP },\n \t\t{ \"repo-config\", cmd_config },\n \t\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n \t\t{ \"reset\", cmd_reset, RUN_SETUP },\ndiff --git a/remote.c b/remote.c\nindex 7e19372..f3f7375 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -357,7 +357,8 @@ static int handle_config(const char *key, const char *value)\n \t\t\tremote->fetch_tags = -1;\n \t} else if (!strcmp(subkey, \".proxy\")) {\n \t\tremote->http_proxy = xstrdup(value);\n-\t}\n+\t} else if (!strcmp(subkey, \".skipdefaultupdate\"))\n+\t\tremote->skip_default_update = 1;\n \treturn 0;\n }\n \ndiff --git a/remote.h b/remote.h\nindex 0f6033f..f1dedf1 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -25,6 +25,7 @@ struct remote {\n \t * 2 to always fetch tags\n \t */\n \tint fetch_tags;\n+\tint skip_default_update;\n \n \tconst char *receivepack;\n \tconst char *uploadpack;\ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex e1e0a18..5986982 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -97,9 +97,9 @@ test_expect_success 'remove remote' '\n cat > test/expect << EOF\n * remote origin\n   URL: $(pwd)/one/.git\n-  Remote branch(es) merged with 'git pull' while on branch master\n+  Remote branch merged with 'git pull' while on branch master\n     master\n-  New remote branches (next fetch will store in remotes/origin)\n+  New remote branch (next fetch will store in remotes/origin)\n     master\n   Tracked remote branches\n     side master\n-- \n1.5.4.3.431.g066fa\n\n\n"},{"id":"70347","messageId":"alpine.LSU.1.00.0802290145550.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0802290144130.22527@racer.site","subject":"[PATCH 5/5] builtin-remote: prune remotes correctly that were added with --mirror","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T01:46:07Z","receivedAt":"2008-02-29T01:46:07Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis adds special handling for mirror remotes.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin-remote.c  |   16 +++++++++++++---\n t/t5505-remote.sh |   16 ++++++++++++++++\n 2 files changed, 29 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin-remote.c b/builtin-remote.c\nindex d229919..3954926 100644\n--- a/builtin-remote.c\n+++ b/builtin-remote.c\n@@ -396,12 +396,22 @@ static int show_or_prune(int argc, const char **argv, int prune)\n \n \t\tif (prune) {\n \t\t\tstruct strbuf buf;\n+\t\t\tint prefix_len;\n \n \t\t\tstrbuf_init(&buf, 0);\n+\t\t\tif (states.remote->fetch_refspec_nr == 1 &&\n+\t\t\t\t\tstates.remote->fetch->pattern &&\n+\t\t\t\t\t!strcmp(states.remote->fetch->src,\n+\t\t\t\t\t\tstates.remote->fetch->dst))\n+\t\t\t\t/* handle --mirror remote */\n+\t\t\t\tstrbuf_addstr(&buf, \"refs/heads/\");\n+\t\t\telse\n+\t\t\t\tstrbuf_addf(&buf, \"refs/remotes/%s/\", *argv);\n+\t\t\tprefix_len = buf.len;\n+\n \t\t\tfor (i = 0; i < states.stale.nr; i++) {\n-\t\t\t\tstrbuf_reset(&buf);\n-\t\t\t\tstrbuf_addf(&buf, \"refs/remotes/%s/%s\", *argv,\n-\t\t\t\t\t\tstates.stale.items[i].path);\n+\t\t\t\tstrbuf_setlen(&buf, prefix_len);\n+\t\t\t\tstrbuf_addstr(&buf, states.stale.items[i].path);\n \t\t\t\tresult |= delete_ref(buf.buf, NULL);\n \t\t\t}\n \ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex 5986982..0a25c8b 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -128,4 +128,20 @@ test_expect_success 'prune' '\n \t ! git rev-parse refs/remotes/origin/side)\n '\n \n+test_expect_success 'add --mirror && prune' '\n+\t(mkdir mirror &&\n+\t cd mirror &&\n+\t git init &&\n+\t git remote add --mirror -f origin ../one) &&\n+\t(cd one &&\n+\t git branch -m side2 side) &&\n+\t(cd mirror &&\n+\t git rev-parse --verify refs/heads/side2 &&\n+\t ! git rev-parse --verify refs/heads/side &&\n+\t git fetch origin &&\n+\t git remote prune origin &&\n+\t ! git rev-parse --verify refs/heads/side2 &&\n+\t git rev-parse --verify refs/heads/side)\n+'\n+\n test_done\n-- \n1.5.4.3.431.g066fa\n\n\n"},{"id":"70350","messageId":"7vwsoofrue.fsf@gitster.siamese.dyndns.org","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0802290144130.22527@racer.site","subject":"Re: [PATCH 0/5] Builtin \"git remote\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-29T01:56:25Z","receivedAt":"2008-02-29T01:56:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> It also demonstrates that format-patch --cover-letter should default to -M\n> for the diffstat (search for \"git-remote.perl\"...).\n\nIt probably should inherit the settings for the primary part.\nYou did generate the series with -M, especially [PATCH 4/5],\ndidn't you?\n\n> Johannes Schindelin (5):\n>       path-list: add functions to work with unsorted lists\n>       parseopt: add flag to stop on first non option\n>       Test \"git remote show\" and \"git remote prune\"\n>       Make git-remote a builtin\n>       builtin-remote: prune remotes correctly that were added with --mirror\n\nAlso I wish the default indentation were not that deep, and also\nline-wrapped at around 72-76 columns.\n"},{"id":"70351","messageId":"7vprugfrgw.fsf@gitster.siamese.dyndns.org","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0802290144410.22527@racer.site","subject":"Re: [PATCH 1/5] path-list: add functions to work with unsorted lists","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-29T02:04:31Z","receivedAt":"2008-02-29T02:04:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> \tThis is probably useful to a number of existing non-users of\n> \tpath_list.\n\nI suspect most of the non-users will stay non-users, until the\nthing is renamed to something more sensible.\n\nThe name gives a false impression that this is a special-purpose\ndata structure that is meant to handle pathnames very well\n(e.g. canonicalizing \"foo//../bar\" to \"bar\" before doing\ncomparsion) but in reality it does not do anything like that,\nand is a general purpose \"table keyed with string\" mechanism.\n\nThe wholesale renaming, if we were to do so, should happen when\nthings are quiet, and this is probably not a good time for it.\n\n\n"},{"id":"70352","messageId":"alpine.LSU.1.00.0802290211460.22527@racer.site","threadId":"12377","inReplyTo":"7vwsoofrue.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 0/5] Builtin \"git remote\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T02:13:45Z","receivedAt":"2008-02-29T02:13:45Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > It also demonstrates that format-patch --cover-letter should default \n> > to -M for the diffstat (search for \"git-remote.perl\"...).\n> \n> It probably should inherit the settings for the primary part.\n> You did generate the series with -M, especially [PATCH 4/5],\n> didn't you?\n\nYes, I did.\n\n> > Johannes Schindelin (5):\n> >       path-list: add functions to work with unsorted lists\n> >       parseopt: add flag to stop on first non option\n> >       Test \"git remote show\" and \"git remote prune\"\n> >       Make git-remote a builtin\n> >       builtin-remote: prune remotes correctly that were added with --mirror\n> \n> Also I wish the default indentation were not that deep, and also\n> line-wrapped at around 72-76 columns.\n\nRight.\n\nI still have a few patches in my personal tree to implement \"git-fmt\", and \nI think that it should be easy to rework them into something usable for \nthis purpose (4-character indent for the first line, 8-character for every \nsubsequent one).\n\nAlso, it might be a good idea to teach \"git log\" to use these wrapping \nfunctions, as there are still regular contributors, even to Git itself, \nwho seem to be unwilling to use <=76 characters/line.\n\nCiao,\nDscho\n\n"},{"id":"70353","messageId":"alpine.LSU.1.00.0802290214150.22527@racer.site","threadId":"12377","inReplyTo":"7vprugfrgw.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/5] path-list: add functions to work with unsorted lists","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T02:15:07Z","receivedAt":"2008-02-29T02:15:07Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > \tThis is probably useful to a number of existing non-users of\n> > \tpath_list.\n> \n> I suspect most of the non-users will stay non-users, until the\n> thing is renamed to something more sensible.\n> \n> The wholesale renaming, if we were to do so, should happen when things \n> are quiet, and this is probably not a good time for it.\n\nRight.  Will try to think of a patch when the right time has come.  Just \nto make sure: \"string_list\"?\n\nCiao,\nDscho\n\n"},{"id":"70354","messageId":"alpine.LNX.1.00.0802282104500.19665@iabervon.org","threadId":"12377","inReplyTo":"7vwsoofrue.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 0/5] Builtin \"git remote\"","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-02-29T02:17:43Z","receivedAt":"2008-02-29T02:17:43Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Thu, 28 Feb 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > It also demonstrates that format-patch --cover-letter should default to -M\n> > for the diffstat (search for \"git-remote.perl\"...).\n> \n> It probably should inherit the settings for the primary part.\n> You did generate the series with -M, especially [PATCH 4/5],\n> didn't you?\n\nObviously not the output_format, but everything else, I assume? Easy \nenough to pass the main diff options into make_cover_letter() and use them \nto initialize the diff options there.\n\n> > Johannes Schindelin (5):\n> >       path-list: add functions to work with unsorted lists\n> >       parseopt: add flag to stop on first non option\n> >       Test \"git remote show\" and \"git remote prune\"\n> >       Make git-remote a builtin\n> >       builtin-remote: prune remotes correctly that were added with --mirror\n> \n> Also I wish the default indentation were not that deep, and also\n> line-wrapped at around 72-76 columns.\n\nOnly for the cover letter, and not shortlog in general, I assume? It \nshould be easy to set the struct shortlog fields to whatever suits your \ntaste. Making it configurable (without getting tangled in other option \nparsing) is trickier, though.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"70379","messageId":"alpine.LSU.1.00.0802291118540.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LNX.1.00.0802282104500.19665@iabervon.org","subject":"Re: [PATCH 0/5] Builtin \"git remote\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-29T11:21:46Z","receivedAt":"2008-02-29T11:21:46Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Daniel Barkalow wrote:\n\n> On Thu, 28 Feb 2008, Junio C Hamano wrote:\n> \n> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> > \n> > > It also demonstrates that format-patch --cover-letter should default to -M\n> > > for the diffstat (search for \"git-remote.perl\"...).\n> > \n> > It probably should inherit the settings for the primary part.\n> > You did generate the series with -M, especially [PATCH 4/5],\n> > didn't you?\n> \n> Obviously not the output_format, but everything else, I assume? Easy \n> enough to pass the main diff options into make_cover_letter() and use \n> them to initialize the diff options there.\n\nNice.\n\n> > > Johannes Schindelin (5):\n> > >       path-list: add functions to work with unsorted lists\n> > >       parseopt: add flag to stop on first non option\n> > >       Test \"git remote show\" and \"git remote prune\"\n> > >       Make git-remote a builtin\n> > >       builtin-remote: prune remotes correctly that were added with --mirror\n> > \n> > Also I wish the default indentation were not that deep, and also\n> > line-wrapped at around 72-76 columns.\n> \n> Only for the cover letter, and not shortlog in general, I assume? It \n> should be easy to set the struct shortlog fields to whatever suits your \n> taste. Making it configurable (without getting tangled in other option \n> parsing) is trickier, though.\n\nIt is not really well documented, but with -w, you _can_ drive shortlog to \ndo that.  In the API, you have to set the members wrap_lines = 1, in1 = \nfirst_indent, in2 = indent, wrap = width in struct shortlog.\n\nI suggest the values 4,8,76, respectively.\n\nCiao,\nDscho\n\n"},{"id":"70521","messageId":"alpine.LSU.1.00.0803011313020.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0802290214150.22527@racer.site","subject":"[PATCH 0/6] Builtin remote, v2","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-01T13:14:39Z","receivedAt":"2008-03-01T13:14:39Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\n(Yes, I know, it is not v2, but I lost track...)\n\nThe only change is that path_list was renamed to string_list.  This is the\nfirst patch, and pretty intrusive (even if the changes are all straight\nforward...).\n\nOn Fri, 29 Feb 2008, Johannes Schindelin wrote:\n\n> On Thu, 28 Feb 2008, Junio C Hamano wrote:\n> \n> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> > \n> > > This is probably useful to a number of existing non-users of \n> > > path_list.\n> > \n> > I suspect most of the non-users will stay non-users, until the thing \n> > is renamed to something more sensible.\n> > \n> > The wholesale renaming, if we were to do so, should happen when things \n> > are quiet, and this is probably not a good time for it.\n> \n> Right.  Will try to think of a patch when the right time has come.  Just \n> to make sure: \"string_list\"?\n\nJust in case, I did it.  I have no problems resending it later, too, just \nwanted to let you know that I have the patches ready.\n\nJohannes Schindelin (6):\n      Rename path_list to string_list\n      string-list: add functions to work with unsorted lists\n      parseopt: add flag to stop on first non option\n      Test \"git remote show\" and \"git remote prune\"\n      Make git-remote a builtin\n      builtin-remote: prune remotes correctly that were added with --mirror\n\n Documentation/CodingGuidelines            |    5 +-\n Documentation/technical/api-path-list.txt |    4 +-\n Makefile                                  |    7 +-\n builtin-blame.c                           |    4 +-\n builtin-commit.c                          |   20 +-\n builtin-fast-export.c                     |   14 +-\n builtin-fetch.c                           |   16 +-\n builtin-mailsplit.c                       |   12 +-\n builtin-merge-recursive.c                 |   96 +++---\n builtin-mv.c                              |   39 +-\n builtin-remote.c                          |  558 +++++++++++++++++++++++++++++\n builtin-rerere.c                          |   48 ++--\n builtin-shortlog.c                        |   42 ++--\n builtin-show-ref.c                        |   10 +-\n builtin.h                                 |    1 +\n contrib/examples/git-remote.perl          |  477 ++++++++++++++++++++++++\n diff-lib.c                                |   22 +-\n git-remote.perl                           |  477 ------------------------\n git.c                                     |    1 +\n mailmap.c                                 |   12 +-\n mailmap.h                                 |    4 +-\n parse-options.c                           |    2 +\n parse-options.h                           |    1 +\n path-list.c                               |  104 ------\n path-list.h                               |   22 --\n reflog-walk.c                             |   10 +-\n remote.c                                  |    3 +-\n remote.h                                  |    1 +\n shortlog.h                                |    6 +-\n string-list.c                             |  134 +++++++\n string-list.h                             |   28 ++\n t/t5505-remote.sh                         |   50 +++\n 32 files changed, 1442 insertions(+), 788 deletions(-)\n create mode 100644 builtin-remote.c\n create mode 100755 contrib/examples/git-remote.perl\n delete mode 100755 git-remote.perl\n delete mode 100644 path-list.c\n delete mode 100644 path-list.h\n create mode 100644 string-list.c\n create mode 100644 string-list.h\n\n"},{"id":"70522","messageId":"alpine.LSU.1.00.0803011315180.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803011313020.22527@racer.site","subject":"[PATCH 1/6] Rename path_list to string_list","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-01T13:15:31Z","receivedAt":"2008-03-01T13:15:31Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThe name path_list was correct for the first usage of that data structure,\nbut it really is a general-purpose string list.\n\n$ perl -i -pe 's/path-list/string-list/g' $(git grep -l path-list)\n$ perl -i -pe 's/path_list/string_list/g' $(git grep -l path_list)\n$ git mv path-list.h string-list.h\n$ git mv path-list.c string-list.c\n$ perl -i -pe 's/has_path/has_string/g' $(git grep -l has_path)\n$ perl -i -pe 's/path/string/g' string-list.[ch]\n\n... and then fix all users of string-list to access the member \"string\"\ninstead of \"path\"...\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Documentation/CodingGuidelines            |    2 +-\n Documentation/technical/api-path-list.txt |    4 +-\n Makefile                                  |    4 +-\n builtin-blame.c                           |    4 +-\n builtin-commit.c                          |   20 +++---\n builtin-fast-export.c                     |   14 ++--\n builtin-fetch.c                           |   16 +++---\n builtin-mailsplit.c                       |   12 ++--\n builtin-merge-recursive.c                 |   96 ++++++++++++++--------------\n builtin-mv.c                              |   39 ++++++------\n builtin-rerere.c                          |   48 +++++++-------\n builtin-shortlog.c                        |   42 ++++++------\n builtin-show-ref.c                        |   10 ++--\n diff-lib.c                                |   22 +++---\n mailmap.c                                 |   12 ++--\n mailmap.h                                 |    4 +-\n path-list.h                               |   22 -------\n reflog-walk.c                             |   10 ++--\n shortlog.h                                |    6 +-\n path-list.c => string-list.c              |   41 ++++++------\n string-list.h                             |   22 +++++++\n 21 files changed, 226 insertions(+), 224 deletions(-)\n delete mode 100644 path-list.h\n rename path-list.c => string-list.c (53%)\n create mode 100644 string-list.h\n\ndiff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines\nindex 3b042db..fe7c74b 100644\n--- a/Documentation/CodingGuidelines\n+++ b/Documentation/CodingGuidelines\n@@ -91,7 +91,7 @@ For C programs:\n \n  - Use the API.  No, really.  We have a strbuf (variable length\n    string), several arrays with the ALLOC_GROW() macro, a\n-   path_list for sorted string lists, a hash map (mapping struct\n+   string_list for sorted string lists, a hash map (mapping struct\n    objects) named \"struct decorate\", amongst other things.\n \n  - When you come up with an API, document it.\ndiff --git a/Documentation/technical/api-path-list.txt b/Documentation/technical/api-path-list.txt\nindex d077683..8892cf0 100644\n--- a/Documentation/technical/api-path-list.txt\n+++ b/Documentation/technical/api-path-list.txt\n@@ -1,7 +1,7 @@\n-path-list API\n+string-list API\n =============\n \n-Talk about <path-list.h>, things like\n+Talk about <string-list.h>, things like\n \n * it is not just paths but strings in general;\n * the calling sequence.\ndiff --git a/Makefile b/Makefile\nindex 88f1c7e..ad214d3 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -302,7 +302,7 @@ LIB_H = \\\n \tarchive.h blob.h cache.h cache-tree.h commit.h csum-file.h delta.h grep.h \\\n \tdiff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.h \\\n \trun-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \\\n-\ttree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \\\n+\ttree-walk.h log-tree.h dir.h string-list.h unpack-trees.h builtin.h \\\n \tutf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \\\n \tmailmap.h remote.h parse-options.h transport.h diffcore.h hash.h ll-merge.h\n \n@@ -324,7 +324,7 @@ LIB_OBJS = \\\n \ttag.o tree.o usage.o config.o environment.o ctype.o copy.o \\\n \trevision.o pager.o tree-walk.o xdiff-interface.o \\\n \twrite_or_die.o trace.o list-objects.o grep.o match-trees.o \\\n-\talloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \\\n+\talloc.o merge-file.o string-list.o help.o unpack-trees.o $(DIFF_OBJS) \\\n \tcolor.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \\\n \tconvert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \\\n \ttransport.o bundle.o walker.o parse-options.o ws.o archive.o branch.o \\\ndiff --git a/builtin-blame.c b/builtin-blame.c\nindex bfd562d..25c7996 100644\n--- a/builtin-blame.c\n+++ b/builtin-blame.c\n@@ -16,7 +16,7 @@\n #include \"quote.h\"\n #include \"xdiff-interface.h\"\n #include \"cache-tree.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"mailmap.h\"\n \n static char blame_usage[] =\n@@ -47,7 +47,7 @@ static int blank_boundary;\n static int incremental;\n static int cmd_is_annotate;\n static int xdl_opts = XDF_NEED_MINIMAL;\n-static struct path_list mailmap;\n+static struct string_list mailmap;\n \n #ifndef DEBUG\n #define DEBUG 0\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex f49c22e..380dcdc 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -21,7 +21,7 @@\n #include \"strbuf.h\"\n #include \"utf8.h\"\n #include \"parse-options.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"unpack-trees.h\"\n \n static const char * const builtin_commit_usage[] = {\n@@ -146,7 +146,7 @@ static int commit_index_files(void)\n  * Take a union of paths in the index and the named tree (typically, \"HEAD\"),\n  * and return the paths that match the given pattern in list.\n  */\n-static int list_paths(struct path_list *list, const char *with_tree,\n+static int list_paths(struct string_list *list, const char *with_tree,\n \t\t      const char *prefix, const char **pattern)\n {\n \tint i;\n@@ -165,21 +165,21 @@ static int list_paths(struct path_list *list, const char *with_tree,\n \t\t\tcontinue;\n \t\tif (!pathspec_match(pattern, m, ce->name, 0))\n \t\t\tcontinue;\n-\t\tpath_list_insert(ce->name, list);\n+\t\tstring_list_insert(ce->name, list);\n \t}\n \n \treturn report_path_error(m, pattern, prefix ? strlen(prefix) : 0);\n }\n \n-static void add_remove_files(struct path_list *list)\n+static void add_remove_files(struct string_list *list)\n {\n \tint i;\n \tfor (i = 0; i < list->nr; i++) {\n-\t\tstruct path_list_item *p = &(list->items[i]);\n-\t\tif (file_exists(p->path))\n-\t\t\tadd_file_to_cache(p->path, 0);\n+\t\tstruct string_list_item *p = &(list->items[i]);\n+\t\tif (file_exists(p->string))\n+\t\t\tadd_file_to_cache(p->string, 0);\n \t\telse\n-\t\t\tremove_file_from_cache(p->path);\n+\t\t\tremove_file_from_cache(p->string);\n \t}\n }\n \n@@ -212,7 +212,7 @@ static void create_base_index(void)\n static char *prepare_index(int argc, const char **argv, const char *prefix)\n {\n \tint fd;\n-\tstruct path_list partial;\n+\tstruct string_list partial;\n \tconst char **pathspec = NULL;\n \n \tif (interactive) {\n@@ -294,7 +294,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)\n \t\tdie(\"cannot do a partial commit during a merge.\");\n \n \tmemset(&partial, 0, sizeof(partial));\n-\tpartial.strdup_paths = 1;\n+\tpartial.strdup_strings = 1;\n \tif (list_paths(&partial, initial_commit ? NULL : \"HEAD\", prefix, pathspec))\n \t\texit(1);\n \ndiff --git a/builtin-fast-export.c b/builtin-fast-export.c\nindex e1c5630..a705029 100755\n--- a/builtin-fast-export.c\n+++ b/builtin-fast-export.c\n@@ -13,7 +13,7 @@\n #include \"log-tree.h\"\n #include \"revision.h\"\n #include \"decorate.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"utf8.h\"\n #include \"parse-options.h\"\n \n@@ -286,7 +286,7 @@ static void handle_tag(const char *name, struct tag *tag)\n }\n \n static void get_tags_and_duplicates(struct object_array *pending,\n-\t\t\t\t    struct path_list *extra_refs)\n+\t\t\t\t    struct string_list *extra_refs)\n {\n \tstruct tag *tag;\n \tint i;\n@@ -307,7 +307,7 @@ static void get_tags_and_duplicates(struct object_array *pending,\n \t\tcase OBJ_TAG:\n \t\t\ttag = (struct tag *)e->item;\n \t\t\twhile (tag && tag->object.type == OBJ_TAG) {\n-\t\t\t\tpath_list_insert(full_name, extra_refs)->util = tag;\n+\t\t\t\tstring_list_insert(full_name, extra_refs)->util = tag;\n \t\t\t\ttag = (struct tag *)tag->tagged;\n \t\t\t}\n \t\t\tif (!tag)\n@@ -327,19 +327,19 @@ static void get_tags_and_duplicates(struct object_array *pending,\n \t\t}\n \t\tif (commit->util)\n \t\t\t/* more than one name for the same object */\n-\t\t\tpath_list_insert(full_name, extra_refs)->util = commit;\n+\t\t\tstring_list_insert(full_name, extra_refs)->util = commit;\n \t\telse\n \t\t\tcommit->util = full_name;\n \t}\n }\n \n-static void handle_tags_and_duplicates(struct path_list *extra_refs)\n+static void handle_tags_and_duplicates(struct string_list *extra_refs)\n {\n \tstruct commit *commit;\n \tint i;\n \n \tfor (i = extra_refs->nr - 1; i >= 0; i--) {\n-\t\tconst char *name = extra_refs->items[i].path;\n+\t\tconst char *name = extra_refs->items[i].string;\n \t\tstruct object *object = extra_refs->items[i].util;\n \t\tswitch (object->type) {\n \t\tcase OBJ_TAG:\n@@ -360,7 +360,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n {\n \tstruct rev_info revs;\n \tstruct object_array commits = { 0, 0, NULL };\n-\tstruct path_list extra_refs = { NULL, 0, 0, 0 };\n+\tstruct string_list extra_refs = { NULL, 0, 0, 0 };\n \tstruct commit *commit;\n \tstruct option options[] = {\n \t\tOPT_INTEGER(0, \"progress\", &progress,\ndiff --git a/builtin-fetch.c b/builtin-fetch.c\nindex ac335f2..94e3e74 100644\n--- a/builtin-fetch.c\n+++ b/builtin-fetch.c\n@@ -5,7 +5,7 @@\n #include \"refs.h\"\n #include \"commit.h\"\n #include \"builtin.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"remote.h\"\n #include \"transport.h\"\n #include \"run-command.h\"\n@@ -447,16 +447,16 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)\n static int add_existing(const char *refname, const unsigned char *sha1,\n \t\t\tint flag, void *cbdata)\n {\n-\tstruct path_list *list = (struct path_list *)cbdata;\n-\tpath_list_insert(refname, list);\n+\tstruct string_list *list = (struct string_list *)cbdata;\n+\tstring_list_insert(refname, list);\n \treturn 0;\n }\n \n static struct ref *find_non_local_tags(struct transport *transport,\n \t\t\t\t       struct ref *fetch_map)\n {\n-\tstatic struct path_list existing_refs = { NULL, 0, 0, 0 };\n-\tstruct path_list new_refs = { NULL, 0, 0, 1 };\n+\tstatic struct string_list existing_refs = { NULL, 0, 0, 0 };\n+\tstruct string_list new_refs = { NULL, 0, 0, 1 };\n \tchar *ref_name;\n \tint ref_name_len;\n \tconst unsigned char *ref_sha1;\n@@ -487,10 +487,10 @@ static struct ref *find_non_local_tags(struct transport *transport,\n \t\t\t}\n \t\t}\n \n-\t\tif (!path_list_has_path(&existing_refs, ref_name) &&\n-\t\t    !path_list_has_path(&new_refs, ref_name) &&\n+\t\tif (!string_list_has_string(&existing_refs, ref_name) &&\n+\t\t    !string_list_has_string(&new_refs, ref_name) &&\n \t\t    has_sha1_file(ref->old_sha1)) {\n-\t\t\tpath_list_insert(ref_name, &new_refs);\n+\t\t\tstring_list_insert(ref_name, &new_refs);\n \n \t\t\trm = alloc_ref(strlen(ref_name) + 1);\n \t\t\tstrcpy(rm->name, ref_name);\ndiff --git a/builtin-mailsplit.c b/builtin-mailsplit.c\nindex 46b27cd..29df10f 100644\n--- a/builtin-mailsplit.c\n+++ b/builtin-mailsplit.c\n@@ -6,7 +6,7 @@\n  */\n #include \"cache.h\"\n #include \"builtin.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n \n static const char git_mailsplit_usage[] =\n \"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>|<Maildir>...\";\n@@ -97,7 +97,7 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)\n \texit(1);\n }\n \n-static int populate_maildir_list(struct path_list *list, const char *path)\n+static int populate_maildir_list(struct string_list *list, const char *path)\n {\n \tDIR *dir;\n \tstruct dirent *dent;\n@@ -118,7 +118,7 @@ static int populate_maildir_list(struct path_list *list, const char *path)\n \t\t\tif (dent->d_name[0] == '.')\n \t\t\t\tcontinue;\n \t\t\tsnprintf(name, sizeof(name), \"%s/%s\", *sub, dent->d_name);\n-\t\t\tpath_list_insert(name, list);\n+\t\t\tstring_list_insert(name, list);\n \t\t}\n \n \t\tclosedir(dir);\n@@ -134,14 +134,14 @@ static int split_maildir(const char *maildir, const char *dir,\n \tchar name[PATH_MAX];\n \tint ret = -1;\n \tint i;\n-\tstruct path_list list = {NULL, 0, 0, 1};\n+\tstruct string_list list = {NULL, 0, 0, 1};\n \n \tif (populate_maildir_list(&list, maildir) < 0)\n \t\tgoto out;\n \n \tfor (i = 0; i < list.nr; i++) {\n \t\tFILE *f;\n-\t\tsnprintf(file, sizeof(file), \"%s/%s\", maildir, list.items[i].path);\n+\t\tsnprintf(file, sizeof(file), \"%s/%s\", maildir, list.items[i].string);\n \t\tf = fopen(file, \"r\");\n \t\tif (!f) {\n \t\t\terror(\"cannot open mail %s (%s)\", file, strerror(errno));\n@@ -161,7 +161,7 @@ static int split_maildir(const char *maildir, const char *dir,\n \n \tret = skip;\n out:\n-\tpath_list_clear(&list, 1);\n+\tstring_list_clear(&list, 1);\n \treturn ret;\n }\n \ndiff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c\nindex 5a0a7b5..8e77e8b 100644\n--- a/builtin-merge-recursive.c\n+++ b/builtin-merge-recursive.c\n@@ -13,7 +13,7 @@\n #include \"diffcore.h\"\n #include \"tag.h\"\n #include \"unpack-trees.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"xdiff-interface.h\"\n #include \"ll-merge.h\"\n #include \"interpolate.h\"\n@@ -87,8 +87,8 @@ struct stage_data\n \tunsigned processed:1;\n };\n \n-static struct path_list current_file_set = {NULL, 0, 0, 1};\n-static struct path_list current_directory_set = {NULL, 0, 0, 1};\n+static struct string_list current_file_set = {NULL, 0, 0, 1};\n+static struct string_list current_directory_set = {NULL, 0, 0, 1};\n \n static int call_depth = 0;\n static int verbosity = 2;\n@@ -262,9 +262,9 @@ static int save_files_dirs(const unsigned char *sha1,\n \tnewpath[baselen + len] = '\\0';\n \n \tif (S_ISDIR(mode))\n-\t\tpath_list_insert(newpath, &current_directory_set);\n+\t\tstring_list_insert(newpath, &current_directory_set);\n \telse\n-\t\tpath_list_insert(newpath, &current_file_set);\n+\t\tstring_list_insert(newpath, &current_file_set);\n \tfree(newpath);\n \n \treturn READ_TREE_RECURSIVE;\n@@ -285,9 +285,9 @@ static int get_files_dirs(struct tree *tree)\n  */\n static struct stage_data *insert_stage_data(const char *path,\n \t\tstruct tree *o, struct tree *a, struct tree *b,\n-\t\tstruct path_list *entries)\n+\t\tstruct string_list *entries)\n {\n-\tstruct path_list_item *item;\n+\tstruct string_list_item *item;\n \tstruct stage_data *e = xcalloc(1, sizeof(struct stage_data));\n \tget_tree_entry(o->object.sha1, path,\n \t\t\te->stages[1].sha, &e->stages[1].mode);\n@@ -295,7 +295,7 @@ static struct stage_data *insert_stage_data(const char *path,\n \t\t\te->stages[2].sha, &e->stages[2].mode);\n \tget_tree_entry(b->object.sha1, path,\n \t\t\te->stages[3].sha, &e->stages[3].mode);\n-\titem = path_list_insert(path, entries);\n+\titem = string_list_insert(path, entries);\n \titem->util = e;\n \treturn e;\n }\n@@ -304,23 +304,23 @@ static struct stage_data *insert_stage_data(const char *path,\n  * Create a dictionary mapping file names to stage_data objects. The\n  * dictionary contains one entry for every path with a non-zero stage entry.\n  */\n-static struct path_list *get_unmerged(void)\n+static struct string_list *get_unmerged(void)\n {\n-\tstruct path_list *unmerged = xcalloc(1, sizeof(struct path_list));\n+\tstruct string_list *unmerged = xcalloc(1, sizeof(struct string_list));\n \tint i;\n \n-\tunmerged->strdup_paths = 1;\n+\tunmerged->strdup_strings = 1;\n \n \tfor (i = 0; i < active_nr; i++) {\n-\t\tstruct path_list_item *item;\n+\t\tstruct string_list_item *item;\n \t\tstruct stage_data *e;\n \t\tstruct cache_entry *ce = active_cache[i];\n \t\tif (!ce_stage(ce))\n \t\t\tcontinue;\n \n-\t\titem = path_list_lookup(ce->name, unmerged);\n+\t\titem = string_list_lookup(ce->name, unmerged);\n \t\tif (!item) {\n-\t\t\titem = path_list_insert(ce->name, unmerged);\n+\t\t\titem = string_list_insert(ce->name, unmerged);\n \t\t\titem->util = xcalloc(1, sizeof(struct stage_data));\n \t\t}\n \t\te = item->util;\n@@ -345,17 +345,17 @@ struct rename\n  * 'b_tree') to be able to associate the correct cache entries with\n  * the rename information. 'tree' is always equal to either a_tree or b_tree.\n  */\n-static struct path_list *get_renames(struct tree *tree,\n+static struct string_list *get_renames(struct tree *tree,\n \t\t\t\t\tstruct tree *o_tree,\n \t\t\t\t\tstruct tree *a_tree,\n \t\t\t\t\tstruct tree *b_tree,\n-\t\t\t\t\tstruct path_list *entries)\n+\t\t\t\t\tstruct string_list *entries)\n {\n \tint i;\n-\tstruct path_list *renames;\n+\tstruct string_list *renames;\n \tstruct diff_options opts;\n \n-\trenames = xcalloc(1, sizeof(struct path_list));\n+\trenames = xcalloc(1, sizeof(struct string_list));\n \tdiff_setup(&opts);\n \tDIFF_OPT_SET(&opts, RECURSIVE);\n \topts.detect_rename = DIFF_DETECT_RENAME;\n@@ -366,7 +366,7 @@ static struct path_list *get_renames(struct tree *tree,\n \tdiff_tree_sha1(o_tree->object.sha1, tree->object.sha1, \"\", &opts);\n \tdiffcore_std(&opts);\n \tfor (i = 0; i < diff_queued_diff.nr; ++i) {\n-\t\tstruct path_list_item *item;\n+\t\tstruct string_list_item *item;\n \t\tstruct rename *re;\n \t\tstruct diff_filepair *pair = diff_queued_diff.queue[i];\n \t\tif (pair->status != 'R') {\n@@ -376,20 +376,20 @@ static struct path_list *get_renames(struct tree *tree,\n \t\tre = xmalloc(sizeof(*re));\n \t\tre->processed = 0;\n \t\tre->pair = pair;\n-\t\titem = path_list_lookup(re->pair->one->path, entries);\n+\t\titem = string_list_lookup(re->pair->one->path, entries);\n \t\tif (!item)\n \t\t\tre->src_entry = insert_stage_data(re->pair->one->path,\n \t\t\t\t\to_tree, a_tree, b_tree, entries);\n \t\telse\n \t\t\tre->src_entry = item->util;\n \n-\t\titem = path_list_lookup(re->pair->two->path, entries);\n+\t\titem = string_list_lookup(re->pair->two->path, entries);\n \t\tif (!item)\n \t\t\tre->dst_entry = insert_stage_data(re->pair->two->path,\n \t\t\t\t\to_tree, a_tree, b_tree, entries);\n \t\telse\n \t\t\tre->dst_entry = item->util;\n-\t\titem = path_list_insert(pair->one->path, renames);\n+\t\titem = string_list_insert(pair->one->path, renames);\n \t\titem->util = re;\n \t}\n \topts.output_format = DIFF_FORMAT_NO_OUTPUT;\n@@ -466,12 +466,12 @@ static char *unique_path(const char *path, const char *branch)\n \tfor (; *p; ++p)\n \t\tif ('/' == *p)\n \t\t\t*p = '_';\n-\twhile (path_list_has_path(&current_file_set, newpath) ||\n-\t       path_list_has_path(&current_directory_set, newpath) ||\n+\twhile (string_list_has_string(&current_file_set, newpath) ||\n+\t       string_list_has_string(&current_directory_set, newpath) ||\n \t       lstat(newpath, &st) == 0)\n \t\tsprintf(p, \"_%d\", suffix++);\n \n-\tpath_list_insert(newpath, &current_file_set);\n+\tstring_list_insert(newpath, &current_file_set);\n \treturn newpath;\n }\n \n@@ -716,13 +716,13 @@ static void conflict_rename_rename(struct rename *ren1,\n \tconst char *ren2_dst = ren2->pair->two->path;\n \tconst char *dst_name1 = ren1_dst;\n \tconst char *dst_name2 = ren2_dst;\n-\tif (path_list_has_path(&current_directory_set, ren1_dst)) {\n+\tif (string_list_has_string(&current_directory_set, ren1_dst)) {\n \t\tdst_name1 = del[delp++] = unique_path(ren1_dst, branch1);\n \t\toutput(1, \"%s is a directory in %s added as %s instead\",\n \t\t       ren1_dst, branch2, dst_name1);\n \t\tremove_file(0, ren1_dst, 0);\n \t}\n-\tif (path_list_has_path(&current_directory_set, ren2_dst)) {\n+\tif (string_list_has_string(&current_directory_set, ren2_dst)) {\n \t\tdst_name2 = del[delp++] = unique_path(ren2_dst, branch2);\n \t\toutput(1, \"%s is a directory in %s added as %s instead\",\n \t\t       ren2_dst, branch1, dst_name2);\n@@ -772,30 +772,30 @@ static void conflict_rename_rename_2(struct rename *ren1,\n \tfree(new_path1);\n }\n \n-static int process_renames(struct path_list *a_renames,\n-\t\t\t   struct path_list *b_renames,\n+static int process_renames(struct string_list *a_renames,\n+\t\t\t   struct string_list *b_renames,\n \t\t\t   const char *a_branch,\n \t\t\t   const char *b_branch)\n {\n \tint clean_merge = 1, i, j;\n-\tstruct path_list a_by_dst = {NULL, 0, 0, 0}, b_by_dst = {NULL, 0, 0, 0};\n+\tstruct string_list a_by_dst = {NULL, 0, 0, 0}, b_by_dst = {NULL, 0, 0, 0};\n \tconst struct rename *sre;\n \n \tfor (i = 0; i < a_renames->nr; i++) {\n \t\tsre = a_renames->items[i].util;\n-\t\tpath_list_insert(sre->pair->two->path, &a_by_dst)->util\n+\t\tstring_list_insert(sre->pair->two->path, &a_by_dst)->util\n \t\t\t= sre->dst_entry;\n \t}\n \tfor (i = 0; i < b_renames->nr; i++) {\n \t\tsre = b_renames->items[i].util;\n-\t\tpath_list_insert(sre->pair->two->path, &b_by_dst)->util\n+\t\tstring_list_insert(sre->pair->two->path, &b_by_dst)->util\n \t\t\t= sre->dst_entry;\n \t}\n \n \tfor (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) {\n \t\tint compare;\n \t\tchar *src;\n-\t\tstruct path_list *renames1, *renames2, *renames2Dst;\n+\t\tstruct string_list *renames1, *renames2, *renames2Dst;\n \t\tstruct rename *ren1 = NULL, *ren2 = NULL;\n \t\tconst char *branch1, *branch2;\n \t\tconst char *ren1_src, *ren1_dst;\n@@ -807,8 +807,8 @@ static int process_renames(struct path_list *a_renames,\n \t\t\tcompare = -1;\n \t\t\tren1 = a_renames->items[i++].util;\n \t\t} else {\n-\t\t\tcompare = strcmp(a_renames->items[i].path,\n-\t\t\t\t\tb_renames->items[j].path);\n+\t\t\tcompare = strcmp(a_renames->items[i].string,\n+\t\t\t\t\tb_renames->items[j].string);\n \t\t\tif (compare <= 0)\n \t\t\t\tren1 = a_renames->items[i++].util;\n \t\t\tif (compare >= 0)\n@@ -897,7 +897,7 @@ static int process_renames(struct path_list *a_renames,\n \t\t\t}\n \t\t} else {\n \t\t\t/* Renamed in 1, maybe changed in 2 */\n-\t\t\tstruct path_list_item *item;\n+\t\t\tstruct string_list_item *item;\n \t\t\t/* we only use sha1 and mode of these */\n \t\t\tstruct diff_filespec src_other, dst_other;\n \t\t\tint try_merge, stage = a_renames == renames1 ? 3: 2;\n@@ -911,7 +911,7 @@ static int process_renames(struct path_list *a_renames,\n \n \t\t\ttry_merge = 0;\n \n-\t\t\tif (path_list_has_path(&current_directory_set, ren1_dst)) {\n+\t\t\tif (string_list_has_string(&current_directory_set, ren1_dst)) {\n \t\t\t\tclean_merge = 0;\n \t\t\t\toutput(1, \"CONFLICT (rename/directory): Renamed %s->%s in %s \"\n \t\t\t\t       \" directory %s added in %s\",\n@@ -936,7 +936,7 @@ static int process_renames(struct path_list *a_renames,\n \t\t\t\tnew_path = unique_path(ren1_dst, branch2);\n \t\t\t\toutput(1, \"Added as %s instead\", new_path);\n \t\t\t\tupdate_file(0, dst_other.sha1, dst_other.mode, new_path);\n-\t\t\t} else if ((item = path_list_lookup(ren1_dst, renames2Dst))) {\n+\t\t\t} else if ((item = string_list_lookup(ren1_dst, renames2Dst))) {\n \t\t\t\tren2 = item->util;\n \t\t\t\tclean_merge = 0;\n \t\t\t\tren2->processed = 1;\n@@ -992,8 +992,8 @@ static int process_renames(struct path_list *a_renames,\n \t\t\t}\n \t\t}\n \t}\n-\tpath_list_clear(&a_by_dst, 0);\n-\tpath_list_clear(&b_by_dst, 0);\n+\tstring_list_clear(&a_by_dst, 0);\n+\tstring_list_clear(&b_by_dst, 0);\n \n \treturn clean_merge;\n }\n@@ -1071,7 +1071,7 @@ static int process_entry(const char *path, struct stage_data *entry,\n \t\t\tsha = b_sha;\n \t\t\tconf = \"directory/file\";\n \t\t}\n-\t\tif (path_list_has_path(&current_directory_set, path)) {\n+\t\tif (string_list_has_string(&current_directory_set, path)) {\n \t\t\tconst char *new_path = unique_path(path, add_branch);\n \t\t\tclean_merge = 0;\n \t\t\toutput(1, \"CONFLICT (%s): There is a directory with name %s in %s. \"\n@@ -1162,10 +1162,10 @@ int merge_trees(struct tree *head,\n \t\t    sha1_to_hex(merge->object.sha1));\n \n \tif (unmerged_cache()) {\n-\t\tstruct path_list *entries, *re_head, *re_merge;\n+\t\tstruct string_list *entries, *re_head, *re_merge;\n \t\tint i;\n-\t\tpath_list_clear(&current_file_set, 1);\n-\t\tpath_list_clear(&current_directory_set, 1);\n+\t\tstring_list_clear(&current_file_set, 1);\n+\t\tstring_list_clear(&current_directory_set, 1);\n \t\tget_files_dirs(head);\n \t\tget_files_dirs(merge);\n \n@@ -1175,16 +1175,16 @@ int merge_trees(struct tree *head,\n \t\tclean = process_renames(re_head, re_merge,\n \t\t\t\tbranch1, branch2);\n \t\tfor (i = 0; i < entries->nr; i++) {\n-\t\t\tconst char *path = entries->items[i].path;\n+\t\t\tconst char *path = entries->items[i].string;\n \t\t\tstruct stage_data *e = entries->items[i].util;\n \t\t\tif (!e->processed\n \t\t\t\t&& !process_entry(path, e, branch1, branch2))\n \t\t\t\tclean = 0;\n \t\t}\n \n-\t\tpath_list_clear(re_merge, 0);\n-\t\tpath_list_clear(re_head, 0);\n-\t\tpath_list_clear(entries, 1);\n+\t\tstring_list_clear(re_merge, 0);\n+\t\tstring_list_clear(re_head, 0);\n+\t\tstring_list_clear(entries, 1);\n \n \t}\n \telse\ndiff --git a/builtin-mv.c b/builtin-mv.c\nindex 68aa2a6..6d22106 100644\n--- a/builtin-mv.c\n+++ b/builtin-mv.c\n@@ -7,7 +7,7 @@\n #include \"builtin.h\"\n #include \"dir.h\"\n #include \"cache-tree.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"parse-options.h\"\n \n static const char * const builtin_mv_usage[] = {\n@@ -40,13 +40,14 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,\n \treturn result;\n }\n \n-static void show_list(const char *label, struct path_list *list)\n+static void show_list(const char *label, struct string_list *list)\n {\n \tif (list->nr > 0) {\n \t\tint i;\n \t\tprintf(\"%s\", label);\n \t\tfor (i = 0; i < list->nr; i++)\n-\t\t\tprintf(\"%s%s\", i > 0 ? \", \" : \"\", list->items[i].path);\n+\t\t\tprintf(\"%s%s\", i > 0 ? \", \" : \"\",\n+\t\t\t\t\tlist->items[i].string);\n \t\tputchar('\\n');\n \t}\n }\n@@ -79,11 +80,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \tconst char **source, **destination, **dest_path;\n \tenum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes;\n \tstruct stat st;\n-\tstruct path_list overwritten = {NULL, 0, 0, 0};\n-\tstruct path_list src_for_dst = {NULL, 0, 0, 0};\n-\tstruct path_list added = {NULL, 0, 0, 0};\n-\tstruct path_list deleted = {NULL, 0, 0, 0};\n-\tstruct path_list changed = {NULL, 0, 0, 0};\n+\tstruct string_list overwritten = {NULL, 0, 0, 0};\n+\tstruct string_list src_for_dst = {NULL, 0, 0, 0};\n+\tstruct string_list added = {NULL, 0, 0, 0};\n+\tstruct string_list deleted = {NULL, 0, 0, 0};\n+\tstruct string_list changed = {NULL, 0, 0, 0};\n \n \tgit_config(git_default_config);\n \n@@ -193,16 +194,16 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \t\t\t\t\t\t\t\" will overwrite!\\n\",\n \t\t\t\t\t\t\tbad);\n \t\t\t\t\tbad = NULL;\n-\t\t\t\t\tpath_list_insert(dst, &overwritten);\n+\t\t\t\t\tstring_list_insert(dst, &overwritten);\n \t\t\t\t} else\n \t\t\t\t\tbad = \"Cannot overwrite\";\n \t\t\t}\n \t\t} else if (cache_name_pos(src, length) < 0)\n \t\t\tbad = \"not under version control\";\n-\t\telse if (path_list_has_path(&src_for_dst, dst))\n+\t\telse if (string_list_has_string(&src_for_dst, dst))\n \t\t\tbad = \"multiple sources for the same target\";\n \t\telse\n-\t\t\tpath_list_insert(dst, &src_for_dst);\n+\t\t\tstring_list_insert(dst, &src_for_dst);\n \n \t\tif (bad) {\n \t\t\tif (ignore_errors) {\n@@ -232,15 +233,15 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \t\t\tcontinue;\n \n \t\tif (cache_name_pos(src, strlen(src)) >= 0) {\n-\t\t\tpath_list_insert(src, &deleted);\n+\t\t\tstring_list_insert(src, &deleted);\n \n \t\t\t/* destination can be a directory with 1 file inside */\n-\t\t\tif (path_list_has_path(&overwritten, dst))\n-\t\t\t\tpath_list_insert(dst, &changed);\n+\t\t\tif (string_list_has_string(&overwritten, dst))\n+\t\t\t\tstring_list_insert(dst, &changed);\n \t\t\telse\n-\t\t\t\tpath_list_insert(dst, &added);\n+\t\t\t\tstring_list_insert(dst, &added);\n \t\t} else\n-\t\t\tpath_list_insert(dst, &added);\n+\t\t\tstring_list_insert(dst, &added);\n \t}\n \n \tif (show_only) {\n@@ -249,7 +250,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \t\tshow_list(\"Deleting : \", &deleted);\n \t} else {\n \t\tfor (i = 0; i < changed.nr; i++) {\n-\t\t\tconst char *path = changed.items[i].path;\n+\t\t\tconst char *path = changed.items[i].string;\n \t\t\tint j = cache_name_pos(path, strlen(path));\n \t\t\tstruct cache_entry *ce = active_cache[j];\n \n@@ -259,12 +260,12 @@ int cmd_mv(int argc, const char **argv, const char *prefix)\n \t\t}\n \n \t\tfor (i = 0; i < added.nr; i++) {\n-\t\t\tconst char *path = added.items[i].path;\n+\t\t\tconst char *path = added.items[i].string;\n \t\t\tadd_file_to_cache(path, verbose);\n \t\t}\n \n \t\tfor (i = 0; i < deleted.nr; i++)\n-\t\t\tremove_file_from_cache(deleted.items[i].path);\n+\t\t\tremove_file_from_cache(deleted.items[i].string);\n \n \t\tif (active_cache_changed) {\n \t\t\tif (write_cache(newfd, active_cache, active_nr) ||\ndiff --git a/builtin-rerere.c b/builtin-rerere.c\nindex c607aad..963b19e 100644\n--- a/builtin-rerere.c\n+++ b/builtin-rerere.c\n@@ -1,6 +1,6 @@\n #include \"builtin.h\"\n #include \"cache.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"xdiff/xdiff.h\"\n #include \"xdiff-interface.h\"\n \n@@ -23,7 +23,7 @@ static const char *rr_path(const char *name, const char *file)\n \treturn git_path(\"rr-cache/%s/%s\", name, file);\n }\n \n-static void read_rr(struct path_list *rr)\n+static void read_rr(struct string_list *rr)\n {\n \tunsigned char sha1[20];\n \tchar buf[PATH_MAX];\n@@ -43,18 +43,18 @@ static void read_rr(struct path_list *rr)\n \t\t\t; /* do nothing */\n \t\tif (i == sizeof(buf))\n \t\t\tdie(\"filename too long\");\n-\t\tpath_list_insert(buf, rr)->util = xstrdup(name);\n+\t\tstring_list_insert(buf, rr)->util = xstrdup(name);\n \t}\n \tfclose(in);\n }\n \n static struct lock_file write_lock;\n \n-static int write_rr(struct path_list *rr, int out_fd)\n+static int write_rr(struct string_list *rr, int out_fd)\n {\n \tint i;\n \tfor (i = 0; i < rr->nr; i++) {\n-\t\tconst char *path = rr->items[i].path;\n+\t\tconst char *path = rr->items[i].string;\n \t\tint length = strlen(path) + 1;\n \t\tif (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||\n \t\t    write_in_full(out_fd, \"\\t\", 1) != 1 ||\n@@ -138,7 +138,7 @@ static int handle_file(const char *path,\n \treturn hunk_no;\n }\n \n-static int find_conflict(struct path_list *conflict)\n+static int find_conflict(struct string_list *conflict)\n {\n \tint i;\n \tif (read_cache() < 0)\n@@ -151,7 +151,7 @@ static int find_conflict(struct path_list *conflict)\n \t\t    ce_same_name(e2, e3) &&\n \t\t    S_ISREG(e2->ce_mode) &&\n \t\t    S_ISREG(e3->ce_mode)) {\n-\t\t\tpath_list_insert((const char *)e2->name, conflict);\n+\t\t\tstring_list_insert((const char *)e2->name, conflict);\n \t\t\ti++; /* skip over both #2 and #3 */\n \t\t}\n \t}\n@@ -198,9 +198,9 @@ static void unlink_rr_item(const char *name)\n \trmdir(git_path(\"rr-cache/%s\", name));\n }\n \n-static void garbage_collect(struct path_list *rr)\n+static void garbage_collect(struct string_list *rr)\n {\n-\tstruct path_list to_remove = { NULL, 0, 0, 1 };\n+\tstruct string_list to_remove = { NULL, 0, 0, 1 };\n \tchar buf[1024];\n \tDIR *dir;\n \tstruct dirent *e;\n@@ -226,12 +226,12 @@ static void garbage_collect(struct path_list *rr)\n \t\tcutoff = stat(buf, &st) ? cutoff_noresolve : cutoff_resolve;\n \t\tif (then < now - cutoff * 86400) {\n \t\t\tbuf[len + i] = '\\0';\n-\t\t\tpath_list_insert(xstrdup(name), &to_remove);\n+\t\t\tstring_list_insert(xstrdup(name), &to_remove);\n \t\t}\n \t}\n \tfor (i = 0; i < to_remove.nr; i++)\n-\t\tunlink_rr_item(to_remove.items[i].path);\n-\tpath_list_clear(&to_remove, 0);\n+\t\tunlink_rr_item(to_remove.items[i].string);\n+\tstring_list_clear(&to_remove, 0);\n }\n \n static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)\n@@ -267,9 +267,9 @@ static int diff_two(const char *file1, const char *label1,\n \treturn 0;\n }\n \n-static int do_plain_rerere(struct path_list *rr, int fd)\n+static int do_plain_rerere(struct string_list *rr, int fd)\n {\n-\tstruct path_list conflict = { NULL, 0, 0, 1 };\n+\tstruct string_list conflict = { NULL, 0, 0, 1 };\n \tint i;\n \n \tfind_conflict(&conflict);\n@@ -282,8 +282,8 @@ static int do_plain_rerere(struct path_list *rr, int fd)\n \t */\n \n \tfor (i = 0; i < conflict.nr; i++) {\n-\t\tconst char *path = conflict.items[i].path;\n-\t\tif (!path_list_has_path(rr, path)) {\n+\t\tconst char *path = conflict.items[i].string;\n+\t\tif (!string_list_has_string(rr, path)) {\n \t\t\tunsigned char sha1[20];\n \t\t\tchar *hex;\n \t\t\tint ret;\n@@ -291,7 +291,7 @@ static int do_plain_rerere(struct path_list *rr, int fd)\n \t\t\tif (ret < 1)\n \t\t\t\tcontinue;\n \t\t\thex = xstrdup(sha1_to_hex(sha1));\n-\t\t\tpath_list_insert(path, rr)->util = hex;\n+\t\t\tstring_list_insert(path, rr)->util = hex;\n \t\t\tif (mkdir(git_path(\"rr-cache/%s\", hex), 0755))\n \t\t\t\tcontinue;;\n \t\t\thandle_file(path, NULL, rr_path(hex, \"preimage\"));\n@@ -308,7 +308,7 @@ static int do_plain_rerere(struct path_list *rr, int fd)\n \tfor (i = 0; i < rr->nr; i++) {\n \t\tstruct stat st;\n \t\tint ret;\n-\t\tconst char *path = rr->items[i].path;\n+\t\tconst char *path = rr->items[i].string;\n \t\tconst char *name = (const char *)rr->items[i].util;\n \n \t\tif (!stat(rr_path(name, \"preimage\"), &st) &&\n@@ -372,7 +372,7 @@ static int is_rerere_enabled(void)\n \treturn 1;\n }\n \n-static int setup_rerere(struct path_list *merge_rr)\n+static int setup_rerere(struct string_list *merge_rr)\n {\n \tint fd;\n \n@@ -388,7 +388,7 @@ static int setup_rerere(struct path_list *merge_rr)\n \n int rerere(void)\n {\n-\tstruct path_list merge_rr = { NULL, 0, 0, 1 };\n+\tstruct string_list merge_rr = { NULL, 0, 0, 1 };\n \tint fd;\n \n \tfd = setup_rerere(&merge_rr);\n@@ -399,7 +399,7 @@ int rerere(void)\n \n int cmd_rerere(int argc, const char **argv, const char *prefix)\n {\n-\tstruct path_list merge_rr = { NULL, 0, 0, 1 };\n+\tstruct string_list merge_rr = { NULL, 0, 0, 1 };\n \tint i, fd;\n \n \tfd = setup_rerere(&merge_rr);\n@@ -422,16 +422,16 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)\n \t\tgarbage_collect(&merge_rr);\n \telse if (!strcmp(argv[1], \"status\"))\n \t\tfor (i = 0; i < merge_rr.nr; i++)\n-\t\t\tprintf(\"%s\\n\", merge_rr.items[i].path);\n+\t\t\tprintf(\"%s\\n\", merge_rr.items[i].string);\n \telse if (!strcmp(argv[1], \"diff\"))\n \t\tfor (i = 0; i < merge_rr.nr; i++) {\n-\t\t\tconst char *path = merge_rr.items[i].path;\n+\t\t\tconst char *path = merge_rr.items[i].string;\n \t\t\tconst char *name = (const char *)merge_rr.items[i].util;\n \t\t\tdiff_two(rr_path(name, \"preimage\"), path, path, path);\n \t\t}\n \telse\n \t\tusage(git_rerere_usage);\n \n-\tpath_list_clear(&merge_rr, 1);\n+\tstring_list_clear(&merge_rr, 1);\n \treturn 0;\n }\ndiff --git a/builtin-shortlog.c b/builtin-shortlog.c\nindex af31aba..fe37515 100644\n--- a/builtin-shortlog.c\n+++ b/builtin-shortlog.c\n@@ -2,7 +2,7 @@\n #include \"cache.h\"\n #include \"commit.h\"\n #include \"diff.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"revision.h\"\n #include \"utf8.h\"\n #include \"mailmap.h\"\n@@ -13,8 +13,8 @@ static const char shortlog_usage[] =\n \n static int compare_by_number(const void *a1, const void *a2)\n {\n-\tconst struct path_list_item *i1 = a1, *i2 = a2;\n-\tconst struct path_list *l1 = i1->util, *l2 = i2->util;\n+\tconst struct string_list_item *i1 = a1, *i2 = a2;\n+\tconst struct string_list *l1 = i1->util, *l2 = i2->util;\n \n \tif (l1->nr < l2->nr)\n \t\treturn 1;\n@@ -30,8 +30,8 @@ static void insert_one_record(struct shortlog *log,\n {\n \tconst char *dot3 = log->common_repo_prefix;\n \tchar *buffer, *p;\n-\tstruct path_list_item *item;\n-\tstruct path_list *onelines;\n+\tstruct string_list_item *item;\n+\tstruct string_list *onelines;\n \tchar namebuf[1024];\n \tsize_t len;\n \tconst char *eol;\n@@ -64,9 +64,9 @@ static void insert_one_record(struct shortlog *log,\n \t}\n \n \tbuffer = xstrdup(namebuf);\n-\titem = path_list_insert(buffer, &log->list);\n+\titem = string_list_insert(buffer, &log->list);\n \tif (item->util == NULL)\n-\t\titem->util = xcalloc(1, sizeof(struct path_list));\n+\t\titem->util = xcalloc(1, sizeof(struct string_list));\n \telse\n \t\tfree(buffer);\n \n@@ -103,11 +103,11 @@ static void insert_one_record(struct shortlog *log,\n \t\tonelines->alloc = alloc_nr(onelines->nr);\n \t\tonelines->items = xrealloc(onelines->items,\n \t\t\t\tonelines->alloc\n-\t\t\t\t* sizeof(struct path_list_item));\n+\t\t\t\t* sizeof(struct string_list_item));\n \t}\n \n \tonelines->items[onelines->nr].util = NULL;\n-\tonelines->items[onelines->nr++].path = buffer;\n+\tonelines->items[onelines->nr++].string = buffer;\n }\n \n static void read_from_stdin(struct shortlog *log)\n@@ -218,7 +218,7 @@ void shortlog_init(struct shortlog *log)\n \n \tread_mailmap(&log->mailmap, \".mailmap\", &log->common_repo_prefix);\n \n-\tlog->list.strdup_paths = 1;\n+\tlog->list.strdup_strings = 1;\n \tlog->wrap = DEFAULT_WRAPLEN;\n \tlog->in1 = DEFAULT_INDENT1;\n \tlog->in2 = DEFAULT_INDENT2;\n@@ -274,17 +274,17 @@ void shortlog_output(struct shortlog *log)\n {\n \tint i, j;\n \tif (log->sort_by_number)\n-\t\tqsort(log->list.items, log->list.nr, sizeof(struct path_list_item),\n+\t\tqsort(log->list.items, log->list.nr, sizeof(struct string_list_item),\n \t\t\tcompare_by_number);\n \tfor (i = 0; i < log->list.nr; i++) {\n-\t\tstruct path_list *onelines = log->list.items[i].util;\n+\t\tstruct string_list *onelines = log->list.items[i].util;\n \n \t\tif (log->summary) {\n-\t\t\tprintf(\"%6d\\t%s\\n\", onelines->nr, log->list.items[i].path);\n+\t\t\tprintf(\"%6d\\t%s\\n\", onelines->nr, log->list.items[i].string);\n \t\t} else {\n-\t\t\tprintf(\"%s (%d):\\n\", log->list.items[i].path, onelines->nr);\n+\t\t\tprintf(\"%s (%d):\\n\", log->list.items[i].string, onelines->nr);\n \t\t\tfor (j = onelines->nr - 1; j >= 0; j--) {\n-\t\t\t\tconst char *msg = onelines->items[j].path;\n+\t\t\t\tconst char *msg = onelines->items[j].string;\n \n \t\t\t\tif (log->wrap_lines) {\n \t\t\t\t\tint col = print_wrapped_text(msg, log->in1, log->in2, log->wrap);\n@@ -297,14 +297,14 @@ void shortlog_output(struct shortlog *log)\n \t\t\tputchar('\\n');\n \t\t}\n \n-\t\tonelines->strdup_paths = 1;\n-\t\tpath_list_clear(onelines, 1);\n+\t\tonelines->strdup_strings = 1;\n+\t\tstring_list_clear(onelines, 1);\n \t\tfree(onelines);\n \t\tlog->list.items[i].util = NULL;\n \t}\n \n-\tlog->list.strdup_paths = 1;\n-\tpath_list_clear(&log->list, 1);\n-\tlog->mailmap.strdup_paths = 1;\n-\tpath_list_clear(&log->mailmap, 1);\n+\tlog->list.strdup_strings = 1;\n+\tstring_list_clear(&log->list, 1);\n+\tlog->mailmap.strdup_strings = 1;\n+\tstring_list_clear(&log->mailmap, 1);\n }\ndiff --git a/builtin-show-ref.c b/builtin-show-ref.c\nindex a323633..add1600 100644\n--- a/builtin-show-ref.c\n+++ b/builtin-show-ref.c\n@@ -3,7 +3,7 @@\n #include \"refs.h\"\n #include \"object.h\"\n #include \"tag.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n \n static const char show_ref_usage[] = \"git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=<length>]] [--abbrev[=<length>]] [--tags] [--heads] [--] [pattern*] < ref-list\";\n \n@@ -98,8 +98,8 @@ match:\n \n static int add_existing(const char *refname, const unsigned char *sha1, int flag, void *cbdata)\n {\n-\tstruct path_list *list = (struct path_list *)cbdata;\n-\tpath_list_insert(refname, list);\n+\tstruct string_list *list = (struct string_list *)cbdata;\n+\tstring_list_insert(refname, list);\n \treturn 0;\n }\n \n@@ -114,7 +114,7 @@ static int add_existing(const char *refname, const unsigned char *sha1, int flag\n  */\n static int exclude_existing(const char *match)\n {\n-\tstatic struct path_list existing_refs = { NULL, 0, 0, 0 };\n+\tstatic struct string_list existing_refs = { NULL, 0, 0, 0 };\n \tchar buf[1024];\n \tint matchlen = match ? strlen(match) : 0;\n \n@@ -143,7 +143,7 @@ static int exclude_existing(const char *match)\n \t\t\tfprintf(stderr, \"warning: ref '%s' ignored\\n\", ref);\n \t\t\tcontinue;\n \t\t}\n-\t\tif (!path_list_has_path(&existing_refs, ref)) {\n+\t\tif (!string_list_has_string(&existing_refs, ref)) {\n \t\t\tprintf(\"%s\\n\", buf);\n \t\t}\n \t}\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 94b150e..42e012f 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -8,14 +8,14 @@\n #include \"diffcore.h\"\n #include \"revision.h\"\n #include \"cache-tree.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"unpack-trees.h\"\n \n /*\n  * diff-files\n  */\n \n-static int read_directory(const char *path, struct path_list *list)\n+static int read_directory(const char *path, struct string_list *list)\n {\n \tDIR *dir;\n \tstruct dirent *e;\n@@ -25,7 +25,7 @@ static int read_directory(const char *path, struct path_list *list)\n \n \twhile ((e = readdir(dir)))\n \t\tif (strcmp(\".\", e->d_name) && strcmp(\"..\", e->d_name))\n-\t\t\tpath_list_insert(e->d_name, list);\n+\t\t\tstring_list_insert(e->d_name, list);\n \n \tclosedir(dir);\n \treturn 0;\n@@ -59,13 +59,13 @@ static int queue_diff(struct diff_options *o,\n \n \tif (S_ISDIR(mode1) || S_ISDIR(mode2)) {\n \t\tchar buffer1[PATH_MAX], buffer2[PATH_MAX];\n-\t\tstruct path_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};\n+\t\tstruct string_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};\n \t\tint len1 = 0, len2 = 0, i1, i2, ret = 0;\n \n \t\tif (name1 && read_directory(name1, &p1))\n \t\t\treturn -1;\n \t\tif (name2 && read_directory(name2, &p2)) {\n-\t\t\tpath_list_clear(&p1, 0);\n+\t\t\tstring_list_clear(&p1, 0);\n \t\t\treturn -1;\n \t\t}\n \n@@ -94,14 +94,14 @@ static int queue_diff(struct diff_options *o,\n \t\t\telse if (i2 == p2.nr)\n \t\t\t\tcomp = -1;\n \t\t\telse\n-\t\t\t\tcomp = strcmp(p1.items[i1].path,\n-\t\t\t\t\tp2.items[i2].path);\n+\t\t\t\tcomp = strcmp(p1.items[i1].string,\n+\t\t\t\t\tp2.items[i2].string);\n \n \t\t\tif (comp > 0)\n \t\t\t\tn1 = NULL;\n \t\t\telse {\n \t\t\t\tn1 = buffer1;\n-\t\t\t\tstrncpy(buffer1 + len1, p1.items[i1++].path,\n+\t\t\t\tstrncpy(buffer1 + len1, p1.items[i1++].string,\n \t\t\t\t\t\tPATH_MAX - len1);\n \t\t\t}\n \n@@ -109,14 +109,14 @@ static int queue_diff(struct diff_options *o,\n \t\t\t\tn2 = NULL;\n \t\t\telse {\n \t\t\t\tn2 = buffer2;\n-\t\t\t\tstrncpy(buffer2 + len2, p2.items[i2++].path,\n+\t\t\t\tstrncpy(buffer2 + len2, p2.items[i2++].string,\n \t\t\t\t\t\tPATH_MAX - len2);\n \t\t\t}\n \n \t\t\tret = queue_diff(o, n1, n2);\n \t\t}\n-\t\tpath_list_clear(&p1, 0);\n-\t\tpath_list_clear(&p2, 0);\n+\t\tstring_list_clear(&p1, 0);\n+\t\tstring_list_clear(&p2, 0);\n \n \t\treturn ret;\n \t} else {\ndiff --git a/mailmap.c b/mailmap.c\nindex f017255..88fc6f3 100644\n--- a/mailmap.c\n+++ b/mailmap.c\n@@ -1,8 +1,8 @@\n #include \"cache.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"mailmap.h\"\n \n-int read_mailmap(struct path_list *map, const char *filename, char **repo_abbrev)\n+int read_mailmap(struct string_list *map, const char *filename, char **repo_abbrev)\n {\n \tchar buffer[1024];\n \tFILE *f = fopen(filename, \"r\");\n@@ -54,16 +54,16 @@ int read_mailmap(struct path_list *map, const char *filename, char **repo_abbrev\n \t\tfor (i = 0; i < right_bracket - left_bracket - 1; i++)\n \t\t\temail[i] = tolower(left_bracket[i + 1]);\n \t\temail[right_bracket - left_bracket - 1] = '\\0';\n-\t\tpath_list_insert(email, map)->util = name;\n+\t\tstring_list_insert(email, map)->util = name;\n \t}\n \tfclose(f);\n \treturn 0;\n }\n \n-int map_email(struct path_list *map, const char *email, char *name, int maxlen)\n+int map_email(struct string_list *map, const char *email, char *name, int maxlen)\n {\n \tchar *p;\n-\tstruct path_list_item *item;\n+\tstruct string_list_item *item;\n \tchar buf[1024], *mailbuf;\n \tint i;\n \n@@ -80,7 +80,7 @@ int map_email(struct path_list *map, const char *email, char *name, int maxlen)\n \tfor (i = 0; i < p - email; i++)\n \t\tmailbuf[i] = tolower(email[i]);\n \tmailbuf[i] = 0;\n-\titem = path_list_lookup(mailbuf, map);\n+\titem = string_list_lookup(mailbuf, map);\n \tif (mailbuf != buf)\n \t\tfree(mailbuf);\n \tif (item != NULL) {\ndiff --git a/mailmap.h b/mailmap.h\nindex 3503fd2..6e48f83 100644\n--- a/mailmap.h\n+++ b/mailmap.h\n@@ -1,7 +1,7 @@\n #ifndef MAILMAP_H\n #define MAILMAP_H\n \n-int read_mailmap(struct path_list *map, const char *filename, char **repo_abbrev);\n-int map_email(struct path_list *mailmap, const char *email, char *name, int maxlen);\n+int read_mailmap(struct string_list *map, const char *filename, char **repo_abbrev);\n+int map_email(struct string_list *mailmap, const char *email, char *name, int maxlen);\n \n #endif\ndiff --git a/path-list.h b/path-list.h\ndeleted file mode 100644\nindex 5931e2c..0000000\n--- a/path-list.h\n+++ /dev/null\n@@ -1,22 +0,0 @@\n-#ifndef PATH_LIST_H\n-#define PATH_LIST_H\n-\n-struct path_list_item {\n-\tchar *path;\n-\tvoid *util;\n-};\n-struct path_list\n-{\n-\tstruct path_list_item *items;\n-\tunsigned int nr, alloc;\n-\tunsigned int strdup_paths:1;\n-};\n-\n-void print_path_list(const char *text, const struct path_list *p);\n-\n-int path_list_has_path(const struct path_list *list, const char *path);\n-void path_list_clear(struct path_list *list, int free_util);\n-struct path_list_item *path_list_insert(const char *path, struct path_list *list);\n-struct path_list_item *path_list_lookup(const char *path, struct path_list *list);\n-\n-#endif /* PATH_LIST_H */\ndiff --git a/reflog-walk.c b/reflog-walk.c\nindex ee1456b..f751fdc 100644\n--- a/reflog-walk.c\n+++ b/reflog-walk.c\n@@ -3,7 +3,7 @@\n #include \"refs.h\"\n #include \"diff.h\"\n #include \"revision.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n #include \"reflog-walk.h\"\n \n struct complete_reflogs {\n@@ -127,7 +127,7 @@ struct commit_reflog {\n \n struct reflog_walk_info {\n \tstruct commit_info_lifo reflogs;\n-\tstruct path_list complete_reflogs;\n+\tstruct string_list complete_reflogs;\n \tstruct commit_reflog *last_commit_reflog;\n };\n \n@@ -141,7 +141,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info,\n {\n \tunsigned long timestamp = 0;\n \tint recno = -1;\n-\tstruct path_list_item *item;\n+\tstruct string_list_item *item;\n \tstruct complete_reflogs *reflogs;\n \tchar *branch, *at = strchr(name, '@');\n \tstruct commit_reflog *commit_reflog;\n@@ -161,7 +161,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info,\n \t} else\n \t\trecno = 0;\n \n-\titem = path_list_lookup(branch, &info->complete_reflogs);\n+\titem = string_list_lookup(branch, &info->complete_reflogs);\n \tif (item)\n \t\treflogs = item->util;\n \telse {\n@@ -189,7 +189,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info,\n \t\t}\n \t\tif (!reflogs || reflogs->nr == 0)\n \t\t\treturn -1;\n-\t\tpath_list_insert(branch, &info->complete_reflogs)->util\n+\t\tstring_list_insert(branch, &info->complete_reflogs)->util\n \t\t\t= reflogs;\n \t}\n \ndiff --git a/shortlog.h b/shortlog.h\nindex 31ff491..46a0991 100644\n--- a/shortlog.h\n+++ b/shortlog.h\n@@ -1,10 +1,10 @@\n #ifndef SHORTLOG_H\n #define SHORTLOG_H\n \n-#include \"path-list.h\"\n+#include \"string-list.h\"\n \n struct shortlog {\n-\tstruct path_list list;\n+\tstruct string_list list;\n \tint summary;\n \tint wrap_lines;\n \tint sort_by_number;\n@@ -14,7 +14,7 @@ struct shortlog {\n \n \tchar *common_repo_prefix;\n \tint email;\n-\tstruct path_list mailmap;\n+\tstruct string_list mailmap;\n };\n \n void shortlog_init(struct shortlog *log);\ndiff --git a/path-list.c b/string-list.c\nsimilarity index 53%\nrename from path-list.c\nrename to string-list.c\nindex 3d83b7b..699e754 100644\n--- a/path-list.c\n+++ b/string-list.c\n@@ -1,16 +1,16 @@\n #include \"cache.h\"\n-#include \"path-list.h\"\n+#include \"string-list.h\"\n \n /* if there is no exact match, point to the index where the entry could be\n  * inserted */\n-static int get_entry_index(const struct path_list *list, const char *path,\n+static int get_entry_index(const struct string_list *list, const char *string,\n \t\tint *exact_match)\n {\n \tint left = -1, right = list->nr;\n \n \twhile (left + 1 < right) {\n \t\tint middle = (left + right) / 2;\n-\t\tint compare = strcmp(path, list->items[middle].path);\n+\t\tint compare = strcmp(string, list->items[middle].string);\n \t\tif (compare < 0)\n \t\t\tright = middle;\n \t\telse if (compare > 0)\n@@ -26,10 +26,10 @@ static int get_entry_index(const struct path_list *list, const char *path,\n }\n \n /* returns -1-index if already exists */\n-static int add_entry(struct path_list *list, const char *path)\n+static int add_entry(struct string_list *list, const char *string)\n {\n \tint exact_match;\n-\tint index = get_entry_index(list, path, &exact_match);\n+\tint index = get_entry_index(list, string, &exact_match);\n \n \tif (exact_match)\n \t\treturn -1 - index;\n@@ -37,23 +37,23 @@ static int add_entry(struct path_list *list, const char *path)\n \tif (list->nr + 1 >= list->alloc) {\n \t\tlist->alloc += 32;\n \t\tlist->items = xrealloc(list->items, list->alloc\n-\t\t\t\t* sizeof(struct path_list_item));\n+\t\t\t\t* sizeof(struct string_list_item));\n \t}\n \tif (index < list->nr)\n \t\tmemmove(list->items + index + 1, list->items + index,\n \t\t\t\t(list->nr - index)\n-\t\t\t\t* sizeof(struct path_list_item));\n-\tlist->items[index].path = list->strdup_paths ?\n-\t\txstrdup(path) : (char *)path;\n+\t\t\t\t* sizeof(struct string_list_item));\n+\tlist->items[index].string = list->strdup_strings ?\n+\t\txstrdup(string) : (char *)string;\n \tlist->items[index].util = NULL;\n \tlist->nr++;\n \n \treturn index;\n }\n \n-struct path_list_item *path_list_insert(const char *path, struct path_list *list)\n+struct string_list_item *string_list_insert(const char *string, struct string_list *list)\n {\n-\tint index = add_entry(list, path);\n+\tint index = add_entry(list, string);\n \n \tif (index < 0)\n \t\tindex = -1 - index;\n@@ -61,28 +61,28 @@ struct path_list_item *path_list_insert(const char *path, struct path_list *list\n \treturn list->items + index;\n }\n \n-int path_list_has_path(const struct path_list *list, const char *path)\n+int string_list_has_string(const struct string_list *list, const char *string)\n {\n \tint exact_match;\n-\tget_entry_index(list, path, &exact_match);\n+\tget_entry_index(list, string, &exact_match);\n \treturn exact_match;\n }\n \n-struct path_list_item *path_list_lookup(const char *path, struct path_list *list)\n+struct string_list_item *string_list_lookup(const char *string, struct string_list *list)\n {\n-\tint exact_match, i = get_entry_index(list, path, &exact_match);\n+\tint exact_match, i = get_entry_index(list, string, &exact_match);\n \tif (!exact_match)\n \t\treturn NULL;\n \treturn list->items + i;\n }\n \n-void path_list_clear(struct path_list *list, int free_util)\n+void string_list_clear(struct string_list *list, int free_util)\n {\n \tif (list->items) {\n \t\tint i;\n-\t\tif (list->strdup_paths) {\n+\t\tif (list->strdup_strings) {\n \t\t\tfor (i = 0; i < list->nr; i++)\n-\t\t\t\tfree(list->items[i].path);\n+\t\t\t\tfree(list->items[i].string);\n \t\t}\n \t\tif (free_util) {\n \t\t\tfor (i = 0; i < list->nr; i++)\n@@ -94,11 +94,12 @@ void path_list_clear(struct path_list *list, int free_util)\n \tlist->nr = list->alloc = 0;\n }\n \n-void print_path_list(const char *text, const struct path_list *p)\n+void print_string_list(const char *text, const struct string_list *p)\n {\n \tint i;\n \tif ( text )\n \t\tprintf(\"%s\\n\", text);\n \tfor (i = 0; i < p->nr; i++)\n-\t\tprintf(\"%s:%p\\n\", p->items[i].path, p->items[i].util);\n+\t\tprintf(\"%s:%p\\n\", p->items[i].string, p->items[i].util);\n }\n+\ndiff --git a/string-list.h b/string-list.h\nnew file mode 100644\nindex 0000000..6195791\n--- /dev/null\n+++ b/string-list.h\n@@ -0,0 +1,22 @@\n+#ifndef PATH_LIST_H\n+#define PATH_LIST_H\n+\n+struct string_list_item {\n+\tchar *string;\n+\tvoid *util;\n+};\n+struct string_list\n+{\n+\tstruct string_list_item *items;\n+\tunsigned int nr, alloc;\n+\tunsigned int strdup_strings:1;\n+};\n+\n+void print_string_list(const char *text, const struct string_list *p);\n+\n+int string_list_has_string(const struct string_list *list, const char *string);\n+void string_list_clear(struct string_list *list, int free_util);\n+struct string_list_item *string_list_insert(const char *string, struct string_list *list);\n+struct string_list_item *string_list_lookup(const char *string, struct string_list *list);\n+\n+#endif /* PATH_LIST_H */\n-- \n1.5.4.3.446.gbe8932\n\n\n"},{"id":"70523","messageId":"alpine.LSU.1.00.0803011315400.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803011313020.22527@racer.site","subject":"[PATCH 2/6] string-list: add functions to work with unsorted lists","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-01T13:15:47Z","receivedAt":"2008-03-01T13:15:47Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nUp to now, string-lists were sorted at all times.  But sometimes it\nis much more convenient to build the list and sort it at the end,\nor sort it not at all.\n\nAdd string_list_append() and sort_string_list() to allow that.\n\nAlso, add the unsorted_string_list_has_string() function, to do a\nlinear search.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Documentation/CodingGuidelines |    5 +++--\n string-list.c                  |   29 +++++++++++++++++++++++++++++\n string-list.h                  |    8 +++++++-\n 3 files changed, 39 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines\nindex fe7c74b..7507053 100644\n--- a/Documentation/CodingGuidelines\n+++ b/Documentation/CodingGuidelines\n@@ -91,8 +91,9 @@ For C programs:\n \n  - Use the API.  No, really.  We have a strbuf (variable length\n    string), several arrays with the ALLOC_GROW() macro, a\n-   string_list for sorted string lists, a hash map (mapping struct\n-   objects) named \"struct decorate\", amongst other things.\n+   string_list for sorted and unsorted string lists, a hash map\n+   (mapping struct objects) named \"struct decorate\", amongst other\n+   things.\n \n  - When you come up with an API, document it.\n \ndiff --git a/string-list.c b/string-list.c\nindex 699e754..ddd83c8 100644\n--- a/string-list.c\n+++ b/string-list.c\n@@ -103,3 +103,32 @@ void print_string_list(const char *text, const struct string_list *p)\n \t\tprintf(\"%s:%p\\n\", p->items[i].string, p->items[i].util);\n }\n \n+struct string_list_item *string_list_append(const char *string, struct string_list *list)\n+{\n+\tALLOC_GROW(list->items, list->nr + 1, list->alloc);\n+\tlist->items[list->nr].string =\n+\t\tlist->strdup_strings ? xstrdup(string) : (char *)string;\n+\treturn list->items + list->nr++;\n+}\n+\n+static int cmp_items(const void *a, const void *b)\n+{\n+\tconst struct string_list_item *one = a;\n+\tconst struct string_list_item *two = b;\n+\treturn strcmp(one->string, two->string);\n+}\n+\n+void sort_string_list(struct string_list *list)\n+{\n+\tqsort(list->items, list->nr, sizeof(*list->items), cmp_items);\n+}\n+\n+int unsorted_string_list_has_string(struct string_list *list, const char *string)\n+{\n+\tint i;\n+\tfor (i = 0; i < list->nr; i++)\n+\t\tif (!strcmp(string, list->items[i].string))\n+\t\t\treturn 1;\n+\treturn 0;\n+}\n+\ndiff --git a/string-list.h b/string-list.h\nindex 6195791..4d6a705 100644\n--- a/string-list.h\n+++ b/string-list.h\n@@ -13,10 +13,16 @@ struct string_list\n };\n \n void print_string_list(const char *text, const struct string_list *p);\n+void string_list_clear(struct string_list *list, int free_util);\n \n+/* Use these functions only on sorted lists: */\n int string_list_has_string(const struct string_list *list, const char *string);\n-void string_list_clear(struct string_list *list, int free_util);\n struct string_list_item *string_list_insert(const char *string, struct string_list *list);\n struct string_list_item *string_list_lookup(const char *string, struct string_list *list);\n \n+/* Use these functions only on unsorted lists: */\n+struct string_list_item *string_list_append(const char *string, struct string_list *list);\n+void sort_string_list(struct string_list *list);\n+int unsorted_string_list_has_string(struct string_list *list, const char *string);\n+\n #endif /* PATH_LIST_H */\n-- \n1.5.4.3.446.gbe8932\n\n\n"},{"id":"70524","messageId":"alpine.LSU.1.00.0803011315540.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803011313020.22527@racer.site","subject":"[PATCH 3/6] parseopt: add flag to stop on first non option","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-01T13:16:02Z","receivedAt":"2008-03-01T13:16:02Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n parse-options.c |    2 ++\n parse-options.h |    1 +\n 2 files changed, 3 insertions(+), 0 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex d9562ba..be35785 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -249,6 +249,8 @@ int parse_options(int argc, const char **argv, const struct option *options,\n \t\tconst char *arg = args.argv[0];\n \n \t\tif (*arg != '-' || !arg[1]) {\n+\t\t\tif (flags & PARSE_OPT_STOP_AT_NON_OPTION)\n+\t\t\t\tbreak;\n \t\t\targv[j++] = args.argv[0];\n \t\t\tcontinue;\n \t\t}\ndiff --git a/parse-options.h b/parse-options.h\nindex 102ac31..0d40cd2 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -18,6 +18,7 @@ enum parse_opt_type {\n \n enum parse_opt_flags {\n \tPARSE_OPT_KEEP_DASHDASH = 1,\n+\tPARSE_OPT_STOP_AT_NON_OPTION = 2,\n };\n \n enum parse_opt_option_flags {\n-- \n1.5.4.3.446.gbe8932\n\n\n"},{"id":"70525","messageId":"alpine.LSU.1.00.0803011316160.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803011313020.22527@racer.site","subject":"[PATCH 4/6] Test \"git remote show\" and \"git remote prune\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-01T13:16:29Z","receivedAt":"2008-03-01T13:16:29Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nWhile at it, also fix a few instances where a cd was done outside of a\nsubshell.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n t/t5505-remote.sh |   34 ++++++++++++++++++++++++++++++++++\n 1 files changed, 34 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex 4fc62f5..e1e0a18 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -94,4 +94,38 @@ test_expect_success 'remove remote' '\n )\n '\n \n+cat > test/expect << EOF\n+* remote origin\n+  URL: $(pwd)/one/.git\n+  Remote branch(es) merged with 'git pull' while on branch master\n+    master\n+  New remote branches (next fetch will store in remotes/origin)\n+    master\n+  Tracked remote branches\n+    side master\n+EOF\n+\n+test_expect_success 'show' '\n+\t(cd test &&\n+\t git config --add remote.origin.fetch \\\n+\t\trefs/heads/master:refs/heads/upstream &&\n+\t git fetch &&\n+\t git branch -d -r origin/master &&\n+\t (cd ../one &&\n+\t  echo 1 > file &&\n+\t  git commit -m update file) &&\n+\t git remote show origin > output &&\n+\t git diff expect output)\n+'\n+\n+test_expect_success 'prune' '\n+\t(cd one &&\n+\t git branch -m side side2) &&\n+\t(cd test &&\n+\t git fetch origin &&\n+\t git remote prune origin &&\n+\t git rev-parse refs/remotes/origin/side2 &&\n+\t ! git rev-parse refs/remotes/origin/side)\n+'\n+\n test_done\n-- \n1.5.4.3.446.gbe8932\n\n\n"},{"id":"70526","messageId":"alpine.LSU.1.00.0803011316360.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803011313020.22527@racer.site","subject":"[PATCH 5/6] Make git-remote a builtin","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-01T13:16:46Z","receivedAt":"2008-03-01T13:16:46Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis includes the fix to guard remote->url accesses by checking\nremote->url_nr, as suggested by Johannes Sixt.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Makefile                                           |    3 +-\n builtin-remote.c                                   |  547 ++++++++++++++++++++\n builtin.h                                          |    1 +\n .../examples/git-remote.perl                       |    0 \n git.c                                              |    1 +\n remote.c                                           |    3 +-\n remote.h                                           |    1 +\n t/t5505-remote.sh                                  |    4 +-\n 8 files changed, 556 insertions(+), 4 deletions(-)\n create mode 100644 builtin-remote.c\n rename git-remote.perl => contrib/examples/git-remote.perl (100%)\n\ndiff --git a/Makefile b/Makefile\nindex ad214d3..8847bbe 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -243,7 +243,7 @@ SCRIPT_SH = \\\n SCRIPT_PERL = \\\n \tgit-add--interactive.perl \\\n \tgit-archimport.perl git-cvsimport.perl git-relink.perl \\\n-\tgit-cvsserver.perl git-remote.perl git-cvsexportcommit.perl \\\n+\tgit-cvsserver.perl git-cvsexportcommit.perl \\\n \tgit-send-email.perl git-svn.perl\n \n SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \\\n@@ -380,6 +380,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-push.o \\\n \tbuiltin-read-tree.o \\\n \tbuiltin-reflog.o \\\n+\tbuiltin-remote.o \\\n \tbuiltin-send-pack.o \\\n \tbuiltin-config.o \\\n \tbuiltin-rerere.o \\\ndiff --git a/builtin-remote.c b/builtin-remote.c\nnew file mode 100644\nindex 0000000..2c10df3\n--- /dev/null\n+++ b/builtin-remote.c\n@@ -0,0 +1,547 @@\n+#include \"cache.h\"\n+#include \"parse-options.h\"\n+#include \"transport.h\"\n+#include \"remote.h\"\n+#include \"string-list.h\"\n+#include \"strbuf.h\"\n+#include \"run-command.h\"\n+#include \"refs.h\"\n+\n+static const char * const builtin_remote_usage[] = {\n+\t\"git remote\",\n+        \"git remote add <name> <url>\",\n+        \"git remote rm <name>\",\n+        \"git remote show <name>\",\n+        \"git remote prune <name>\",\n+        \"git remote update [group]\",\n+\tNULL\n+};\n+\n+static int verbose;\n+\n+static inline int postfixcmp(const char *string, const char *postfix)\n+{\n+\tint len1 = strlen(string), len2 = strlen(postfix);\n+\tif (len1 < len2)\n+\t\treturn 1;\n+\treturn strcmp(string + len1 - len2, postfix);\n+}\n+\n+static inline const char *skip_prefix(const char *name, const char *prefix)\n+{\n+\treturn !name ? \"\" :\n+\t\tprefixcmp(name, prefix) ?  name : name + strlen(prefix);\n+}\n+\n+static int opt_parse_track(const struct option *opt, const char *arg, int not)\n+{\n+\tstruct string_list *list = opt->value;\n+\tif (not)\n+\t\tstring_list_clear(list, 0);\n+\telse\n+\t\tstring_list_append(arg, list);\n+\treturn 0;\n+}\n+\n+static int fetch_remote(const char *name)\n+{\n+\tconst char *argv[] = { \"fetch\", name, NULL };\n+\tif (run_command_v_opt(argv, RUN_GIT_CMD))\n+\t\treturn error (\"Could not fetch %s\", name);\n+\treturn 0;\n+}\n+\n+static int add(int argc, const char **argv)\n+{\n+\tint fetch = 0, mirror = 0;\n+\tstruct string_list track = { NULL, 0, 0 };\n+\tconst char *master = NULL;\n+\tstruct remote *remote;\n+\tstruct strbuf buf, buf2;\n+\tconst char *name, *url;\n+\tint i;\n+\n+\tstruct option options[] = {\n+\t\tOPT_GROUP(\"add specific options\"),\n+\t\tOPT_BOOLEAN('f', \"fetch\", &fetch, \"fetch the remote branches\"),\n+\t\tOPT_CALLBACK('t', \"track\", &track, \"branch\",\n+\t\t\t\"branch(es) to track\", opt_parse_track),\n+\t\tOPT_STRING('m', \"master\", &master, \"branch\", \"master branch\"),\n+\t\tOPT_BOOLEAN(0, \"mirror\", &mirror, \"no separate remotes\"),\n+\t\tOPT_END()\n+\t};\n+\n+\targc = parse_options(argc, argv, options, builtin_remote_usage, 0);\n+\n+\tif (argc < 2)\n+\t\tusage_with_options(builtin_remote_usage, options);\n+\n+\tname = argv[0];\n+\turl = argv[1];\n+\n+\tremote = remote_get(name);\n+\tif (remote && (remote->url_nr > 1 || strcmp(name, remote->url[0]) ||\n+\t\t\tremote->fetch_refspec_nr))\n+\t\tdie (\"remote %s already exists.\", name);\n+\n+\tstrbuf_init(&buf, 0);\n+\tstrbuf_init(&buf2, 0);\n+\n+\tstrbuf_addf(&buf, \"remote.%s.url\", name);\n+\tif (git_config_set(buf.buf, url))\n+\t\treturn 1;\n+\n+\tif (track.nr == 0)\n+\t\tstring_list_append(\"*\", &track);\n+\tfor (i = 0; i < track.nr; i++) {\n+\t\tstruct string_list_item *item = track.items + i;\n+\n+\t\tstrbuf_reset(&buf);\n+\t\tstrbuf_addf(&buf, \"remote.%s.fetch\", name);\n+\n+\t\tstrbuf_reset(&buf2);\n+\t\tif (mirror)\n+\t\t\tstrbuf_addf(&buf2, \"refs/%s:refs/%s\",\n+\t\t\t\t\titem->string, item->string);\n+\t\telse\n+\t\t\tstrbuf_addf(&buf2, \"refs/heads/%s:refs/remotes/%s/%s\",\n+\t\t\t\t\titem->string, name, item->string);\n+\t\tif (git_config_set_multivar(buf.buf, buf2.buf, \"^$\", 0))\n+\t\t\treturn 1;\n+\t}\n+\n+\tif (fetch && fetch_remote(name))\n+\t\treturn 1;\n+\n+\tif (master) {\n+\t\tstrbuf_reset(&buf);\n+\t\tstrbuf_addf(&buf, \"refs/remotes/%s/HEAD\", name);\n+\n+\t\tstrbuf_reset(&buf2);\n+\t\tstrbuf_addf(&buf2, \"refs/remotes/%s/%s\", name, master);\n+\n+\t\tif (create_symref(buf.buf, buf2.buf, \"remote add\"))\n+\t\t\treturn error (\"Could not setup master '%s'\", master);\n+\t}\n+\n+\tstrbuf_release(&buf);\n+\tstrbuf_release(&buf2);\n+\tstring_list_clear(&track, 0);\n+\n+\treturn 0;\n+}\n+\n+struct branch_info {\n+\tchar *remote;\n+\tstruct string_list merge;\n+};\n+\n+static struct string_list branch_list;\n+\n+static int config_read_branches(const char *key, const char *value)\n+{\n+\tif (!prefixcmp(key, \"branch.\")) {\n+\t\tchar *name;\n+\t\tstruct string_list_item *item;\n+\t\tstruct branch_info *info;\n+\t\tenum { REMOTE, MERGE } type;\n+\n+\t\tkey += 7;\n+\t\tif (!postfixcmp(key, \".remote\")) {\n+\t\t\tname = xstrndup(key, strlen(key) - 7);\n+\t\t\ttype = REMOTE;\n+\t\t} else if (!postfixcmp(key, \".merge\")) {\n+\t\t\tname = xstrndup(key, strlen(key) - 6);\n+\t\t\ttype = MERGE;\n+\t\t} else\n+\t\t\treturn 0;\n+\n+\t\titem = string_list_insert(name, &branch_list);\n+\n+\t\tif (!item->util)\n+\t\t\titem->util = xcalloc(sizeof(struct branch_info), 1);\n+\t\tinfo = item->util;\n+\t\tif (type == REMOTE) {\n+\t\t\tif (info->remote)\n+\t\t\t\twarning (\"more than one branch.%s\", key);\n+\t\t\tinfo->remote = xstrdup(value);\n+\t\t} else {\n+\t\t\tchar *space = strchr(value, ' ');\n+\t\t\tvalue = skip_prefix(value, \"refs/heads/\");\n+\t\t\twhile (space) {\n+\t\t\t\tchar *merge;\n+\t\t\t\tmerge = xstrndup(value, space - value);\n+\t\t\t\tstring_list_append(merge, &info->merge);\n+\t\t\t\tvalue = skip_prefix(space + 1, \"refs/heads/\");\n+\t\t\t\tspace = strchr(value, ' ');\n+\t\t\t}\n+\t\t\tstring_list_append(xstrdup(value), &info->merge);\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static void read_branches()\n+{\n+\tif (branch_list.nr)\n+\t\treturn;\n+\tgit_config(config_read_branches);\n+\tsort_string_list(&branch_list);\n+}\n+\n+struct ref_states {\n+\tstruct remote *remote;\n+\tstruct strbuf remote_prefix;\n+\tstruct string_list new, stale, tracked;\n+};\n+\n+static int handle_one_branch(const char *refname,\n+\tconst unsigned char *sha1, int flags, void *cb_data)\n+{\n+\tstruct ref_states *states = cb_data;\n+\tstruct refspec refspec;\n+\n+\tmemset(&refspec, 0, sizeof(refspec));\n+\trefspec.dst = (char *)refname;\n+\tif (!remote_find_tracking(states->remote, &refspec)) {\n+\t\tstruct string_list_item *item;\n+\t\tconst char *name = skip_prefix(refspec.src, \"refs/heads/\");\n+\t\tif (unsorted_string_list_has_string(&states->tracked, name) ||\n+\t\t\t\tunsorted_string_list_has_string(&states->new,\n+\t\t\t\t\tname))\n+\t\t\treturn 0;\n+\t\titem = string_list_append(name, &states->stale);\n+\t\titem->util = xstrdup(refname);\n+\t}\n+\treturn 0;\n+}\n+\n+static int get_ref_states(const struct ref *ref, struct ref_states *states)\n+{\n+\tstruct ref *fetch_map = NULL, **tail = &fetch_map;\n+\tint i;\n+\n+\tfor (i = 0; i < states->remote->fetch_refspec_nr; i++)\n+\t\tif (get_fetch_map(ref, states->remote->fetch +i, &tail, 1))\n+\t\t\tdie (\"Could not get fetch map for refspec %s\",\n+\t\t\t\tstates->remote->fetch_refspec[i]);\n+\n+\tstates->new.strdup_strings = states->tracked.strdup_strings = 1;\n+\tfor (ref = fetch_map; ref; ref = ref->next) {\n+\t\tstruct string_list *target = &states->tracked;\n+\t\tunsigned char sha1[20];\n+\t\tvoid *util = NULL;\n+\n+\t\tif (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1))\n+\t\t\ttarget = &states->new;\n+\t\telse {\n+\t\t\ttarget = &states->tracked;\n+\t\t\tif (hashcmp(sha1, ref->new_sha1))\n+\t\t\t\tutil = &states;\n+\t\t}\n+\t\tstring_list_append(skip_prefix(ref->name, \"refs/heads/\"),\n+\t\t\t\ttarget)->util = util;\n+\t}\n+\tfree_refs(fetch_map);\n+\n+\tstrbuf_addf(&states->remote_prefix,\n+\t\t\"refs/remotes/%s/\", states->remote->name);\n+\tfor_each_ref(handle_one_branch, states);\n+\tsort_string_list(&states->stale);\n+\n+\treturn 0;\n+}\n+\n+struct branches_for_remote {\n+\tconst char *prefix;\n+\tstruct string_list *branches;\n+};\n+\n+static int add_branch_for_removal(const char *refname,\n+\tconst unsigned char *sha1, int flags, void *cb_data)\n+{\n+\tstruct branches_for_remote *branches = cb_data;\n+\n+\tif (!prefixcmp(refname, branches->prefix)) {\n+\t\tstruct string_list_item *item;\n+\t\titem = string_list_append(refname, branches->branches);\n+\t\titem->util = xmalloc(20);\n+\t\thashcpy(item->util, sha1);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int remove_branches(struct string_list *branches)\n+{\n+\tint i, result = 0;\n+\tfor (i = 0; i < branches->nr; i++) {\n+\t\tstruct string_list_item *item = branches->items + i;\n+\t\tconst char *refname = item->string;\n+\t\tunsigned char *sha1 = item->util;\n+\n+\t\tif (delete_ref(refname, sha1))\n+\t\t\tresult |= error(\"Could not remove branch %s\", refname);\n+\t}\n+\treturn result;\n+}\n+\n+static int rm(int argc, const char **argv)\n+{\n+\tstruct option options[] = {\n+\t\tOPT_END()\n+\t};\n+\tstruct remote *remote;\n+\tstruct strbuf buf;\n+\tstruct string_list branches = { NULL, 0, 0, 1 };\n+\tstruct branches_for_remote cb_data = { NULL, &branches };\n+\tint i;\n+\n+\tif (argc != 2)\n+\t\tusage_with_options(builtin_remote_usage, options);\n+\n+\tremote = remote_get(argv[1]);\n+\tif (!remote)\n+\t\tdie (\"No such remote: %s\", argv[1]);\n+\n+\tstrbuf_init(&buf, 0);\n+\tstrbuf_addf(&buf, \"remote.%s\", remote->name);\n+\tif (git_config_rename_section(buf.buf, NULL) < 1)\n+\t\treturn error(\"Could not remove config section '%s'\", buf.buf);\n+\n+\tread_branches();\n+\tfor (i = 0; i < branch_list.nr; i++) {\n+\t\tstruct string_list_item *item = branch_list.items +i;\n+\t\tstruct branch_info *info = item->util;\n+\t\tif (info->remote && !strcmp(info->remote, remote->name)) {\n+\t\t\tconst char *keys[] = { \"remote\", \"merge\", NULL }, **k;\n+\t\t\tfor (k = keys; *k; k++) {\n+\t\t\t\tstrbuf_reset(&buf);\n+\t\t\t\tstrbuf_addf(&buf, \"branch.%s.%s\",\n+\t\t\t\t\t\titem->string, *k);\n+\t\t\t\tif (git_config_set(buf.buf, NULL)) {\n+\t\t\t\t\tstrbuf_release(&buf);\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * We cannot just pass a function to for_each_ref() which deletes\n+\t * the branches one by one, since for_each_ref() relies on cached\n+\t * refs, which are invalidated when deleting a branch.\n+\t */\n+\tstrbuf_reset(&buf);\n+\tstrbuf_addf(&buf, \"refs/remotes/%s/\", remote->name);\n+\tcb_data.prefix = buf.buf;\n+\ti = for_each_ref(add_branch_for_removal, &cb_data);\n+\tstrbuf_release(&buf);\n+\n+\tif (!i)\n+\t\ti = remove_branches(&branches);\n+\tstring_list_clear(&branches, 1);\n+\n+\treturn i;\n+}\n+\n+static void show_list(const char *title, struct string_list *list)\n+{\n+\tint i;\n+\n+\tif (!list->nr)\n+\t\treturn;\n+\n+\tprintf(title, list->nr > 1 ? \"es\" : \"\");\n+\tprintf(\"\\n    \");\n+\tfor (i = 0; i < list->nr; i++)\n+\t\tprintf(\"%s%s\", i ? \" \" : \"\", list->items[i].string);\n+\tprintf(\"\\n\");\n+}\n+\n+static int show_or_prune(int argc, const char **argv, int prune)\n+{\n+\tint dry_run = 0, result = 0;\n+\tstruct option options[] = {\n+\t\tOPT_GROUP(\"show specific options\"),\n+\t\tOPT__DRY_RUN(&dry_run),\n+\t\tOPT_END()\n+\t};\n+\tstruct ref_states states;\n+\n+\targc = parse_options(argc, argv, options, builtin_remote_usage, 0);\n+\n+\tif (argc < 1)\n+\t\tusage_with_options(builtin_remote_usage, options);\n+\n+\tmemset(&states, 0, sizeof(states));\n+\tfor (; argc; argc--, argv++) {\n+\t\tstruct transport *transport;\n+\t\tconst struct ref *ref;\n+\t\tstruct strbuf buf;\n+\t\tint i, got_states;\n+\n+\t\tstates.remote = remote_get(*argv);\n+\t\tif (!states.remote)\n+\t\t\treturn error(\"No such remote: %s\", *argv);\n+\t\ttransport = transport_get(NULL, states.remote->url_nr > 0 ?\n+\t\t\tstates.remote->url[0] : NULL);\n+\t\tref = transport_get_remote_refs(transport);\n+\n+\t\tread_branches();\n+\t\tgot_states = get_ref_states(ref, &states);\n+\t\tif (got_states)\n+\t\t\tresult = error(\"Error getting local info for '%s'\",\n+\t\t\t\t\tstates.remote->name);\n+\n+\t\tif (prune) {\n+\t\t\tstruct strbuf buf;\n+\n+\t\t\tstrbuf_init(&buf, 0);\n+\t\t\tfor (i = 0; i < states.stale.nr; i++) {\n+\t\t\t\tstrbuf_reset(&buf);\n+\t\t\t\tstrbuf_addf(&buf, \"refs/remotes/%s/%s\", *argv,\n+\t\t\t\t\t\tstates.stale.items[i].string);\n+\t\t\t\tresult |= delete_ref(buf.buf, NULL);\n+\t\t\t}\n+\n+\t\t\tstrbuf_release(&buf);\n+\t\t\tgoto cleanup_states;\n+\t\t}\n+\n+\t\tprintf(\"* remote %s\\n  URL: %s\\n\", *argv,\n+\t\t\tstates.remote->url_nr > 0 ?\n+\t\t\t\tstates.remote->url[0] : \"(no URL)\");\n+\n+\t\tfor (i = 0; i < branch_list.nr; i++) {\n+\t\t\tstruct string_list_item *branch = branch_list.items + i;\n+\t\t\tstruct branch_info *info = branch->util;\n+\t\t\tint j;\n+\n+\t\t\tif (!info->merge.nr || strcmp(*argv, info->remote))\n+\t\t\t\tcontinue;\n+\t\t\tprintf(\"  Remote branch%s merged with 'git pull' \"\n+\t\t\t\t\"while on branch %s\\n   \",\n+\t\t\t\tinfo->merge.nr > 1 ? \"es\" : \"\",\n+\t\t\t\tbranch->string);\n+\t\t\tfor (j = 0; j < info->merge.nr; j++)\n+\t\t\t\tprintf(\" %s\", info->merge.items[j].string);\n+\t\t\tprintf(\"\\n\");\n+\t\t}\n+\n+\t\tif (got_states)\n+\t\t\tcontinue;\n+\t\tstrbuf_init(&buf, 0);\n+\t\tstrbuf_addf(&buf, \"  New remote branch%%s (next fetch will \"\n+\t\t\t\"store in remotes/%s)\", states.remote->name);\n+\t\tshow_list(buf.buf, &states.new);\n+\t\tstrbuf_release(&buf);\n+\t\tshow_list(\"  Stale tracking branch%s (use 'git remote prune')\",\n+\t\t\t\t&states.stale);\n+\t\tshow_list(\"  Tracked remote branch%s\",\n+\t\t\t\t&states.tracked);\n+\n+\t\tif (states.remote->push_refspec_nr) {\n+\t\t\tprintf(\"  Local branch%s pushed with 'git push'\\n   \",\n+\t\t\t\tstates.remote->push_refspec_nr > 1 ?\n+\t\t\t\t\t\"es\" : \"\");\n+\t\t\tfor (i = 0; i < states.remote->push_refspec_nr; i++) {\n+\t\t\t\tstruct refspec *spec = states.remote->push + i;\n+\t\t\t\tprintf(\" %s%s%s%s\", spec->force ? \"+\" : \"\",\n+\t\t\t\t\tskip_prefix(spec->src, \"refs/heads/\"),\n+\t\t\t\t\tspec->dst ? \":\" : \"\",\n+\t\t\t\t\tskip_prefix(spec->dst, \"refs/heads/\"));\n+\t\t\t}\n+\t\t}\n+cleanup_states:\n+\t\t/* NEEDSWORK: free remote */\n+\t\tstring_list_clear(&states.new, 0);\n+\t\tstring_list_clear(&states.stale, 0);\n+\t\tstring_list_clear(&states.tracked, 0);\n+\t}\n+\n+\treturn result;\n+}\n+\n+static int update_one(struct remote *remote, void *priv)\n+{\n+\tif (!remote->skip_default_update)\n+\t\treturn fetch_remote(remote->name);\n+\treturn 0;\n+}\n+\n+static int update(int argc, const char **argv)\n+{\n+\tint i;\n+\n+\tif (argc < 2)\n+\t\treturn for_each_remote(update_one, NULL);\n+\n+\tfor (i = 1; i < argc; i++)\n+\t\tif (fetch_remote(argv[i]))\n+\t\t\treturn 1;\n+\treturn 0;\n+}\n+\n+static int get_one_entry(struct remote *remote, void *priv)\n+{\n+\tstruct string_list *list = priv;\n+\n+\tstring_list_append(remote->name, list)->util = remote->url_nr ?\n+\t\t(void *)remote->url[0] : NULL;\n+\tif (remote->url_nr > 1)\n+\t\twarning (\"Remote %s has more than one URL\", remote->name);\n+\n+\treturn 0;\n+}\n+\n+static int show_all()\n+{\n+\tstruct string_list list = { NULL, 0, 0 };\n+\tint result = for_each_remote(get_one_entry, &list);\n+\n+\tif (!result) {\n+\t\tint i;\n+\n+\t\tsort_string_list(&list);\n+\t\tfor (i = 0; i < list.nr; i++) {\n+\t\t\tstruct string_list_item *item = list.items + i;\n+\t\t\tprintf(\"%s%s%s\\n\", item->string,\n+\t\t\t\tverbose ? \"\\t\" : \"\",\n+\t\t\t\tverbose && item->util ?\n+\t\t\t\t\t(const char *)item->util : \"\");\n+\t\t}\n+\t}\n+\treturn result;\n+}\n+\n+int cmd_remote(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct option options[] = {\n+\t\tOPT__VERBOSE(&verbose),\n+\t\tOPT_END()\n+\t};\n+\tint result;\n+\n+\targc = parse_options(argc, argv, options, builtin_remote_usage,\n+\t\tPARSE_OPT_STOP_AT_NON_OPTION);\n+\n+\tif (argc < 1)\n+\t\tresult = show_all();\n+\telse if (!strcmp(argv[0], \"add\"))\n+\t\tresult = add(argc, argv);\n+\telse if (!strcmp(argv[0], \"rm\"))\n+\t\tresult = rm(argc, argv);\n+\telse if (!strcmp(argv[0], \"show\"))\n+\t\tresult = show_or_prune(argc, argv, 0);\n+\telse if (!strcmp(argv[0], \"prune\"))\n+\t\tresult = show_or_prune(argc, argv, 1);\n+\telse if (!strcmp(argv[0], \"update\"))\n+\t\tresult = update(argc, argv);\n+\telse {\n+\t\terror (\"Unknown subcommand: %s\", argv[0]);\n+\t\tusage_with_options(builtin_remote_usage, options);\n+\t}\n+\n+\treturn result ? 1 : 0;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex 674c8a1..95126fd 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -67,6 +67,7 @@ extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);\n extern int cmd_push(int argc, const char **argv, const char *prefix);\n extern int cmd_read_tree(int argc, const char **argv, const char *prefix);\n extern int cmd_reflog(int argc, const char **argv, const char *prefix);\n+extern int cmd_remote(int argc, const char **argv, const char *prefix);\n extern int cmd_config(int argc, const char **argv, const char *prefix);\n extern int cmd_rerere(int argc, const char **argv, const char *prefix);\n extern int cmd_reset(int argc, const char **argv, const char *prefix);\ndiff --git a/git-remote.perl b/contrib/examples/git-remote.perl\nsimilarity index 100%\nrename from git-remote.perl\nrename to contrib/examples/git-remote.perl\ndiff --git a/git.c b/git.c\nindex 9cca81a..1e3eb10 100644\n--- a/git.c\n+++ b/git.c\n@@ -334,6 +334,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"push\", cmd_push, RUN_SETUP },\n \t\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n \t\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n+\t\t{ \"remote\", cmd_remote, RUN_SETUP },\n \t\t{ \"repo-config\", cmd_config },\n \t\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n \t\t{ \"reset\", cmd_reset, RUN_SETUP },\ndiff --git a/remote.c b/remote.c\nindex 7e19372..f3f7375 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -357,7 +357,8 @@ static int handle_config(const char *key, const char *value)\n \t\t\tremote->fetch_tags = -1;\n \t} else if (!strcmp(subkey, \".proxy\")) {\n \t\tremote->http_proxy = xstrdup(value);\n-\t}\n+\t} else if (!strcmp(subkey, \".skipdefaultupdate\"))\n+\t\tremote->skip_default_update = 1;\n \treturn 0;\n }\n \ndiff --git a/remote.h b/remote.h\nindex 0f6033f..f1dedf1 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -25,6 +25,7 @@ struct remote {\n \t * 2 to always fetch tags\n \t */\n \tint fetch_tags;\n+\tint skip_default_update;\n \n \tconst char *receivepack;\n \tconst char *uploadpack;\ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex e1e0a18..5986982 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -97,9 +97,9 @@ test_expect_success 'remove remote' '\n cat > test/expect << EOF\n * remote origin\n   URL: $(pwd)/one/.git\n-  Remote branch(es) merged with 'git pull' while on branch master\n+  Remote branch merged with 'git pull' while on branch master\n     master\n-  New remote branches (next fetch will store in remotes/origin)\n+  New remote branch (next fetch will store in remotes/origin)\n     master\n   Tracked remote branches\n     side master\n-- \n1.5.4.3.446.gbe8932\n\n\n"},{"id":"70527","messageId":"alpine.LSU.1.00.0803011317100.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803011313020.22527@racer.site","subject":"[PATCH 6/6] builtin-remote: prune remotes correctly that were added with --mirror","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-01T13:17:18Z","receivedAt":"2008-03-01T13:17:18Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis adds special handling for mirror remotes.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin-remote.c  |   15 +++++++++++++--\n t/t5505-remote.sh |   16 ++++++++++++++++\n 2 files changed, 29 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin-remote.c b/builtin-remote.c\nindex 2c10df3..221d2d6 100644\n--- a/builtin-remote.c\n+++ b/builtin-remote.c\n@@ -396,11 +396,22 @@ static int show_or_prune(int argc, const char **argv, int prune)\n \n \t\tif (prune) {\n \t\t\tstruct strbuf buf;\n+\t\t\tint prefix_len;\n \n \t\t\tstrbuf_init(&buf, 0);\n+\t\t\tif (states.remote->fetch_refspec_nr == 1 &&\n+\t\t\t\t\tstates.remote->fetch->pattern &&\n+\t\t\t\t\t!strcmp(states.remote->fetch->src,\n+\t\t\t\t\t\tstates.remote->fetch->dst))\n+\t\t\t\t/* handle --mirror remote */\n+\t\t\t\tstrbuf_addstr(&buf, \"refs/heads/\");\n+\t\t\telse\n+\t\t\t\tstrbuf_addf(&buf, \"refs/remotes/%s/\", *argv);\n+\t\t\tprefix_len = buf.len;\n+\n \t\t\tfor (i = 0; i < states.stale.nr; i++) {\n-\t\t\t\tstrbuf_reset(&buf);\n-\t\t\t\tstrbuf_addf(&buf, \"refs/remotes/%s/%s\", *argv,\n+\t\t\t\tstrbuf_setlen(&buf, prefix_len);\n+\t\t\t\tstrbuf_addstr(&buf,\n \t\t\t\t\t\tstates.stale.items[i].string);\n \t\t\t\tresult |= delete_ref(buf.buf, NULL);\n \t\t\t}\ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex 5986982..0a25c8b 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -128,4 +128,20 @@ test_expect_success 'prune' '\n \t ! git rev-parse refs/remotes/origin/side)\n '\n \n+test_expect_success 'add --mirror && prune' '\n+\t(mkdir mirror &&\n+\t cd mirror &&\n+\t git init &&\n+\t git remote add --mirror -f origin ../one) &&\n+\t(cd one &&\n+\t git branch -m side2 side) &&\n+\t(cd mirror &&\n+\t git rev-parse --verify refs/heads/side2 &&\n+\t ! git rev-parse --verify refs/heads/side &&\n+\t git fetch origin &&\n+\t git remote prune origin &&\n+\t ! git rev-parse --verify refs/heads/side2 &&\n+\t git rev-parse --verify refs/heads/side)\n+'\n+\n test_done\n-- \n1.5.4.3.446.gbe8932\n\n\n"},{"id":"70642","messageId":"alpine.LSU.1.00.0803021511420.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0802291118540.22527@racer.site","subject":"Re: [PATCH 0/5] Builtin \"git remote\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-02T15:15:00Z","receivedAt":"2008-03-02T15:15:00Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"[PATCH] format-patch: use the diff options for the cover letter, too\n\nEarlier, when you called \"git format-patch --cover-letter -M\", the\ndiffstat in the cover letter would not inherit the \"-M\".  Now it does.\n\nWhile at it, add a few \"|| break\" statements in the test's loops;\notherwise, breakages inside the loops would not be caught.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tOn Fri, 29 Feb 2008, Johannes Schindelin wrote:\n\n\t> On Thu, 28 Feb 2008, Daniel Barkalow wrote:\n\t> \n\t> > On Thu, 28 Feb 2008, Junio C Hamano wrote:\n\t> > \n\t> > > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\t> > > \n\t> > > > It also demonstrates that format-patch --cover-letter \n\t> > > > should default to -M for the diffstat (search for \n\t> > > > \"git-remote.perl\"...).\n\t> > > \n\t> > > It probably should inherit the settings for the primary \n\t> > > part. You did generate the series with -M, especially [PATCH \n\t> > > 4/5], didn't you?\n\t> > \n\t> > Obviously not the output_format, but everything else, I \n\t> > assume? Easy enough to pass the main diff options into \n\t> > make_cover_letter() and use them to initialize the diff \n\t> > options there.\n\n\tVoila.\n\n\tI thought that the changes in the for loops do not merit an own\n\tpatch, but if you think otherwise, let me know, and I'll resend.\n\n builtin-log.c           |    2 +-\n t/t4014-format-patch.sh |   18 ++++++++++++++----\n 2 files changed, 15 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex bbadbc0..17e491b 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -694,7 +694,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tif (!origin)\n \t\treturn;\n \n-\tdiff_setup(&opts);\n+\tmemcpy(&opts, &rev->diffopt, sizeof(opts));\n \topts.output_format |= DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;\n \n \tdiff_setup_done(&opts);\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 16aa99d..6d86b7d 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -147,7 +147,7 @@ test_expect_success 'thread' '\n \tfor i in patches/0002-* patches/0003-*\n \tdo\n \t  grep \"References: $FIRST_MID\" $i &&\n-\t  grep \"In-Reply-To: $FIRST_MID\" $i\n+\t  grep \"In-Reply-To: $FIRST_MID\" $i || break\n \tdone\n '\n \n@@ -160,7 +160,7 @@ test_expect_success 'thread in-reply-to' '\n \tfor i in patches/*\n \tdo\n \t  grep \"References: $FIRST_MID\" $i &&\n-\t  grep \"In-Reply-To: $FIRST_MID\" $i\n+\t  grep \"In-Reply-To: $FIRST_MID\" $i || break\n \tdone\n '\n \n@@ -173,7 +173,7 @@ test_expect_success 'thread cover-letter' '\n \tfor i in patches/0001-* patches/0002-* patches/0003-* \n \tdo\n \t  grep \"References: $FIRST_MID\" $i &&\n-\t  grep \"In-Reply-To: $FIRST_MID\" $i\n+\t  grep \"In-Reply-To: $FIRST_MID\" $i || break\n \tdone\n '\n \n@@ -186,7 +186,7 @@ test_expect_success 'thread cover-letter in-reply-to' '\n \tfor i in patches/*\n \tdo\n \t  grep \"References: $FIRST_MID\" $i &&\n-\t  grep \"In-Reply-To: $FIRST_MID\" $i\n+\t  grep \"In-Reply-To: $FIRST_MID\" $i || break\n \tdone\n '\n \n@@ -201,4 +201,14 @@ test_expect_success 'excessive subject' '\n \tls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch\n '\n \n+test_expect_success 'cover-letter inherits diff options' '\n+\n+\tgit mv file foo &&\n+\tgit commit -m foo &&\n+\tgit format-patch --cover-letter -1 &&\n+\t! grep \"file => foo .* 0 *$\" 0000-cover-letter.patch &&\n+\tgit format-patch --cover-letter -1 -M &&\n+\tgrep \"file => foo .* 0 *$\" 0000-cover-letter.patch\n+\n+'\n test_done\n-- \n1.5.4.3.510.g7cdd\n\n"},{"id":"70643","messageId":"alpine.LSU.1.00.0803021531230.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803021511420.22527@racer.site","subject":"Re: [PATCH 0/5] Builtin \"git remote\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-02T15:40:52Z","receivedAt":"2008-03-02T15:40:52Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 2 Mar 2008, Johannes Schindelin wrote:\n\n> diff --git a/builtin-log.c b/builtin-log.c\n> index bbadbc0..17e491b 100644\n> --- a/builtin-log.c\n> +++ b/builtin-log.c\n> @@ -694,7 +694,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n>  \tif (!origin)\n>  \t\treturn;\n>  \n> -\tdiff_setup(&opts);\n> +\tmemcpy(&opts, &rev->diffopt, sizeof(opts));\n>  \topts.output_format |= DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;\n>  \n>  \tdiff_setup_done(&opts);\n\nOoops, I forgot to \"make test\"!  And sure enough, t4013 breaks, because \nthe \"|=\" was bogus to begin with.\n\nWill resend, together with a patch to wrap the shortlog nicely.\n\n... after \"make test\" ;-)\n\nCiao,\nDscho\n\n"},{"id":"70650","messageId":"alpine.LSU.1.00.0803021552210.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803021531230.22527@racer.site","subject":"[PATCH 0/2] format-patch --cover-letter improvements","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-02T15:52:36Z","receivedAt":"2008-03-02T15:52:36Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis patch pair brings two improvements to the cover letter:\n\n\t- when calling format-patch with a diff option, this options\n\t  will be heeded by the cover-letter's diffstat, and\n\n\t- the onelines in the shortlog are wrapped around, just like\n\t  in Junio's \"What's in ...\" messages.\n\n\nJohannes Schindelin (2):\n  format-patch: use the diff options for the cover letter, too\n  format-patch: wrap cover-letter's shortlog sensibly\n\n builtin-log.c                                      |    8 +++-\n ...tch_--stdout_--cover-letter_-n_initial..master^ |    4 +-\n t/t4014-format-patch.sh                            |   37 +++++++++++++++++--\n 3 files changed, 41 insertions(+), 8 deletions(-)\n\n\n"},{"id":"70651","messageId":"alpine.LSU.1.00.0803021552480.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803021552210.22527@racer.site","subject":"[PATCH 1/2] format-patch: use the diff options for the cover letter, too","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-02T15:53:04Z","receivedAt":"2008-03-02T15:53:04Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nEarlier, when you called \"git format-patch --cover-letter -M\", the\ndiffstat in the cover letter would not inherit the \"-M\".  Now it does.\n\nWhile at it, add a few \"|| break\" statements in the test's loops;\notherwise, breakages inside the loops would not be caught.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin-log.c           |    4 ++--\n t/t4014-format-patch.sh |   18 ++++++++++++++----\n 2 files changed, 16 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex bbadbc0..fd9b3ae 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -694,8 +694,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tif (!origin)\n \t\treturn;\n \n-\tdiff_setup(&opts);\n-\topts.output_format |= DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;\n+\tmemcpy(&opts, &rev->diffopt, sizeof(opts));\n+\topts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;\n \n \tdiff_setup_done(&opts);\n \ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 16aa99d..6d86b7d 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -147,7 +147,7 @@ test_expect_success 'thread' '\n \tfor i in patches/0002-* patches/0003-*\n \tdo\n \t  grep \"References: $FIRST_MID\" $i &&\n-\t  grep \"In-Reply-To: $FIRST_MID\" $i\n+\t  grep \"In-Reply-To: $FIRST_MID\" $i || break\n \tdone\n '\n \n@@ -160,7 +160,7 @@ test_expect_success 'thread in-reply-to' '\n \tfor i in patches/*\n \tdo\n \t  grep \"References: $FIRST_MID\" $i &&\n-\t  grep \"In-Reply-To: $FIRST_MID\" $i\n+\t  grep \"In-Reply-To: $FIRST_MID\" $i || break\n \tdone\n '\n \n@@ -173,7 +173,7 @@ test_expect_success 'thread cover-letter' '\n \tfor i in patches/0001-* patches/0002-* patches/0003-* \n \tdo\n \t  grep \"References: $FIRST_MID\" $i &&\n-\t  grep \"In-Reply-To: $FIRST_MID\" $i\n+\t  grep \"In-Reply-To: $FIRST_MID\" $i || break\n \tdone\n '\n \n@@ -186,7 +186,7 @@ test_expect_success 'thread cover-letter in-reply-to' '\n \tfor i in patches/*\n \tdo\n \t  grep \"References: $FIRST_MID\" $i &&\n-\t  grep \"In-Reply-To: $FIRST_MID\" $i\n+\t  grep \"In-Reply-To: $FIRST_MID\" $i || break\n \tdone\n '\n \n@@ -201,4 +201,14 @@ test_expect_success 'excessive subject' '\n \tls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch\n '\n \n+test_expect_success 'cover-letter inherits diff options' '\n+\n+\tgit mv file foo &&\n+\tgit commit -m foo &&\n+\tgit format-patch --cover-letter -1 &&\n+\t! grep \"file => foo .* 0 *$\" 0000-cover-letter.patch &&\n+\tgit format-patch --cover-letter -1 -M &&\n+\tgrep \"file => foo .* 0 *$\" 0000-cover-letter.patch\n+\n+'\n test_done\n-- \n1.5.4.3.510.g7cdd\n\n\n"},{"id":"70652","messageId":"alpine.LSU.1.00.0803021553090.22527@racer.site","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803021552210.22527@racer.site","subject":"[PATCH 2/2] format-patch: wrap cover-letter's shortlog sensibly","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-02T15:53:39Z","receivedAt":"2008-03-02T15:53:39Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nEarlier, overly-long onelines would not be wrapped at all, and indented\nwith 6 spaces.\n\nInstead, we now wrap around at 72 characters, with a first-line indent\nof 2 spaces, and the rest with 4 spaces (like the \"What's in\" messages\nof Junio).\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin-log.c                                      |    4 ++++\n ...tch_--stdout_--cover-letter_-n_initial..master^ |    4 ++--\n t/t4014-format-patch.sh                            |   19 +++++++++++++++++++\n 3 files changed, 25 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex fd9b3ae..fe8fc6f 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -683,6 +683,10 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,\n \tstrbuf_release(&sb);\n \n \tshortlog_init(&log);\n+\tlog.wrap_lines = 1;\n+\tlog.wrap = 72;\n+\tlog.in1 = 2;\n+\tlog.in2 = 4;\n \tfor (i = 0; i < nr; i++)\n \t\tshortlog_add_commit(&log, list[i]);\n \ndiff --git a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^\nindex 0151453..8dab4bf 100644\n--- a/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^\n+++ b/t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^\n@@ -7,8 +7,8 @@ Subject: [DIFFERENT_PREFIX 0/2] *** SUBJECT HERE ***\n *** BLURB HERE ***\n \n A U Thor (2):\n-      Second\n-      Third\n+  Second\n+  Third\n \n  dir/sub |    4 ++++\n  file0   |    3 +++\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 6d86b7d..b2b7a8d 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -211,4 +211,23 @@ test_expect_success 'cover-letter inherits diff options' '\n \tgrep \"file => foo .* 0 *$\" 0000-cover-letter.patch\n \n '\n+\n+cat > expect << EOF\n+  This is an excessively long subject line for a message due to the\n+    habit some projects have of not having a short, one-line subject at\n+    the start of the commit message, but rather sticking a whole\n+    paragraph right at the start as the only thing in the commit\n+    message. It had better not become the filename for the patch.\n+  foo\n+\n+EOF\n+\n+test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '\n+\n+\tgit format-patch --cover-letter -2 &&\n+\tsed -e \"1,/A U Thor/d\" -e \"/^$/q\" < 0000-cover-letter.patch > output &&\n+\tgit diff expect output\n+\n+'\n+\n test_done\n-- \n1.5.4.3.510.g7cdd\n\n\n"},{"id":"70666","messageId":"7vejatoy2w.fsf@gitster.siamese.dyndns.org","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803021553090.22527@racer.site","subject":"Re: [PATCH 2/2] format-patch: wrap cover-letter's shortlog sensibly","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-02T17:05:59Z","receivedAt":"2008-03-02T17:05:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> Earlier, overly-long onelines would not be wrapped at all, and indented\n> with 6 spaces.\n>\n> Instead, we now wrap around at 72 characters, with a first-line indent\n> of 2 spaces, and the rest with 4 spaces (like the \"What's in\" messages\n> of Junio).\n\nHeh, I seem to personally use 76,2,4 but otherwise I think this makes it\neasier to read.  Thanks.\n"},{"id":"70673","messageId":"alpine.LSU.1.00.0803021736510.22527@racer.site","threadId":"12377","inReplyTo":"7vejatoy2w.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 2/2] format-patch: wrap cover-letter's shortlog sensibly","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-02T17:38:29Z","receivedAt":"2008-03-02T17:38:29Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 2 Mar 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > Earlier, overly-long onelines would not be wrapped at all, and indented\n> > with 6 spaces.\n> >\n> > Instead, we now wrap around at 72 characters, with a first-line indent \n> > of 2 spaces, and the rest with 4 spaces (like the \"What's in\" messages \n> > of Junio).\n> \n> Heh, I seem to personally use 76,2,4 but otherwise I think this makes it \n> easier to read.  Thanks.\n\nOh?  My first patch was 76,4,8, but then I was unsure, and went to your \ntodo branch, and found this:\n\n$ git grep -e -w.*7\nSummary:git shortlog -w72,2,4 --no-merges $bottom..$top\nWI:     git shortlog -w76,2,4 --no-merges \"$@\"\n\nObviously, I missed the second one, and took the first one.\n\nCiao,\nDscho\n\n"},{"id":"71730","messageId":"87iqztz0z5.fsf@lysator.liu.se","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803011315180.22527@racer.site","subject":"Re: [PATCH 1/6] Rename path_list to string_list","fromName":"David Kågedal","fromEmail":"davidk@lysator.liu.se","sentAt":"2008-03-11T16:20:30Z","receivedAt":"2008-03-11T16:20:30Z","isPatch":true,"sender":{"key":"davidk@lysator.liu.se","avatar":"https://avatars.githubusercontent.com/u/60530?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> diff --git a/Documentation/technical/api-path-list.txt b/Documentation/technical/api-path-list.txt\n> index d077683..8892cf0 100644\n> --- a/Documentation/technical/api-path-list.txt\n> +++ b/Documentation/technical/api-path-list.txt\n> @@ -1,7 +1,7 @@\n> -path-list API\n> +string-list API\n>  =============\n\nLooks like you'll want to add two = here.\n\n-- \nDavid Kågedal\n"},{"id":"71734","messageId":"alpine.LSU.1.00.0803111725480.3873@racer.site","threadId":"12377","inReplyTo":"87iqztz0z5.fsf@lysator.liu.se","subject":"Re: [PATCH 1/6] Rename path_list to string_list","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-11T16:26:18Z","receivedAt":"2008-03-11T16:26:18Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 11 Mar 2008, David Kågedal wrote:\n\n> The following message is a courtesy copy of an article\n> that has been posted to gmane.comp.version-control.git as well.\n\nI hate having to readd the Cc: to the list.\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > diff --git a/Documentation/technical/api-path-list.txt b/Documentation/technical/api-path-list.txt\n> > index d077683..8892cf0 100644\n> > --- a/Documentation/technical/api-path-list.txt\n> > +++ b/Documentation/technical/api-path-list.txt\n> > @@ -1,7 +1,7 @@\n> > -path-list API\n> > +string-list API\n> >  =============\n> \n> Looks like you'll want to add two = here.\n\nYes.\n\nCiao,\nDscho\n"},{"id":"71735","messageId":"87d4q1yzv6.fsf@lysator.liu.se","threadId":"12377","inReplyTo":"alpine.LSU.1.00.0803111725480.3873@racer.site","subject":"Re: [PATCH 1/6] Rename path_list to string_list","fromName":"David Kågedal","fromEmail":"davidk@lysator.liu.se","sentAt":"2008-03-11T16:44:29Z","receivedAt":"2008-03-11T16:44:29Z","isPatch":true,"sender":{"key":"davidk@lysator.liu.se","avatar":"https://avatars.githubusercontent.com/u/60530?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> Hi,\n>\n> On Tue, 11 Mar 2008, David Kågedal wrote:\n>\n>> The following message is a courtesy copy of an article\n>> that has been posted to gmane.comp.version-control.git as well.\n>\n> I hate having to readd the Cc: to the list.\n\nSorry about that.\n\n-- \nDavid Kågedal\n"}]}