{"thread":{"id":"581","subject":"[PATCH] Add git-ls-files -k option.","startedAt":"2005-05-12T09:23:57Z","lastAt":"2005-05-12T19:20:00Z","messageCount":2,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"3126","messageId":"7vk6m4iyqa.fsf@assigned-by-dhcp.cox.net","threadId":"581","inReplyTo":null,"subject":"[PATCH] Add git-ls-files -k option.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-12T09:23:57Z","receivedAt":"2005-05-12T09:23:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Pasky, you may remember the discussion on how \"chilly\" the\nproposed behaviour of checkout-cache -f obliterating conflicting\npaths was, and what I think is needed for the Porcelain layer if\nit chooses to save such files before checking things out.\n\nHere is a patch to add -k (killed) option to git-ls-files to\nfind out what files are need to be killed to make checkout-cache\nto succeed.  The Porcelain can run it immediately before\ncheckout-cache, save the files reported, and the run\ncheckout-cache -f.  If your checkout-cache does not have that\n\"chilly\" enhancement, in addition to saving the files above, it\nalso has to move them out of the way.\n\nNote: To be applied after ls-files --other symlink fix.\n\n------------\n\nWhen checkout-cache attempts to check out a non-directory where\na directory exists on the work tree, or to check out a file\nunder directory D when path D is a non-directory on the work\ntree, the attempt fails.  Before running checkout-cache, the\nuser can run git-ls-files with the -k (killed) option to get a\nlist of such paths.\n\nThis also includes the test for this functionality and\ndocumentation of the new option.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\nDocumentation/git-ls-files.txt |   10 +++-\nls-files.c                     |   95 +++++++++++++++++++++++++++++++++--------\nt/t0500-ls-files.sh            |   55 +++++++++++++++++++++++\n3 files changed, 140 insertions(+), 20 deletions(-)\n\n--- a/Documentation/git-ls-files.txt\n+++ b/Documentation/git-ls-files.txt\n@@ -10,8 +10,8 @@ git-ls-files - Information about files i\n SYNOPSIS\n --------\n 'git-ls-files' [-z] [-t]\n-\t\t(--[cached|deleted|others|ignored|stage|unmerged])\\*\n-\t\t(-[c|d|o|i|s|u])\\*\n+\t\t(--[cached|deleted|others|ignored|stage|unmerged|killed])\\*\n+\t\t(-[c|d|o|i|s|u|k])\\*\n \t\t[-x <pattern>|--exclude=<pattern>]\n \t\t[-X <file>|--exclude-from=<file>]\n \n@@ -45,6 +45,11 @@ OPTIONS\n -u|--unmerged::\n \tShow unmerged files in the output (forces --stage)\n \n+-k|--killed::\n+\tShow files on the filesystem that need to be removed due\n+\tto file/directory conflicts for checkout-cache to\n+\tsucceed.\n+\n -z::\n \t\\0 line termination on output\n \n@@ -65,6 +70,7 @@ OPTIONS\n \tH\tcached\n \tM\tunmerged\n \tR\tremoved/deleted\n+\tK\tto be killed\n \t?\tother\n \n Output\n--- a/ls-files.c\n+++ b/ls-files.c\n@@ -16,12 +16,14 @@ static int show_others = 0;\n static int show_ignored = 0;\n static int show_stage = 0;\n static int show_unmerged = 0;\n+static int show_killed = 0;\n static int line_terminator = '\\n';\n \n static const char *tag_cached = \"\";\n static const char *tag_unmerged = \"\";\n static const char *tag_removed = \"\";\n static const char *tag_other = \"\";\n+static const char *tag_killed = \"\";\n \n static int nr_excludes;\n static const char **excludes;\n@@ -87,24 +89,36 @@ static int excluded(const char *pathname\n \treturn 0;\n }\n \n-static const char **dir;\n+struct nond_on_fs {\n+\tint len;\n+#define IN_CACHE 1\n+#define REPORTED_KILL 2\n+\tchar flag;\n+\tchar name[0];\n+};\n+\n+static struct nond_on_fs **dir;\n static int nr_dir;\n static int dir_alloc;\n \n static void add_name(const char *pathname, int len)\n {\n-\tchar *name;\n+\tstruct nond_on_fs *ent;\n+\tint pos;\n \n-\tif (cache_name_pos(pathname, len) >= 0)\n+\tpos = cache_name_pos(pathname, len);\n+\tif (!show_killed && pos >= 0)\n \t\treturn;\n \n \tif (nr_dir == dir_alloc) {\n \t\tdir_alloc = alloc_nr(dir_alloc);\n-\t\tdir = xrealloc(dir, dir_alloc*sizeof(char *));\n+\t\tdir = xrealloc(dir, dir_alloc*sizeof(ent));\n \t}\n-\tname = xmalloc(len + 1);\n-\tmemcpy(name, pathname, len + 1);\n-\tdir[nr_dir++] = name;\n+\tent = xmalloc(sizeof(*ent) + len + 1);\n+\tent->flag = (0 <= pos) ? IN_CACHE : 0;\n+\tent->len = len;\n+\tmemcpy(ent->name, pathname, len);\n+\tdir[nr_dir++] = ent;\n }\n \n /*\n@@ -164,11 +178,46 @@ static void read_directory(const char *p\n \n static int cmp_name(const void *p1, const void *p2)\n {\n-\tconst char *n1 = *(const char **)p1;\n-\tconst char *n2 = *(const char **)p2;\n-\tint l1 = strlen(n1), l2 = strlen(n2);\n+\tconst struct nond_on_fs *e1 = *(const struct nond_on_fs **)p1;\n+\tconst struct nond_on_fs *e2 = *(const struct nond_on_fs **)p2;\n+\n+\treturn cache_name_compare(e1->name, e1->len,\n+\t\t\t\t  e2->name, e2->len);\n+}\n+\n+static void show_killed_files()\n+{\n+\tint i, j;\n \n-\treturn cache_name_compare(n1, l1, n2, l2);\n+\tfor (i = 0; i < active_nr; i++) {\n+\t\tstruct cache_entry *ce = active_cache[i];\n+\t\tif (ce_stage(ce))\n+\t\t\tcontinue; /* these won't be checked out */\n+\t\t/* Find things that are being killed; that is,\n+\t\t * the ones are prefix of ce->name, or suffix of it.\n+\t\t * The ones that are exactly the same as ce->name\n+\t\t * are fine, because they are what are going to be\n+\t\t * checked out.\n+\t\t */\n+\t\tfor (j = 0; j < nr_dir; j++) {\n+\t\t\tint len;\n+\t\t\tint l;\n+\t\t\tif (dir[j]->flag & REPORTED_KILL)\n+\t\t\t\tcontinue;\n+\t\t\tlen = ce_namelen(ce);\n+\t\t\tl = (len < dir[j]->len) ? len : dir[j]->len;\n+\t\t\tif (!strncmp(ce->name, dir[j]->name, l) &&\n+\t\t\t    ( ((len < dir[j]->len) &&\n+\t\t\t       (dir[j]->name[l] == '/')) ||\n+\t\t\t      ((dir[j]->len < len) &&\n+\t\t\t       (ce->name[l] == '/')) ) ) {\n+\t\t\t\tprintf(\"%s%.*s%c\", tag_killed,\n+\t\t\t\t       dir[i]->len, dir[i]->name,\n+\t\t\t\t       line_terminator);\n+\t\t\t\tdir[j]->flag |= REPORTED_KILL;\n+\t\t\t}\n+\t\t}\n+\t}\n }\n \n static void show_files(void)\n@@ -176,11 +225,18 @@ static void show_files(void)\n \tint i;\n \n \t/* For cached/deleted files we don't need to even do the readdir */\n-\tif (show_others) {\n+\tif (show_others || show_killed) {\n \t\tread_directory(\".\", \"\", 0);\n-\t\tqsort(dir, nr_dir, sizeof(char *), cmp_name);\n-\t\tfor (i = 0; i < nr_dir; i++)\n-\t\t\tprintf(\"%s%s%c\", tag_other, dir[i], line_terminator);\n+\t\tqsort(dir, nr_dir, sizeof(struct nond_on_fs *), cmp_name);\n+\t\tif (show_others)\n+\t\t\tfor (i = 0; i < nr_dir; i++)\n+\t\t\t\tif (!(dir[i]->flag & IN_CACHE))\n+\t\t\t\t\tprintf(\"%s%.*s%c\", tag_other,\n+\t\t\t\t\t       dir[i]->len,\n+\t\t\t\t\t       dir[i]->name,\n+\t\t\t\t\t       line_terminator);\n+\t\tif (show_killed)\n+\t\t\tshow_killed_files();\n \t}\n \tif (show_cached | show_stage) {\n \t\tfor (i = 0; i < active_nr; i++) {\n@@ -219,8 +275,8 @@ static void show_files(void)\n }\n \n static const char *ls_files_usage =\n-\t\"ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged])* \"\n-\t\"[ --ignored [--exclude=<pattern>] [--exclude-from=<file>) ]\";\n+\"ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed])* \"\n+\"[ --ignored [--exclude=<pattern>] [--exclude-from=<file>) ]\";\n \n int main(int argc, char **argv)\n {\n@@ -236,6 +292,7 @@ int main(int argc, char **argv)\n \t\t\ttag_unmerged = \"M \";\n \t\t\ttag_removed = \"R \";\n \t\t\ttag_other = \"? \";\n+\t\t\ttag_killed = \"K \";\n \t\t} else if (!strcmp(arg, \"-c\") || !strcmp(arg, \"--cached\")) {\n \t\t\tshow_cached = 1;\n \t\t} else if (!strcmp(arg, \"-d\") || !strcmp(arg, \"--deleted\")) {\n@@ -246,6 +303,8 @@ int main(int argc, char **argv)\n \t\t\tshow_ignored = 1;\n \t\t} else if (!strcmp(arg, \"-s\") || !strcmp(arg, \"--stage\")) {\n \t\t\tshow_stage = 1;\n+\t\t} else if (!strcmp(arg, \"-k\") || !strcmp(arg, \"--killed\")) {\n+\t\t\tshow_killed = 1;\n \t\t} else if (!strcmp(arg, \"-u\") || !strcmp(arg, \"--unmerged\")) {\n \t\t\t/* There's no point in showing unmerged unless\n \t\t\t * you also show the stage information.\n@@ -271,7 +330,7 @@ int main(int argc, char **argv)\n \t}\n \n \t/* With no flags, we default to showing the cached files */\n-\tif (!(show_stage | show_deleted | show_others | show_unmerged))\n+\tif (!(show_stage | show_deleted | show_others | show_unmerged | show_killed))\n \t\tshow_cached = 1;\n \n \tread_cache();\nCreated: t/t0500-ls-files.sh (mode:100755)\n--- /dev/null\n+++ b/t/t0500-ls-files.sh\n@@ -0,0 +1,55 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005 Junio C Hamano\n+#\n+\n+. ./test-lib.sh\n+test_description \"$@\" 'git-ls-files -k flag test.\n+\n+This test prepares the following in the cache:\n+\n+    path0       - a file\n+    path1       - a symlink\n+    path2/file2 - a file in a directory\n+    path3/file3 - a file in a directory\n+\n+and the following on the filesystem:\n+\n+    path0/file0 - a file in a directory\n+    path1/file1 - a file in a directory\n+    path2       - a file\n+    path3       - a symlink\n+    path4\t- a file\n+    path5\t- a symlink\n+    path6/file6 - a file in a directory\n+\n+git-ls-files -k should report that existing filesystem\n+objects except path4, path5 and path6/file6 to be killed.\n+'\n+\n+date >path0\n+ln -s xyzzy path1\n+mkdir path2 path3\n+date >path2/file2\n+date >path3/file3\n+git-update-cache --add -- path0 path1 path?/file?\n+\n+rm -fr path?\n+date >path2\n+ln -s frotz path3\n+ln -s nitfol path5\n+mkdir path0 path1 path6\n+date >path0/file0\n+date >path1/file1\n+date >path6/file6\n+\n+git-ls-files -k >.output\n+cat >.expected <<EOF\n+path0/file0\n+path1/file1\n+path2\n+path3\n+EOF\n+\n+test_expect_success 'diff .output .expected'\n+test_done\n\n"},{"id":"3178","messageId":"7vekccgskf.fsf@assigned-by-dhcp.cox.net","threadId":"581","inReplyTo":"7vk6m4iyqa.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Add git-ls-files -k (take 2).","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-12T19:20:00Z","receivedAt":"2005-05-12T19:20:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When checkout-cache attempts to check out a non-directory where\na directory exists on the work tree, or to check out a file\nunder directory D when path D is a non-directory on the work\ntree, the attempt fails.  Before running checkout-cache, the\nuser can run git-ls-files with the -k (killed) option to get a\nlist of such paths.  The tagged output format uses \"K\" to denote\nsuch paths.\n\nThis also includes the test for this functionality and\ndocumentation of the new option.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n*** This is a reworked patch that fixes performance problem in\n*** the one I sent out earlier.  Discard the earlier one and\n*** apply this on top of \"git-ls-files --others symlink fix\".\n\nDocumentation/git-ls-files.txt |   10 +++-\nls-files.c                     |  101 ++++++++++++++++++++++++++++++++++-------\nt/t0500-ls-files.sh            |   55 ++++++++++++++++++++++\n3 files changed, 147 insertions(+), 19 deletions(-)\n\n--- a/Documentation/git-ls-files.txt\n+++ b/Documentation/git-ls-files.txt\n@@ -10,8 +10,8 @@ git-ls-files - Information about files i\n SYNOPSIS\n --------\n 'git-ls-files' [-z] [-t]\n-\t\t(--[cached|deleted|others|ignored|stage|unmerged])\\*\n-\t\t(-[c|d|o|i|s|u])\\*\n+\t\t(--[cached|deleted|others|ignored|stage|unmerged|killed])\\*\n+\t\t(-[c|d|o|i|s|u|k])\\*\n \t\t[-x <pattern>|--exclude=<pattern>]\n \t\t[-X <file>|--exclude-from=<file>]\n \n@@ -45,6 +45,11 @@ OPTIONS\n -u|--unmerged::\n \tShow unmerged files in the output (forces --stage)\n \n+-k|--killed::\n+\tShow files on the filesystem that need to be removed due\n+\tto file/directory conflicts for checkout-cache to\n+\tsucceed.\n+\n -z::\n \t\\0 line termination on output\n \n@@ -65,6 +70,7 @@ OPTIONS\n \tH\tcached\n \tM\tunmerged\n \tR\tremoved/deleted\n+\tK\tto be killed\n \t?\tother\n \n Output\n--- a/ls-files.c\n+++ b/ls-files.c\n@@ -16,12 +16,14 @@ static int show_others = 0;\n static int show_ignored = 0;\n static int show_stage = 0;\n static int show_unmerged = 0;\n+static int show_killed = 0;\n static int line_terminator = '\\n';\n \n static const char *tag_cached = \"\";\n static const char *tag_unmerged = \"\";\n static const char *tag_removed = \"\";\n static const char *tag_other = \"\";\n+static const char *tag_killed = \"\";\n \n static int nr_excludes;\n static const char **excludes;\n@@ -87,24 +89,30 @@ static int excluded(const char *pathname\n \treturn 0;\n }\n \n-static const char **dir;\n+struct nond_on_fs {\n+\tint len;\n+\tchar name[0];\n+};\n+\n+static struct nond_on_fs **dir;\n static int nr_dir;\n static int dir_alloc;\n \n static void add_name(const char *pathname, int len)\n {\n-\tchar *name;\n+\tstruct nond_on_fs *ent;\n \n \tif (cache_name_pos(pathname, len) >= 0)\n \t\treturn;\n \n \tif (nr_dir == dir_alloc) {\n \t\tdir_alloc = alloc_nr(dir_alloc);\n-\t\tdir = xrealloc(dir, dir_alloc*sizeof(char *));\n+\t\tdir = xrealloc(dir, dir_alloc*sizeof(ent));\n \t}\n-\tname = xmalloc(len + 1);\n-\tmemcpy(name, pathname, len + 1);\n-\tdir[nr_dir++] = name;\n+\tent = xmalloc(sizeof(*ent) + len + 1);\n+\tent->len = len;\n+\tmemcpy(ent->name, pathname, len);\n+\tdir[nr_dir++] = ent;\n }\n \n /*\n@@ -164,11 +172,62 @@ static void read_directory(const char *p\n \n static int cmp_name(const void *p1, const void *p2)\n {\n-\tconst char *n1 = *(const char **)p1;\n-\tconst char *n2 = *(const char **)p2;\n-\tint l1 = strlen(n1), l2 = strlen(n2);\n+\tconst struct nond_on_fs *e1 = *(const struct nond_on_fs **)p1;\n+\tconst struct nond_on_fs *e2 = *(const struct nond_on_fs **)p2;\n+\n+\treturn cache_name_compare(e1->name, e1->len,\n+\t\t\t\t  e2->name, e2->len);\n+}\n \n-\treturn cache_name_compare(n1, l1, n2, l2);\n+static void show_killed_files()\n+{\n+\tint i;\n+\tfor (i = 0; i < nr_dir; i++) {\n+\t\tstruct nond_on_fs *ent = dir[i];\n+\t\tchar *cp, *sp;\n+\t\tint pos, len, killed = 0;\n+\n+\t\tfor (cp = ent->name; cp - ent->name < ent->len; cp = sp + 1) {\n+\t\t\tsp = strchr(cp, '/');\n+\t\t\tif (!sp) {\n+\t\t\t\t/* If ent->name is prefix of an entry in the\n+\t\t\t\t * cache, it will be killed.\n+\t\t\t\t */\n+\t\t\t\tpos = cache_name_pos(ent->name, ent->len);\n+\t\t\t\tif (0 <= pos)\n+\t\t\t\t\tdie(\"bug in show-killed-files\");\n+\t\t\t\tpos = -pos - 1;\n+\t\t\t\twhile (pos < active_nr &&\n+\t\t\t\t       ce_stage(active_cache[pos]))\n+\t\t\t\t\tpos++; /* skip unmerged */\n+\t\t\t\tif (active_nr <= pos)\n+\t\t\t\t\tbreak;\n+\t\t\t\t/* pos points at a name immediately after\n+\t\t\t\t * ent->name in the cache.  Does it expect\n+\t\t\t\t * ent->name to be a directory?\n+\t\t\t\t */\n+\t\t\t\tlen = ce_namelen(active_cache[pos]);\n+\t\t\t\tif ((ent->len < len) &&\n+\t\t\t\t    !strncmp(active_cache[pos]->name,\n+\t\t\t\t\t     ent->name, ent->len) &&\n+\t\t\t\t    active_cache[pos]->name[ent->len] == '/')\n+\t\t\t\t\tkilled = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tif (0 <= cache_name_pos(ent->name, sp - ent->name)) {\n+\t\t\t\t/* If any of the leading directories in\n+\t\t\t\t * ent->name is registered in the cache,\n+\t\t\t\t * ent->name will be killed.\n+\t\t\t\t */\n+\t\t\t\tkilled = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tif (killed)\n+\t\t\tprintf(\"%s%.*s%c\", tag_killed,\n+\t\t\t       dir[i]->len, dir[i]->name,\n+\t\t\t       line_terminator);\n+\t}\n }\n \n static void show_files(void)\n@@ -176,11 +235,16 @@ static void show_files(void)\n \tint i;\n \n \t/* For cached/deleted files we don't need to even do the readdir */\n-\tif (show_others) {\n+\tif (show_others || show_killed) {\n \t\tread_directory(\".\", \"\", 0);\n-\t\tqsort(dir, nr_dir, sizeof(char *), cmp_name);\n-\t\tfor (i = 0; i < nr_dir; i++)\n-\t\t\tprintf(\"%s%s%c\", tag_other, dir[i], line_terminator);\n+\t\tqsort(dir, nr_dir, sizeof(struct nond_on_fs *), cmp_name);\n+\t\tif (show_others)\n+\t\t\tfor (i = 0; i < nr_dir; i++)\n+\t\t\t\tprintf(\"%s%.*s%c\", tag_other,\n+\t\t\t\t       dir[i]->len, dir[i]->name,\n+\t\t\t\t       line_terminator);\n+\t\tif (show_killed)\n+\t\t\tshow_killed_files();\n \t}\n \tif (show_cached | show_stage) {\n \t\tfor (i = 0; i < active_nr; i++) {\n@@ -219,8 +283,8 @@ static void show_files(void)\n }\n \n static const char *ls_files_usage =\n-\t\"ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged])* \"\n-\t\"[ --ignored [--exclude=<pattern>] [--exclude-from=<file>) ]\";\n+\"ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed])* \"\n+\"[ --ignored [--exclude=<pattern>] [--exclude-from=<file>) ]\";\n \n int main(int argc, char **argv)\n {\n@@ -236,6 +300,7 @@ int main(int argc, char **argv)\n \t\t\ttag_unmerged = \"M \";\n \t\t\ttag_removed = \"R \";\n \t\t\ttag_other = \"? \";\n+\t\t\ttag_killed = \"K \";\n \t\t} else if (!strcmp(arg, \"-c\") || !strcmp(arg, \"--cached\")) {\n \t\t\tshow_cached = 1;\n \t\t} else if (!strcmp(arg, \"-d\") || !strcmp(arg, \"--deleted\")) {\n@@ -246,6 +311,8 @@ int main(int argc, char **argv)\n \t\t\tshow_ignored = 1;\n \t\t} else if (!strcmp(arg, \"-s\") || !strcmp(arg, \"--stage\")) {\n \t\t\tshow_stage = 1;\n+\t\t} else if (!strcmp(arg, \"-k\") || !strcmp(arg, \"--killed\")) {\n+\t\t\tshow_killed = 1;\n \t\t} else if (!strcmp(arg, \"-u\") || !strcmp(arg, \"--unmerged\")) {\n \t\t\t/* There's no point in showing unmerged unless\n \t\t\t * you also show the stage information.\n@@ -271,7 +338,7 @@ int main(int argc, char **argv)\n \t}\n \n \t/* With no flags, we default to showing the cached files */\n-\tif (!(show_stage | show_deleted | show_others | show_unmerged))\n+\tif (!(show_stage | show_deleted | show_others | show_unmerged | show_killed))\n \t\tshow_cached = 1;\n \n \tread_cache();\nCreated: t/t0500-ls-files.sh (mode:100755)\n--- /dev/null\n+++ b/t/t0500-ls-files.sh\n@@ -0,0 +1,55 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005 Junio C Hamano\n+#\n+\n+. ./test-lib.sh\n+test_description \"$@\" 'git-ls-files -k flag test.\n+\n+This test prepares the following in the cache:\n+\n+    path0       - a file\n+    path1       - a symlink\n+    path2/file2 - a file in a directory\n+    path3/file3 - a file in a directory\n+\n+and the following on the filesystem:\n+\n+    path0/file0 - a file in a directory\n+    path1/file1 - a file in a directory\n+    path2       - a file\n+    path3       - a symlink\n+    path4\t- a file\n+    path5\t- a symlink\n+    path6/file6 - a file in a directory\n+\n+git-ls-files -k should report that existing filesystem\n+objects except path4, path5 and path6/file6 to be killed.\n+'\n+\n+date >path0\n+ln -s xyzzy path1\n+mkdir path2 path3\n+date >path2/file2\n+date >path3/file3\n+git-update-cache --add -- path0 path1 path?/file?\n+\n+rm -fr path?\n+date >path2\n+ln -s frotz path3\n+ln -s nitfol path5\n+mkdir path0 path1 path6\n+date >path0/file0\n+date >path1/file1\n+date >path6/file6\n+\n+git-ls-files -k >.output\n+cat >.expected <<EOF\n+path0/file0\n+path1/file1\n+path2\n+path3\n+EOF\n+\n+test_expect_success 'diff .output .expected'\n+test_done\n\n"}]}