diff options
| author | Junio C Hamano <junkio@cox.net> | 2006-06-17 17:56:52 -0700 | 
|---|---|---|
| committer | Junio C Hamano <junkio@cox.net> | 2006-06-17 17:56:52 -0700 | 
| commit | 75c3a5ccdf114b5485e4828db1923bf4a35b19e2 (patch) | |
| tree | e919c376fa68f0ce8b46918b499d8ed8516c048a | |
| parent | 8c278abcbe35b23e9f93e99daf2144336fad1849 (diff) | |
| parent | d6970e42a1763b549ccf93558de7f54a78819d7a (diff) | |
| download | git-75c3a5ccdf114b5485e4828db1923bf4a35b19e2.tar.gz | |
Merge branch 'jc/rw-prefix'
* jc/rw-prefix:
  read-tree: reorganize bind_merge code.
  write-tree: --prefix=<path>
  read-tree: --prefix=<path>/ option.
| -rw-r--r-- | Documentation/git-read-tree.txt | 11 | ||||
| -rw-r--r-- | Documentation/git-write-tree.txt | 8 | ||||
| -rw-r--r-- | builtin-read-tree.c | 70 | ||||
| -rw-r--r-- | cache-tree.c | 26 | ||||
| -rw-r--r-- | cache-tree.h | 2 | ||||
| -rwxr-xr-x | t/t0000-basic.sh | 14 | ||||
| -rw-r--r-- | write-tree.c | 23 | 
7 files changed, 141 insertions, 13 deletions
| diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index d894f537ba..11bd9c0adc 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -8,7 +8,7 @@ git-read-tree - Reads tree information into the index  SYNOPSIS  -------- -'git-read-tree' (<tree-ish> | [[-m [--aggressive]| --reset] [-u | -i]] <tree-ish1> [<tree-ish2> [<tree-ish3>]]) +'git-read-tree' (<tree-ish> | [[-m [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] <tree-ish1> [<tree-ish2> [<tree-ish3>]])  DESCRIPTION @@ -63,6 +63,15 @@ OPTIONS  * when both sides adds a path identically.  The resolution    is to add that path. +--prefix=<prefix>/:: +	Keep the current index contents, and read the contents +	of named tree-ish under directory at `<prefix>`.  The +	original index file cannot have anything at the path +	`<prefix>` itself, and have nothing in `<prefix>/` +	directory.  Note that the `<prefix>/` value must end +	with a slash. + +  <tree-ish#>::  	The id of the tree object(s) to be read/merged. diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt index 77e12cb949..c85fa89c30 100644 --- a/Documentation/git-write-tree.txt +++ b/Documentation/git-write-tree.txt @@ -8,7 +8,7 @@ git-write-tree - Creates a tree object from the current index  SYNOPSIS  -------- -'git-write-tree' [--missing-ok] +'git-write-tree' [--missing-ok] [--prefix=<prefix>/]  DESCRIPTION  ----------- @@ -30,6 +30,12 @@ OPTIONS  	directory exist in the object database.  This option disables this  	check. +--prefix=<prefix>/:: +	Writes a tree object that represents a subdirectory +	`<prefix>`.  This can be used to write the tree object +	for a subproject that is in the named subdirectory. + +  Author  ------  Written by Linus Torvalds <torvalds@osdl.org> diff --git a/builtin-read-tree.c b/builtin-read-tree.c index bb50fbd274..04506da892 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -24,6 +24,7 @@ static int trivial_merges_only = 0;  static int aggressive = 0;  static int verbose_update = 0;  static volatile int progress_update = 0; +static const char *prefix = NULL;  static int head_idx = -1;  static int merge_size = 0; @@ -412,7 +413,8 @@ static int unpack_trees(merge_fn_t fn)  			posns[i] = create_tree_entry_list((struct tree *) posn->item);  			posn = posn->next;  		} -		if (unpack_trees_rec(posns, len, "", fn, &indpos)) +		if (unpack_trees_rec(posns, len, prefix ? prefix : "", +				     fn, &indpos))  			return -1;  	} @@ -762,6 +764,28 @@ static int twoway_merge(struct cache_entry **src)  }  /* + * Bind merge. + * + * Keep the index entries at stage0, collapse stage1 but make sure + * stage0 does not have anything there. + */ +static int bind_merge(struct cache_entry **src) +{ +	struct cache_entry *old = src[0]; +	struct cache_entry *a = src[1]; + +	if (merge_size != 1) +		return error("Cannot do a bind merge of %d trees\n", +			     merge_size); +	if (a && old) +		die("Entry '%s' overlaps.  Cannot bind.", a->name); +	if (!a) +		return keep_entry(old); +	else +		return merged_entry(a, NULL); +} + +/*   * One-way merge.   *   * The rule is: @@ -851,7 +875,7 @@ static void prime_cache_tree(void)  } -static const char read_tree_usage[] = "git-read-tree (<sha> | -m [--aggressive] [-u | -i] <sha1> [<sha2> [<sha3>]])"; +static const char read_tree_usage[] = "git-read-tree (<sha> | [[-m [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] <sha1> [<sha2> [<sha3>]])";  static struct lock_file lock_file; @@ -896,12 +920,27 @@ int cmd_read_tree(int argc, const char **argv, char **envp)  			continue;  		} +		/* "--prefix=<subdirectory>/" means keep the current index +		 *  entries and put the entries from the tree under the +		 * given subdirectory. +		 */ +		if (!strncmp(arg, "--prefix=", 9)) { +			if (stage || merge || prefix) +				usage(read_tree_usage); +			prefix = arg + 9; +			merge = 1; +			stage = 1; +			if (read_cache_unmerged()) +				die("you need to resolve your current index first"); +			continue; +		} +  		/* This differs from "-m" in that we'll silently ignore  		 * unmerged entries and overwrite working tree files that  		 * correspond to them.  		 */  		if (!strcmp(arg, "--reset")) { -			if (stage || merge) +			if (stage || merge || prefix)  				usage(read_tree_usage);  			reset = 1;  			merge = 1; @@ -922,7 +961,7 @@ int cmd_read_tree(int argc, const char **argv, char **envp)  		/* "-m" stands for "merge", meaning we start in stage 1 */  		if (!strcmp(arg, "-m")) { -			if (stage || merge) +			if (stage || merge || prefix)  				usage(read_tree_usage);  			if (read_cache_unmerged())  				die("you need to resolve your current index first"); @@ -944,12 +983,31 @@ int cmd_read_tree(int argc, const char **argv, char **envp)  	if ((update||index_only) && !merge)  		usage(read_tree_usage); +	if (prefix) { +		int pfxlen = strlen(prefix); +		int pos; +		if (prefix[pfxlen-1] != '/') +			die("prefix must end with /"); +		if (stage != 2) +			die("binding merge takes only one tree"); +		pos = cache_name_pos(prefix, pfxlen); +		if (0 <= pos) +			die("corrupt index file"); +		pos = -pos-1; +		if (pos < active_nr && +		    !strncmp(active_cache[pos]->name, prefix, pfxlen)) +			die("subdirectory '%s' already exists.", prefix); +		pos = cache_name_pos(prefix, pfxlen-1); +		if (0 <= pos) +			die("file '%.*s' already exists.", pfxlen-1, prefix); +	} +  	if (merge) {  		if (stage < 2)  			die("just how do you expect me to merge %d trees?", stage-1);  		switch (stage - 1) {  		case 1: -			fn = oneway_merge; +			fn = prefix ? bind_merge : oneway_merge;  			break;  		case 2:  			fn = twoway_merge; @@ -975,7 +1033,7 @@ int cmd_read_tree(int argc, const char **argv, char **envp)  	 * valid cache-tree because the index must match exactly  	 * what came from the tree.  	 */ -	if (trees && trees->item && (!merge || (stage == 2))) { +	if (trees && trees->item && !prefix && (!merge || (stage == 2))) {  		cache_tree_free(&active_cache_tree);  		prime_cache_tree();  	} diff --git a/cache-tree.c b/cache-tree.c index a880c97b38..d9f7e1e3dd 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -529,3 +529,29 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size)  		return NULL; /* not the whole tree */  	return read_one(&buffer, &size);  } + +struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path) +{ +	while (*path) { +		const char *slash; +		struct cache_tree_sub *sub; + +		slash = strchr(path, '/'); +		if (!slash) +			slash = path + strlen(path); +		/* between path and slash is the name of the +		 * subtree to look for. +		 */ +		sub = find_subtree(it, path, slash - path, 0); +		if (!sub) +			return NULL; +		it = sub->cache_tree; +		if (slash) +			while (*slash && *slash == '/') +				slash++; +		if (!slash || !*slash) +			return it; /* prefix ended with slashes */ +		path = slash; +	} +	return it; +} diff --git a/cache-tree.h b/cache-tree.h index 72c64801f5..119407e3a1 100644 --- a/cache-tree.h +++ b/cache-tree.h @@ -28,4 +28,6 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);  int cache_tree_fully_valid(struct cache_tree *);  int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int, int); +struct cache_tree *cache_tree_find(struct cache_tree *, const char *); +  #endif diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index cf33989b56..2c9bbb59b0 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -195,6 +195,20 @@ test_expect_success \      'git-ls-tree -r output for a known tree.' \      'diff current expected' +test_expect_success \ +    'writing partial tree out with git-write-tree --prefix.' \ +    'ptree=$(git-write-tree --prefix=path3)' +test_expect_success \ +    'validate object ID for a known tree.' \ +    'test "$ptree" = 21ae8269cacbe57ae09138dcc3a2887f904d02b3' + +test_expect_success \ +    'writing partial tree out with git-write-tree --prefix.' \ +    'ptree=$(git-write-tree --prefix=path3/subp3)' +test_expect_success \ +    'validate object ID for a known tree.' \ +    'test "$ptree" = 3c5e5399f3a333eddecce7a9b9465b63f65f51e2' +  ################################################################  rm .git/index  test_expect_success \ diff --git a/write-tree.c b/write-tree.c index d6a605893d..bd07da6183 100644 --- a/write-tree.c +++ b/write-tree.c @@ -8,8 +8,10 @@  #include "cache-tree.h"  static int missing_ok = 0; +static char *prefix = NULL; -static const char write_tree_usage[] = "git-write-tree [--missing-ok]"; +static const char write_tree_usage[] = +"git-write-tree [--missing-ok] [--prefix=<prefix>/]";  static struct lock_file lock_file; @@ -21,13 +23,18 @@ int main(int argc, char **argv)  	newfd = hold_lock_file_for_update(&lock_file, get_index_file());  	entries = read_cache(); -	if (argc == 2) { -		if (!strcmp(argv[1], "--missing-ok")) + +	while (1 < argc) { +		char *arg = argv[1]; +		if (!strcmp(arg, "--missing-ok"))  			missing_ok = 1; +		else if (!strncmp(arg, "--prefix=", 9)) +			prefix = arg + 9;  		else  			die(write_tree_usage); +		argc--; argv++;  	} -	 +  	if (argc > 2)  		die("too many options"); @@ -54,6 +61,12 @@ int main(int argc, char **argv)  		 * performance penalty and not a big deal.  		 */  	} -	printf("%s\n", sha1_to_hex(active_cache_tree->sha1)); +	if (prefix) { +		struct cache_tree *subtree = +			cache_tree_find(active_cache_tree, prefix); +		printf("%s\n", sha1_to_hex(subtree->sha1)); +	} +	else +		printf("%s\n", sha1_to_hex(active_cache_tree->sha1));  	return 0;  } | 
