From: Junio C Hamano Date: Mon, 25 Jul 2016 21:13:45 +0000 (-0700) Subject: Merge branch 'mh/blame-worktree' X-Git-Tag: v2.10.0-rc0~84 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/37e9c7f5e15aa423cef640cc4dc137da2f73c5af?ds=inline;hp=-c Merge branch 'mh/blame-worktree' "git blame file" allowed the lineage of lines in the uncommitted, unadded contents of "file" to be inspected, but it refused when "file" did not appear in the current commit. When "file" was created by renaming an existing file (but the change has not been committed), this restriction was unnecessarily tight. * mh/blame-worktree: t/t8003-blame-corner-cases.sh: Use here documents blame: allow to blame paths freshly added to the index --- 37e9c7f5e15aa423cef640cc4dc137da2f73c5af diff --combined builtin/blame.c index 8fec0e1fb3,12c765acfe..ab66cde2c2 --- a/builtin/blame.c +++ b/builtin/blame.c @@@ -56,7 -56,7 +56,7 @@@ static int show_progress static struct date_mode blame_date_mode = { DATE_ISO8601 }; static size_t blame_date_width; -static struct string_list mailmap; +static struct string_list mailmap = STRING_LIST_INIT_NODUP; #ifndef DEBUG #define DEBUG 0 @@@ -134,7 -134,7 +134,7 @@@ struct progress_info int blamed_lines; }; -static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen, +static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, xdl_emit_hunk_consume_func_t hunk_func, void *cb_data) { xpparam_t xpp = {0}; @@@ -142,6 -142,7 +142,6 @@@ xdemitcb_t ecb = {NULL}; xpp.flags = xdl_opts; - xecfg.ctxlen = ctxlen; xecfg.hunk_func = hunk_func; ecb.priv = cb_data; return xdi_diff(file_a, file_b, &xpp, &xecfg, &ecb); @@@ -598,7 -599,7 +598,7 @@@ static struct origin *find_origin(struc p->status); case 'M': porigin = get_origin(sb, parent, origin->path); - hashcpy(porigin->blob_sha1, p->one->sha1); + hashcpy(porigin->blob_sha1, p->one->oid.hash); porigin->mode = p->one->mode; break; case 'A': @@@ -608,7 -609,7 +608,7 @@@ } } diff_flush(&diff_opts); - free_pathspec(&diff_opts.pathspec); + clear_pathspec(&diff_opts.pathspec); return porigin; } @@@ -644,13 -645,13 +644,13 @@@ static struct origin *find_rename(struc if ((p->status == 'R' || p->status == 'C') && !strcmp(p->two->path, origin->path)) { porigin = get_origin(sb, parent, p->one->path); - hashcpy(porigin->blob_sha1, p->one->sha1); + hashcpy(porigin->blob_sha1, p->one->oid.hash); porigin->mode = p->one->mode; break; } } diff_flush(&diff_opts); - free_pathspec(&diff_opts.pathspec); + clear_pathspec(&diff_opts.pathspec); return porigin; } @@@ -979,7 -980,7 +979,7 @@@ static void pass_blame_to_parent(struc fill_origin_blob(&sb->revs->diffopt, target, &file_o); num_get_patch++; - if (diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d)) + if (diff_hunks(&file_p, &file_o, blame_chunk_cb, &d)) die("unable to generate diff (%s -> %s)", oid_to_hex(&parent->commit->object.oid), oid_to_hex(&target->commit->object.oid)); @@@ -1128,7 -1129,7 +1128,7 @@@ static void find_copy_in_blob(struct sc * file_p partially may match that image. */ memset(split, 0, sizeof(struct blame_entry [3])); - if (diff_hunks(file_p, &file_o, 1, handle_split_cb, &d)) + if (diff_hunks(file_p, &file_o, handle_split_cb, &d)) die("unable to generate diff (%s)", oid_to_hex(&parent->commit->object.oid)); /* remainder, if any, all match the preimage */ @@@ -1308,7 -1309,7 +1308,7 @@@ static void find_copy_in_parent(struct continue; norigin = get_origin(sb, parent, p->one->path); - hashcpy(norigin->blob_sha1, p->one->sha1); + hashcpy(norigin->blob_sha1, p->one->oid.hash); norigin->mode = p->one->mode; fill_origin_blob(&sb->revs->diffopt, norigin, &file_p); if (!file_p.ptr) @@@ -1342,7 -1343,7 +1342,7 @@@ } while (unblamed); target->suspects = reverse_blame(leftover, NULL); diff_flush(&diff_opts); - free_pathspec(&diff_opts.pathspec); + clear_pathspec(&diff_opts.pathspec); } /* @@@ -2229,6 -2230,7 +2229,7 @@@ static int git_blame_config(const char static void verify_working_tree_path(struct commit *work_tree, const char *path) { struct commit_list *parents; + int pos; for (parents = work_tree->parents; parents; parents = parents->next) { const unsigned char *commit_sha1 = parents->item->object.oid.hash; @@@ -2239,7 -2241,14 +2240,14 @@@ sha1_object_info(blob_sha1, NULL) == OBJ_BLOB) return; } - die("no such path '%s' in HEAD", path); + + pos = cache_name_pos(path, strlen(path)); + if (pos >= 0) + ; /* path is in the index */ + else if (!strcmp(active_cache[-1 - pos]->name, path)) + ; /* path is in the index, unmerged */ + else + die("no such path '%s' in HEAD", path); } static struct commit_list **append_parent(struct commit_list **tail, const unsigned char *sha1) @@@ -2424,7 -2433,8 +2432,7 @@@ static struct commit *find_single_final struct object *obj = revs->pending.objects[i].item; if (obj->flags & UNINTERESTING) continue; - while (obj->type == OBJ_TAG) - obj = deref_tag(obj, NULL, 0); + obj = deref_tag(obj, NULL, 0); if (obj->type != OBJ_COMMIT) die("Non commit %s?", revs->pending.objects[i].name); if (found) @@@ -2459,7 -2469,8 +2467,7 @@@ static char *prepare_initial(struct sco struct object *obj = revs->pending.objects[i].item; if (!(obj->flags & UNINTERESTING)) continue; - while (obj->type == OBJ_TAG) - obj = deref_tag(obj, NULL, 0); + obj = deref_tag(obj, NULL, 0); if (obj->type != OBJ_COMMIT) die("Non commit %s?", revs->pending.objects[i].name); if (sb->final) @@@ -2519,12 -2530,12 +2527,12 @@@ int cmd_blame(int argc, const char **ar enum object_type type; struct commit *final_commit = NULL; - static struct string_list range_list; - static int output_option = 0, opt = 0; - static int show_stats = 0; - static const char *revs_file = NULL; - static const char *contents_from = NULL; - static const struct option options[] = { + struct string_list range_list = STRING_LIST_INIT_NODUP; + int output_option = 0, opt = 0; + int show_stats = 0; + const char *revs_file = NULL; + const char *contents_from = NULL; + const struct option options[] = { OPT_BOOL(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")), OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")), OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),