{"thread":{"id":"17057","subject":"[PATCH 0/2] Allow cloning to an existing empty directory","startedAt":"2009-01-08T23:24:21Z","lastAt":"2009-01-10T02:48:39Z","messageCount":8,"participants":["Alexander Potashev","Johannes Sixt","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"99745","messageId":"1231457063-29186-1-git-send-email-aspotashev@gmail.com","threadId":"17057","inReplyTo":null,"subject":"[PATCH 0/2] Allow cloning to an existing empty directory","fromName":"Alexander Potashev","fromEmail":"aspotashev@gmail.com","sentAt":"2009-01-08T23:24:21Z","receivedAt":"2009-01-08T23:24:21Z","isPatch":true,"sender":{"key":"aspotashev@gmail.com","avatar":null},"body":"The problem I experienced today was that I couldn't clone a repo to a\nseparate filesystem. I've created a new LVM volume, a FS on it (XFS)\nand mounted it to a directory.\n\nBut wasn't able to clone the repo to that directory. It's impossible to\nmount a FS to a non-existent directory, right? But Git refuses to clone\nto an existing directory.\n\nThe solution in my first patch allows cloning to an existing empty\ndirectory. However, there could be problems doing the same as I did\nwith XFS using ext2-like filesystems, because they have lost+found\ndirectories, i.e. the root directory of those FSs is never empty.\n\n\n\nThe first patch adds a function (is_pseudo_dir_name) to compare a\nstring with \".\" and \"..\", the second patch reuses that function in\nthe rest of the code.\n\n\nAlexander Potashev (2):\n  Allow cloning to an existing empty directory\n  Use is_pseudo_dir_name everywhere\n\n builtin-clone.c         |    8 +++++---\n builtin-count-objects.c |    5 ++---\n builtin-fsck.c          |   14 ++++----------\n builtin-prune.c         |   14 ++++----------\n builtin-rerere.c        |   11 +++++------\n dir.c                   |   31 +++++++++++++++++++++++--------\n dir.h                   |    8 ++++++++\n entry.c                 |    5 ++---\n remote.c                |    6 ++----\n transport.c             |    4 +---\n 10 files changed, 56 insertions(+), 50 deletions(-)\n"},{"id":"99746","messageId":"1231457063-29186-2-git-send-email-aspotashev@gmail.com","threadId":"17057","inReplyTo":"1231457063-29186-1-git-send-email-aspotashev@gmail.com","subject":"[PATCH 1/2] Allow cloning to an existing empty directory","fromName":"Alexander Potashev","fromEmail":"aspotashev@gmail.com","sentAt":"2009-01-08T23:24:22Z","receivedAt":"2009-01-08T23:24:22Z","isPatch":true,"sender":{"key":"aspotashev@gmail.com","avatar":null},"body":"The die() message changed accordingly.\n\nThe previous behaviour was to only allow cloning when the destination\ndirectory doesn't exist.\n\nA new inline function is_pseudo_dir_name is used to check if the\ndirectory name is either \".\" or \"..\". It returns a non-zero value if\nthe given string is \".\" or \"..\". It's applicable to a lot of other Git\nsource code.\n\nSigned-off-by: Alexander Potashev <aspotashev@gmail.com>\n---\n builtin-clone.c |    8 +++++---\n dir.c           |   19 +++++++++++++++++++\n dir.h           |    8 ++++++++\n 3 files changed, 32 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin-clone.c b/builtin-clone.c\nindex f1a1a0c..e732f15 100644\n--- a/builtin-clone.c\n+++ b/builtin-clone.c\n@@ -357,6 +357,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \tstruct stat buf;\n \tconst char *repo_name, *repo, *work_tree, *git_dir;\n \tchar *path, *dir;\n+\tint dest_exists;\n \tconst struct ref *refs, *head_points_at, *remote_head, *mapped_refs;\n \tstruct strbuf key = STRBUF_INIT, value = STRBUF_INIT;\n \tstruct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;\n@@ -406,8 +407,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\tdir = guess_dir_name(repo_name, is_bundle, option_bare);\n \tstrip_trailing_slashes(dir);\n \n-\tif (!stat(dir, &buf))\n-\t\tdie(\"destination directory '%s' already exists.\", dir);\n+\tif ((dest_exists = !stat(dir, &buf)) && !is_empty_dir(dir))\n+\t\tdie(\"destination path '%s' already exists and is not \"\n+\t\t\t\"an empty directory.\", dir);\n \n \tstrbuf_addf(&reflog_msg, \"clone: from %s\", repo);\n \n@@ -431,7 +433,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \t\tif (safe_create_leading_directories_const(work_tree) < 0)\n \t\t\tdie(\"could not create leading directories of '%s': %s\",\n \t\t\t\t\twork_tree, strerror(errno));\n-\t\tif (mkdir(work_tree, 0755))\n+\t\tif (!dest_exists && mkdir(work_tree, 0755))\n \t\t\tdie(\"could not create work tree dir '%s': %s.\",\n \t\t\t\t\twork_tree, strerror(errno));\n \t\tset_git_work_tree(work_tree);\ndiff --git a/dir.c b/dir.c\nindex 0131983..bd97e50 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -779,6 +779,25 @@ int is_inside_dir(const char *dir)\n \treturn get_relative_cwd(buffer, sizeof(buffer), dir) != NULL;\n }\n \n+int is_empty_dir(const char *path)\n+{\n+\tDIR *dir = opendir(path);\n+\tstruct dirent *e;\n+\tint ret = 1;\n+\n+\tif (!dir)\n+\t\treturn 0;\n+\n+\twhile ((e = readdir(dir)) != NULL)\n+\t\tif (!is_pseudo_dir_name(e->d_name)) {\n+\t\t\tret = 0;\n+\t\t\tbreak;\n+\t\t}\n+\n+\tclosedir(dir);\n+\treturn ret;\n+}\n+\n int remove_dir_recursively(struct strbuf *path, int only_empty)\n {\n \tDIR *dir = opendir(path->buf);\ndiff --git a/dir.h b/dir.h\nindex 768425a..940e057 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -77,6 +77,14 @@ extern int file_exists(const char *);\n extern char *get_relative_cwd(char *buffer, int size, const char *dir);\n extern int is_inside_dir(const char *dir);\n \n+static inline int is_pseudo_dir_name(const char *name)\n+{\n+\treturn name[0] == '.' && (name[1] == '\\0' ||\n+\t\t(name[1] == '.' && name[2] == '\\0')); /* \".\" and \"..\" */\n+}\n+\n+extern int is_empty_dir(const char *dir);\n+\n extern void setup_standard_excludes(struct dir_struct *dir);\n extern int remove_dir_recursively(struct strbuf *path, int only_empty);\n \n-- \n1.6.1.77.g84c9\n"},{"id":"99747","messageId":"1231457063-29186-3-git-send-email-aspotashev@gmail.com","threadId":"17057","inReplyTo":"1231457063-29186-2-git-send-email-aspotashev@gmail.com","subject":"[PATCH 2/2] Use is_pseudo_dir_name everywhere","fromName":"Alexander Potashev","fromEmail":"aspotashev@gmail.com","sentAt":"2009-01-08T23:24:23Z","receivedAt":"2009-01-08T23:24:23Z","isPatch":true,"sender":{"key":"aspotashev@gmail.com","avatar":null},"body":"Signed-off-by: Alexander Potashev <aspotashev@gmail.com>\n---\n builtin-count-objects.c |    5 ++---\n builtin-fsck.c          |   14 ++++----------\n builtin-prune.c         |   14 ++++----------\n builtin-rerere.c        |   11 +++++------\n dir.c                   |   12 ++++--------\n entry.c                 |    5 ++---\n remote.c                |    6 ++----\n transport.c             |    4 +---\n 8 files changed, 24 insertions(+), 47 deletions(-)\n\ndiff --git a/builtin-count-objects.c b/builtin-count-objects.c\nindex ab35b65..492a173 100644\n--- a/builtin-count-objects.c\n+++ b/builtin-count-objects.c\n@@ -5,6 +5,7 @@\n  */\n \n #include \"cache.h\"\n+#include \"dir.h\"\n #include \"builtin.h\"\n #include \"parse-options.h\"\n \n@@ -21,9 +22,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,\n \t\tconst char *cp;\n \t\tint bad = 0;\n \n-\t\tif ((ent->d_name[0] == '.') &&\n-\t\t    (ent->d_name[1] == 0 ||\n-\t\t     ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))))\n+\t\tif (is_pseudo_dir_name(ent->d_name))\n \t\t\tcontinue;\n \t\tfor (cp = ent->d_name; *cp; cp++) {\n \t\t\tint ch = *cp;\ndiff --git a/builtin-fsck.c b/builtin-fsck.c\nindex 297b2c4..291ca8e 100644\n--- a/builtin-fsck.c\n+++ b/builtin-fsck.c\n@@ -10,6 +10,7 @@\n #include \"tree-walk.h\"\n #include \"fsck.h\"\n #include \"parse-options.h\"\n+#include \"dir.h\"\n \n #define REACHABLE 0x0001\n #define SEEN      0x0002\n@@ -395,19 +396,12 @@ static void fsck_dir(int i, char *path)\n \twhile ((de = readdir(dir)) != NULL) {\n \t\tchar name[100];\n \t\tunsigned char sha1[20];\n-\t\tint len = strlen(de->d_name);\n \n-\t\tswitch (len) {\n-\t\tcase 2:\n-\t\t\tif (de->d_name[1] != '.')\n-\t\t\t\tbreak;\n-\t\tcase 1:\n-\t\t\tif (de->d_name[0] != '.')\n-\t\t\t\tbreak;\n+\t\tif (is_pseudo_dir_name(de->d_name))\n \t\t\tcontinue;\n-\t\tcase 38:\n+\t\tif (strlen(de->d_name) == 38) {\n \t\t\tsprintf(name, \"%02x\", i);\n-\t\t\tmemcpy(name+2, de->d_name, len+1);\n+\t\t\tmemcpy(name+2, de->d_name, 39);\n \t\t\tif (get_sha1_hex(name, sha1) < 0)\n \t\t\t\tbreak;\n \t\t\tadd_sha1_list(sha1, DIRENT_SORT_HINT(de));\ndiff --git a/builtin-prune.c b/builtin-prune.c\nindex 7b4ec80..06b61ea 100644\n--- a/builtin-prune.c\n+++ b/builtin-prune.c\n@@ -5,6 +5,7 @@\n #include \"builtin.h\"\n #include \"reachable.h\"\n #include \"parse-options.h\"\n+#include \"dir.h\"\n \n static const char * const prune_usage[] = {\n \t\"git prune [-n] [-v] [--expire <time>] [--] [<head>...]\",\n@@ -61,19 +62,12 @@ static int prune_dir(int i, char *path)\n \twhile ((de = readdir(dir)) != NULL) {\n \t\tchar name[100];\n \t\tunsigned char sha1[20];\n-\t\tint len = strlen(de->d_name);\n \n-\t\tswitch (len) {\n-\t\tcase 2:\n-\t\t\tif (de->d_name[1] != '.')\n-\t\t\t\tbreak;\n-\t\tcase 1:\n-\t\t\tif (de->d_name[0] != '.')\n-\t\t\t\tbreak;\n+\t\tif (is_pseudo_dir_name(de->d_name))\n \t\t\tcontinue;\n-\t\tcase 38:\n+\t\tif (strlen(de->d_name) == 38) {\n \t\t\tsprintf(name, \"%02x\", i);\n-\t\t\tmemcpy(name+2, de->d_name, len+1);\n+\t\t\tmemcpy(name+2, de->d_name, 39);\n \t\t\tif (get_sha1_hex(name, sha1) < 0)\n \t\t\t\tbreak;\n \ndiff --git a/builtin-rerere.c b/builtin-rerere.c\nindex d4dec6b..1ac5225 100644\n--- a/builtin-rerere.c\n+++ b/builtin-rerere.c\n@@ -1,5 +1,6 @@\n #include \"builtin.h\"\n #include \"cache.h\"\n+#include \"dir.h\"\n #include \"string-list.h\"\n #include \"rerere.h\"\n #include \"xdiff/xdiff.h\"\n@@ -59,17 +60,15 @@ static void garbage_collect(struct string_list *rr)\n \tgit_config(git_rerere_gc_config, NULL);\n \tdir = opendir(git_path(\"rr-cache\"));\n \twhile ((e = readdir(dir))) {\n-\t\tconst char *name = e->d_name;\n-\t\tif (name[0] == '.' &&\n-\t\t    (name[1] == '\\0' || (name[1] == '.' && name[2] == '\\0')))\n+\t\tif (is_pseudo_dir_name (e->d_name))\n \t\t\tcontinue;\n-\t\tthen = rerere_created_at(name);\n+\t\tthen = rerere_created_at(e->d_name);\n \t\tif (!then)\n \t\t\tcontinue;\n-\t\tcutoff = (has_resolution(name)\n+\t\tcutoff = (has_resolution(e->d_name)\n \t\t\t  ? cutoff_resolve : cutoff_noresolve);\n \t\tif (then < now - cutoff * 86400)\n-\t\t\tstring_list_append(name, &to_remove);\n+\t\t\tstring_list_append(e->d_name, &to_remove);\n \t}\n \tfor (i = 0; i < to_remove.nr; i++)\n \t\tunlink_rr_item(to_remove.items[i].string);\ndiff --git a/dir.c b/dir.c\nindex bd97e50..cdd3beb 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -585,10 +585,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co\n \t\t\tint len, dtype;\n \t\t\tint exclude;\n \n-\t\t\tif ((de->d_name[0] == '.') &&\n-\t\t\t    (de->d_name[1] == 0 ||\n-\t\t\t     !strcmp(de->d_name + 1, \".\") ||\n-\t\t\t     !strcmp(de->d_name + 1, \"git\")))\n+\t\t\tif (is_pseudo_dir_name(de->d_name) ||\n+\t\t\t     !strcmp(de->d_name, \".git\"))\n \t\t\t\tcontinue;\n \t\t\tlen = strlen(de->d_name);\n \t\t\t/* Ignore overly long pathnames! */\n@@ -812,10 +810,8 @@ int remove_dir_recursively(struct strbuf *path, int only_empty)\n \tlen = path->len;\n \twhile ((e = readdir(dir)) != NULL) {\n \t\tstruct stat st;\n-\t\tif ((e->d_name[0] == '.') &&\n-\t\t    ((e->d_name[1] == 0) ||\n-\t\t     ((e->d_name[1] == '.') && e->d_name[2] == 0)))\n-\t\t\tcontinue; /* \".\" and \"..\" */\n+\t\tif (is_pseudo_dir_name(e->d_name))\n+\t\t\tcontinue;\n \n \t\tstrbuf_setlen(path, len);\n \t\tstrbuf_addstr(path, e->d_name);\ndiff --git a/entry.c b/entry.c\nindex aa2ee46..9c6a9cf 100644\n--- a/entry.c\n+++ b/entry.c\n@@ -1,5 +1,6 @@\n #include \"cache.h\"\n #include \"blob.h\"\n+#include \"dir.h\"\n \n static void create_directories(const char *path, const struct checkout *state)\n {\n@@ -62,9 +63,7 @@ static void remove_subtree(const char *path)\n \t*name++ = '/';\n \twhile ((de = readdir(dir)) != NULL) {\n \t\tstruct stat st;\n-\t\tif ((de->d_name[0] == '.') &&\n-\t\t    ((de->d_name[1] == 0) ||\n-\t\t     ((de->d_name[1] == '.') && de->d_name[2] == 0)))\n+\t\tif (is_pseudo_dir_name(de->d_name))\n \t\t\tcontinue;\n \t\tstrcpy(name, de->d_name);\n \t\tif (lstat(pathbuf, &st))\ndiff --git a/remote.c b/remote.c\nindex 570e112..2fb5143 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -4,6 +4,7 @@\n #include \"commit.h\"\n #include \"diff.h\"\n #include \"revision.h\"\n+#include \"dir.h\"\n \n static struct refspec s_tag_refspec = {\n \t0,\n@@ -634,10 +635,7 @@ static struct refspec *parse_push_refspec(int nr_refspec, const char **refspec)\n \n static int valid_remote_nick(const char *name)\n {\n-\tif (!name[0] || /* not empty */\n-\t    (name[0] == '.' && /* not \".\" */\n-\t     (!name[1] || /* not \"..\" */\n-\t      (name[1] == '.' && !name[2]))))\n+\tif (!name[0] || is_pseudo_dir_name(name))\n \t\treturn 0;\n \treturn !strchr(name, '/'); /* no slash */\n }\ndiff --git a/transport.c b/transport.c\nindex 56831c5..d4e3c25 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -50,9 +50,7 @@ static int read_loose_refs(struct strbuf *path, int name_offset,\n \tmemset (&list, 0, sizeof(list));\n \n \twhile ((de = readdir(dir))) {\n-\t\tif (de->d_name[0] == '.' && (de->d_name[1] == '\\0' ||\n-\t\t\t\t(de->d_name[1] == '.' &&\n-\t\t\t\t de->d_name[2] == '\\0')))\n+\t\tif (is_pseudo_dir_name(de->d_name))\n \t\t\tcontinue;\n \t\tALLOC_GROW(list.entries, list.nr + 1, list.alloc);\n \t\tlist.entries[list.nr++] = xstrdup(de->d_name);\n-- \n1.6.1.77.g84c9\n"},{"id":"99764","messageId":"4966F6BB.90408@viscovery.net","threadId":"17057","inReplyTo":"1231457063-29186-3-git-send-email-aspotashev@gmail.com","subject":"Re: [PATCH 2/2] Use is_pseudo_dir_name everywhere","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-01-09T07:03:23Z","receivedAt":"2009-01-09T07:03:23Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Alexander Potashev schrieb:\n> -\t\tif ((ent->d_name[0] == '.') &&\n> -\t\t    (ent->d_name[1] == 0 ||\n> -\t\t     ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))))\n> +\t\tif (is_pseudo_dir_name(ent->d_name))\n\nNit-pick: When I read the resulting code, then I will have to look up that\n  is_pseudo_dir_name() indeed only checks for \".\" and \"..\". But if it were\nnamed is_dot_or_dotdot(), then I would have to do that.\n\n-- Hannes\n"},{"id":"99765","messageId":"4966FB36.2030409@viscovery.net","threadId":"17057","inReplyTo":"4966F6BB.90408@viscovery.net","subject":"Re: [PATCH 2/2] Use is_pseudo_dir_name everywhere","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-01-09T07:22:30Z","receivedAt":"2009-01-09T07:22:30Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Johannes Sixt schrieb:\n> Alexander Potashev schrieb:\n>> -\t\tif ((ent->d_name[0] == '.') &&\n>> -\t\t    (ent->d_name[1] == 0 ||\n>> -\t\t     ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))))\n>> +\t\tif (is_pseudo_dir_name(ent->d_name))\n> \n> Nit-pick: When I read the resulting code, then I will have to look up that\n>   is_pseudo_dir_name() indeed only checks for \".\" and \"..\". But if it were\n> named is_dot_or_dotdot(), then I would have to do that.\n\n... then I would *not* have to do that, of course.\n\n-- Hannes\n"},{"id":"99767","messageId":"7vy6xk280e.fsf@gitster.siamese.dyndns.org","threadId":"17057","inReplyTo":"4966FB36.2030409@viscovery.net","subject":"Re: [PATCH 2/2] Use is_pseudo_dir_name everywhere","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-09T08:33:53Z","receivedAt":"2009-01-09T08:33:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j.sixt@viscovery.net> writes:\n\n> Johannes Sixt schrieb:\n>> Alexander Potashev schrieb:\n>>> -\t\tif ((ent->d_name[0] == '.') &&\n>>> -\t\t    (ent->d_name[1] == 0 ||\n>>> -\t\t     ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))))\n>>> +\t\tif (is_pseudo_dir_name(ent->d_name))\n>> \n>> Nit-pick: When I read the resulting code, then I will have to look up that\n>>   is_pseudo_dir_name() indeed only checks for \".\" and \"..\". But if it were\n>> named is_dot_or_dotdot(), then I would have to do that.\n>\n> ... then I would *not* have to do that, of course.\n\nI think the unstated motivation of this choice of the name is to keep the\ndoor open to include lost+found and friends to the repertoire, and perhaps\nto have an isolated place for customization for non-POSIX platforms and\nfor local conventions.  It is more like is_uninteresting_dirent_name().\n\nAs long as this function is used only to detect and skip \"uninteresting\"\ndirent, I think that is not a bad direction.\n\nOn the other hand, I am a bit worried about is_empty_dir() abused outside\nits intended purpose to say \"this directory does not have anything\ninteresting\".  E.g. \"Oh, it's empty so we can nuke it\":\n\n\tif (is_empty_dir(dir))\n        \trmdir(dir);\n\neven though the current callers do not do something crazy like this (the\nusual order we do things is rmdir() and then check for errors).\n"},{"id":"99780","messageId":"20090109102407.GA4089@myhost","threadId":"17057","inReplyTo":"7vy6xk280e.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 2/2] Use is_pseudo_dir_name everywhere","fromName":"Alexander Potashev","fromEmail":"aspotashev@gmail.com","sentAt":"2009-01-09T10:24:07Z","receivedAt":"2009-01-09T10:24:07Z","isPatch":true,"sender":{"key":"aspotashev@gmail.com","avatar":null},"body":"On 00:33 Fri 09 Jan     , Junio C Hamano wrote:\n> Johannes Sixt <j.sixt@viscovery.net> writes:\n> \n> > Johannes Sixt schrieb:\n> >> Alexander Potashev schrieb:\n> >>> -\t\tif ((ent->d_name[0] == '.') &&\n> >>> -\t\t    (ent->d_name[1] == 0 ||\n> >>> -\t\t     ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))))\n> >>> +\t\tif (is_pseudo_dir_name(ent->d_name))\n> >> \n> >> Nit-pick: When I read the resulting code, then I will have to look up that\n> >>   is_pseudo_dir_name() indeed only checks for \".\" and \"..\". But if it were\n> >> named is_dot_or_dotdot(), then I would have to do that.\n> >\n> > ... then I would *not* have to do that, of course.\n> \n> I think the unstated motivation of this choice of the name is to keep the\n> door open to include lost+found and friends to the repertoire, and perhaps\n> to have an isolated place for customization for non-POSIX platforms and\n> for local conventions.  It is more like is_uninteresting_dirent_name().\n\nI didn't think over the support of 'lost+found'. But the name like\nis_uninteresting_dirent_name is more flexible, indeed. I prefer a bit\nshorter name, 'is_dummy_dirent_name'.\n\nBut if you're going to support 'lost+found's, remember that a Git\nrepository might have its own 'lost+found' directory. It's a bit crazy,\nbut it's possible:\n\t---\n\t lost+found/file |    1 +\n\t 1 files changed, 1 insertions(+), 0 deletions(-)\n\t create mode 100644 lost+found/file\n\n\tdiff --git a/lost+found/file b/lost+found/file\n\tnew file mode 100644\n\tindex 0000000..190a180\n\t--- /dev/null\n\t+++ b/lost+found/file\n\t@@ -0,0 +1 @@\n\t+123\n\t-- \n\nGit shouldn't allow to clone at least repositories that have lost+found\ndirectory into a directory with already existing lost+found (neither\nit's a ordinary directory created using 'mkdir' nor it's an ext2's\nproperty)\n\nWe should probably forbid cloning to a directory with lost+found,\nbecause a 'lost+found' may appear after pulling from somebody and the\nuser won't be able to resolve this anyhow.\n\n> \n> As long as this function is used only to detect and skip \"uninteresting\"\n> dirent, I think that is not a bad direction.\n> \n> On the other hand, I am a bit worried about is_empty_dir() abused outside\n> its intended purpose to say \"this directory does not have anything\n> interesting\".  E.g. \"Oh, it's empty so we can nuke it\":\n\nI propose to rename it (if it's really necessary) to is_clean_dir, which\nmeans \"There's no old crap here, we can safely clone\".\n\n> \n> \tif (is_empty_dir(dir))\n>         \trmdir(dir);\n> \n> even though the current callers do not do something crazy like this (the\n> usual order we do things is rmdir() and then check for errors).\n\nI think, it's rather early to send [PATCHES v2] (with updated function\nnames), will wait for your comments.\n"},{"id":"99849","messageId":"7viqonzxiw.fsf@gitster.siamese.dyndns.org","threadId":"17057","inReplyTo":"20090109102407.GA4089@myhost","subject":"Re: [PATCH 2/2] Use is_pseudo_dir_name everywhere","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-10T02:48:39Z","receivedAt":"2009-01-10T02:48:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alexander Potashev <aspotashev@gmail.com> writes:\n\n> I didn't think over the support of 'lost+found'.\n\nYeah, I do not think it is particularly a good idea, but that is what (I\nthought) you implied in your original message.  \n\nIn any case, you can always do\n\n    $ git clone -n $there it.git\n    $ mv it.git/.git . && rmdir it.git && git checkout -f\n\nor something like that (adjust what you move out of it.git when you are\ndoing a bare clone), so in that sense I do not deeply care about the\nmotivation of your patch myself.\n\nBut I liked the helper function to abstract away the many identical checks\nwe do for \"is it a dot or a dot dot?\", and that was the primary reason why\nI commented on your patches.\n"}]}