{"thread":{"id":"22651","subject":"[PATCH v3 1/5] make_absolute_path(): Do not append redundant slash","startedAt":"2010-02-14T15:44:41Z","lastAt":"2010-02-16T19:47:49Z","messageCount":8,"participants":["Nguyễn Thái Ngọc Duy","Johannes Sixt","=?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?="],"isPatch":true,"patchVersion":3,"patchTotal":5},"messages":[{"id":"134543","messageId":"1266162285-10955-1-git-send-email-pclouds@gmail.com","threadId":"22651","inReplyTo":null,"subject":"[PATCH v3 1/5] make_absolute_path(): Do not append redundant slash","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-02-14T15:44:41Z","receivedAt":"2010-02-14T15:44:41Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"When concatenating two paths, if the first one already have '/', do\nnot put another '/' in between the two paths.\n\nUsually this is not the case as getcwd() won't return '/foo/bar/',\nexcept when you are standing at root, then it will return '/'.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n abspath.c |    5 +++--\n 1 files changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/abspath.c b/abspath.c\nindex b88122c..c91a29c 100644\n--- a/abspath.c\n+++ b/abspath.c\n@@ -54,8 +54,9 @@ const char *make_absolute_path(const char *path)\n \t\t\tif (len + strlen(last_elem) + 2 > PATH_MAX)\n \t\t\t\tdie (\"Too long path name: '%s/%s'\",\n \t\t\t\t\t\tbuf, last_elem);\n-\t\t\tbuf[len] = '/';\n-\t\t\tstrcpy(buf + len + 1, last_elem);\n+\t\t\tif (len && buf[len-1] != '/')\n+\t\t\t\tbuf[len++] = '/';\n+\t\t\tstrcpy(buf + len, last_elem);\n \t\t\tfree(last_elem);\n \t\t\tlast_elem = NULL;\n \t\t}\n-- \n1.7.0.195.g637a2\n"},{"id":"134544","messageId":"1266162285-10955-2-git-send-email-pclouds@gmail.com","threadId":"22651","inReplyTo":"1266162285-10955-1-git-send-email-pclouds@gmail.com","subject":"[PATCH v3 2/5] init-db, rev-parse --git-dir: do not append redundant slash","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-02-14T15:44:42Z","receivedAt":"2010-02-14T15:44:42Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"If git_dir already has the trailing slash, don't put another one\nbefore .git. This only happens when git_dir is '/' or 'C:/'\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin-init-db.c   |    9 ++++++---\n builtin-rev-parse.c |    4 +++-\n 2 files changed, 9 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex dd84cae..aae7a4d 100644\n--- a/builtin-init-db.c\n+++ b/builtin-init-db.c\n@@ -331,11 +331,14 @@ int init_db(const char *template_dir, unsigned int flags)\n \t\tgit_config_set(\"receive.denyNonFastforwards\", \"true\");\n \t}\n \n-\tif (!(flags & INIT_DB_QUIET))\n-\t\tprintf(\"%s%s Git repository in %s/\\n\",\n+\tif (!(flags & INIT_DB_QUIET)) {\n+\t\tconst char *git_dir = get_git_dir();\n+\t\tint len = strlen(git_dir);\n+\t\tprintf(\"%s%s Git repository in %s%s\\n\",\n \t\t       reinit ? \"Reinitialized existing\" : \"Initialized empty\",\n \t\t       shared_repository ? \" shared\" : \"\",\n-\t\t       get_git_dir());\n+\t\t       git_dir, len && git_dir[len-1] != '/' ? \"/\" : \"\");\n+\t}\n \n \treturn 0;\n }\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex a8c5043..88bad9a 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -637,6 +637,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\tif (!strcmp(arg, \"--git-dir\")) {\n \t\t\t\tconst char *gitdir = getenv(GIT_DIR_ENVIRONMENT);\n \t\t\t\tstatic char cwd[PATH_MAX];\n+\t\t\t\tint len;\n \t\t\t\tif (gitdir) {\n \t\t\t\t\tputs(gitdir);\n \t\t\t\t\tcontinue;\n@@ -647,7 +648,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\t}\n \t\t\t\tif (!getcwd(cwd, PATH_MAX))\n \t\t\t\t\tdie_errno(\"unable to get current working directory\");\n-\t\t\t\tprintf(\"%s/.git\\n\", cwd);\n+\t\t\t\tlen = strlen(cwd);\n+\t\t\t\tprintf(\"%s%s.git\\n\", cwd, len && cwd[len-1] != '/' ? \"/\" : \"\");\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--is-inside-git-dir\")) {\n-- \n1.7.0.195.g637a2\n"},{"id":"134547","messageId":"1266162285-10955-3-git-send-email-pclouds@gmail.com","threadId":"22651","inReplyTo":"1266162285-10955-1-git-send-email-pclouds@gmail.com","subject":"[PATCH v3 3/5] Move offset_1st_component() to path.c","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-02-14T15:44:43Z","receivedAt":"2010-02-14T15:44:43Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n cache.h     |    1 +\n path.c      |    7 +++++++\n sha1_file.c |    7 -------\n 3 files changed, 8 insertions(+), 7 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex d478eff..ff23cd1 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -675,6 +675,7 @@ int normalize_path_copy(char *dst, const char *src);\n int longest_ancestor_length(const char *path, const char *prefix_list);\n char *strip_path_suffix(const char *path, const char *suffix);\n int daemon_avoid_alias(const char *path);\n+int offset_1st_component(const char *path);\n \n /* Read and unpack a sha1 file into memory, write memory to a sha1 file */\n extern int sha1_object_info(const unsigned char *, unsigned long *);\ndiff --git a/path.c b/path.c\nindex 0005df3..fd70e88 100644\n--- a/path.c\n+++ b/path.c\n@@ -649,3 +649,10 @@ int daemon_avoid_alias(const char *p)\n \t\t}\n \t}\n }\n+\n+int offset_1st_component(const char *path)\n+{\n+\tif (has_dos_drive_prefix(path))\n+\t\treturn 2 + (path[2] == '/');\n+\treturn *path == '/';\n+}\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 657825e..52052b9 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -35,13 +35,6 @@ static size_t sz_fmt(size_t s) { return s; }\n \n const unsigned char null_sha1[20];\n \n-static inline int offset_1st_component(const char *path)\n-{\n-\tif (has_dos_drive_prefix(path))\n-\t\treturn 2 + (path[2] == '/');\n-\treturn *path == '/';\n-}\n-\n int safe_create_leading_directories(char *path)\n {\n \tchar *pos = path + offset_1st_component(path);\n-- \n1.7.0.195.g637a2\n"},{"id":"134546","messageId":"1266162285-10955-4-git-send-email-pclouds@gmail.com","threadId":"22651","inReplyTo":"1266162285-10955-1-git-send-email-pclouds@gmail.com","subject":"[PATCH v3 4/5] Support working directory located at root","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-02-14T15:44:44Z","receivedAt":"2010-02-14T15:44:44Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Git should work regardless where the working directory is located,\neven at root. This patch fixes two places where it assumes working\ndirectory always have parent directory.\n\nIn setup_git_directory_gently(), when Git goes up to root and finds\n.git there, it happily sets worktree to \"\" instead of \"/\".\n\nIn prefix_path(), loosen the outside repo check a little bit. Usually\nwhen a path XXX is inside worktree /foo, it must be either \"/foo\", or\n\"/foo/...\". When worktree is simply \"/\", we can safely ignore the\ncheck: we have a slash at the beginning already.\n\nNot related to worktree, but also set gitdir correctly if a bare repo\nis placed (insanely?) at root.\n\nThanks João Carlos Mendes Luís for pointing out this problem.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n setup.c |   13 ++++++++-----\n 1 files changed, 8 insertions(+), 5 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex b38cbee..08df00e 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -18,14 +18,15 @@ const char *prefix_path(const char *prefix, int len, const char *path)\n \tif (normalize_path_copy(sanitized, sanitized))\n \t\tgoto error_out;\n \tif (is_absolute_path(orig)) {\n-\t\tsize_t len, total;\n+\t\tsize_t root_len, len, total;\n \t\tconst char *work_tree = get_git_work_tree();\n \t\tif (!work_tree)\n \t\t\tgoto error_out;\n \t\tlen = strlen(work_tree);\n+\t\troot_len = offset_1st_component(work_tree);\n \t\ttotal = strlen(sanitized) + 1;\n \t\tif (strncmp(sanitized, work_tree, len) ||\n-\t\t    (sanitized[len] != '\\0' && sanitized[len] != '/')) {\n+\t\t    (len > root_len && sanitized[len] != '\\0' && sanitized[len] != '/')) {\n \t\terror_out:\n \t\t\tdie(\"'%s' is outside repository\", orig);\n \t\t}\n@@ -321,7 +322,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \tstatic char cwd[PATH_MAX+1];\n \tconst char *gitdirenv;\n \tconst char *gitfile_dir;\n-\tint len, offset, ceil_offset;\n+\tint len, offset, ceil_offset, root_len;\n \n \t/*\n \t * Let's assume that we are in a git repository.\n@@ -403,7 +404,8 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\tif (!work_tree_env)\n \t\t\t\tinside_work_tree = 0;\n \t\t\tif (offset != len) {\n-\t\t\t\tcwd[offset] = '\\0';\n+\t\t\t\troot_len = offset_1st_component(cwd);\n+\t\t\t\tcwd[offset > root_len ? offset : root_len] = '\\0';\n \t\t\t\tset_git_dir(cwd);\n \t\t\t} else\n \t\t\t\tset_git_dir(\".\");\n@@ -427,7 +429,8 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \tinside_git_dir = 0;\n \tif (!work_tree_env)\n \t\tinside_work_tree = 1;\n-\tgit_work_tree_cfg = xstrndup(cwd, offset);\n+\troot_len = offset_1st_component(cwd);\n+\tgit_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);\n \tif (check_repository_format_gently(nongit_ok))\n \t\treturn NULL;\n \tif (offset == len)\n-- \n1.7.0.195.g637a2\n"},{"id":"134545","messageId":"1266162285-10955-5-git-send-email-pclouds@gmail.com","threadId":"22651","inReplyTo":"1266162285-10955-1-git-send-email-pclouds@gmail.com","subject":"[PATCH v3 5/5] Add test for using Git at root of file system","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-02-14T15:44:45Z","receivedAt":"2010-02-14T15:44:45Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This kind of test requires a throw-away root filesystem so that it can\nplay on. If you have such a system, go ahead, \"chmod 777 /\" and run\nthis test manually. Because this is a dangerous test, you are required\nto set an env variable, and not to use root to run it.\n\nScript prepare-root.sh may help you set up a chroot environment with\nGit test suite inside. You will need Linux, static linked busybox,\nrsync and root permission to use it.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n t/t1509-root-worktree.sh  |  249 +++++++++++++++++++++++++++++++++++++++++++++\n t/t1509/excludes          |   14 +++\n t/t1509/prepare-chroot.sh |   38 +++++++\n 3 files changed, 301 insertions(+), 0 deletions(-)\n create mode 100755 t/t1509-root-worktree.sh\n create mode 100644 t/t1509/excludes\n create mode 100755 t/t1509/prepare-chroot.sh\n\ndiff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh\nnew file mode 100755\nindex 0000000..5322a3b\n--- /dev/null\n+++ b/t/t1509-root-worktree.sh\n@@ -0,0 +1,249 @@\n+#!/bin/sh\n+\n+test_description='Test Git when git repository is located at root\n+\n+This test requires write access in root. Do not bother if you do not\n+have a throwaway chroot or VM.\n+\n+Script t1509/prepare-chroot.sh may help you setup chroot, then you\n+can chroot in and execute this test from there.\n+'\n+\n+. ./test-lib.sh\n+\n+test_cmp_val() {\n+\techo \"$1\" > expected\n+\techo \"$2\" > result\n+\ttest_cmp expected result\n+}\n+\n+test_vars() {\n+\ttest_expect_success \"$1: gitdir\" '\n+\t\ttest_cmp_val \"'\"$2\"'\" \"$(git rev-parse --git-dir)\"\n+\t'\n+\n+\ttest_expect_success \"$1: worktree\" '\n+\t\ttest_cmp_val \"'\"$3\"'\" \"$(git rev-parse --show-toplevel)\"\n+\t'\n+\n+\ttest_expect_success \"$1: prefix\" '\n+\t\ttest_cmp_val \"'\"$4\"'\" \"$(git rev-parse --show-prefix)\"\n+\t'\n+}\n+\n+test_foobar_root() {\n+\ttest_expect_success 'add relative' '\n+\t\ttest -z \"$(cd / && git ls-files)\" &&\n+\t\tgit add foo/foome &&\n+\t\tgit add foo/bar/barme &&\n+\t\tgit add me &&\n+\t\t( cd / && git ls-files --stage ) > result &&\n+\t\ttest_cmp /ls.expected result &&\n+\t\trm \"$(git rev-parse --git-dir)/index\"\n+\t'\n+\n+\ttest_expect_success 'add absolute' '\n+\t\ttest -z \"$(cd / && git ls-files)\" &&\n+\t\tgit add /foo/foome &&\n+\t\tgit add /foo/bar/barme &&\n+\t\tgit add /me &&\n+\t\t( cd / && git ls-files --stage ) > result &&\n+\t\ttest_cmp /ls.expected result &&\n+\t\trm \"$(git rev-parse --git-dir)/index\"\n+\t'\n+\n+}\n+\n+test_foobar_foo() {\n+\ttest_expect_success 'add relative' '\n+\t\ttest -z \"$(cd / && git ls-files)\" &&\n+\t\tgit add foome &&\n+\t\tgit add bar/barme &&\n+\t\tgit add ../me &&\n+\t\t( cd / && git ls-files --stage ) > result &&\n+\t\ttest_cmp /ls.expected result &&\n+\t\trm \"$(git rev-parse --git-dir)/index\"\n+\t'\n+\n+\ttest_expect_success 'add absolute' '\n+\t\ttest -z \"$(cd / && git ls-files)\" &&\n+\t\tgit add /foo/foome &&\n+\t\tgit add /foo/bar/barme &&\n+\t\tgit add /me &&\n+\t\t( cd / && git ls-files --stage ) > result &&\n+\t\ttest_cmp /ls.expected result &&\n+\t\trm \"$(git rev-parse --git-dir)/index\"\n+\t'\n+}\n+\n+test_foobar_foobar() {\n+\ttest_expect_success 'add relative' '\n+\t\ttest -z \"$(cd / && git ls-files)\" &&\n+\t\tgit add ../foome &&\n+\t\tgit add barme &&\n+\t\tgit add ../../me &&\n+\t\t( cd / && git ls-files --stage ) > result &&\n+\t\ttest_cmp /ls.expected result &&\n+\t\trm \"$(git rev-parse --git-dir)/index\"\n+\t'\n+\n+\ttest_expect_success 'add absolute' '\n+\t\ttest -z \"$(cd / && git ls-files)\" &&\n+\t\tgit add /foo/foome &&\n+\t\tgit add /foo/bar/barme &&\n+\t\tgit add /me &&\n+\t\t( cd / && git ls-files --stage ) > result &&\n+\t\ttest_cmp /ls.expected result &&\n+\t\trm \"$(git rev-parse --git-dir)/index\"\n+\t'\n+}\n+\n+if ! test_have_prereq POSIXPERM || ! [ -w / ]; then\n+\tsay \"Dangerous test skipped. Read this test if you want to execute it\"\n+\ttest_done\n+fi\n+\n+if [ \"$IKNOWWHATIAMDOING\" != \"YES\" ]; then\n+\tsay \"You must set env var IKNOWWHATIAMDOING=YES in order to run this test\"\n+\ttest_done\n+fi\n+\n+if [ \"$UID\" = 0 ]; then\n+\tsay \"No you can't run this with root\"\n+\ttest_done\n+fi\n+\n+ONE_SHA1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d\n+\n+test_expect_success 'setup' '\n+\trm -rf /foo\n+\tmkdir /foo &&\n+\tmkdir /foo/bar &&\n+\techo 1 > /foo/foome &&\n+\techo 1 > /foo/bar/barme &&\n+\techo 1 > /me\n+'\n+\n+say \"GIT_DIR absolute, GIT_WORK_TREE set\"\n+\n+test_expect_success 'go to /' 'cd /'\n+\n+cat >ls.expected <<EOF\n+100644 $ONE_SHA1 0\tfoo/bar/barme\n+100644 $ONE_SHA1 0\tfoo/foome\n+100644 $ONE_SHA1 0\tme\n+EOF\n+\n+export GIT_DIR=\"$TRASH_DIRECTORY/.git\"\n+export GIT_WORK_TREE=/\n+\n+test_vars 'abs gitdir, root' \"$GIT_DIR\" \"/\" \"\"\n+test_foobar_root\n+\n+test_expect_success 'go to /foo' 'cd /foo'\n+\n+test_vars 'abs gitdir, foo' \"$GIT_DIR\" \"/\" \"foo/\"\n+test_foobar_foo\n+\n+test_expect_success 'go to /foo/bar' 'cd /foo/bar'\n+\n+test_vars 'abs gitdir, foo/bar' \"$GIT_DIR\" \"/\" \"foo/bar/\"\n+test_foobar_foobar\n+\n+say \"GIT_DIR relative, GIT_WORK_TREE set\"\n+\n+test_expect_success 'go to /' 'cd /'\n+\n+export GIT_DIR=\"$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git\"\n+export GIT_WORK_TREE=/\n+\n+test_vars 'rel gitdir, root' \"$GIT_DIR\" \"/\" \"\"\n+test_foobar_root\n+\n+test_expect_success 'go to /foo' 'cd /foo'\n+\n+export GIT_DIR=\"../$TRASH_DIRECTORY/.git\"\n+export GIT_WORK_TREE=/\n+\n+test_vars 'rel gitdir, foo' \"$TRASH_DIRECTORY/.git\" \"/\" \"foo/\"\n+test_foobar_foo\n+\n+test_expect_success 'go to /foo/bar' 'cd /foo/bar'\n+\n+export GIT_DIR=\"../../$TRASH_DIRECTORY/.git\"\n+export GIT_WORK_TREE=/\n+\n+test_vars 'rel gitdir, foo/bar' \"$TRASH_DIRECTORY/.git\" \"/\" \"foo/bar/\"\n+test_foobar_foobar\n+\n+say \"GIT_DIR relative, GIT_WORK_TREE relative\"\n+\n+test_expect_success 'go to /' 'cd /'\n+\n+export GIT_DIR=\"$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git\"\n+export GIT_WORK_TREE=.\n+\n+test_vars 'rel gitdir, root' \"$GIT_DIR\" \"/\" \"\"\n+test_foobar_root\n+\n+test_expect_success 'go to /' 'cd /foo'\n+\n+export GIT_DIR=\"../$TRASH_DIRECTORY/.git\"\n+export GIT_WORK_TREE=..\n+\n+test_vars 'rel gitdir, foo' \"$TRASH_DIRECTORY/.git\" \"/\" \"foo/\"\n+test_foobar_foo\n+\n+test_expect_success 'go to /foo/bar' 'cd /foo/bar'\n+\n+export GIT_DIR=\"../../$TRASH_DIRECTORY/.git\"\n+export GIT_WORK_TREE=../..\n+\n+test_vars 'rel gitdir, foo/bar' \"$TRASH_DIRECTORY/.git\" \"/\" \"foo/bar/\"\n+test_foobar_foobar\n+\n+say \".git at root\"\n+\n+unset GIT_DIR\n+unset GIT_WORK_TREE\n+\n+test_expect_success 'go to /' 'cd /'\n+test_expect_success 'setup' '\n+\trm -rf /.git\n+\techo \"Initialized empty Git repository in /.git/\" > expected &&\n+\tgit init > result &&\n+\ttest_cmp expected result\n+'\n+\n+test_vars 'auto gitdir, root' \".git\" \"/\" \"\"\n+test_foobar_root\n+\n+test_expect_success 'go to /foo' 'cd /foo'\n+test_vars 'auto gitdir, foo' \"/.git\" \"/\" \"foo/\"\n+test_foobar_foo\n+\n+test_expect_success 'go to /foo/bar' 'cd /foo/bar'\n+test_vars 'auto gitdir, foo/bar' \"/.git\" \"/\" \"foo/bar/\"\n+test_foobar_foobar\n+\n+test_expect_success 'cleanup' 'rm -rf /.git'\n+\n+say \"auto bare gitdir\"\n+\n+# DESTROYYYYY!!!!!\n+test_expect_success 'setup' '\n+\trm -rf /refs /objects /info /hooks\n+\trm /*\n+\tcd / &&\n+\techo \"Initialized empty Git repository in /\" > expected &&\n+\tgit init --bare > result &&\n+\ttest_cmp expected result\n+'\n+\n+test_vars 'auto gitdir, root' \".\" \"\" \"\"\n+\n+test_expect_success 'go to /foo' 'cd /foo'\n+\n+test_vars 'auto gitdir, root' \"/\" \"\" \"\"\n+\n+test_done\ndiff --git a/t/t1509/excludes b/t/t1509/excludes\nnew file mode 100644\nindex 0000000..d4d21d3\n--- /dev/null\n+++ b/t/t1509/excludes\n@@ -0,0 +1,14 @@\n+*.o\n+*~\n+*.bak\n+*.c\n+*.h\n+.git\n+contrib\n+Documentation\n+git-gui\n+gitk-git\n+gitweb\n+t/t4013\n+t/t5100\n+t/t5515\ndiff --git a/t/t1509/prepare-chroot.sh b/t/t1509/prepare-chroot.sh\nnew file mode 100755\nindex 0000000..c5334a8\n--- /dev/null\n+++ b/t/t1509/prepare-chroot.sh\n@@ -0,0 +1,38 @@\n+#!/bin/sh\n+\n+die() {\n+\techo >&2 \"$@\"\n+\texit 1\n+}\n+\n+xmkdir() {\n+\twhile [ -n \"$1\" ]; do\n+\t\t[ -d \"$1\" ] || mkdir \"$1\" || die \"Unable to mkdir $1\"\n+\t\tshift\n+\tdone\n+}\n+\n+R=\"$1\"\n+\n+[ -n \"$R\" ] || die \"Usage: prepare-chroot.sh <root>\"\n+[ -x git ] || die \"This script needs to be executed at git source code's top directory\"\n+[ -x /bin/busybox ] || die \"You need busybox\"\n+\n+xmkdir \"$R\" \"$R/bin\" \"$R/etc\" \"$R/lib\" \"$R/dev\"\n+[ -c \"$R/dev/null\" ] || die \"/dev/null is missing. Do mknod $R/dev/null c 1 3 && chmod 666 $R/dev/null\"\n+echo \"root:x:0:0:root:/:/bin/sh\" > \"$R/etc/passwd\"\n+echo \"$(id -nu):x:$(id -u):$(id -g)::$(pwd)/t:/bin/sh\" >> \"$R/etc/passwd\"\n+echo \"root::0:root\" > \"$R/etc/group\"\n+echo \"$(id -ng)::$(id -g):$(id -nu)\" >> \"$R/etc/group\"\n+\n+[ -x \"$R/bin/busybox\" ] || cp /bin/busybox \"$R/bin/busybox\"\n+[ -x \"$R/bin/sh\" ] || ln -s /bin/busybox \"$R/bin/sh\"\n+[ -x \"$R/bin/su\" ] || ln -s /bin/busybox \"$R/bin/su\"\n+\n+mkdir -p \"$R$(pwd)\"\n+rsync --exclude-from t/t1509/excludes -Ha . \"$R$(pwd)\"\n+ldd git | grep '/' | sed 's,.*\\s\\(/[^ ]*\\).*,\\1,' | while read i; do\n+\tmkdir -p \"$R$(dirname $i)\"\n+\tcp \"$i\" \"$R/$i\"\n+done\n+echo \"Execute this in root: 'chroot $R /bin/su - $(id -nu)'\"\n-- \n1.7.0.195.g637a2\n"},{"id":"134657","messageId":"4B79A3ED.4090308@kdbg.org","threadId":"22651","inReplyTo":"1266162285-10955-3-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH v3 3/5] Move offset_1st_component() to path.c","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-02-15T19:43:41Z","receivedAt":"2010-02-15T19:43:41Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Nguyễn Thái Ngọc Duy schrieb:\n> +int offset_1st_component(const char *path)\n> +{\n> +\tif (has_dos_drive_prefix(path))\n> +\t\treturn 2 + (path[2] == '/');\n> +\treturn *path == '/';\n> +}\n\nI'd have expected that you future-proofed this function by using \nis_dir_sep() or even use your previous implementation of is_root_path \n(because this implementation is a bit cryptic).\n\nBut if the new callers of this function will only pass the results of \nnormalize_path_copy() and getcwd() (both return only forward-slashes on \nWindows), then I'm fine with this version. Do they?\n\n-- Hannes\n"},{"id":"134698","messageId":"20100216052208.GA18438@do","threadId":"22651","inReplyTo":"4B79A3ED.4090308@kdbg.org","subject":"[PATCH v3 3/5] Move offset_1st_component() to path.c","fromName":"=?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?=","fromEmail":"pclouds@gmail.com","sentAt":"2010-02-16T05:22:08Z","receivedAt":"2010-02-16T05:22:08Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The implementation is also lightly modified to use is_dir_sep()\ninstead of hardcoding '/'.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n  On Mon, Feb 15, 2010 at 08:43:41PM +0100, Johannes Sixt wrote:\n  > Nguyễn Thái Ngọc Duy schrieb:\n  >> +int offset_1st_component(const char *path)\n  >> +{\n  >> +\tif (has_dos_drive_prefix(path))\n  >> +\t\treturn 2 + (path[2] == '/');\n  >> +\treturn *path == '/';\n  >> +}\n  >\n  > I'd have expected that you future-proofed this function by using \n  > is_dir_sep() or even use your previous implementation of is_root_path \n  > (because this implementation is a bit cryptic).\n  >\n  > But if the new callers of this function will only pass the results of \n  > normalize_path_copy() and getcwd() (both return only forward-slashes on \n  > Windows), then I'm fine with this version. Do they?\n\n  They do. But future-proofing can never be a bad thing.\n\n cache.h     |    1 +\n path.c      |   10 ++++++++++\n sha1_file.c |    7 -------\n 3 files changed, 11 insertions(+), 7 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex d478eff..ff23cd1 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -675,6 +675,7 @@ int normalize_path_copy(char *dst, const char *src);\n int longest_ancestor_length(const char *path, const char *prefix_list);\n char *strip_path_suffix(const char *path, const char *suffix);\n int daemon_avoid_alias(const char *path);\n+int offset_1st_component(const char *path);\n \n /* Read and unpack a sha1 file into memory, write memory to a sha1 file */\n extern int sha1_object_info(const unsigned char *, unsigned long *);\ndiff --git a/path.c b/path.c\nindex 0005df3..6304805 100644\n--- a/path.c\n+++ b/path.c\n@@ -649,3 +649,13 @@ int daemon_avoid_alias(const char *p)\n \t\t}\n \t}\n }\n+\n+int offset_1st_component(const char *path)\n+{\n+\tint len = 0;\n+\tif (has_dos_drive_prefix(path))\n+\t\tlen += 2;\n+\tif (is_dir_sep(path[len]))\n+\t\treturn len++;\n+\treturn len;\n+}\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 657825e..52052b9 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -35,13 +35,6 @@ static size_t sz_fmt(size_t s) { return s; }\n \n const unsigned char null_sha1[20];\n \n-static inline int offset_1st_component(const char *path)\n-{\n-\tif (has_dos_drive_prefix(path))\n-\t\treturn 2 + (path[2] == '/');\n-\treturn *path == '/';\n-}\n-\n int safe_create_leading_directories(char *path)\n {\n \tchar *pos = path + offset_1st_component(path);\n-- \n1.7.0.195.g637a2\n"},{"id":"134781","messageId":"4B7AF665.5030207@kdbg.org","threadId":"22651","inReplyTo":"20100216052208.GA18438@do","subject":"Re: [PATCH v3 3/5] Move offset_1st_component() to path.c","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-02-16T19:47:49Z","receivedAt":"2010-02-16T19:47:49Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Nguyễn Thái Ngọc Duy schrieb:\n>   > is_dir_sep() or even use your previous implementation of is_root_path \n>   > (because this implementation is a bit cryptic).\n>   >\n>   > But if the new callers of this function will only pass the results of \n>   > normalize_path_copy() and getcwd() (both return only forward-slashes on \n>   > Windows), then I'm fine with this version. Do they?\n> \n>   They do. But future-proofing can never be a bad thing.\n\nThanks, but...\n\n> +int offset_1st_component(const char *path)\n> +{\n> +\tint len = 0;\n> +\tif (has_dos_drive_prefix(path))\n> +\t\tlen += 2;\n> +\tif (is_dir_sep(path[len]))\n> +\t\treturn len++;\n\noops, does this work at all for you? You must not have 'return' here.\n\n> +\treturn len;\n> +}\n\n-- Hannes\n"}]}