From: Junio C Hamano Date: Thu, 28 Sep 2006 05:23:12 +0000 (-0700) Subject: Merge branch 'master' into lj/refs X-Git-Tag: v1.4.4-rc1~43^2~12 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/2958d9b5dbebeb82e7230bbfd3f421781d90f3f7?ds=sidebyside;hp=-c Merge branch 'master' into lj/refs * master: (72 commits) runstatus: do not recurse into subdirectories if not needed grep: fix --fixed-strings combined with expression. grep: free expressions and patterns when done. Corrected copy-and-paste thinko in ignore executable bit test case. An illustration of rev-list --parents --pretty=raw Allow git-checkout when on a non-existant branch. gitweb: Decode long title for link tooltips git-svn: Fix fetch --no-ignore-externals with GIT_SVN_NO_LIB=1 Ignore executable bit when adding files if filemode=0. Remove empty ref directories that prevent creating a ref. Use const for interpolate arguments git-archive: update documentation Deprecate merge-recursive.py gitweb: fix over-eager application of esc_html(). Allow '(no author)' in git-svn's authors file. Allow 'svn fetch' on '(no date)' revisions in Subversion. git-repack: allow git-repack to run in subdirectory Remove upload-tar and make git-tar-tree a thin wrapper to git-archive git-tar-tree: Move code for git-archive --format=tar to archive-tar.c git-tar-tree: Remove duplicate git_config() call ... --- 2958d9b5dbebeb82e7230bbfd3f421781d90f3f7 diff --combined .gitignore index 0ffe14ac4e,25eb4637a6..4c8c8e4115 --- a/.gitignore +++ b/.gitignore @@@ -37,7 -37,6 +37,7 @@@ git-fetc git-fetch-pack git-findtags git-fmt-merge-msg +git-for-each-ref git-format-patch git-fsck-objects git-get-tar-commit-id @@@ -66,6 -65,7 +66,7 @@@ git-merge-one-fil git-merge-ours git-merge-recur git-merge-recursive + git-merge-recursive-old git-merge-resolve git-merge-stupid git-mktag @@@ -74,7 -74,6 +75,7 @@@ git-name-re git-mv git-pack-redundant git-pack-objects +git-pack-refs git-parse-remote git-patch-id git-peek-remote @@@ -106,7 -105,6 +107,7 @@@ git-shortlo git-show git-show-branch git-show-index +git-show-ref git-ssh-fetch git-ssh-pull git-ssh-push @@@ -125,13 -123,11 +126,11 @@@ git-update-re git-update-server-info git-upload-archive git-upload-pack - git-upload-tar git-var git-verify-pack git-verify-tag git-whatchanged git-write-tree - git-zip-tree git-core-*/?* gitweb/gitweb.cgi test-date diff --combined Makefile index af4d68fd7e,c888c810bf..65fb8284f3 --- a/Makefile +++ b/Makefile @@@ -81,8 -81,6 +81,6 @@@ all # Define NO_ACCURATE_DIFF if your diff program at least sometimes misses # a missing newline at the end of the file. # - # Define NO_PYTHON if you want to lose all benefits of the recursive merge. - # # Define COLLISION_CHECK below if you believe that SHA1's # 1461501637330902918203684832716283019655932542976 hashes do not give you # sufficient guarantee that no collisions between objects will ever happen. @@@ -174,7 -172,7 +172,7 @@@ SCRIPT_PERL = git-send-email.perl git-svn.perl SCRIPT_PYTHON = \ - git-merge-recursive.py + git-merge-recursive-old.py SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.perl,%,$(SCRIPT_PERL)) \ @@@ -199,7 -197,7 +197,7 @@@ PROGRAMS = git-upload-pack$X git-verify-pack$X \ git-pack-redundant$X git-var$X \ git-describe$X git-merge-tree$X git-blame$X git-imap-send$X \ - git-merge-recur$X \ + git-merge-recursive$X \ $(EXTRA_PROGRAMS) # Empty... @@@ -234,7 -232,7 +232,7 @@@ LIB_FILE=libgit. XDIFF_LIB=xdiff/lib.a LIB_H = \ - archive.h blob.h cache.h commit.h csum-file.h delta.h \ + archive.h blob.h cache.h commit.h csum-file.h delta.h grep.h \ diff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.h \ run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \ tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h @@@ -246,15 -244,17 +244,17 @@@ DIFF_OBJS = LIB_OBJS = \ blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \ - date.o diff-delta.o entry.o exec_cmd.o ident.o lockfile.o \ + date.o diff-delta.o entry.o exec_cmd.o ident.o \ + interpolate.o \ + lockfile.o \ object.o pack-check.o patch-delta.o path.o pkt-line.o sideband.o \ quote.o read-cache.o refs.o run-command.o dir.o object-refs.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \ - write_or_die.o trace.o list-objects.o \ + write_or_die.o trace.o list-objects.o grep.o \ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ - color.o wt-status.o + color.o wt-status.o archive-zip.o archive-tar.o BUILTIN_OBJS = \ builtin-add.o \ @@@ -271,7 -271,6 +271,7 @@@ builtin-diff-stages.o \ builtin-diff-tree.o \ builtin-fmt-merge-msg.o \ + builtin-for-each-ref.o \ builtin-grep.o \ builtin-init-db.o \ builtin-log.o \ @@@ -299,12 -298,8 +299,10 @@@ builtin-update-index.o \ builtin-update-ref.o \ builtin-upload-archive.o \ - builtin-upload-tar.o \ builtin-verify-pack.o \ - builtin-write-tree.o + builtin-write-tree.o \ - builtin-zip-tree.o \ + builtin-show-ref.o \ + builtin-pack-refs.o GITLIBS = $(LIB_FILE) $(XDIFF_LIB) LIBS = $(GITLIBS) -lz @@@ -573,7 -568,8 +571,8 @@@ LIB_OBJS += $(COMPAT_OBJS export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir ### Build rules - all: $(ALL_PROGRAMS) $(BUILT_INS) git$X gitk gitweb/gitweb.cgi + all: $(ALL_PROGRAMS) $(BUILT_INS) git$X gitk gitweb/gitweb.cgi \ + git-merge-recur$X all: $(MAKE) -C templates @@@ -588,6 -584,9 +587,9 @@@ git$X: git.c common-cmds.h $(BUILTIN_OB help.o: common-cmds.h + git-merge-recur$X: git-merge-recursive$X + rm -f $@ && ln git-merge-recursive$X $@ + $(BUILT_INS): git$X rm -f $@ && ln git$X $@ @@@ -725,11 -724,6 +727,6 @@@ git-http-push$X: revision.o http.o http $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) - merge-recursive.o path-list.o: path-list.h - git-merge-recur$X: merge-recursive.o path-list.o $(GITLIBS) - $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ - $(LIBS) - $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) $(DIFF_OBJS): diffcore.h @@@ -890,6 -884,7 +887,7 @@@ check-docs: case "$$v" in \ git-merge-octopus | git-merge-ours | git-merge-recursive | \ git-merge-resolve | git-merge-stupid | git-merge-recur | \ + git-merge-recursive-old | \ git-ssh-pull | git-ssh-push ) continue ;; \ esac ; \ test -f "Documentation/$$v.txt" || \ diff --combined builtin-init-db.c index 23b7714f89,c3ed1ce492..235a0ee48f --- a/builtin-init-db.c +++ b/builtin-init-db.c @@@ -218,8 -218,8 +218,8 @@@ static void create_default_files(const * branch, if it does not exist yet. */ strcpy(path + len, "HEAD"); - if (read_ref(path, sha1) < 0) { - if (create_symref(path, "refs/heads/master") < 0) + if (read_ref("HEAD", sha1) < 0) { + if (create_symref("HEAD", "refs/heads/master") < 0) exit(1); } @@@ -311,6 -311,7 +311,7 @@@ int cmd_init_db(int argc, const char ** */ sprintf(buf, "%d", shared_repository); git_config_set("core.sharedrepository", buf); + git_config_set("receive.denyNonFastforwards", "true"); } return 0; diff --combined builtin-update-index.c index 09214c8a11,a3c0a455ae..7f9c638466 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@@ -112,11 -112,13 +112,13 @@@ static int add_file_to_cache(const cha ce->ce_mode = create_ce_mode(st.st_mode); if (!trust_executable_bit) { /* If there is an existing entry, pick the mode bits - * from it. + * from it, otherwise force to 644. */ int pos = cache_name_pos(path, namelen); if (0 <= pos) ce->ce_mode = active_cache[pos]->ce_mode; + else + ce->ce_mode = create_ce_mode(S_IFREG | 0644); } if (index_path(ce->sha1, path, &st, !info_only)) @@@ -404,9 -406,9 +406,9 @@@ static int unresolve_one(const char *pa static void read_head_pointers(void) { - if (read_ref(git_path("HEAD"), head_sha1)) + if (read_ref("HEAD", head_sha1)) die("No HEAD -- no initial commit yet?\n"); - if (read_ref(git_path("MERGE_HEAD"), merge_head_sha1)) { + if (read_ref("MERGE_HEAD", merge_head_sha1)) { fprintf(stderr, "Not in the middle of a merge.\n"); exit(0); } @@@ -443,7 -445,7 +445,7 @@@ static int do_reupdate(int ac, const ch int has_head = 1; const char **pathspec = get_pathspec(prefix, av + 1); - if (read_ref(git_path("HEAD"), head_sha1)) + if (read_ref("HEAD", head_sha1)) /* If there is no HEAD, that means it is an initial * commit. Update everything in the index. */ diff --combined builtin.h index 6bf0ace375,f9fa9ff1d2..721b8d8037 --- a/builtin.h +++ b/builtin.h @@@ -26,7 -26,6 +26,7 @@@ extern int cmd_diff(int argc, const cha extern int cmd_diff_stages(int argc, const char **argv, const char *prefix); extern int cmd_diff_tree(int argc, const char **argv, const char *prefix); extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix); +extern int cmd_for_each_ref(int argc, const char **argv, const char *prefix); extern int cmd_format_patch(int argc, const char **argv, const char *prefix); extern int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix); extern int cmd_grep(int argc, const char **argv, const char *prefix); @@@ -49,12 -48,11 +49,11 @@@ extern int cmd_rev_list(int argc, cons extern int cmd_rev_parse(int argc, const char **argv, const char *prefix); extern int cmd_rm(int argc, const char **argv, const char *prefix); extern int cmd_runstatus(int argc, const char **argv, const char *prefix); -extern int cmd_show_branch(int argc, const char **argv, const char *prefix); extern int cmd_show(int argc, const char **argv, const char *prefix); +extern int cmd_show_branch(int argc, const char **argv, const char *prefix); extern int cmd_stripspace(int argc, const char **argv, const char *prefix); extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix); extern int cmd_tar_tree(int argc, const char **argv, const char *prefix); - extern int cmd_zip_tree(int argc, const char **argv, const char *prefix); extern int cmd_unpack_objects(int argc, const char **argv, const char *prefix); extern int cmd_update_index(int argc, const char **argv, const char *prefix); extern int cmd_update_ref(int argc, const char **argv, const char *prefix); @@@ -64,7 -62,5 +63,7 @@@ extern int cmd_version(int argc, const extern int cmd_whatchanged(int argc, const char **argv, const char *prefix); extern int cmd_write_tree(int argc, const char **argv, const char *prefix); extern int cmd_verify_pack(int argc, const char **argv, const char *prefix); +extern int cmd_show_ref(int argc, const char **argv, const char *prefix); +extern int cmd_pack_refs(int argc, const char **argv, const char *prefix); #endif diff --combined cache.h index 6e004505be,97debd03c5..0565333f05 --- a/cache.h +++ b/cache.h @@@ -179,7 -179,6 +179,7 @@@ struct lock_file extern int hold_lock_file_for_update(struct lock_file *, const char *path, int); extern int commit_lock_file(struct lock_file *); extern void rollback_lock_file(struct lock_file *); +extern int delete_ref(const char *, unsigned char *sha1); /* Environment bits from configuration mechanism */ extern int use_legacy_headers; @@@ -189,6 -188,7 +189,7 @@@ extern int prefer_symlink_refs extern int log_all_ref_updates; extern int warn_ambiguous_refs; extern int shared_repository; + extern int deny_non_fast_forwards; extern const char *apply_default_whitespace; extern int zlib_compression_level; @@@ -279,6 -279,12 +280,12 @@@ enum object_type OBJ_BAD, }; + extern signed char hexval_table[256]; + static inline unsigned int hexval(unsigned int c) + { + return hexval_table[c]; + } + /* Convert to/from hex/sha1 representation */ #define MINIMUM_ABBREV 4 #define DEFAULT_ABBREV 7 @@@ -287,9 -293,9 +294,9 @@@ extern int get_sha1(const char *str, un extern int get_sha1_hex(const char *hex, unsigned char *sha1); extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */ extern int read_ref(const char *filename, unsigned char *sha1); -extern const char *resolve_ref(const char *path, unsigned char *sha1, int); -extern int create_symref(const char *git_HEAD, const char *refs_heads_master); -extern int validate_symref(const char *git_HEAD); +extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *); +extern int create_symref(const char *ref, const char *refs_heads_master); +extern int validate_symref(const char *ref); extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2); extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2); @@@ -384,10 -390,10 +391,10 @@@ extern void unuse_packed_git(struct pac extern struct packed_git *add_packed_git(char *, int, int); extern int num_packed_objects(const struct packed_git *p); extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*); - extern int find_pack_entry_one(const unsigned char *, struct pack_entry *, struct packed_git *); - extern void *unpack_entry_gently(struct pack_entry *, char *, unsigned long *); + extern unsigned long find_pack_entry_one(const unsigned char *, struct packed_git *); + extern void *unpack_entry_gently(struct packed_git *, unsigned long, char *, unsigned long *); extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep); - extern void packed_object_info_detail(struct pack_entry *, char *, unsigned long *, unsigned long *, unsigned int *, unsigned char *); + extern void packed_object_info_detail(struct packed_git *, unsigned long, char *, unsigned long *, unsigned long *, unsigned int *, unsigned char *); /* Dumb servers support */ extern int update_server_info(int); diff --combined git-branch.sh index 4379a07210,4f31903d63..bf84b30695 --- a/git-branch.sh +++ b/git-branch.sh @@@ -21,7 -21,7 +21,7 @@@ delete_branch () ,,) die "What branch are you on anyway?" ;; esac - branch=$(cat "$GIT_DIR/refs/heads/$branch_name") && + branch=$(git-show-ref --verify --hash -- "refs/heads/$branch_name") && branch=$(git-rev-parse --verify "$branch^0") || die "Seriously, what branch are you talking about?" case "$option" in @@@ -42,7 -42,8 +42,7 @@@ If you are sure you want to delete it, esac ;; esac - rm -f "$GIT_DIR/logs/refs/heads/$branch_name" - rm -f "$GIT_DIR/refs/heads/$branch_name" + git update-ref -d "refs/heads/$branch_name" "$branch" echo "Deleted branch $branch_name." done exit 0 @@@ -111,8 -112,17 +111,18 @@@ rev=$(git-rev-parse --verify "$head") | git-check-ref-format "heads/$branchname" || die "we do not like '$branchname' as a branch name." + if [ -d "$GIT_DIR/refs/heads/$branchname" ] + then + for refdir in `cd "$GIT_DIR" && \ + find "refs/heads/$branchname" -type d | sort -r` + do + rmdir "$GIT_DIR/$refdir" || \ + die "Could not delete '$refdir', there may still be a ref there." + done + fi + -if [ -e "$GIT_DIR/refs/heads/$branchname" ] +prev='' +if git-show-ref --verify --quiet -- "refs/heads/$branchname" then if test '' = "$force" then @@@ -121,11 -131,10 +131,11 @@@ then die "cannot force-update the current branch." fi + prev=`git rev-parse --verify "refs/heads/$branchname"` fi if test "$create_log" = 'yes' then mkdir -p $(dirname "$GIT_DIR/logs/refs/heads/$branchname") touch "$GIT_DIR/logs/refs/heads/$branchname" fi -git update-ref -m "branch: Created from $head" "refs/heads/$branchname" $rev +git update-ref -m "branch: Created from $head" "refs/heads/$branchname" "$rev" "$prev" diff --combined git-checkout.sh index f03620b054,dd477245fb..119bca1ffb --- a/git-checkout.sh +++ b/git-checkout.sh @@@ -4,8 -4,8 +4,8 @@@ USAGE='[-f] [-b ] [-m] [
/dev/null) new= new_name= force= @@@ -22,7 -22,7 +22,7 @@@ while [ "$#" != "0" ]; d shift [ -z "$newbranch" ] && die "git checkout: -b needs a branch name" - [ -e "$GIT_DIR/refs/heads/$newbranch" ] && + git-show-ref --verify --quiet -- "refs/heads/$newbranch" && die "git checkout: branch $newbranch already exists" git-check-ref-format "heads/$newbranch" || die "git checkout: we do not like '$newbranch' as a branch name." @@@ -51,8 -51,7 +51,8 @@@ fi new="$rev" new_name="$arg^0" - if [ -f "$GIT_DIR/refs/heads/$arg" ]; then + if git-show-ref --verify --quiet -- "refs/heads/$arg" + then branch="$arg" fi elif rev=$(git-rev-parse --verify "$arg^{tree}" 2>/dev/null) @@@ -140,6 -139,13 +140,13 @@@ f die "git checkout: to checkout the requested commit you need to specify a name for a new branch which is created and switched to" + if [ "X$old" = X ] + then + echo "warning: You do not appear to currently be on a branch." >&2 + echo "warning: Forcing checkout of $new_name." >&2 + force=1 + fi + if [ "$force" ] then git-read-tree --reset -u $new diff --combined git.c index f7e7841649,ae80e78456..9108fec808 --- a/git.c +++ b/git.c @@@ -232,7 -232,6 +232,7 @@@ static void handle_internal_command(in { "diff-stages", cmd_diff_stages, RUN_SETUP }, { "diff-tree", cmd_diff_tree, RUN_SETUP }, { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP }, + { "for-each-ref", cmd_for_each_ref, RUN_SETUP }, { "format-patch", cmd_format_patch, RUN_SETUP }, { "get-tar-commit-id", cmd_get_tar_commit_id }, { "grep", cmd_grep, RUN_SETUP }, @@@ -260,18 -259,14 +260,16 @@@ { "stripspace", cmd_stripspace }, { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP }, { "tar-tree", cmd_tar_tree, RUN_SETUP }, - { "zip-tree", cmd_zip_tree, RUN_SETUP }, { "unpack-objects", cmd_unpack_objects, RUN_SETUP }, { "update-index", cmd_update_index, RUN_SETUP }, { "update-ref", cmd_update_ref, RUN_SETUP }, { "upload-archive", cmd_upload_archive }, - { "upload-tar", cmd_upload_tar }, { "version", cmd_version }, { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER }, { "write-tree", cmd_write_tree, RUN_SETUP }, { "verify-pack", cmd_verify_pack }, + { "show-ref", cmd_show_ref, RUN_SETUP }, + { "pack-refs", cmd_pack_refs, RUN_SETUP }, }; int i; diff --combined receive-pack.c index c8aacbbdd3,ea2dbd4e33..1fcf3a9112 --- a/receive-pack.c +++ b/receive-pack.c @@@ -2,6 -2,8 +2,8 @@@ #include "refs.h" #include "pkt-line.h" #include "run-command.h" + #include "commit.h" + #include "object.h" static const char receive_pack_usage[] = "git-receive-pack "; @@@ -12,7 -14,7 +14,7 @@@ static int report_status static char capabilities[] = "report-status"; static int capabilities_sent; -static int show_ref(const char *path, const unsigned char *sha1) +static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) { if (capabilities_sent) packet_write(1, "%s %s\n", sha1_to_hex(sha1), path); @@@ -25,9 -27,9 +27,9 @@@ static void write_head_info(void) { - for_each_ref(show_ref); + for_each_ref(show_ref, NULL); if (!capabilities_sent) - show_ref("capabilities^{}", null_sha1); + show_ref("capabilities^{}", null_sha1, 0, NULL); } @@@ -41,6 -43,34 +43,6 @@@ struct command static struct command *commands; -static int is_all_zeroes(const char *hex) -{ - int i; - for (i = 0; i < 40; i++) - if (*hex++ != '0') - return 0; - return 1; -} - -static int verify_old_ref(const char *name, char *hex_contents) -{ - int fd, ret; - char buffer[60]; - - if (is_all_zeroes(hex_contents)) - return 0; - fd = open(name, O_RDONLY); - if (fd < 0) - return -1; - ret = read(fd, buffer, 40); - close(fd); - if (ret != 40) - return -1; - if (memcmp(buffer, hex_contents, 40)) - return -1; - return 0; -} - static char update_hook[] = "hooks/update"; static int run_update_hook(const char *refname, @@@ -77,8 -107,8 +79,8 @@@ static int update(struct command *cmd const char *name = cmd->ref_name; unsigned char *old_sha1 = cmd->old_sha1; unsigned char *new_sha1 = cmd->new_sha1; - char new_hex[60], *old_hex, *lock_name; - int newfd, namelen, written; + char new_hex[41], old_hex[41]; + struct ref_lock *lock; cmd->error_string = NULL; if (!strncmp(name, "refs/", 5) && check_ref_format(name + 5)) { @@@ -87,27 -117,74 +89,42 @@@ name); } - namelen = strlen(name); - lock_name = xmalloc(namelen + 10); - memcpy(lock_name, name, namelen); - memcpy(lock_name + namelen, ".lock", 6); - strcpy(new_hex, sha1_to_hex(new_sha1)); - old_hex = sha1_to_hex(old_sha1); + strcpy(old_hex, sha1_to_hex(old_sha1)); if (!has_sha1_file(new_sha1)) { cmd->error_string = "bad pack"; return error("unpack should have generated %s, " "but I can't find it!", new_hex); } + if (deny_non_fast_forwards && !is_null_sha1(old_sha1)) { + struct commit *old_commit, *new_commit; + struct commit_list *bases, *ent; + + old_commit = (struct commit *)parse_object(old_sha1); + new_commit = (struct commit *)parse_object(new_sha1); + bases = get_merge_bases(old_commit, new_commit, 1); + for (ent = bases; ent; ent = ent->next) + if (!hashcmp(old_sha1, ent->item->object.sha1)) + break; + free_commit_list(bases); + if (!ent) + return error("denying non-fast forward;" + " you should pull first"); + } - safe_create_leading_directories(lock_name); - - newfd = open(lock_name, O_CREAT | O_EXCL | O_WRONLY, 0666); - if (newfd < 0) { - cmd->error_string = "can't lock"; - return error("unable to create %s (%s)", - lock_name, strerror(errno)); - } - - /* Write the ref with an ending '\n' */ - new_hex[40] = '\n'; - new_hex[41] = 0; - written = write(newfd, new_hex, 41); - /* Remove the '\n' again */ - new_hex[40] = 0; - - close(newfd); - if (written != 41) { - unlink(lock_name); - cmd->error_string = "can't write"; - return error("unable to write %s", lock_name); - } - if (verify_old_ref(name, old_hex) < 0) { - unlink(lock_name); - cmd->error_string = "raced"; - return error("%s changed during push", name); - } if (run_update_hook(name, old_hex, new_hex)) { - unlink(lock_name); cmd->error_string = "hook declined"; return error("hook declined to update %s", name); } - else if (rename(lock_name, name) < 0) { - unlink(lock_name); - cmd->error_string = "can't rename"; - return error("unable to replace %s", name); - } - else { - fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex); - return 0; + + lock = lock_any_ref_for_update(name, old_sha1); + if (!lock) { + cmd->error_string = "failed to lock"; + return error("failed to lock %s", name); } + write_ref_sha1(lock, new_sha1, "push"); + + fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex); + return 0; } static char update_post_hook[] = "hooks/post-update"; @@@ -258,12 -335,9 +275,12 @@@ int main(int argc, char **argv if (!dir) usage(receive_pack_usage); - if(!enter_repo(dir, 0)) + if (!enter_repo(dir, 0)) die("'%s': unable to chdir or not a git archive", dir); + setup_ident(); + git_config(git_default_config); + write_head_info(); /* EOF */ diff --combined revision.c index cb13b90776,93f25130a0..d87cb6cd64 --- a/revision.c +++ b/revision.c @@@ -6,6 -6,8 +6,8 @@@ #include "diff.h" #include "refs.h" #include "revision.h" + #include + #include "grep.h" static char *path_name(struct name_path *path, const char *name) { @@@ -466,7 -468,7 +468,7 @@@ static void limit_list(struct rev_info static int all_flags; static struct rev_info *all_revs; -static int handle_one_ref(const char *path, const unsigned char *sha1) +static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) { struct object *object = get_reference(all_revs, path, sha1, all_flags); add_pending_object(all_revs, object, ""); @@@ -477,7 -479,7 +479,7 @@@ static void handle_all(struct rev_info { all_revs = revs; all_flags = flags; - for_each_ref(handle_one_ref); + for_each_ref(handle_one_ref, NULL); } static int add_parents_only(struct rev_info *revs, const char *arg, int flags) @@@ -672,6 -674,42 +674,42 @@@ int handle_revision_arg(const char *arg return 0; } + static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what) + { + if (!revs->grep_filter) { + struct grep_opt *opt = xcalloc(1, sizeof(*opt)); + opt->status_only = 1; + opt->pattern_tail = &(opt->pattern_list); + opt->regflags = REG_NEWLINE; + revs->grep_filter = opt; + } + append_grep_pattern(revs->grep_filter, ptn, + "command line", 0, what); + } + + static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern) + { + char *pat; + const char *prefix; + int patlen, fldlen; + + fldlen = strlen(field); + patlen = strlen(pattern); + pat = xmalloc(patlen + fldlen + 10); + prefix = ".*"; + if (*pattern == '^') { + prefix = ""; + pattern++; + } + sprintf(pat, "^%s %s%s", field, prefix, pattern); + add_grep(revs, pat, GREP_PATTERN_HEAD); + } + + static void add_message_grep(struct rev_info *revs, const char *pattern) + { + add_grep(revs, pattern, GREP_PATTERN_BODY); + } + static void add_ignore_packed(struct rev_info *revs, const char *name) { int num = ++revs->num_ignore_packed; @@@ -913,6 -951,23 +951,23 @@@ int setup_revisions(int argc, const cha revs->relative_date = 1; continue; } + + /* + * Grepping the commit log + */ + if (!strncmp(arg, "--author=", 9)) { + add_header_grep(revs, "author", arg+9); + continue; + } + if (!strncmp(arg, "--committer=", 12)) { + add_header_grep(revs, "committer", arg+12); + continue; + } + if (!strncmp(arg, "--grep=", 7)) { + add_message_grep(revs, arg+7); + continue; + } + opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i); if (opts > 0) { revs->diff = 1; @@@ -973,6 -1028,9 +1028,9 @@@ if (diff_setup_done(&revs->diffopt) < 0) die("diff_setup_done failed"); + if (revs->grep_filter) + compile_grep_patterns(revs->grep_filter); + return left; } @@@ -1045,6 -1103,15 +1103,15 @@@ static void mark_boundary_to_show(struc } } + static int commit_match(struct commit *commit, struct rev_info *opt) + { + if (!opt->grep_filter) + return 1; + return grep_buffer(opt->grep_filter, + NULL, /* we say nothing, not even filename */ + commit->buffer, strlen(commit->buffer)); + } + struct commit *get_revision(struct rev_info *revs) { struct commit_list *list = revs->commits; @@@ -1105,6 -1172,8 +1172,8 @@@ if (revs->no_merges && commit->parents && commit->parents->next) continue; + if (!commit_match(commit, revs)) + continue; if (revs->prune_fn && revs->dense) { /* Commit without changes? */ if (!(commit->object.flags & TREECHANGE)) { diff --combined sha1_name.c index 84d24c6abf,9b226e3579..ed711f2079 --- a/sha1_name.c +++ b/sha1_name.c @@@ -247,8 -247,8 +247,8 @@@ static int get_sha1_basic(const char *s NULL }; static const char *warning = "warning: refname '%.*s' is ambiguous.\n"; - const char **p, *pathname; - char *real_path = NULL; + const char **p, *ref; + char *real_ref = NULL; int refs_found = 0, am; unsigned long at_time = (unsigned long)-1; unsigned char *this_result; @@@ -276,10 -276,10 +276,10 @@@ for (p = fmt; *p; p++) { this_result = refs_found ? sha1_from_ref : sha1; - pathname = resolve_ref(git_path(*p, len, str), this_result, 1); - if (pathname) { + ref = resolve_ref(mkpath(*p, len, str), this_result, 1, NULL); + if (ref) { if (!refs_found++) - real_path = xstrdup(pathname); + real_ref = xstrdup(ref); if (!warn_ambiguous_refs) break; } @@@ -293,12 -293,12 +293,12 @@@ if (at_time != (unsigned long)-1) { read_ref_at( - real_path + strlen(git_path(".")) - 1, + real_ref, at_time, sha1); } - free(real_path); + free(real_ref); return 0; } @@@ -431,6 -431,26 +431,26 @@@ static int peel_onion(const char *name return 0; } + static int get_describe_name(const char *name, int len, unsigned char *sha1) + { + const char *cp; + + for (cp = name + len - 1; name + 2 <= cp; cp--) { + char ch = *cp; + if (hexval(ch) & ~0377) { + /* We must be looking at g in "SOMETHING-g" + * for it to be describe output. + */ + if (ch == 'g' && cp[-1] == '-') { + cp++; + len -= cp - name; + return get_short_sha1(cp, len, sha1, 1); + } + } + } + return -1; + } + static int get_sha1_1(const char *name, int len, unsigned char *sha1) { int ret, has_suffix; @@@ -472,6 -492,12 +492,12 @@@ ret = get_sha1_basic(name, len, sha1); if (!ret) return 0; + + /* It could be describe output that is "SOMETHING-gXXXX" */ + ret = get_describe_name(name, len, sha1); + if (!ret) + return 0; + return get_short_sha1(name, len, sha1, 0); }