{"thread":{"id":"17075","subject":"[PATCH] add is_dot_or_dotdot inline function","startedAt":"2009-01-10T12:07:50Z","lastAt":"2009-01-11T22:19:51Z","messageCount":3,"participants":["Alexander Potashev","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"99879","messageId":"1231589270-15812-1-git-send-email-aspotashev@gmail.com","threadId":"17075","inReplyTo":null,"subject":"[PATCH] add is_dot_or_dotdot inline function","fromName":"Alexander Potashev","fromEmail":"aspotashev@gmail.com","sentAt":"2009-01-10T12:07:50Z","receivedAt":"2009-01-10T12:07:50Z","isPatch":true,"sender":{"key":"aspotashev@gmail.com","avatar":null},"body":"A new inline function is_dot_or_dotdot 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 Git\nsource code.\n\nSigned-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 dir.h                   |    6 ++++++\n entry.c                 |    5 ++---\n remote.c                |    6 ++----\n transport.c             |    4 +---\n 9 files changed, 30 insertions(+), 47 deletions(-)\n\ndiff --git a/builtin-count-objects.c b/builtin-count-objects.c\nindex ab35b65..62fd1f0 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_dot_or_dotdot(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..79b87ed 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_dot_or_dotdot(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..545e9c1 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_dot_or_dotdot(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..bd8fc77 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_dot_or_dotdot(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 0131983..3347f46 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_dot_or_dotdot(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@@ -793,10 +791,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_dot_or_dotdot(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/dir.h b/dir.h\nindex 768425a..e1640a8 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -77,6 +77,12 @@ 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_dot_or_dotdot(const char *name)\n+{\n+\treturn name[0] == '.' && (name[1] == '\\0' ||\n+\t\t(name[1] == '.' && name[2] == '\\0')); /* \".\" and \"..\" */\n+}\n+\n extern void setup_standard_excludes(struct dir_struct *dir);\n extern int remove_dir_recursively(struct strbuf *path, int only_empty);\n \ndiff --git a/entry.c b/entry.c\nindex aa2ee46..5f24816 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_dot_or_dotdot(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..d7079c6 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_dot_or_dotdot(name))\n \t\treturn 0;\n \treturn !strchr(name, '/'); /* no slash */\n }\ndiff --git a/transport.c b/transport.c\nindex 56831c5..9ad4a16 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_dot_or_dotdot(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.76.gc123b.dirty\n"},{"id":"99951","messageId":"1231676352-16082-1-git-send-email-aspotashev@gmail.com","threadId":"17075","inReplyTo":"1231589270-15812-1-git-send-email-aspotashev@gmail.com","subject":"[PATCH] Allow cloning to an existing empty directory","fromName":"Alexander Potashev","fromEmail":"aspotashev@gmail.com","sentAt":"2009-01-11T12:19:12Z","receivedAt":"2009-01-11T12:19:12Z","isPatch":true,"sender":{"key":"aspotashev@gmail.com","avatar":null},"body":"The die() message updated accordingly.\n\nThe previous behaviour was to only allow cloning when the destination\ndirectory doesn't exist.\n\nSigned-off-by: Alexander Potashev <aspotashev@gmail.com>\n---\n builtin-clone.c |    8 +++++---\n dir.c           |   19 +++++++++++++++++++\n dir.h           |    2 ++\n 3 files changed, 26 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 3347f46..7c59829 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -777,6 +777,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_dot_or_dotdot(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 e1640a8..c950c83 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -83,6 +83,8 @@ static inline int is_dot_or_dotdot(const char *name)\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\n"},{"id":"100015","messageId":"7vr639pjso.fsf@gitster.siamese.dyndns.org","threadId":"17075","inReplyTo":"1231676352-16082-1-git-send-email-aspotashev@gmail.com","subject":"Re: [PATCH] Allow cloning to an existing empty directory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-11T22:19:51Z","receivedAt":"2009-01-11T22:19:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thanks; will queue both with minor style fix-ups and a trivial test.\n"}]}