All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Smith <whydoubt@gmail.com>
To: git@vger.kernel.org
Cc: gitster@pobox.com, peff@peff.net, Jeff Smith <whydoubt@gmail.com>
Subject: [RFC PATCH 07/10] Break out scoreboard a little better
Date: Fri,  5 May 2017 00:27:26 -0500	[thread overview]
Message-ID: <20170505052729.7576-8-whydoubt@gmail.com> (raw)
In-Reply-To: <20170505052729.7576-1-whydoubt@gmail.com>

Signed-off-by: Jeff Smith <whydoubt@gmail.com>
---
 builtin/blame.c | 149 +++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 93 insertions(+), 56 deletions(-)

diff --git a/builtin/blame.c b/builtin/blame.c
index c873cc2..dc7600c 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -62,11 +62,6 @@ static struct string_list mailmap = STRING_LIST_INIT_NODUP;
 #define DEBUG 0
 #endif
 
-/* stats */
-static int num_read_blob;
-static int num_get_patch;
-static int num_commits;
-
 #define PICKAXE_BLAME_MOVE		01
 #define PICKAXE_BLAME_COPY		02
 #define PICKAXE_BLAME_COPY_HARDER	04
@@ -91,7 +86,7 @@ struct progress_info {
 };
 
 static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b,
-		      xdl_emit_hunk_consume_func_t hunk_func, void *cb_data)
+		      xdl_emit_hunk_consume_func_t hunk_func, void *cb_data, int xdl_opts)
 {
 	xpparam_t xpp = {0};
 	xdemitconf_t xecfg = {0};
@@ -108,13 +103,13 @@ static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b,
  * diff machinery
  */
 static void fill_origin_blob(struct diff_options *opt,
-			     struct origin *o, mmfile_t *file)
+			     struct origin *o, mmfile_t *file, int *num_read_blob)
 {
 	if (!o->file.ptr) {
 		enum object_type type;
 		unsigned long file_size;
 
-		num_read_blob++;
+		(*num_read_blob)++;
 		if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
 		    textconv_object(o->path, o->mode, &o->blob_oid, 1, &file->ptr, &file_size))
 			;
@@ -265,9 +260,36 @@ struct scoreboard {
 	/* look-up a line in the final buffer */
 	int num_lines;
 	int *lineno;
+
+	/*
+	 * blame for a blame_entry with score lower than these thresholds
+	 * is not passed to the parent using move/copy logic.
+	 */
+	unsigned blame_move_score;
+	unsigned blame_copy_score;
+
+	/* stats */
+	int num_read_blob;
+	int num_get_patch;
+	int num_commits;
+
+	/* options */
+	int show_root;
+	int reverse;
+	int xdl_opts;
+	int no_whole_file_rename;
+
+	/* callbacks */
+	void(*sanity_check)(struct scoreboard *);
+	void(*found_guilty_entry)(struct blame_entry *, void *);
+
+	void *found_guilty_entry_data;
 };
 
-static void sanity_check_refcnt(struct scoreboard *);
+static void blame_sort_final(struct scoreboard *sb)
+{
+	sb->ent = blame_sort(sb->ent, compare_blame_final);
+}
 
 /*
  * If two blame entries that are next to each other came from
@@ -290,8 +312,8 @@ static void coalesce(struct scoreboard *sb)
 		}
 	}
 
-	if (DEBUG) /* sanity */
-		sanity_check_refcnt(sb);
+	if (sb->sanity_check) /* sanity */
+		sb->sanity_check(sb);
 }
 
 /*
@@ -787,11 +809,11 @@ static void pass_blame_to_parent(struct scoreboard *sb,
 	d.offset = 0;
 	d.dstq = &newdest; d.srcq = &target->suspects;
 
-	fill_origin_blob(&sb->revs->diffopt, parent, &file_p);
-	fill_origin_blob(&sb->revs->diffopt, target, &file_o);
-	num_get_patch++;
+	fill_origin_blob(&sb->revs->diffopt, parent, &file_p, &sb->num_read_blob);
+	fill_origin_blob(&sb->revs->diffopt, target, &file_o, &sb->num_read_blob);
+	sb->num_get_patch++;
 
-	if (diff_hunks(&file_p, &file_o, blame_chunk_cb, &d))
+	if (diff_hunks(&file_p, &file_o, blame_chunk_cb, &d, sb->xdl_opts))
 		die("unable to generate diff (%s -> %s)",
 		    oid_to_hex(&parent->commit->object.oid),
 		    oid_to_hex(&target->commit->object.oid));
@@ -940,7 +962,7 @@ static void find_copy_in_blob(struct scoreboard *sb,
 	 * file_p partially may match that image.
 	 */
 	memset(split, 0, sizeof(struct blame_entry [3]));
