Commits

Junio C Hamano  committed 9cac9d3 Merge

Merge branch 'jc/subdir'

  • Participants
  • Parent commits 5401f30, 99e0169

Comments (0)

Files changed (38)

 //  --numstat does numeric diffstat, and doesn't actually apply
 //  --index-info shows the old and new index info for paths if available.
 //
+static const char *prefix;
+static int prefix_length = -1;
+
 static int allow_binary_replacement = 0;
 static int check_index = 0;
 static int write_index = 0;
 			return 0;
 		x = x->next;
 	}
+	if (0 < prefix_length) {
+		int pathlen = strlen(pathname);
+		if (pathlen <= prefix_length ||
+		    memcmp(prefix, pathname, prefix_length))
+			return 0;
+	}
 	return 1;
 }
 
 			line_termination = 0;
 			continue;
 		}
+
+		if (check_index && prefix_length < 0) {
+			prefix = setup_git_directory();
+			prefix_length = prefix ? strlen(prefix) : 0;
+			git_config(git_default_config);
+		}
+		if (0 < prefix_length)
+			arg = prefix_filename(prefix, prefix_length, arg);
+
 		fd = open(arg, O_RDONLY);
 		if (fd < 0)
 			usage(apply_usage);
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
 extern const char **get_pathspec(const char *prefix, const char **pathspec);
+extern const char *setup_git_directory_gently(int *);
 extern const char *setup_git_directory(void);
 extern const char *prefix_path(const char *prefix, int len, const char *path);
+extern const char *prefix_filename(const char *prefix, int len, const char *path);
 
 #define alloc_nr(x) (((x)+16)*3/2)
 

File checkout-index.c

  */
 #include "cache.h"
 
+static const char *prefix;
+static int prefix_length;
+
 static struct checkout state = {
 	.base_dir = "",
 	.base_dir_len = 0,
 		struct cache_entry *ce = active_cache[i];
 		if (ce_stage(ce))
 			continue;
+		if (prefix && *prefix &&
+		    ( ce_namelen(ce) <= prefix_length ||
+		      memcmp(prefix, ce->name, prefix_length) ))
+			continue;
 		if (checkout_entry(ce, &state) < 0)
 			errs++;
 	}
 	int newfd = -1;
 	int all = 0;
 
+	prefix = setup_git_directory();
+	prefix_length = prefix ? strlen(prefix) : 0;
+
 	if (read_cache() < 0) {
 		die("invalid cache");
 	}
 
 		if (all)
 			die("git-checkout-index: don't mix '--all' and explicit filenames");
-		checkout_file(arg);
+		checkout_file(prefix_path(prefix, prefix_length, arg));
 	}
 
 	if (all)

File clone-pack.c

 	int fd[2];
 	pid_t pid;
 
