From: Junio C Hamano Date: Mon, 10 Sep 2012 22:31:06 +0000 (-0700) Subject: Merge branch 'maint-1.7.11' into maint X-Git-Tag: v1.7.12.1~28 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/e3f26752b5e9d38e88a09671d124b61fb0cd5dbf?ds=inline;hp=-c Merge branch 'maint-1.7.11' into maint * maint-1.7.11: Almost 1.7.11.6 gitweb: URL-decode $my_url/$my_uri when stripping PATH_INFO rebase -i: use full onto sha1 in reflog sh-setup: protect from exported IFS receive-pack: do not leak output from auto-gc to standard output t/t5400: demonstrate breakage caused by informational message from prune setup: clarify error messages for file/revisions ambiguity send-email: improve RFC2047 quote parsing fsck: detect null sha1 in tree entries do not write null sha1s to on-disk index diff: do not use null sha1 as a sentinel value --- e3f26752b5e9d38e88a09671d124b61fb0cd5dbf diff --combined builtin.h index ba6626b035,dffb34ef4e..8e377522fe --- a/builtin.h +++ b/builtin.h @@@ -9,6 -9,7 +9,6 @@@ #define DEFAULT_MERGE_LOG_LEN 20 -extern const char git_version_string[]; extern const char git_usage_string[]; extern const char git_more_info_string[]; @@@ -43,7 -44,7 +43,7 @@@ extern int check_pager_config(const cha struct diff_options; extern void setup_diff_pager(struct diff_options *); - extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, char **buf, unsigned long *buf_size); + extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size); extern int cmd_add(int argc, const char **argv, const char *prefix); extern int cmd_annotate(int argc, const char **argv, const char *prefix); @@@ -67,7 -68,6 +67,7 @@@ extern int cmd_commit(int argc, const c extern int cmd_commit_tree(int argc, const char **argv, const char *prefix); extern int cmd_config(int argc, const char **argv, const char *prefix); extern int cmd_count_objects(int argc, const char **argv, const char *prefix); +extern int cmd_credential(int argc, const char **argv, const char *prefix); extern int cmd_describe(int argc, const char **argv, const char *prefix); extern int cmd_diff_files(int argc, const char **argv, const char *prefix); extern int cmd_diff_index(int argc, const char **argv, const char *prefix); diff --combined builtin/blame.c index 0d50273ce9,a9705d06a5..f2c48ef5af --- a/builtin/blame.c +++ b/builtin/blame.c @@@ -110,6 -110,7 +110,7 @@@ static int diff_hunks(mmfile_t *file_a int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, + int sha1_valid, char **buf, unsigned long *buf_size) { @@@ -117,7 -118,7 +118,7 @@@ struct userdiff_driver *textconv; df = alloc_filespec(path); - fill_filespec(df, sha1, mode); + fill_filespec(df, sha1, sha1_valid, mode); textconv = get_textconv(df); if (!textconv) { free_filespec(df); @@@ -142,7 -143,7 +143,7 @@@ static void fill_origin_blob(struct dif num_read_blob++; if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) && - textconv_object(o->path, o->mode, o->blob_sha1, &file->ptr, &file_size)) + textconv_object(o->path, o->mode, o->blob_sha1, 1, &file->ptr, &file_size)) ; else file->ptr = read_sha1_file(o->blob_sha1, &type, &file_size); @@@ -2123,7 -2124,7 +2124,7 @@@ static struct commit *fake_working_tree switch (st.st_mode & S_IFMT) { case S_IFREG: if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) && - textconv_object(read_from, mode, null_sha1, &buf_ptr, &buf_len)) + textconv_object(read_from, mode, null_sha1, 0, &buf_ptr, &buf_len)) strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1); else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size) die_errno("cannot open or read '%s'", read_from); @@@ -2171,8 -2172,7 +2172,8 @@@ ce = xcalloc(1, size); hashcpy(ce->sha1, origin->blob_sha1); memcpy(ce->name, path, len); - ce->ce_flags = create_ce_flags(len, 0); + ce->ce_flags = create_ce_flags(0); + ce->ce_namelen = len; ce->ce_mode = create_ce_mode(mode); add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); @@@ -2516,7 -2516,7 +2517,7 @@@ parse_done die("no such path %s in %s", path, final_commit_name); if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) && - textconv_object(path, o->mode, o->blob_sha1, (char **) &sb.final_buf, + textconv_object(path, o->mode, o->blob_sha1, 1, (char **) &sb.final_buf, &sb.final_buf_size)) ; else diff --combined builtin/cat-file.c index af74e775a1,60568f9c39..0eca2d7bd0 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@@ -91,7 -91,7 +91,7 @@@ static int cat_one_file(int opt, const unsigned long size; struct object_context obj_context; - if (get_sha1_with_context(obj_name, sha1, &obj_context)) + if (get_sha1_with_context(obj_name, 0, sha1, &obj_context)) die("Not a valid object name %s", obj_name); buf = NULL; @@@ -146,7 -146,7 +146,7 @@@ die("git cat-file --textconv %s: must be ", obj_name); - if (!textconv_object(obj_context.path, obj_context.mode, sha1, &buf, &size)) + if (!textconv_object(obj_context.path, obj_context.mode, sha1, 1, &buf, &size)) die("git cat-file --textconv: unable to run textconv on %s", obj_name); break; diff --combined diff.c index 95706a5b40,15125e8894..359f40a210 --- a/diff.c +++ b/diff.c @@@ -1397,7 -1397,7 +1397,7 @@@ int print_stat_summary(FILE *fp, int fi if (!files) { assert(insertions == 0 && deletions == 0); - return fputs(_(" 0 files changed\n"), fp); + return fprintf(fp, "%s\n", _(" 0 files changed")); } strbuf_addf(&sb, @@@ -2541,12 -2541,12 +2541,12 @@@ void free_filespec(struct diff_filespe } void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, - unsigned short mode) + int sha1_valid, unsigned short mode) { if (mode) { spec->mode = canon_mode(mode); hashcpy(spec->sha1, sha1); - spec->sha1_valid = !is_null_sha1(sha1); + spec->sha1_valid = sha1_valid; } } @@@ -4693,6 -4693,7 +4693,7 @@@ static int is_submodule_ignored(const c void diff_addremove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, + int sha1_valid, const char *concatpath, unsigned dirty_submodule) { struct diff_filespec *one, *two; @@@ -4724,9 -4725,9 +4725,9 @@@ two = alloc_filespec(concatpath); if (addremove != '+') - fill_filespec(one, sha1, mode); + fill_filespec(one, sha1, sha1_valid, mode); if (addremove != '-') { - fill_filespec(two, sha1, mode); + fill_filespec(two, sha1, sha1_valid, mode); two->dirty_submodule = dirty_submodule; } @@@ -4739,6 -4740,7 +4740,7 @@@ void diff_change(struct diff_options *o unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, + int old_sha1_valid, int new_sha1_valid, const char *concatpath, unsigned old_dirty_submodule, unsigned new_dirty_submodule) { @@@ -4753,6 -4755,8 +4755,8 @@@ const unsigned char *tmp_c; tmp = old_mode; old_mode = new_mode; new_mode = tmp; tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c; + tmp = old_sha1_valid; old_sha1_valid = new_sha1_valid; + new_sha1_valid = tmp; tmp = old_dirty_submodule; old_dirty_submodule = new_dirty_submodule; new_dirty_submodule = tmp; } @@@ -4763,8 -4767,8 +4767,8 @@@ one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); - fill_filespec(one, old_sha1, old_mode); - fill_filespec(two, new_sha1, new_mode); + fill_filespec(one, old_sha1, old_sha1_valid, old_mode); + fill_filespec(two, new_sha1, new_sha1_valid, new_mode); one->dirty_submodule = old_dirty_submodule; two->dirty_submodule = new_dirty_submodule; diff --combined git-rebase--interactive.sh index 0d2056f027,84926783d1..a09e8423dd --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@@ -9,7 -9,9 +9,7 @@@ # # The original idea comes from Eric W. Biederman, in # http://article.gmane.org/gmane.comp.version-control.git/22407 - -. git-sh-setup - +# # The file containing rebase commands, comments, and empty lines. # This file is created by "git rebase -i" then edited by the user. As # the lines are processed, they are removed from the front of this @@@ -415,29 -417,6 +415,29 @@@ record_in_rewritten() esac } +do_pick () { + if test "$(git rev-parse HEAD)" = "$squash_onto" + then + # Set the correct commit message and author info on the + # sentinel root before cherry-picking the original changes + # without committing (-n). Finally, update the sentinel again + # to include these changes. If the cherry-pick results in a + # conflict, this means our behaviour is similar to a standard + # failed cherry-pick during rebase, with a dirty index to + # resolve before manually running git commit --amend then git + # rebase --continue. + git commit --allow-empty --allow-empty-message --amend \ + --no-post-rewrite -n -q -C $1 && + pick_one -n $1 && + git commit --allow-empty --allow-empty-message \ + --amend --no-post-rewrite -n -q -C $1 || + die_with_patch $1 "Could not apply $1... $2" + else + pick_one $1 || + die_with_patch $1 "Could not apply $1... $2" + fi +} + do_next () { rm -f "$msg" "$author_script" "$amend" || exit read -r command sha1 rest < "$todo" @@@ -449,14 -428,16 +449,14 @@@ comment_for_reflog pick mark_action_done - pick_one $sha1 || - die_with_patch $sha1 "Could not apply $sha1... $rest" + do_pick $sha1 "$rest" record_in_rewritten $sha1 ;; reword|r) comment_for_reflog reword mark_action_done - pick_one $sha1 || - die_with_patch $sha1 "Could not apply $sha1... $rest" + do_pick $sha1 "$rest" git commit --amend --no-post-rewrite || { warn "Could not amend commit after successfully picking $sha1... $rest" warn "This is most likely due to an empty commit message, or the pre-commit hook" @@@ -470,7 -451,8 +470,7 @@@ comment_for_reflog edit mark_action_done - pick_one $sha1 || - die_with_patch $sha1 "Could not apply $sha1... $rest" + do_pick $sha1 "$rest" warn "Stopped at $sha1... $rest" exit_with_patch $sha1 0 ;; @@@ -493,28 -475,25 +493,28 @@@ author_script_content=$(get_author_ident_from_commit HEAD) echo "$author_script_content" > "$author_script" eval "$author_script_content" - output git reset --soft HEAD^ - pick_one -n $sha1 || die_failed_squash $sha1 "$rest" + if ! pick_one -n $sha1 + then + git rev-parse --verify HEAD >"$amend" + die_failed_squash $sha1 "$rest" + fi case "$(peek_next_command)" in squash|s|fixup|f) # This is an intermediate commit; its message will only be # used in case of trouble. So use the long version: - do_with_author output git commit --no-verify -F "$squash_msg" || + do_with_author output git commit --amend --no-verify -F "$squash_msg" || die_failed_squash $sha1 "$rest" ;; *) # This is the final command of this squash/fixup group if test -f "$fixup_msg" then - do_with_author git commit --no-verify -F "$fixup_msg" || + do_with_author git commit --amend --no-verify -F "$fixup_msg" || die_failed_squash $sha1 "$rest" else cp "$squash_msg" "$GIT_DIR"/SQUASH_MSG || exit rm -f "$GIT_DIR"/MERGE_MSG - do_with_author git commit --no-verify -e || + do_with_author git commit --amend --no-verify -F "$GIT_DIR"/SQUASH_MSG -e || die_failed_squash $sha1 "$rest" fi rm -f "$squash_msg" "$fixup_msg" @@@ -569,11 -548,10 +569,10 @@@ test -s "$todo" && return comment_for_reflog finish && - shortonto=$(git rev-parse --short $onto) && newhead=$(git rev-parse HEAD) && case $head_name in refs/*) - message="$GIT_REFLOG_ACTION: $head_name onto $shortonto" && + message="$GIT_REFLOG_ACTION: $head_name onto $onto" && git update-ref -m "$message" $head_name $newhead $orig_head && git symbolic-ref \ -m "$GIT_REFLOG_ACTION: returning to $head_name" \ @@@ -705,27 -683,6 +704,27 @@@ rearrange_squash () rm -f "$1.sq" "$1.rearranged" } +# Add commands after a pick or after a squash/fixup serie +# in the todo list. +add_exec_commands () { + { + first=t + while read -r insn rest + do + case $insn in + pick) + test -n "$first" || + printf "%s" "$cmd" + ;; + esac + printf "%s %s\n" "$insn" "$rest" + first= + done + printf "%s" "$cmd" + } <"$1" >"$1.new" && + mv "$1.new" "$1" +} + case "$action" in continue) # do we have anything to commit? @@@ -751,6 -708,7 +750,6 @@@ In both case, once you're done, continu fi . "$author_script" || die "Error trying to find the author identity to amend commit" - current_head= if test -f "$amend" then current_head=$(git rev-parse --verify HEAD) @@@ -758,12 -716,13 +757,12 @@@ die "\ You have uncommitted changes in your working tree. Please, commit them first and then run 'git rebase --continue' again." - git reset --soft HEAD^ || - die "Cannot rewind the HEAD" + do_with_author git commit --amend --no-verify -F "$msg" -e || + die "Could not commit staged changes." + else + do_with_author git commit --no-verify -F "$msg" -e || + die "Could not commit staged changes." fi - do_with_author git commit --no-verify -F "$msg" -e || { - test -n "$current_head" && git reset --soft $current_head - die "Could not commit staged changes." - } fi record_in_rewritten "$(cat "$state_dir"/stopped-sha)" @@@ -897,8 -856,6 +896,8 @@@ f test -s "$todo" || echo noop >> "$todo" test -n "$autosquash" && rearrange_squash "$todo" +test -n "$cmd" && add_exec_commands "$todo" + cat >> "$todo" << EOF # Rebase $shortrevisions onto $shortonto diff --combined gitweb/gitweb.perl index 3d6a705388,a40ed0ceb0..7f8c1878d4 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@@ -54,6 -54,11 +54,11 @@@ sub evaluate_uri # to build the base URL ourselves: our $path_info = decode_utf8($ENV{"PATH_INFO"}); if ($path_info) { + # $path_info has already been URL-decoded by the web server, but + # $my_url and $my_uri have not. URL-decode them so we can properly + # strip $path_info. + $my_url = unescape($my_url); + $my_uri = unescape($my_uri); if ($my_url =~ s,\Q$path_info\E$,, && $my_uri =~ s,\Q$path_info\E$,, && defined $ENV{'SCRIPT_NAME'}) { @@@ -4484,33 -4489,30 +4489,33 @@@ sub git_print_log } # print log - my $signoff = 0; - my $empty = 0; + my $skip_blank_line = 0; foreach my $line (@$log) { - if ($line =~ m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i) { - $signoff = 1; - $empty = 0; + if ($line =~ m/^\s*([A-Z][-A-Za-z]*-[Bb]y|C[Cc]): /) { if (! $opts{'-remove_signoff'}) { print "" . esc_html($line) . "
\n"; - next; - } else { - # remove signoff lines - next; + $skip_blank_line = 1; } - } else { - $signoff = 0; + next; + } + + if ($line =~ m,\s*([a-z]*link): (https?://\S+),i) { + if (! $opts{'-remove_signoff'}) { + print "" . esc_html($1) . ": " . + "" . esc_html($2) . "" . + "
\n"; + $skip_blank_line = 1; + } + next; } # print only one empty line # do not print empty line after signoff if ($line eq "") { - next if ($empty || $signoff); - $empty = 1; + next if ($skip_blank_line); + $skip_blank_line = 1; } else { - $empty = 0; + $skip_blank_line = 0; } print format_log_line_html($line) . "
\n"; @@@ -4518,7 -4520,7 +4523,7 @@@ if ($opts{'-final_empty_line'}) { # end with single empty line - print "
\n" unless $empty; + print "
\n" unless $skip_blank_line; } } diff --combined read-cache.c index 2f8159fb16,7d4bf68e33..d2be78ea95 --- a/read-cache.c +++ b/read-cache.c @@@ -17,10 -17,6 +17,10 @@@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really); +/* Mask for the name length in ce_flags in the on-disk index */ + +#define CE_NAMEMASK (0x0fff) + /* Index extensions. * * The first letter should be 'A'..'Z' for extensions that are not @@@ -58,8 -54,8 +58,8 @@@ void rename_index_entry_at(struct index new = xmalloc(cache_entry_size(namelen)); copy_cache_entry(new, old); - new->ce_flags &= ~(CE_STATE_MASK | CE_NAMEMASK); - new->ce_flags |= (namelen >= CE_NAMEMASK ? CE_NAMEMASK : namelen); + new->ce_flags &= ~CE_STATE_MASK; + new->ce_namelen = namelen; memcpy(new->name, new_name, namelen + 1); cache_tree_invalidate_path(istate->cache_tree, old->name); @@@ -399,10 -395,17 +399,10 @@@ int df_name_compare(const char *name1, return c1 - c2; } -int cache_name_compare(const char *name1, int flags1, const char *name2, int flags2) +int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2) { - int len1, len2, len, cmp; - - len1 = flags1 & CE_NAMEMASK; - if (CE_NAMEMASK <= len1) - len1 = strlen(name1 + CE_NAMEMASK) + CE_NAMEMASK; - len2 = flags2 & CE_NAMEMASK; - if (CE_NAMEMASK <= len2) - len2 = strlen(name2 + CE_NAMEMASK) + CE_NAMEMASK; - len = len1 < len2 ? len1 : len2; + int len = len1 < len2 ? len1 : len2; + int cmp; cmp = memcmp(name1, name2, len); if (cmp) @@@ -412,19 -415,18 +412,19 @@@ if (len1 > len2) return 1; - /* Compare stages */ - flags1 &= CE_STAGEMASK; - flags2 &= CE_STAGEMASK; - - if (flags1 < flags2) + if (stage1 < stage2) return -1; - if (flags1 > flags2) + if (stage1 > stage2) return 1; return 0; } -int index_name_pos(const struct index_state *istate, const char *name, int namelen) +int cache_name_compare(const char *name1, int len1, const char *name2, int len2) +{ + return cache_name_stage_compare(name1, len1, 0, name2, len2, 0); +} + +int index_name_stage_pos(const struct index_state *istate, const char *name, int namelen, int stage) { int first, last; @@@ -433,7 -435,7 +433,7 @@@ while (last > first) { int next = (last + first) >> 1; struct cache_entry *ce = istate->cache[next]; - int cmp = cache_name_compare(name, namelen, ce->name, ce->ce_flags); + int cmp = cache_name_stage_compare(name, namelen, stage, ce->name, ce_namelen(ce), ce_stage(ce)); if (!cmp) return next; if (cmp < 0) { @@@ -445,11 -447,6 +445,11 @@@ return -first-1; } +int index_name_pos(const struct index_state *istate, const char *name, int namelen) +{ + return index_name_stage_pos(istate, name, namelen, 0); +} + /* Remove entry, return true if there are more entries to go.. */ int remove_index_entry_at(struct index_state *istate, int pos) { @@@ -589,7 -586,7 +589,7 @@@ int add_to_index(struct index_state *is size = cache_entry_size(namelen); ce = xcalloc(1, size); memcpy(ce->name, path, namelen); - ce->ce_flags = namelen; + ce->ce_namelen = namelen; if (!intent_only) fill_stat_cache_info(ce, st); else @@@ -691,8 -688,7 +691,8 @@@ struct cache_entry *make_cache_entry(un hashcpy(ce->sha1, sha1); memcpy(ce->name, path, len); - ce->ce_flags = create_ce_flags(len, stage); + ce->ce_flags = create_ce_flags(stage); + ce->ce_namelen = len; ce->ce_mode = create_ce_mode(mode); if (refresh) @@@ -829,7 -825,7 +829,7 @@@ static int has_dir_name(struct index_st } len = slash - name; - pos = index_name_pos(istate, name, create_ce_flags(len, stage)); + pos = index_name_stage_pos(istate, name, len, stage); if (pos >= 0) { /* * Found one, but not so fast. This could @@@ -919,7 -915,7 +919,7 @@@ static int add_index_entry_with_check(s int new_only = option & ADD_CACHE_NEW_ONLY; cache_tree_invalidate_path(istate->cache_tree, ce->name); - pos = index_name_pos(istate, ce->name, ce->ce_flags); + pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce)); /* existing match? Just replace it. */ if (pos >= 0) { @@@ -951,7 -947,7 +951,7 @@@ if (!ok_to_replace) return error("'%s' appears as both a file and as a directory", ce->name); - pos = index_name_pos(istate, ce->name, ce->ce_flags); + pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce)); pos = -pos-1; } return pos + 1; @@@ -1128,7 -1124,7 +1128,7 @@@ int refresh_index(struct index_state *i continue; if (pathspec && - !match_pathspec(pathspec, ce->name, strlen(ce->name), 0, seen)) + !match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen)) filtered = 1; if (ce_stage(ce)) { @@@ -1328,8 -1324,7 +1328,8 @@@ static struct cache_entry *cache_entry_ ce->ce_uid = ntoh_l(ondisk->uid); ce->ce_gid = ntoh_l(ondisk->gid); ce->ce_size = ntoh_l(ondisk->size); - ce->ce_flags = flags; + ce->ce_flags = flags & ~CE_NAMEMASK; + ce->ce_namelen = len; hashcpy(ce->sha1, ondisk->sha1); memcpy(ce->name, name, len); ce->name[len] = '\0'; @@@ -1656,8 -1651,6 +1656,8 @@@ static void ce_smudge_racily_clean_entr static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk, struct cache_entry *ce) { + short flags; + ondisk->ctime.sec = htonl(ce->ce_ctime.sec); ondisk->mtime.sec = htonl(ce->ce_mtime.sec); ondisk->ctime.nsec = htonl(ce->ce_ctime.nsec); @@@ -1669,10 -1662,7 +1669,10 @@@ ondisk->gid = htonl(ce->ce_gid); ondisk->size = htonl(ce->ce_size); hashcpy(ondisk->sha1, ce->sha1); - ondisk->flags = htons(ce->ce_flags); + + flags = ce->ce_flags; + flags |= (ce_namelen(ce) >= CE_NAMEMASK ? CE_NAMEMASK : ce_namelen(ce)); + ondisk->flags = htons(flags); if (ce->ce_flags & CE_EXTENDED) { struct ondisk_cache_entry_extended *ondisk2; ondisk2 = (struct ondisk_cache_entry_extended *)ondisk; @@@ -1800,6 -1790,8 +1800,8 @@@ int write_index(struct index_state *ist continue; if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce)) ce_smudge_racily_clean_entry(ce); + if (is_null_sha1(ce->sha1)) + return error("cache entry has null sha1: %s", ce->name); if (ce_write_entry(&c, newfd, ce, previous_name) < 0) return -1; } @@@ -1856,12 -1848,11 +1858,12 @@@ int read_index_unmerged(struct index_st if (!ce_stage(ce)) continue; unmerged = 1; - len = strlen(ce->name); + len = ce_namelen(ce); size = cache_entry_size(len); new_ce = xcalloc(1, size); memcpy(new_ce->name, ce->name, len); - new_ce->ce_flags = create_ce_flags(len, 0) | CE_CONFLICTED; + new_ce->ce_flags = create_ce_flags(0) | CE_CONFLICTED; + new_ce->ce_namelen = len; new_ce->ce_mode = ce->ce_mode; if (add_index_entry(istate, new_ce, 0)) return error("%s: cannot drop to stage #0", diff --combined revision.c index 9e8f47a25d,74c484ca84..04c7de87d0 --- a/revision.c +++ b/revision.c @@@ -345,6 -345,7 +345,7 @@@ static int tree_difference = REV_TREE_S static void file_add_remove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, + int sha1_valid, const char *fullpath, unsigned dirty_submodule) { int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD; @@@ -358,6 -359,7 +359,7 @@@ static void file_change(struct diff_opt unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, + int old_sha1_valid, int new_sha1_valid, const char *fullpath, unsigned old_dirty_submodule, unsigned new_dirty_submodule) { @@@ -1000,7 -1002,7 +1002,7 @@@ static int add_parents_only(struct rev_ flags ^= UNINTERESTING; arg++; } - if (get_sha1(arg, sha1)) + if (get_sha1_committish(arg, sha1)) return 0; while (1) { it = get_reference(revs, arg, sha1, 0); @@@ -1114,16 -1116,16 +1116,16 @@@ static void prepare_show_merge(struct r revs->limited = 1; } -int handle_revision_arg(const char *arg_, struct rev_info *revs, - int flags, - int cant_be_filename) +int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsigned revarg_opt) { - unsigned mode; + struct object_context oc; char *dotdot; struct object *object; unsigned char sha1[20]; int local_flags; const char *arg = arg_; + int cant_be_filename = revarg_opt & REVARG_CANNOT_BE_FILENAME; + unsigned get_sha1_flags = 0; dotdot = strstr(arg, ".."); if (dotdot) { @@@ -1141,8 -1143,8 +1143,8 @@@ next = "HEAD"; if (dotdot == arg) this = "HEAD"; - if (!get_sha1(this, from_sha1) && - !get_sha1(next, sha1)) { + if (!get_sha1_committish(this, from_sha1) && + !get_sha1_committish(next, sha1)) { struct commit *a, *b; struct commit_list *exclude; @@@ -1201,17 -1203,13 +1203,17 @@@ local_flags = UNINTERESTING; arg++; } - if (get_sha1_with_mode(arg, sha1, &mode)) + + if (revarg_opt & REVARG_COMMITTISH) + get_sha1_flags = GET_SHA1_COMMITTISH; + + if (get_sha1_with_context(arg, get_sha1_flags, sha1, &oc)) return revs->ignore_missing ? 0 : -1; if (!cant_be_filename) verify_non_filename(revs->prefix, arg); object = get_reference(revs, arg, sha1, flags ^ local_flags); add_rev_cmdline(revs, object, arg_, REV_CMD_REV, flags ^ local_flags); - add_pending_object_with_mode(revs, object, arg, mode); + add_pending_object_with_mode(revs, object, arg, oc.mode); return 0; } @@@ -1261,7 -1259,7 +1263,7 @@@ static void read_revisions_from_stdin(s } die("options not supported in --stdin mode"); } - if (handle_revision_arg(sb.buf, revs, 0, 1)) + if (handle_revision_arg(sb.buf, revs, 0, REVARG_CANNOT_BE_FILENAME)) die("bad revision '%s'", sb.buf); } if (seen_dashdash) @@@ -1712,7 -1710,7 +1714,7 @@@ static int handle_revision_pseudo_opt(c */ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct setup_revision_opt *opt) { - int i, flags, left, seen_dashdash, read_from_stdin, got_rev_arg = 0; + int i, flags, left, seen_dashdash, read_from_stdin, got_rev_arg = 0, revarg_opt; struct cmdline_pathspec prune_data; const char *submodule = NULL; @@@ -1740,9 -1738,6 +1742,9 @@@ /* Second, deal with arguments and options */ flags = 0; + revarg_opt = opt ? opt->revarg_opt : 0; + if (seen_dashdash) + revarg_opt |= REVARG_CANNOT_BE_FILENAME; read_from_stdin = 0; for (left = i = 1; i < argc; i++) { const char *arg = argv[i]; @@@ -1778,8 -1773,7 +1780,8 @@@ continue; } - if (handle_revision_arg(arg, revs, flags, seen_dashdash)) { + + if (handle_revision_arg(arg, revs, flags, revarg_opt)) { int j; if (seen_dashdash || *arg == '^') die("bad revision '%s'", arg); @@@ -1830,11 -1824,11 +1832,11 @@@ if (revs->def && !revs->pending.nr && !got_rev_arg) { unsigned char sha1[20]; struct object *object; - unsigned mode; - if (get_sha1_with_mode(revs->def, sha1, &mode)) + struct object_context oc; + if (get_sha1_with_context(revs->def, 0, sha1, &oc)) die("bad default revision '%s'", revs->def); object = get_reference(revs, revs->def, sha1, 0); - add_pending_object_with_mode(revs, object, revs->def, mode); + add_pending_object_with_mode(revs, object, revs->def, oc.mode); } /* Did the user ask for any diff output? Run the diff! */ @@@ -2369,28 -2363,29 +2371,28 @@@ static struct commit *get_revision_inte } /* - * Now pick up what they want to give us + * If our max_count counter has reached zero, then we are done. We + * don't simply return NULL because we still might need to show + * boundary commits. But we want to avoid calling get_revision_1, which + * might do a considerable amount of work finding the next commit only + * for us to throw it away. + * + * If it is non-zero, then either we don't have a max_count at all + * (-1), or it is still counting, in which case we decrement. */ - c = get_revision_1(revs); - if (c) { - while (0 < revs->skip_count) { - revs->skip_count--; - c = get_revision_1(revs); - if (!c) - break; + if (revs->max_count) { + c = get_revision_1(revs); + if (c) { + while (0 < revs->skip_count) { + revs->skip_count--; + c = get_revision_1(revs); + if (!c) + break; + } } - } - /* - * Check the max_count. - */ - switch (revs->max_count) { - case -1: - break; - case 0: - c = NULL; - break; - default: - revs->max_count--; + if (revs->max_count > 0) + revs->max_count--; } if (c) diff --combined setup.c index 9139beefc7,7663a4cbb2..3a1b2fd455 --- a/setup.c +++ b/setup.c @@@ -77,22 -77,27 +77,23 @@@ static void NORETURN die_verify_filenam const char *arg, int diagnose_misspelt_rev) { - unsigned char sha1[20]; - unsigned mode; - if (!diagnose_misspelt_rev) die("%s: no such path in the working tree.\n" - "Use '-- ...' to specify paths that do not exist locally.", + "Use 'git -- ...' to specify paths that do not exist locally.", arg); /* * Saying "'(icase)foo' does not exist in the index" when the * user gave us ":(icase)foo" is just stupid. A magic pathspec * begins with a colon and is followed by a non-alnum; do not - * let get_sha1_with_mode_1(only_to_die=1) to even trigger. + * let maybe_die_on_misspelt_object_name() even trigger. */ if (!(arg[0] == ':' && !isalnum(arg[1]))) - /* try a detailed diagnostic ... */ - get_sha1_with_mode_1(arg, sha1, &mode, 1, prefix); + maybe_die_on_misspelt_object_name(arg, prefix); /* ... or fall back the most general message. */ die("ambiguous argument '%s': unknown revision or path not in the working tree.\n" - "Use '--' to separate paths from revisions", arg); + "Use '--' to separate paths from revisions, like this:\n" + "'git [...] -- [...]'", arg); } @@@ -141,7 -146,8 +142,8 @@@ void verify_non_filename(const char *pr if (!check_filename(prefix, arg)) return; die("ambiguous argument '%s': both revision and filename\n" - "Use '--' to separate filenames from revisions", arg); + "Use '--' to separate paths from revisions, like this:\n" + "'git [...] -- [...]'", arg); } /*