Merge branch 'nd/root-git'
* nd/root-git: Add test for using Git at root of file system Support working directory located at root Move offset_1st_component() to path.c init-db, rev-parse --git-dir: do not append redundant slash make_absolute_path(): Do not append redundant slash Conflicts: setup.c sha1_file.c
This commit is contained in:
commit
c2b456b895
@ -54,8 +54,9 @@ const char *make_absolute_path(const char *path)
|
||||
if (len + strlen(last_elem) + 2 > PATH_MAX)
|
||||
die ("Too long path name: '%s/%s'",
|
||||
buf, last_elem);
|
||||
buf[len] = '/';
|
||||
strcpy(buf + len + 1, last_elem);
|
||||
if (len && buf[len-1] != '/')
|
||||
buf[len++] = '/';
|
||||
strcpy(buf + len, last_elem);
|
||||
free(last_elem);
|
||||
last_elem = NULL;
|
||||
}
|
||||
|
@ -331,11 +331,14 @@ int init_db(const char *template_dir, unsigned int flags)
|
||||
git_config_set("receive.denyNonFastforwards", "true");
|
||||
}
|
||||
|
||||
if (!(flags & INIT_DB_QUIET))
|
||||
printf("%s%s Git repository in %s/\n",
|
||||
if (!(flags & INIT_DB_QUIET)) {
|
||||
const char *git_dir = get_git_dir();
|
||||
int len = strlen(git_dir);
|
||||
printf("%s%s Git repository in %s%s\n",
|
||||
reinit ? "Reinitialized existing" : "Initialized empty",
|
||||
shared_repository ? " shared" : "",
|
||||
get_git_dir());
|
||||
git_dir, len && git_dir[len-1] != '/' ? "/" : "");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -637,6 +637,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
||||
if (!strcmp(arg, "--git-dir")) {
|
||||
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
|
||||
static char cwd[PATH_MAX];
|
||||
int len;
|
||||
if (gitdir) {
|
||||
puts(gitdir);
|
||||
continue;
|
||||
@ -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")) {
|
||||
|
1
cache.h
1
cache.h
@ -679,6 +679,7 @@ int normalize_path_copy(char *dst, const char *src);
|
||||
int longest_ancestor_length(const char *path, const char *prefix_list);
|
||||
char *strip_path_suffix(const char *path, const char *suffix);
|
||||
int daemon_avoid_alias(const char *path);
|
||||
int offset_1st_component(const char *path);
|
||||
|
||||
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
|
||||
extern int sha1_object_info(const unsigned char *, unsigned long *);
|
||||
|
7
path.c
7
path.c
@ -728,3 +728,10 @@ int daemon_avoid_alias(const char *p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int offset_1st_component(const char *path)
|
||||
{
|
||||
if (has_dos_drive_prefix(path))
|
||||
return 2 + is_dir_sep(path[2]);
|
||||
return is_dir_sep(path[0]);
|
||||
}
|
||||
|
13
setup.c
13
setup.c
@ -18,14 +18,15 @@ const char *prefix_path(const char *prefix, int len, const char *path)
|
||||
if (normalize_path_copy(sanitized, sanitized))
|
||||
goto error_out;
|
||||
if (is_absolute_path(orig)) {
|
||||
size_t len, total;
|
||||
size_t root_len, len, total;
|
||||
const char *work_tree = get_git_work_tree();
|
||||
if (!work_tree)
|
||||
goto error_out;
|
||||
len = strlen(work_tree);
|
||||
root_len = offset_1st_component(work_tree);
|
||||
total = strlen(sanitized) + 1;
|
||||
if (strncmp(sanitized, work_tree, len) ||
|
||||
(sanitized[len] != '\0' && sanitized[len] != '/')) {
|
||||
(len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) {
|
||||
error_out:
|
||||
die("'%s' is outside repository", orig);
|
||||
}
|
||||
@ -321,7 +322,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||
static char cwd[PATH_MAX+1];
|
||||
const char *gitdirenv;
|
||||
const char *gitfile_dir;
|
||||
int len, offset, ceil_offset;
|
||||
int len, offset, ceil_offset, root_len;
|
||||
|
||||
/*
|
||||
* Let's assume that we are in a git repository.
|
||||
@ -403,7 +404,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||
if (!work_tree_env)
|
||||
inside_work_tree = 0;
|
||||
if (offset != len) {
|
||||
cwd[offset] = '\0';
|
||||
root_len = offset_1st_component(cwd);
|
||||
cwd[offset > root_len ? offset : root_len] = '\0';
|
||||
set_git_dir(cwd);
|
||||
} else
|
||||
set_git_dir(".");
|
||||
@ -427,7 +429,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||
inside_git_dir = 0;
|
||||
if (!work_tree_env)
|
||||
inside_work_tree = 1;
|
||||
git_work_tree_cfg = xstrndup(cwd, offset);
|
||||
root_len = offset_1st_component(cwd);
|
||||
git_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);
|
||||
if (check_repository_format_gently(nongit_ok))
|
||||
return NULL;
|
||||
if (offset == len)
|
||||
|
@ -35,13 +35,6 @@ static size_t sz_fmt(size_t s) { return s; }
|
||||
|
||||
const unsigned char null_sha1[20];
|
||||
|
||||
static inline int offset_1st_component(const char *path)
|
||||
{
|
||||
if (has_dos_drive_prefix(path))
|
||||
return 2 + (path[2] == '/');
|
||||
return *path == '/';
|
||||
}
|
||||
|
||||
int safe_create_leading_directories(char *path)
|
||||
{
|
||||
char *pos = path + offset_1st_component(path);
|
||||
|
249
t/t1509-root-worktree.sh
Executable file
249
t/t1509-root-worktree.sh
Executable file
@ -0,0 +1,249 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='Test Git when git repository is located at root
|
||||
|
||||
This test requires write access in root. Do not bother if you do not
|
||||
have a throwaway chroot or VM.
|
||||
|
||||
Script t1509/prepare-chroot.sh may help you setup chroot, then you
|
||||
can chroot in and execute this test from there.
|
||||
'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_cmp_val() {
|
||||
echo "$1" > expected
|
||||
echo "$2" > result
|
||||
test_cmp expected result
|
||||
}
|
||||
|
||||
test_vars() {
|
||||
test_expect_success "$1: gitdir" '
|
||||
test_cmp_val "'"$2"'" "$(git rev-parse --git-dir)"
|
||||
'
|
||||
|
||||
test_expect_success "$1: worktree" '
|
||||
test_cmp_val "'"$3"'" "$(git rev-parse --show-toplevel)"
|
||||
'
|
||||
|
||||
test_expect_success "$1: prefix" '
|
||||
test_cmp_val "'"$4"'" "$(git rev-parse --show-prefix)"
|
||||
'
|
||||
}
|
||||
|
||||
test_foobar_root() {
|
||||
test_expect_success 'add relative' '
|
||||
test -z "$(cd / && git ls-files)" &&
|
||||
git add foo/foome &&
|
||||
git add foo/bar/barme &&
|
||||
git add me &&
|
||||
( cd / && git ls-files --stage ) > result &&
|
||||
test_cmp /ls.expected result &&
|
||||
rm "$(git rev-parse --git-dir)/index"
|
||||
'
|
||||
|
||||
test_expect_success 'add absolute' '
|
||||
test -z "$(cd / && git ls-files)" &&
|
||||
git add /foo/foome &&
|
||||
git add /foo/bar/barme &&
|
||||
git add /me &&
|
||||
( cd / && git ls-files --stage ) > result &&
|
||||
test_cmp /ls.expected result &&
|
||||
rm "$(git rev-parse --git-dir)/index"
|
||||
'
|
||||
|
||||
}
|
||||
|
||||
test_foobar_foo() {
|
||||
test_expect_success 'add relative' '
|
||||
test -z "$(cd / && git ls-files)" &&
|
||||
git add foome &&
|
||||
git add bar/barme &&
|
||||
git add ../me &&
|
||||
( cd / && git ls-files --stage ) > result &&
|
||||
test_cmp /ls.expected result &&
|
||||
rm "$(git rev-parse --git-dir)/index"
|
||||
'
|
||||
|
||||
test_expect_success 'add absolute' '
|
||||
test -z "$(cd / && git ls-files)" &&
|
||||
git add /foo/foome &&
|
||||
git add /foo/bar/barme &&
|
||||
git add /me &&
|
||||
( cd / && git ls-files --stage ) > result &&
|
||||
test_cmp /ls.expected result &&
|
||||
rm "$(git rev-parse --git-dir)/index"
|
||||
'
|
||||
}
|
||||
|
||||
test_foobar_foobar() {
|
||||
test_expect_success 'add relative' '
|
||||
test -z "$(cd / && git ls-files)" &&
|
||||
git add ../foome &&
|
||||
git add barme &&
|
||||
git add ../../me &&
|
||||
( cd / && git ls-files --stage ) > result &&
|
||||
test_cmp /ls.expected result &&
|
||||
rm "$(git rev-parse --git-dir)/index"
|
||||
'
|
||||
|
||||
test_expect_success 'add absolute' '
|
||||
test -z "$(cd / && git ls-files)" &&
|
||||
git add /foo/foome &&
|
||||
git add /foo/bar/barme &&
|
||||
git add /me &&
|
||||
( cd / && git ls-files --stage ) > result &&
|
||||
test_cmp /ls.expected result &&
|
||||
rm "$(git rev-parse --git-dir)/index"
|
||||
'
|
||||
}
|
||||
|
||||
if ! test_have_prereq POSIXPERM || ! [ -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 &&
|
||||
echo 1 > /foo/foome &&
|
||||
echo 1 > /foo/bar/barme &&
|
||||
echo 1 > /me
|
||||
'
|
||||
|
||||
say "GIT_DIR absolute, GIT_WORK_TREE set"
|
||||
|
||||
test_expect_success 'go to /' 'cd /'
|
||||
|
||||
cat >ls.expected <<EOF
|
||||
100644 $ONE_SHA1 0 foo/bar/barme
|
||||
100644 $ONE_SHA1 0 foo/foome
|
||||
100644 $ONE_SHA1 0 me
|
||||
EOF
|
||||
|
||||
export GIT_DIR="$TRASH_DIRECTORY/.git"
|
||||
export GIT_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 /'
|
||||
|
||||
export GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git"
|
||||
export GIT_WORK_TREE=/
|
||||
|
||||
test_vars 'rel gitdir, root' "$GIT_DIR" "/" ""
|
||||
test_foobar_root
|
||||
|
||||
test_expect_success 'go to /foo' 'cd /foo'
|
||||
|
||||
export GIT_DIR="../$TRASH_DIRECTORY/.git"
|
||||
export GIT_WORK_TREE=/
|
||||
|
||||
test_vars 'rel gitdir, foo' "$TRASH_DIRECTORY/.git" "/" "foo/"
|
||||
test_foobar_foo
|
||||
|
||||
test_expect_success 'go to /foo/bar' 'cd /foo/bar'
|
||||
|
||||
export GIT_DIR="../../$TRASH_DIRECTORY/.git"
|
||||
export GIT_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 /'
|
||||
|
||||
export GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git"
|
||||
export GIT_WORK_TREE=.
|
||||
|
||||
test_vars 'rel gitdir, root' "$GIT_DIR" "/" ""
|
||||
test_foobar_root
|
||||
|
||||
test_expect_success 'go to /' 'cd /foo'
|
||||
|
||||
export GIT_DIR="../$TRASH_DIRECTORY/.git"
|
||||
export GIT_WORK_TREE=..
|
||||
|
||||
test_vars 'rel gitdir, foo' "$TRASH_DIRECTORY/.git" "/" "foo/"
|
||||
test_foobar_foo
|
||||
|
||||
test_expect_success 'go to /foo/bar' 'cd /foo/bar'
|
||||
|
||||
export GIT_DIR="../../$TRASH_DIRECTORY/.git"
|
||||
export GIT_WORK_TREE=../..
|
||||
|
||||
test_vars 'rel gitdir, foo/bar' "$TRASH_DIRECTORY/.git" "/" "foo/bar/"
|
||||
test_foobar_foobar
|
||||
|
||||
say ".git at root"
|
||||
|
||||
unset GIT_DIR
|
||||
unset GIT_WORK_TREE
|
||||
|
||||
test_expect_success 'go to /' 'cd /'
|
||||
test_expect_success 'setup' '
|
||||
rm -rf /.git
|
||||
echo "Initialized empty Git repository in /.git/" > expected &&
|
||||
git init > result &&
|
||||
test_cmp expected result
|
||||
'
|
||||
|
||||
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 &&
|
||||
git init --bare > result &&
|
||||
test_cmp expected result
|
||||
'
|
||||
|
||||
test_vars 'auto gitdir, root' "." "" ""
|
||||
|
||||
test_expect_success 'go to /foo' 'cd /foo'
|
||||
|
||||
test_vars 'auto gitdir, root' "/" "" ""
|
||||
|
||||
test_done
|
14
t/t1509/excludes
Normal file
14
t/t1509/excludes
Normal file
@ -0,0 +1,14 @@
|
||||
*.o
|
||||
*~
|
||||
*.bak
|
||||
*.c
|
||||
*.h
|
||||
.git
|
||||
contrib
|
||||
Documentation
|
||||
git-gui
|
||||
gitk-git
|
||||
gitweb
|
||||
t/t4013
|
||||
t/t5100
|
||||
t/t5515
|
38
t/t1509/prepare-chroot.sh
Executable file
38
t/t1509/prepare-chroot.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
die() {
|
||||
echo >&2 "$@"
|
||||
exit 1
|
||||
}
|
||||
|
||||
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>"
|
||||
[ -x git ] || 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-from t/t1509/excludes -Ha . "$R$(pwd)"
|
||||
ldd git | grep '/' | sed 's,.*\s\(/[^ ]*\).*,\1,' | while read i; do
|
||||
mkdir -p "$R$(dirname $i)"
|
||||
cp "$i" "$R/$i"
|
||||
done
|
||||
echo "Execute this in root: 'chroot $R /bin/su - $(id -nu)'"
|
Loading…
Reference in New Issue
Block a user