summaryrefslogtreecommitdiff
path: root/builtin/blame.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/blame.c')
-rw-r--r--builtin/blame.c190
1 files changed, 101 insertions, 89 deletions
diff --git a/builtin/blame.c b/builtin/blame.c
index f839571..fd41551 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -2544,6 +2544,105 @@ void init_scoreboard(struct blame_scoreboard *sb)
sb->copy_score = BLAME_DEFAULT_COPY_SCORE;
}
+void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blame_origin **orig)
+{
+ const char *final_commit_name = NULL;
+ struct blame_origin *o;
+ struct commit *final_commit = NULL;
+ enum object_type type;
+
+ if (sb->reverse && sb->contents_from)
+ die(_("--contents and --reverse do not blend well."));
+
+ if (!sb->reverse) {
+ sb->final = find_single_final(sb->revs, &final_commit_name);
+ sb->commits.compare = compare_commits_by_commit_date;
+ } else {
+ sb->final = find_single_initial(sb->revs, &final_commit_name);
+ sb->commits.compare = compare_commits_by_reverse_commit_date;
+ }
+
+ if (sb->final && sb->contents_from)
+ die(_("cannot use --contents with final commit object name"));
+
+ if (sb->reverse && sb->revs->first_parent_only)
+ sb->revs->children.name = NULL;
+
+ if (!sb->final) {
+ /*
+ * "--not A B -- path" without anything positive;
+ * do not default to HEAD, but use the working tree
+ * or "--contents".
+ */
+ setup_work_tree();
+ sb->final = fake_working_tree_commit(&sb->revs->diffopt,
+ path, sb->contents_from);
+ add_pending_object(sb->revs, &(sb->final->object), ":");
+ }
+
+ if (sb->reverse && sb->revs->first_parent_only) {
+ final_commit = find_single_final(sb->revs, NULL);
+ if (!final_commit)
+ die(_("--reverse and --first-parent together require specified latest commit"));
+ }
+
+ /*
+ * If we have bottom, this will mark the ancestors of the
+ * bottom commits we would reach while traversing as
+ * uninteresting.
+ */
+ if (prepare_revision_walk(sb->revs))
+ die(_("revision walk setup failed"));
+
+ if (sb->reverse && sb->revs->first_parent_only) {
+ struct commit *c = final_commit;
+
+ sb->revs->children.name = "children";
+ while (c->parents &&
+ oidcmp(&c->object.oid, &sb->final->object.oid)) {
+ struct commit_list *l = xcalloc(1, sizeof(*l));
+
+ l->item = c;
+ if (add_decoration(&sb->revs->children,
+ &c->parents->item->object, l))
+ die("BUG: not unique item in first-parent chain");
+ c = c->parents->item;
+ }
+
+ if (oidcmp(&c->object.oid, &sb->final->object.oid))
+ die(_("--reverse --first-parent together require range along first-parent chain"));
+ }
+
+ if (is_null_oid(&sb->final->object.oid)) {
+ o = sb->final->util;
+ sb->final_buf = xmemdupz(o->file.ptr, o->file.size);
+ sb->final_buf_size = o->file.size;
+ }
+ else {
+ o = get_origin(sb->final, path);
+ if (fill_blob_sha1_and_mode(o))
+ 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_oid, 1, (char **) &sb->final_buf,
+ &sb->final_buf_size))
+ ;
+ else
+ sb->final_buf = read_sha1_file(o->blob_oid.hash, &type,
+ &sb->final_buf_size);
+
+ if (!sb->final_buf)
+ die(_("cannot read blob %s for path %s"),
+ oid_to_hex(&o->blob_oid),
+ path);
+ }
+ sb->num_read_blob++;
+ prepare_lines(sb);
+
+ if (orig)
+ *orig = o;
+}
+
int cmd_blame(int argc, const char **argv, const char *prefix)
{
struct rev_info revs;
@@ -2552,9 +2651,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
struct blame_origin *o;
struct blame_entry *ent = NULL;
long dashdash_pos, lno;
- const char *final_commit_name = NULL;
- enum object_type type;
- struct commit *final_commit = NULL;
struct progress_info pi = { NULL, 0 };
struct string_list range_list = STRING_LIST_INIT_NODUP;
@@ -2759,92 +2855,8 @@ parse_done:
sb.revs = &revs;
sb.contents_from = contents_from;
sb.reverse = reverse;
-
- if (!reverse) {
- sb.final = find_single_final(&revs, &final_commit_name);
- sb.commits.compare = compare_commits_by_commit_date;
- }
- else if (contents_from)
- die(_("--contents and --reverse do not blend well."));
- else {
- sb.final = find_single_initial(&revs, &final_commit_name);
- sb.commits.compare = compare_commits_by_reverse_commit_date;
- if (revs.first_parent_only)
- revs.children.name = NULL;
- }
-
- if (!sb.final) {
- /*
- * "--not A B -- path" without anything positive;
- * do not default to HEAD, but use the working tree
- * or "--contents".
- */
- setup_work_tree();
- sb.final = fake_working_tree_commit(&sb.revs->diffopt,
- path, contents_from);
- add_pending_object(&revs, &(sb.final->object), ":");
- }
- else if (contents_from)
- die(_("cannot use --contents with final commit object name"));
-
- if (reverse && revs.first_parent_only) {
- final_commit = find_single_final(sb.revs, NULL);
- if (!final_commit)
- die(_("--reverse and --first-parent together require specified latest commit"));
- }
-
- /*
- * If we have bottom, this will mark the ancestors of the
- * bottom commits we would reach while traversing as
- * uninteresting.
- */
- if (prepare_revision_walk(&revs))
- die(_("revision walk setup failed"));
-
- if (reverse && revs.first_parent_only) {
- struct commit *c = final_commit;
-
- sb.revs->children.name = "children";
- while (c->parents &&
- oidcmp(&c->object.oid, &sb.final->object.oid)) {
- struct commit_list *l = xcalloc(1, sizeof(*l));
-
- l->item = c;
- if (add_decoration(&sb.revs->children,
- &c->parents->item->object, l))
- die("BUG: not unique item in first-parent chain");
- c = c->parents->item;
- }
-
- if (oidcmp(&c->object.oid, &sb.final->object.oid))
- die(_("--reverse --first-parent together require range along first-parent chain"));
- }
-
- if (is_null_oid(&sb.final->object.oid)) {
- o = sb.final->util;
- sb.final_buf = xmemdupz(o->file.ptr, o->file.size);
- sb.final_buf_size = o->file.size;
- }
- else {
- o = get_origin(sb.final, path);
- if (fill_blob_sha1_and_mode(o))
- 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_oid, 1, (char **) &sb.final_buf,
- &sb.final_buf_size))
- ;
- else
- sb.final_buf = read_sha1_file(o->blob_oid.hash, &type,
- &sb.final_buf_size);
-
- if (!sb.final_buf)
- die(_("cannot read blob %s for path %s"),
- oid_to_hex(&o->blob_oid),
- path);
- }
- sb.num_read_blob++;
- lno = prepare_lines(&sb);
+ setup_scoreboard(&sb, path, &o);
+ lno = sb.num_lines;
if (lno && !range_list.nr)
string_list_append(&range_list, "1");