From: Junio C Hamano Date: Wed, 26 Apr 2006 10:29:09 +0000 (-0700) Subject: Merge branch 'master' into jc/cache-tree X-Git-Tag: v1.4.1-rc1~179^2 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/b8ed7f0f40743dae6111c8950ba55051933298ca?ds=inline;hp=-c Merge branch 'master' into jc/cache-tree * master: commit-tree: allow generic object name for the tree as well. Makefile: remove and create xdiff library from scratch. t0000-basic: Add ls-tree recursive test back. Libified diff-index: backward compatibility fix. Libify diff-index. Libify diff-files. Makefile: remove and create libgit.a from scratch. Document the configuration file Document git-var -l listing also configuration variables rev-parse: better error message for ambiguous arguments make update-index --chmod work with multiple files and --stdin socksetup: don't return on set_reuse_addr() error Fix "git show --stat" git-update-index --unresolve Add git-unresolve ... Add colordiff for git to contrib/colordiff. gitk: Let git-rev-list do the argument list parsing --- b8ed7f0f40743dae6111c8950ba55051933298ca diff --combined Makefile index 1aa96f4f2e,8ce27a65fb..d2cc01a265 --- a/Makefile +++ b/Makefile @@@ -199,12 -199,12 +199,12 @@@ LIB_H = tree-walk.h log-tree.h DIFF_OBJS = \ - diff-lib.o diffcore-break.o diffcore-order.o \ + diff.o diff-lib.o diffcore-break.o diffcore-order.o \ diffcore-pickaxe.o diffcore-rename.o tree-diff.o combine-diff.o \ diffcore-delta.o log-tree.o LIB_OBJS = \ - blob.o commit.o connect.o csum-file.o \ + blob.o commit.o connect.o csum-file.o cache-tree.o \ date.o diff-delta.o entry.o exec_cmd.o ident.o index.o \ object.o pack-check.o patch-delta.o path.o pkt-line.o \ quote.o read-cache.o refs.o run-command.o \ @@@ -575,12 -575,12 +575,12 @@@ $(patsubst git-%$X,%.o,$(PROGRAMS)): $( $(DIFF_OBJS): diffcore.h $(LIB_FILE): $(LIB_OBJS) - $(AR) rcs $@ $(LIB_OBJS) + rm -f $@ && $(AR) rcs $@ $(LIB_OBJS) XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o $(XDIFF_LIB): $(XDIFF_OBJS) - $(AR) rcs $@ $(XDIFF_OBJS) + rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS) doc: @@@ -611,9 -611,6 +611,9 @@@ test-date$X: test-date.c date.o ctype. test-delta$X: test-delta.c diff-delta.o patch-delta.o $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^ -lz +test-dump-cache-tree$X: dump-cache-tree.o $(GITLIBS) + $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) + check: for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done diff --combined update-index.c index d6d3295e32,facec8d915..258a88cbea --- a/update-index.c +++ b/update-index.c @@@ -6,7 -6,7 +6,8 @@@ #include "cache.h" #include "strbuf.h" #include "quote.h" +#include "cache-tree.h" + #include "tree-walk.h" /* * Default to not allowing changes to the list of files. The @@@ -71,7 -71,6 +72,7 @@@ static int mark_valid(const char *path active_cache[pos]->ce_flags &= ~htons(CE_VALID); break; } + cache_tree_invalidate_path(active_cache_tree, path); active_cache_changed = 1; return 0; } @@@ -85,12 -84,6 +86,12 @@@ static int add_file_to_cache(const cha struct stat st; status = lstat(path, &st); + + /* We probably want to do this in remove_file_from_cache() and + * add_cache_entry() instead... + */ + cache_tree_invalidate_path(active_cache_tree, path); + if (status < 0 || S_ISDIR(st.st_mode)) { /* When we used to have "path" and now we want to add * "path/file", we need a way to remove "path" before @@@ -333,11 -326,10 +334,11 @@@ static int add_cacheinfo(unsigned int m return error("%s: cannot add to the index - missing --add option?", path); report("add '%s'", path); + cache_tree_invalidate_path(active_cache_tree, path); return 0; } - static int chmod_path(int flip, const char *path) + static void chmod_path(int flip, const char *path) { int pos; struct cache_entry *ce; @@@ -345,22 -337,24 +346,25 @@@ pos = cache_name_pos(path, strlen(path)); if (pos < 0) - return -1; + goto fail; ce = active_cache[pos]; mode = ntohl(ce->ce_mode); if (!S_ISREG(mode)) - return -1; + goto fail; switch (flip) { case '+': ce->ce_mode |= htonl(0111); break; case '-': ce->ce_mode &= htonl(~0111); break; default: - return -1; + goto fail; } + cache_tree_invalidate_path(active_cache_tree, path); active_cache_changed = 1; - return 0; + report("chmod %cx '%s'", flip, path); + return; + fail: + die("git-update-index: cannot chmod %cx '%s'", flip, path); } static struct cache_file cache_file; @@@ -377,7 -371,6 +381,7 @@@ static void update_one(const char *path die("Unable to mark file %s", path); return; } + cache_tree_invalidate_path(active_cache_tree, path); if (force_remove) { if (remove_file_from_cache(p)) @@@ -453,7 -446,6 +457,7 @@@ static void read_index_info(int line_te free(path_name); continue; } + cache_tree_invalidate_path(active_cache_tree, path_name); if (!mode) { /* mode == 0 means there is no such path -- remove */ @@@ -483,6 -475,124 +487,124 @@@ static const char update_index_usage[] = "git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--cacheinfo] [--chmod=(+|-)x] [--info-only] [--force-remove] [--stdin] [--index-info] [--ignore-missing] [-z] [--verbose] [--] ..."; + static unsigned char head_sha1[20]; + static unsigned char merge_head_sha1[20]; + + static struct cache_entry *read_one_ent(const char *which, + unsigned char *ent, const char *path, + int namelen, int stage) + { + unsigned mode; + unsigned char sha1[20]; + int size; + struct cache_entry *ce; + + if (get_tree_entry(ent, path, sha1, &mode)) { + error("%s: not in %s branch.", path, which); + return NULL; + } + if (mode == S_IFDIR) { + error("%s: not a blob in %s branch.", path, which); + return NULL; + } + size = cache_entry_size(namelen); + ce = xcalloc(1, size); + + memcpy(ce->sha1, sha1, 20); + memcpy(ce->name, path, namelen); + ce->ce_flags = create_ce_flags(namelen, stage); + ce->ce_mode = create_ce_mode(mode); + return ce; + } + + static int unresolve_one(const char *path) + { + int namelen = strlen(path); + int pos; + int ret = 0; + struct cache_entry *ce_2 = NULL, *ce_3 = NULL; + + /* See if there is such entry in the index. */ + pos = cache_name_pos(path, namelen); + if (pos < 0) { + /* If there isn't, either it is unmerged, or + * resolved as "removed" by mistake. We do not + * want to do anything in the former case. + */ + pos = -pos-1; + if (pos < active_nr) { + struct cache_entry *ce = active_cache[pos]; + if (ce_namelen(ce) == namelen && + !memcmp(ce->name, path, namelen)) { + fprintf(stderr, + "%s: skipping still unmerged path.\n", + path); + goto free_return; + } + } + } + + /* Grab blobs from given path from HEAD and MERGE_HEAD, + * stuff HEAD version in stage #2, + * stuff MERGE_HEAD version in stage #3. + */ + ce_2 = read_one_ent("our", head_sha1, path, namelen, 2); + ce_3 = read_one_ent("their", merge_head_sha1, path, namelen, 3); + + if (!ce_2 || !ce_3) { + ret = -1; + goto free_return; + } + if (!memcmp(ce_2->sha1, ce_3->sha1, 20) && + ce_2->ce_mode == ce_3->ce_mode) { + fprintf(stderr, "%s: identical in both, skipping.\n", + path); + goto free_return; + } + + remove_file_from_cache(path); + if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) { + error("%s: cannot add our version to the index.", path); + ret = -1; + goto free_return; + } + if (!add_cache_entry(ce_3, ADD_CACHE_OK_TO_ADD)) + return 0; + error("%s: cannot add their version to the index.", path); + ret = -1; + free_return: + free(ce_2); + free(ce_3); + return ret; + } + + static void read_head_pointers(void) + { + if (read_ref(git_path("HEAD"), head_sha1)) + die("No HEAD -- no initial commit yet?\n"); + if (read_ref(git_path("MERGE_HEAD"), merge_head_sha1)) { + fprintf(stderr, "Not in the middle of a merge.\n"); + exit(0); + } + } + + static int do_unresolve(int ac, const char **av) + { + int i; + int err = 0; + + /* Read HEAD and MERGE_HEAD; if MERGE_HEAD does not exist, we + * are not doing a merge, so exit with success status. + */ + read_head_pointers(); + + for (i = 1; i < ac; i++) { + const char *arg = av[i]; + err |= unresolve_one(arg); + } + return err; + } + int main(int argc, const char **argv) { int i, newfd, entries, has_errors = 0, line_termination = '\n'; @@@ -490,6 -600,7 +612,7 @@@ int read_from_stdin = 0; const char *prefix = setup_git_directory(); int prefix_length = prefix ? strlen(prefix) : 0; + char set_executable_bit = 0; git_config(git_default_config); @@@ -556,8 -667,7 +679,7 @@@ !strcmp(path, "--chmod=+x")) { if (argc <= i+1) die("git-update-index: %s ", path); - if (chmod_path(path[8], argv[++i])) - die("git-update-index: %s cannot chmod %s", path, argv[i]); + set_executable_bit = path[8]; continue; } if (!strcmp(path, "--assume-unchanged")) { @@@ -593,6 -703,12 +715,12 @@@ read_index_info(line_termination); break; } + if (!strcmp(path, "--unresolve")) { + has_errors = do_unresolve(argc - i, argv + i); + if (has_errors) + active_cache_changed = 0; + goto finish; + } if (!strcmp(path, "--ignore-missing")) { not_new = 1; continue; @@@ -606,6 -722,8 +734,8 @@@ die("unknown option %s", path); } update_one(path, prefix, prefix_length); + if (set_executable_bit) + chmod_path(set_executable_bit, path); } if (read_from_stdin) { struct strbuf buf; @@@ -620,10 -738,16 +750,16 @@@ else path_name = buf.buf; update_one(path_name, prefix, prefix_length); + if (set_executable_bit) { + const char *p = prefix_path(prefix, prefix_length, path_name); + chmod_path(set_executable_bit, p); + } if (path_name != buf.buf) free(path_name); } } + + finish: if (active_cache_changed) { if (write_cache(newfd, active_cache, active_nr) || commit_index_file(&cache_file))