1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-31 03:46:12 +02:00

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:
Junio C Hamano 2010-03-07 12:47:15 -08:00
commit c2b456b895
10 changed files with 329 additions and 18 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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")) {

View File

@ -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
View File

@ -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
View File

@ -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)

View File

@ -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
View 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
View 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
View 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)'"