-	if (diff_hunks(file_p, &file_o, handle_split_cb, &d))
+	if (diff_hunks(file_p, &file_o, handle_split_cb, &d, sb->xdl_opts))
 		die("unable to generate diff (%s)",
 		    oid_to_hex(&parent->commit->object.oid));
 	/* remainder, if any, all match the preimage */
@@ -993,7 +1015,7 @@ static void find_move_in_parent(struct scoreboard *sb,
 	if (!unblamed)
 		return; /* nothing remains for this target */
 
-	fill_origin_blob(&sb->revs->diffopt, parent, &file_p);
+	fill_origin_blob(&sb->revs->diffopt, parent, &file_p, &sb->num_read_blob);
 	if (!file_p.ptr)
 		return;
 
@@ -1009,7 +1031,7 @@ static void find_move_in_parent(struct scoreboard *sb,
 			next = e->next;
 			find_copy_in_blob(sb, e, parent, split, &file_p);
 			if (split[1].suspect &&
-			    blame_move_score < ent_score(sb, &split[1])) {
+			    sb->blame_move_score < ent_score(sb, &split[1])) {
 				split_blame(blamed, &unblamedtail, split, e);
 			} else {
 				e->next = leftover;
@@ -1018,7 +1040,7 @@ static void find_move_in_parent(struct scoreboard *sb,
 			decref_split(split);
 		}
 		*unblamedtail = NULL;
-		toosmall = filter_small(sb, toosmall, &unblamed, blame_move_score);
+		toosmall = filter_small(sb, toosmall, &unblamed, sb->blame_move_score);
 	} while (unblamed);
 	target->suspects = reverse_blame(leftover, NULL);
 }
@@ -1122,7 +1144,7 @@ static void find_copy_in_parent(struct scoreboard *sb,
 			norigin = get_origin(parent, p->one->path);
 			oidcpy(&norigin->blob_oid, &p->one->oid);
 			norigin->mode = p->one->mode;
-			fill_origin_blob(&sb->revs->diffopt, norigin, &file_p);
+			fill_origin_blob(&sb->revs->diffopt, norigin, &file_p, &sb->num_read_blob);
 			if (!file_p.ptr)
 				continue;
 
@@ -1139,7 +1161,7 @@ static void find_copy_in_parent(struct scoreboard *sb,
 		for (j = 0; j < num_ents; j++) {
 			struct blame_entry *split = blame_list[j].split;
 			if (split[1].suspect &&
-			    blame_copy_score < ent_score(sb, &split[1])) {
+			    sb->blame_copy_score < ent_score(sb, &split[1])) {
 				split_blame(blamed, &unblamedtail, split,
 					    blame_list[j].ent);
 			} else {
@@ -1150,7 +1172,7 @@ static void find_copy_in_parent(struct scoreboard *sb,
 		}
 		free(blame_list);
 		*unblamedtail = NULL;
-		toosmall = filter_small(sb, toosmall, &unblamed, blame_copy_score);
+		toosmall = filter_small(sb, toosmall, &unblamed, sb->blame_copy_score);
 	} while (unblamed);
 	target->suspects = reverse_blame(leftover, NULL);
 	diff_flush(&diff_opts);
@@ -1186,7 +1208,8 @@ static void pass_whole_blame(struct scoreboard *sb,
  * "parent" (and "porigin"), but what we mean is to find scapegoat to
  * exonerate ourselves.
  */
-static struct commit_list *first_scapegoat(struct rev_info *revs, struct commit *commit)
+static struct commit_list *first_scapegoat(struct rev_info *revs, struct commit *commit,
+					int reverse)
 {
 	if (!reverse) {
 		if (revs->first_parent_only &&
@@ -1200,9 +1223,9 @@ static struct commit_list *first_scapegoat(struct rev_info *revs, struct commit
 	return lookup_decoration(&revs->children, &commit->object);
 }
 
-static int num_scapegoats(struct rev_info *revs, struct commit *commit)
+static int num_scapegoats(struct rev_info *revs, struct commit *commit, int reverse)
 {
-	struct commit_list *l = first_scapegoat(revs, commit);
+	struct commit_list *l = first_scapegoat(revs, commit, reverse);
 	return commit_list_count(l);
 }
 
@@ -1240,7 +1263,7 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
 	struct blame_entry *toosmall = NULL;
 	struct blame_entry *blames, **blametail = &blames;
 
-	num_sg = num_scapegoats(revs, commit);
+	num_sg = num_scapegoats(revs, commit, sb->reverse);
 	if (!num_sg)
 		goto finish;
 	else if (num_sg < ARRAY_SIZE(sg_buf))
@@ -1252,12 +1275,12 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
 	 * The first pass looks for unrenamed path to optimize for
 	 * common cases, then we look for renames in the second pass.
 	 */
-	for (pass = 0; pass < 2 - no_whole_file_rename; pass++) {
+	for (pass = 0; pass < 2 - sb->no_whole_file_rename; pass++) {
 		struct origin *(*find)(struct scoreboard *,
 				       struct commit *, struct origin *);
 		find = pass ? find_rename : find_origin;
 
-		for (i = 0, sg = first_scapegoat(revs, commit);
+		for (i = 0, sg = first_scapegoat(revs, commit, sb->reverse);
 		     i < num_sg && sg;
 		     sg = sg->next, i++) {
 			struct commit *p = sg->item;
@@ -1288,8 +1311,8 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
 		}
 	}
 
-	num_commits++;
-	for (i = 0, sg = first_scapegoat(revs, commit);
+	sb->num_commits++;
+	for (i = 0, sg = first_scapegoat(revs, commit, sb->reverse);
 	     i < num_sg && sg;
 	     sg = sg->next, i++) {
 		struct origin *porigin = sg_origin[i];
@@ -1308,9 +1331,9 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
 	 * Optionally find moves in parents' files.
 	 */
 	if (opt & PICKAXE_BLAME_MOVE) {
-		filter_small(sb, &toosmall, &origin->suspects, blame_move_score);
+		filter_small(sb, &toosmall, &origin->suspects, sb->blame_move_score);
 		if (origin->suspects) {
-			for (i = 0, sg = first_scapegoat(revs, commit);
+			for (i = 0, sg = first_scapegoat(revs, commit, sb->reverse);
 			     i < num_sg && sg;
 			     sg = sg->next, i++) {
 				struct origin *porigin = sg_origin[i];
@@ -1327,17 +1350,17 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
 	 * Optionally find copies from parents' files.
 	 */
 	if (opt & PICKAXE_BLAME_COPY) {
-		if (blame_copy_score > blame_move_score)
-			filter_small(sb, &toosmall, &origin->suspects, blame_copy_score);
-		else if (blame_copy_score < blame_move_score) {
+		if (sb->blame_copy_score > sb->blame_move_score)
+			filter_small(sb, &toosmall, &origin->suspects, sb->blame_copy_score);
+		else if (sb->blame_copy_score < sb->blame_move_score) {
 			origin->suspects = blame_merge(origin->suspects, toosmall);
 			toosmall = NULL;
-			filter_small(sb, &toosmall, &origin->suspects, blame_copy_score);
+			filter_small(sb, &toosmall, &origin->suspects, sb->blame_copy_score);
 		}
 		if (!origin->suspects)
 			goto finish;
 
-		for (i = 0, sg = first_scapegoat(revs, commit);
+		for (i = 0, sg = first_scapegoat(revs, commit, sb->reverse);
 		     i < num_sg && sg;
 		     sg = sg->next, i++) {
 			struct origin *porigin = sg_origin[i];
@@ -1566,9 +1589,10 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat)
  * The blame_entry is found to be guilty for the range.
  * Show it in incremental output.
  */
-static void found_guilty_entry(struct blame_entry *ent,
-			   struct progress_info *pi)
+static void found_guilty_entry(struct blame_entry *ent, void *data)
 {
+	struct progress_info *pi = (struct progress_info *)data;
+
 	if (incremental) {
 		struct origin *suspect = ent->suspect;
 
@@ -1591,11 +1615,6 @@ static void assign_blame(struct scoreboard *sb, int opt)
 {
 	struct rev_info *revs = sb->revs;
 	struct commit *commit = prio_queue_get(&sb->commits);
-	struct progress_info pi = { NULL, 0 };
-
-	if (show_progress)
-		pi.progress = start_progress_delay(_("Blaming lines"),
-						   sb->num_lines, 50, 1);
 
 	while (commit) {
 		struct blame_entry *ent;
@@ -1618,7 +1637,7 @@ static void assign_blame(struct scoreboard *sb, int opt)
 		 */
 		origin_incref(suspect);
 		parse_commit(commit);
-		if (reverse ||
+		if (sb->reverse ||
 		    (!(commit->object.flags & UNINTERESTING) &&
 		     !(revs->max_age != -1 && commit->date < revs->max_age)))
 			pass_blame(sb, suspect, opt);
@@ -1628,7 +1647,7 @@ static void assign_blame(struct scoreboard *sb, int opt)
 				mark_parents_uninteresting(commit);
 		}
 		/* treat root commit as boundary */
-		if (!commit->parents && !show_root)
+		if (!commit->parents && !sb->show_root)
 			commit->object.flags |= UNINTERESTING;
 
 		/* Take responsibility for the remaining entries */
@@ -1637,7 +1656,8 @@ static void assign_blame(struct scoreboard *sb, int opt)
 			suspect->guilty = 1;
 			for (;;) {
 				struct blame_entry *next = ent->next;
-				found_guilty_entry(ent, &pi);
+				if (sb->found_guilty_entry)
+					sb->found_guilty_entry(ent, sb->found_guilty_entry_data);
 				if (next) {
 					ent = next;
 					continue;
@@ -1650,11 +1670,9 @@ static void assign_blame(struct scoreboard *sb, int opt)
 		}
 		origin_decref(suspect);
 
-		if (DEBUG) /* sanity */
-			sanity_check_refcnt(sb);
+		if (sb->sanity_check) /* sanity */
+			sb->sanity_check(sb);
 	}
-
-	stop_progress(&pi.progress);
 }
 
 static const char *format_time(unsigned long time, const char *tz_str,
@@ -2187,6 +2205,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	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;
 	int output_option = 0, opt = 0;
@@ -2476,7 +2495,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 			    oid_to_hex(&o->blob_oid),
 			    path);
 	}
-	num_read_blob++;
+	sb.num_read_blob++;
 	lno = prepare_lines(&sb);
 
 	if (lno && !range_list.nr)
@@ -2529,10 +2548,28 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	sb.ent = NULL;
 	sb.path = path;
 
+	sb.blame_move_score = blame_move_score;
+	sb.blame_copy_score = blame_copy_score;
+
+	sb.sanity_check = DEBUG ? &sanity_check_refcnt : NULL;
+
+	sb.show_root = show_root;
+	sb.reverse = reverse;
+	sb.xdl_opts = xdl_opts;
+	sb.no_whole_file_rename = no_whole_file_rename;
+
 	read_mailmap(&mailmap, NULL);
 
+	sb.found_guilty_entry = &found_guilty_entry;
+	sb.found_guilty_entry_data = &pi;
+	if (show_progress)
+		pi.progress = start_progress_delay(_("Blaming lines"),
+						   sb.num_lines, 50, 1);
+
 	assign_blame(&sb, opt);
 
+	stop_progress(&pi.progress);
+
 	if (!incremental)
 		setup_pager();
 
@@ -2541,7 +2578,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	if (incremental)
 		return 0;
 
-	sb.ent = blame_sort(sb.ent, compare_blame_final);
+	blame_sort_final(&sb);
 
 	coalesce(&sb);
 
@@ -2557,9 +2594,9 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	}
 
 	if (show_stats) {
-		printf("num read blob: %d\n", num_read_blob);
-		printf("num get patch: %d\n", num_get_patch);
-		printf("num commits: %d\n", num_commits);
+		printf("num read blob: %d\n", sb.num_read_blob);
+		printf("num get patch: %d\n", sb.num_get_patch);
+		printf("num commits: %d\n", sb.num_commits);
 	}
 	return 0;
 }
-- 
2.9.3


  parent reply	other threads:[~2017-05-05  5:27 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-05  5:27 [RFC PATCH 00/10] Add blame to libgit Jeff Smith
2017-05-05  5:27 ` [RFC PATCH 01/10] Remove unneeded dependency on blob.h from blame Jeff Smith
2017-05-05  7:07   ` Ævar Arnfjörð Bjarmason
     [not found]     ` <CAPX7N=6tQi+WidagvV1BA-CoaiNJj7OO4U7GYXNE-QzyvD=QRQ@mail.gmail.com>
2017-05-05 14:03       ` Jeffrey Smith
2017-05-05  5:27 ` [RFC PATCH 02/10] Move textconv_object to be with other textconv methods Jeff Smith
2017-05-05 17:44   ` Junio C Hamano
2017-05-05 17:50     ` Stefan Beller
2017-05-08  1:02       ` Junio C Hamano
2017-05-08 21:55         ` Jeff King
2017-05-08 22:06           ` Stefan Beller
2017-05-09  1:49           ` Junio C Hamano
2017-05-09  2:34             ` Jeff King
2017-05-05  5:27 ` [RFC PATCH 03/10] Add some missing definitions to header files Jeff Smith
2017-05-05 17:42   ` Junio C Hamano
2017-05-05  5:27 ` [RFC PATCH 04/10] Remove unused parameter from get_origin() Jeff Smith
2017-05-05  5:27 ` [RFC PATCH 05/10] Split blame origin into its own file Jeff Smith
2017-05-05  5:27 ` [RFC PATCH 06/10] Move fake_working_tree_commit() to lib Jeff Smith
2017-05-05  5:27 ` Jeff Smith [this message]
2017-05-05 17:52   ` [RFC PATCH 07/10] Break out scoreboard a little better Junio C Hamano
2017-05-05  5:27 ` [RFC PATCH 08/10] Split blame scoreboard into its own file Jeff Smith
2017-05-05  5:27 ` [RFC PATCH 09/10] Break out scoreboard init and setup Jeff Smith
2017-05-05  5:27 ` [RFC PATCH 10/10] Move scoreboard init and setup to lib Jeff Smith
2017-05-05 17:54 ` [RFC PATCH 00/10] Add blame to libgit Junio C Hamano
2017-05-14  3:14 ` [RFC PATCH v2 00/22] " Jeff Smith
2017-05-14  3:14   ` [RFC PATCH v2 01/22] blame: remove unneeded dependency on blob.h Jeff Smith
2017-05-14  3:14   ` [RFC PATCH v2 02/22] blame: move textconv_object with related functions Jeff Smith
2017-05-14  3:14   ` [RFC PATCH v2 03/22] blame: remove unused parameters Jeff Smith
2017-05-14  3:14   ` [RFC PATCH v2 04/22] blame: move origin and entry structures to header Jeff Smith
2017-05-14  8:10     ` Junio C Hamano
2017-05-14  3:14   ` [RFC PATCH v2 05/22] blame: move scoreboard structure " Jeff Smith
2017-05-14  3:14   ` [RFC PATCH v2 06/22] blame: move stat counters to scoreboard Jeff Smith
2017-05-14  3:14   ` [RFC PATCH v2 07/22] blame: move copy/move thresholds " Jeff Smith
2017-05-14  3:14   ` [RFC PATCH v2 08/22] blame: move contents_from " Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 09/22] blame: move reverse flag " Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 10/22] blame: move show_root " Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 11/22] blame: move xdl_opts flags " Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 12/22] blame: move no_whole_file_rename flag " Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 13/22] blame: make sanity_check use a callback in scoreboard Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 14/22] blame: move progess updates to a scoreboard callback Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 15/22] blame: wrap blame_sort and compare_blame_final Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 16/22] blame: rework methods that determine 'final' commit Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 17/22] blame: move origin-related methods to libgit Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 18/22] blame: move fake-commit-related " Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 19/22] blame: move scoreboard-related " Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 20/22] blame: create scoreboard init function in libgit Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 21/22] blame: create scoreboard setup " Jeff Smith
2017-05-14  3:15   ` [RFC PATCH v2 22/22] blame: create entry prepend " Jeff Smith
2017-05-15  9:24   ` [RFC PATCH v2 00/22] Add blame to libgit Junio C Hamano
2017-05-15 13:52     ` Jeffrey Smith
2017-05-16  0:23       ` Junio C Hamano
2017-05-16  2:44         ` Jeffrey Smith
2017-05-16  3:21           ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170505052729.7576-8-whydoubt@gmail.com \
    --to=whydoubt@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.