+	setup_git_directory();
+
 	nr_heads = 0;
 	heads = NULL;
 	for (i = 1; i < argc; i++) {

File commit-tree.c

 	if (argc < 2 || get_sha1_hex(argv[1], tree_sha1) < 0)
 		usage(commit_tree_usage);
 
+	setup_git_directory();
+
 	check_valid(tree_sha1, "tree");
 	for (i = 2; i < argc; i += 2) {
 		char *a, *b;

File convert-objects.c

 	unsigned char sha1[20];
 	struct entry *entry;
 
+	setup_git_directory();
+
 	if (argc != 2 || get_sha1(argv[1], sha1))
 		usage("git-convert-objects <sha1>");
 

File fetch-pack.c

 	int fd[2];
 	pid_t pid;
 
+	setup_git_directory();
+
 	nr_heads = 0;
 	heads = NULL;
 	for (i = 1; i < argc; i++) {

File fsck-objects.c

 {
 	int i, heads;
 
+	setup_git_directory();
+
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 
 #!/bin/sh
 
+die () {
+    echo >&2 "$*"
+    exit 1
+}
+
 usage() {
     die "usage: git add [-n] [-v] <file>..."
 }

File git-branch.sh

 #!/bin/sh
 
-. git-sh-setup
+GIT_DIR=`git-rev-parse --git-dir` || exit $?
+
+die () {
+    echo >&2 "$*"
+    exit 1
+}
 
 usage () {
     echo >&2 "usage: $(basename $0)"' [-d <branch>] | [[-f] <branch> [start-point]]
     exit 1
 }
 
-headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD |
-	sed -e 's|^refs/heads/||')
+headref=$(git-symbolic-ref HEAD | sed -e 's|^refs/heads/||')
 
 delete_branch () {
     option="$1"
 	fi
 fi
 git update-ref "refs/heads/$branchname" $rev
-

File git-count-objects.sh

 # Copyright (c) 2005 Junio C Hamano
 #
 
-. git-sh-setup
+GIT_DIR=`git-rev-parse --git-dir` || exit $?
 
 dc </dev/null 2>/dev/null || {
 	# This is not a real DC at all -- it just knows how
 flags=$(git-rev-parse --no-revs --flags --sq "$@")
 files=$(git-rev-parse --no-revs --no-flags --sq "$@")
 
+die () {
+    echo >&2 "$*"
+    exit 1
+}
+
 # I often say 'git diff --cached -p' and get scolded by git-diff-files, but
 # obviously I mean 'git diff --cached -p HEAD' in that case.
 case "$rev" in

File git-lost-found.sh

 #!/bin/sh
 
-. git-sh-setup
-
+GIT_DIR=`git-rev-parse --git-dir` || exit $?
 laf="$GIT_DIR/lost-found"
 rm -fr "$laf" && mkdir -p "$laf/commit" "$laf/other" || exit
 

File git-ls-remote.sh

     exit 1;
 }
 
+die () {
+    echo >&2 "$*"
+    exit 1
+}
+
 while case "$#" in 0) break;; esac
 do
   case "$1" in

File git-merge-octopus.sh

 LF='
 '
 
+die () {
+    echo >&2 "$*"
+    exit 1
+}
+
 # The first parameters up to -- are merge bases; the rest are heads.
 bases= head= remotes= sep_seen=
 for arg
 #!/bin/sh
 # Copyright (c) 2005 Linus Torvalds
 
-. git-sh-setup
+GIT_DIR=`git-rev-parse --git-dir` || exit $?
 
 usage () {
     echo >&2 "Usage: git-tag [-a | -s | -u <key-id>] [-f | -d] [-m <msg>] <tagname> [<head>]"
     exit 1
 }
 
+die () {
+    echo >&2 "$*"
+    exit 1
+}
+
 annotate=
 signed=
 force=

File git-verify-tag.sh

 #!/bin/sh
-. git-sh-setup
+
+GIT_DIR=`git-rev-parse --git-dir` || exit $?
+
+die () {
+    echo >&2 "$*"
+    exit 1
+}
 
 type="$(git-cat-file -t "$1" 2>/dev/null)" ||
 	die "$1: no such object."
 test "$type" = tag ||
 	die "$1: cannot verify a non-tag object of type $type."
 
-git-cat-file tag "$1" > .tmp-vtag || exit 1
-cat .tmp-vtag | sed '/-----BEGIN PGP/Q' | gpg --verify .tmp-vtag - || exit 1
-rm -f .tmp-vtag
+git-cat-file tag "$1" >"$GIT_DIR/.tmp-vtag" || exit 1
+cat "$GIT_DIR/.tmp-vtag" |
+sed '/-----BEGIN PGP/Q' |
+gpg --verify "$GIT_DIR/.tmp-vtag" - || exit 1
+rm -f "$GIT_DIR/.tmp-vtag"
+

File hash-object.c

 	int i;
 	const char *type = "blob";
 	int write_object = 0;
+	const char *prefix = NULL;
+	int prefix_length = -1;
 
 	for (i = 1 ; i < argc; i++) {
 		if (!strcmp(argv[i], "-t")) {
 				die(hash_object_usage);
 			type = argv[i];
 		}
-		else if (!strcmp(argv[i], "-w"))
+		else if (!strcmp(argv[i], "-w")) {
+			if (prefix_length < 0) {
+				prefix = setup_git_directory();
+				prefix_length = prefix ? strlen(prefix) : 0;
+			}
 			write_object = 1;
-		else
-			hash_object(argv[i], type, write_object);
+		}
+		else {
+			const char *arg = argv[i];
+			if (0 <= prefix_length)
+				arg = prefix_filename(prefix, prefix_length,
+						      arg);
+			hash_object(arg, type, write_object);
+		}
 	}
 	return 0;
 }

File http-fetch.c

 	int arg = 1;
 	int rc = 0;
 
+	setup_git_directory();
+
 	while (arg < argc && argv[arg][0] == '-') {
 		if (argv[arg][1] == 't') {
 			get_tree = 1;
 	int rc = 0;
 	int i;
 
+	setup_git_directory();
 	setup_ident();
 
 	remote = xmalloc(sizeof(*remote));

File local-fetch.c

 	char *commit_id;
 	int arg = 1;
 
+	setup_git_directory();
+
 	while (arg < argc && argv[arg][0] == '-') {
 		if (argv[arg][1] == 't')
 			get_tree = 1;

File merge-base.c

 	struct commit *rev1, *rev2;
 	unsigned char rev1key[20], rev2key[20];
 
+	setup_git_directory();
+
 	while (1 < argc && argv[1][0] == '-') {
 		char *arg = argv[1];
 		if (!strcmp(arg, "-a") || !strcmp(arg, "--all"))

File merge-index.c

 	if (argc < 3)
 		usage("git-merge-index [-o] [-q] <merge-program> (-a | <filename>*)");
 
+	setup_git_directory();
 	read_cache();
 
 	i = 1;
 	if (argc != 1)
 		usage("cat <signaturefile> | git-mktag");
 
+	setup_git_directory();
+
 	// Read the signature
 	size = 0;
 	for (;;) {

File pack-objects.c

 	struct object_entry **list;
 	int i;
 
+	setup_git_directory();
+
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 

File pack-redundant.c

 	unsigned char *sha1;
 	char buf[42]; /* 40 byte sha1 + \n + \0 */
 
+	setup_git_directory();
+
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 		if(!strcmp(arg, "--")) {

File peek-remote.c

 	char *dest = NULL;
 	int fd[2];
 	pid_t pid;
+	int nongit = 0;
+
+	setup_git_directory_gently(&nongit);
 
 	for (i = 1; i < argc; i++) {
 		char *arg = argv[i];

File prune-packed.c

 {
 	int i;
 
+	setup_git_directory();
+
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 
 	unsigned char sha1[20];
 	merge_fn_t fn = NULL;
 
+	setup_git_directory();
+
 	newfd = hold_index_file_for_update(&cache_file, get_index_file());
 	if (newfd < 0)
 		die("unable to create new cachefile");
 	int fd[2], ret;
 	pid_t pid;
 
+	setup_git_directory();
 	argv++;
 	for (i = 1; i < argc; i++, argv++) {
 		char *arg = *argv;
 	return path;
 }
 
+/* 
+ * Unlike prefix_path, this should be used if the named file does
+ * not have to interact with index entry; i.e. name of a random file
+ * on the filesystem.
+ */
+const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
+{
+	static char path[PATH_MAX];
+	if (!pfx || !*pfx || arg[0] == '/')
+		return arg;
+	memcpy(path, pfx, pfx_len);
+	strcpy(path + pfx_len, arg);
+	return path;
+}
+
 const char **get_pathspec(const char *prefix, const char **pathspec)
 {
 	const char *entry = *pathspec;
 	return 1;
 }
 
-static const char *setup_git_directory_1(void)
+const char *setup_git_directory_gently(int *nongit_ok)
 {
 	static char cwd[PATH_MAX+1];
 	int len, offset;
 			break;
 		chdir("..");
 		do {
-			if (!offset)
+			if (!offset) {
+				if (nongit_ok) {
+					if (chdir(cwd))
+						die("Cannot come back to cwd");
+					*nongit_ok = 1;
+					return NULL;
+				}
 				die("Not a git repository");
+			}
 		} while (cwd[--offset] != '/');
 	}
 
 
 const char *setup_git_directory(void)
 {
-	const char *retval = setup_git_directory_1();
+	const char *retval = setup_git_directory_gently(NULL);
 	check_repository_format();
 	return retval;
 }
 	prog = getenv("GIT_SSH_PUSH");
 	if (!prog) prog = "git-ssh-upload";
 
+	setup_git_directory();
+
 	while (arg < argc && argv[arg][0] == '-') {
 		if (argv[arg][1] == 't') {
 			get_tree = 1;

File ssh-upload.c

 
 	prog = getenv(COUNTERPART_ENV_NAME);
 	if (!prog) prog = COUNTERPART_PROGRAM_NAME;
+
+	setup_git_directory();
+
 	while (arg < argc && argv[arg][0] == '-') {
 		if (argv[arg][1] == 'w')
 			arg++;
 	void *buffer;
 	unsigned long size;
 
+	setup_git_directory();
+
 	switch (argc) {
 	case 3:
 		basedir = argv[2];

File unpack-file.c

 	if (argc != 2 || get_sha1(argv[1], sha1))
 		usage("git-unpack-file <sha1>");
 
+	setup_git_directory();
+
 	puts(create_temp_file(sha1));
 	return 0;
 }

File unpack-objects.c

 	int i;
 	unsigned char sha1[20];
 
+	setup_git_directory();
+
 	for (i = 1 ; i < argc; i++) {
 		const char *arg = argv[i];
 

File update-server-info.c

 	if (i != ac)
 		usage(update_server_info_usage);
 
+	setup_git_directory();
+
 	return !!update_server_info(force);
 }

File write-tree.c

 int main(int argc, char **argv)
 {
 	int i, funny;
-	int entries = read_cache();
+	int entries;
 	unsigned char sha1[20];
 	
+	setup_git_directory();
+
+	entries = read_cache();
 	if (argc == 2) {
 		if (!strcmp(argv[1], "--missing-ok"))
 			missing_ok = 1;