When concatenating two paths, if the first one already have '/', do
not put another '/' in between the two paths.
Usually this is not the case as getcwd() won't return '/foo/bar/',
except when you are standing at root, then it will return '/'.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
abspath.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
If git_dir already has the trailing slash, don't put another one
before .git. This only happens when git_dir is '/' or 'C:/'
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
builtin-init-db.c | 9 ++++++---
builtin-rev-parse.c | 4 +++-
2 files changed, 9 insertions(+), 4 deletions(-)
@@ -647,7 +648,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)}if(!getcwd(cwd,PATH_MAX))die_errno("unable to get current working directory");-printf("%s/.git\n",cwd);+len=strlen(cwd);+printf("%s%s.git\n",cwd,len&&cwd[len-1]!='/'?"/":"");continue;}if(!strcmp(arg,"--is-inside-git-dir")){
This kind of test requires a throw-away root filesystem so that it can
play on. If you have such a system, go ahead, "chmod 777 /" and run
this test manually. Because this is a dangerous test, you are required
to set an env variable, and not to use root to run it.
Script prepare-root.sh may help you set up a chroot environment with
Git test suite inside. You will need Linux, static linked busybox,
rsync and root permission to use it.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
t/t1509-root-worktree.sh | 249 +++++++++++++++++++++++++++++++++++++++++++++
t/t1509/excludes | 14 +++
t/t1509/prepare-chroot.sh | 38 +++++++
3 files changed, 301 insertions(+), 0 deletions(-)
create mode 100755 t/t1509-root-worktree.sh
create mode 100644 t/t1509/excludes
create mode 100755 t/t1509/prepare-chroot.sh
@@ -0,0 +1,249 @@+#!/bin/sh++test_description='TestGitwhengitrepositoryislocatedatroot++Thistestrequireswriteaccessinroot.Donotbotherifyoudonot+haveathrowawaychrootorVM.++Scriptt1509/prepare-chroot.shmayhelpyousetupchroot,thenyou+canchrootinandexecutethistestfromthere.+'++../test-lib.sh++test_cmp_val(){+echo"$1">expected+echo"$2">result+test_cmpexpectedresult+}++test_vars(){+test_expect_success"$1: gitdir"'+test_cmp_val"'"$2"'""$(gitrev-parse--git-dir)"+'++test_expect_success"$1: worktree"'+test_cmp_val"'"$3"'""$(gitrev-parse--show-toplevel)"+'++test_expect_success"$1: prefix"'+test_cmp_val"'"$4"'""$(gitrev-parse--show-prefix)"+'+}++test_foobar_root(){+test_expect_success'add relative''+test-z"$(cd/&&gitls-files)"&&+gitaddfoo/foome&&+gitaddfoo/bar/barme&&+gitaddme&&+(cd/&&gitls-files--stage)>result&&+test_cmp/ls.expectedresult&&+rm"$(gitrev-parse--git-dir)/index"+'++test_expect_success'add absolute''+test-z"$(cd/&&gitls-files)"&&+gitadd/foo/foome&&+gitadd/foo/bar/barme&&+gitadd/me&&+(cd/&&gitls-files--stage)>result&&+test_cmp/ls.expectedresult&&+rm"$(gitrev-parse--git-dir)/index"+'++}++test_foobar_foo(){+test_expect_success'add relative''+test-z"$(cd/&&gitls-files)"&&+gitaddfoome&&+gitaddbar/barme&&+gitadd../me&&+(cd/&&gitls-files--stage)>result&&+test_cmp/ls.expectedresult&&+rm"$(gitrev-parse--git-dir)/index"+'++test_expect_success'add absolute''+test-z"$(cd/&&gitls-files)"&&+gitadd/foo/foome&&+gitadd/foo/bar/barme&&+gitadd/me&&+(cd/&&gitls-files--stage)>result&&+test_cmp/ls.expectedresult&&+rm"$(gitrev-parse--git-dir)/index"+'+}++test_foobar_foobar(){+test_expect_success'add relative''+test-z"$(cd/&&gitls-files)"&&+gitadd../foome&&+gitaddbarme&&+gitadd../../me&&+(cd/&&gitls-files--stage)>result&&+test_cmp/ls.expectedresult&&+rm"$(gitrev-parse--git-dir)/index"+'++test_expect_success'add absolute''+test-z"$(cd/&&gitls-files)"&&+gitadd/foo/foome&&+gitadd/foo/bar/barme&&+gitadd/me&&+(cd/&&gitls-files--stage)>result&&+test_cmp/ls.expectedresult&&+rm"$(gitrev-parse--git-dir)/index"+'+}++if!test_have_prereqPOSIXPERM||![-w/];then+say"Dangerous test skipped. Read this test if you want to execute it"+test_done+fi++if["$IKNOWWHATIAMDOING"!="YES"];then+say"You must set env var IKNOWWHATIAMDOING=YES in order to run this test"+test_done+fi++if["$UID"=0];then+say"No you can't run this with root"+test_done+fi++ONE_SHA1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d++test_expect_success'setup''+rm-rf/foo+mkdir/foo&&+mkdir/foo/bar&&+echo1>/foo/foome&&+echo1>/foo/bar/barme&&+echo1>/me+'++say"GIT_DIR absolute, GIT_WORK_TREE set"++test_expect_success'go to /''cd /'++cat>ls.expected<<EOF+100644$ONE_SHA10foo/bar/barme+100644$ONE_SHA10foo/foome+100644$ONE_SHA10me+EOF++exportGIT_DIR="$TRASH_DIRECTORY/.git"+exportGIT_WORK_TREE=/++test_vars'abs gitdir, root'"$GIT_DIR""/"""+test_foobar_root++test_expect_success'go to /foo''cd /foo'++test_vars'abs gitdir, foo'"$GIT_DIR""/""foo/"+test_foobar_foo++test_expect_success'go to /foo/bar''cd /foo/bar'++test_vars'abs gitdir, foo/bar'"$GIT_DIR""/""foo/bar/"+test_foobar_foobar++say"GIT_DIR relative, GIT_WORK_TREE set"++test_expect_success'go to /''cd /'++exportGIT_DIR="$(echo$TRASH_DIRECTORY|sed's,^/,,')/.git"+exportGIT_WORK_TREE=/++test_vars'rel gitdir, root'"$GIT_DIR""/"""+test_foobar_root++test_expect_success'go to /foo''cd /foo'++exportGIT_DIR="../$TRASH_DIRECTORY/.git"+exportGIT_WORK_TREE=/++test_vars'rel gitdir, foo'"$TRASH_DIRECTORY/.git""/""foo/"+test_foobar_foo++test_expect_success'go to /foo/bar''cd /foo/bar'++exportGIT_DIR="../../$TRASH_DIRECTORY/.git"+exportGIT_WORK_TREE=/++test_vars'rel gitdir, foo/bar'"$TRASH_DIRECTORY/.git""/""foo/bar/"+test_foobar_foobar++say"GIT_DIR relative, GIT_WORK_TREE relative"++test_expect_success'go to /''cd /'++exportGIT_DIR="$(echo$TRASH_DIRECTORY|sed's,^/,,')/.git"+exportGIT_WORK_TREE=.++test_vars'rel gitdir, root'"$GIT_DIR""/"""+test_foobar_root++test_expect_success'go to /''cd /foo'++exportGIT_DIR="../$TRASH_DIRECTORY/.git"+exportGIT_WORK_TREE=..++test_vars'rel gitdir, foo'"$TRASH_DIRECTORY/.git""/""foo/"+test_foobar_foo++test_expect_success'go to /foo/bar''cd /foo/bar'++exportGIT_DIR="../../$TRASH_DIRECTORY/.git"+exportGIT_WORK_TREE=../..++test_vars'rel gitdir, foo/bar'"$TRASH_DIRECTORY/.git""/""foo/bar/"+test_foobar_foobar++say".git at root"++unsetGIT_DIR+unsetGIT_WORK_TREE++test_expect_success'go to /''cd /'+test_expect_success'setup''+rm-rf/.git+echo"Initialized empty Git repository in /.git/">expected&&+gitinit>result&&+test_cmpexpectedresult+'++test_vars'auto gitdir, root'".git""/"""+test_foobar_root++test_expect_success'go to /foo''cd /foo'+test_vars'auto gitdir, foo'"/.git""/""foo/"+test_foobar_foo++test_expect_success'go to /foo/bar''cd /foo/bar'+test_vars'auto gitdir, foo/bar'"/.git""/""foo/bar/"+test_foobar_foobar++test_expect_success'cleanup''rm -rf /.git'++say"auto bare gitdir"++# DESTROYYYYY!!!!!+test_expect_success'setup''+rm-rf/refs/objects/info/hooks+rm/*+cd/&&+echo"Initialized empty Git repository in /">expected&&+gitinit--bare>result&&+test_cmpexpectedresult+'++test_vars'auto gitdir, root'"."""""++test_expect_success'go to /foo''cd /foo'++test_vars'auto gitdir, root'"/"""""++test_done
@@ -0,0 +1,38 @@+#!/bin/sh++die(){+echo>&2"$@"+exit1+}++xmkdir(){+while[-n"$1"];do+[-d"$1"]||mkdir"$1"||die"Unable to mkdir $1"+shift+done+}++R="$1"++[-n"$R"]||die"Usage: prepare-chroot.sh <root>"+[-xgit]||die"This script needs to be executed at git source code's top directory"+[-x/bin/busybox]||die"You need busybox"++xmkdir"$R""$R/bin""$R/etc""$R/lib""$R/dev"+[-c"$R/dev/null"]||die"/dev/null is missing. Do mknod $R/dev/null c 1 3 && chmod 666 $R/dev/null"+echo"root:x:0:0:root:/:/bin/sh">"$R/etc/passwd"+echo"$(id-nu):x:$(id-u):$(id-g)::$(pwd)/t:/bin/sh">>"$R/etc/passwd"+echo"root::0:root">"$R/etc/group"+echo"$(id-ng)::$(id-g):$(id-nu)">>"$R/etc/group"++[-x"$R/bin/busybox"]||cp/bin/busybox"$R/bin/busybox"+[-x"$R/bin/sh"]||ln-s/bin/busybox"$R/bin/sh"+[-x"$R/bin/su"]||ln-s/bin/busybox"$R/bin/su"++mkdir-p"$R$(pwd)"+rsync--exclude-fromt/t1509/excludes-Ha."$R$(pwd)"+lddgit|grep'/'|sed's,.*\s\(/[^ ]*\).*,\1,'|whilereadi;do+mkdir-p"$R$(dirname$i)"+cp"$i""$R/$i"+done+echo"Execute this in root: 'chroot $R /bin/su - $(id-nu)'"
Git should work regardless where the working directory is located,
even at root. This patch fixes two places where it assumes working
directory always have parent directory.
In setup_git_directory_gently(), when Git goes up to root and finds
.git there, it happily sets worktree to "" instead of "/".
In prefix_path(), loosen the outside repo check a little bit. Usually
when a path XXX is inside worktree /foo, it must be either "/foo", or
"/foo/...". When worktree is simply "/", we can safely ignore the
check: we have a slash at the beginning already.
Not related to worktree, but also set gitdir correctly if a bare repo
is placed (insanely?) at root.
Thanks João Carlos Mendes Luís for pointing out this problem.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
setup.c | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)
@@ -675,6 +675,7 @@ int normalize_path_copy(char *dst, const char *src);intlongest_ancestor_length(constchar*path,constchar*prefix_list);char*strip_path_suffix(constchar*path,constchar*suffix);intdaemon_avoid_alias(constchar*path);+intoffset_1st_component(constchar*path);/* Read and unpack a sha1 file into memory, write memory to a sha1 file */externintsha1_object_info(constunsignedchar*,unsignedlong*);
I'd have expected that you future-proofed this function by using
is_dir_sep() or even use your previous implementation of is_root_path
(because this implementation is a bit cryptic).
But if the new callers of this function will only pass the results of
normalize_path_copy() and getcwd() (both return only forward-slashes on
Windows), then I'm fine with this version. Do they?
-- Hannes
The implementation is also lightly modified to use is_dir_sep()
instead of hardcoding '/'.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
On Mon, Feb 15, 2010 at 08:43:41PM +0100, Johannes Sixt wrote:
> Nguyễn Thái Ngọc Duy schrieb:
>> +int offset_1st_component(const char *path)
>> +{
>> + if (has_dos_drive_prefix(path))
>> + return 2 + (path[2] == '/');
>> + return *path == '/';
>> +}
>
> I'd have expected that you future-proofed this function by using
> is_dir_sep() or even use your previous implementation of is_root_path
> (because this implementation is a bit cryptic).
>
> But if the new callers of this function will only pass the results of
> normalize_path_copy() and getcwd() (both return only forward-slashes on
> Windows), then I'm fine with this version. Do they?
They do. But future-proofing can never be a bad thing.
cache.h | 1 +
path.c | 10 ++++++++++
sha1_file.c | 7 -------
3 files changed, 11 insertions(+), 7 deletions(-)
@@ -675,6 +675,7 @@ int normalize_path_copy(char *dst, const char *src);intlongest_ancestor_length(constchar*path,constchar*prefix_list);char*strip_path_suffix(constchar*path,constchar*suffix);intdaemon_avoid_alias(constchar*path);+intoffset_1st_component(constchar*path);/* Read and unpack a sha1 file into memory, write memory to a sha1 file */externintsha1_object_info(constunsignedchar*,unsignedlong*);
From: Johannes Sixt <hidden> Date: 2016-06-15 22:48:17
Nguyễn Thái Ngọc Duy schrieb:
> is_dir_sep() or even use your previous implementation of is_root_path
> (because this implementation is a bit cryptic).
>
> But if the new callers of this function will only pass the results of
> normalize_path_copy() and getcwd() (both return only forward-slashes on
> Windows), then I'm fine with this version. Do they?
They do. But future-proofing can never be a bad thing.
Thanks, but...
+int offset_1st_component(const char *path)
+{
+ int len = 0;
+ if (has_dos_drive_prefix(path))
+ len += 2;
+ if (is_dir_sep(path[len]))
+ return len++;
oops, does this work at all for you? You must not have 'return' here.