Browse Source

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
maint
Junio C Hamano 15 years ago
parent
commit
c2b456b895
  1. 5
      abspath.c
  2. 9
      builtin-init-db.c
  3. 4
      builtin-rev-parse.c
  4. 1
      cache.h
  5. 7
      path.c
  6. 13
      setup.c
  7. 7
      sha1_file.c
  8. 249
      t/t1509-root-worktree.sh
  9. 14
      t/t1509/excludes
  10. 38
      t/t1509/prepare-chroot.sh

5
abspath.c

@ -54,8 +54,9 @@ const char *make_absolute_path(const char *path) @@ -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;
}

9
builtin-init-db.c

@ -331,11 +331,14 @@ int init_db(const char *template_dir, unsigned int flags) @@ -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;
}

4
builtin-rev-parse.c

@ -637,6 +637,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) @@ -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) @@ -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

@ -679,6 +679,7 @@ int normalize_path_copy(char *dst, const char *src); @@ -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

@ -728,3 +728,10 @@ int daemon_avoid_alias(const char *p) @@ -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

@ -18,14 +18,15 @@ const char *prefix_path(const char *prefix, int len, const char *path) @@ -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) @@ -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) @@ -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) @@ -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)

7
sha1_file.c

@ -35,13 +35,6 @@ static size_t sz_fmt(size_t s) { return s; } @@ -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

@ -0,0 +1,249 @@ @@ -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

@ -0,0 +1,14 @@ @@ -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

@ -0,0 +1,38 @@ @@ -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…
Cancel
Save