All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Cc: Elliott Cable <me@ell.io>, Jeff King <peff@peff.net>
Subject: [PATCH v2 3/4] sort-in-topological-order: use commit-queue
Date: Sun,  9 Jun 2013 16:24:36 -0700	[thread overview]
Message-ID: <1370820277-30158-4-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1370820277-30158-1-git-send-email-gitster@pobox.com>

Use the commit-queue data structure to implement a priority queue
of commits sorted by committer date, when handling --date-order.
The commit-queue structure can also be used as a simple LIFO stack,
which is a good match for --topo-order processing.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 commit-queue.c | 13 +++++++++++
 commit-queue.h |  3 +++
 commit.c       | 74 ++++++++++++++++++++++++++++++++++------------------------
 3 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/commit-queue.c b/commit-queue.c
index 77d4b02..ffffc4e 100644
--- a/commit-queue.c
+++ b/commit-queue.c
@@ -2,6 +2,19 @@
 #include "commit.h"
 #include "commit-queue.h"
 
+void commit_queue_reverse(struct commit_queue *queue)
+{
+	int i, j;
+
+	if (queue->compare != NULL)
+		die("BUG: commit_queue_reverse() on non-LIFO queue");
+	for (i = 0; i <= (j = (queue->nr - 1) - i); i++) {
+		struct commit *swap = queue->array[i];
+		queue->array[i] = queue->array[j];
+		queue->array[j] = swap;
+	}
+}
+
 void clear_commit_queue(struct commit_queue *queue)
 {
 	free(queue->array);
diff --git a/commit-queue.h b/commit-queue.h
index 7c5dc4c..d3c92e5 100644
--- a/commit-queue.h
+++ b/commit-queue.h
@@ -28,4 +28,7 @@ extern struct commit *commit_queue_get(struct commit_queue *);
 
 extern void clear_commit_queue(struct commit_queue *);
 
+/* Reverse the LIFO elements */
+extern void commit_queue_reverse(struct commit_queue *);
+
 #endif /* COMMIT_QUEUE_H */
diff --git a/commit.c b/commit.c
index 11b9635..cc6d385 100644
--- a/commit.c
+++ b/commit.c
@@ -9,6 +9,7 @@
 #include "gpg-interface.h"
 #include "mergesort.h"
 #include "commit-slab.h"
+#include "commit-queue.h"
 
 static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
 
@@ -509,21 +510,41 @@ struct commit *pop_commit(struct commit_list **stack)
 /* count number of children that have not been emitted */
 define_commit_slab(indegree_slab, int);
 
+static int compare_commits_by_commit_date(struct commit *a, struct commit *b, void *unused)
+{
+	/* newer commits with larger date first */
+	if (a->date < b->date)
+		return 1;
+	else if (a->date > b->date)
+		return -1;
+	return 0;
+}
+
 /*
  * Performs an in-place topological sort on the list supplied.
  */
-void sort_in_topological_order(struct commit_list ** list, enum rev_sort_order sort_order)
+void sort_in_topological_order(struct commit_list **list, enum rev_sort_order sort_order)
 {
 	struct commit_list *next, *orig = *list;
-	struct commit_list *work, **insert;
 	struct commit_list **pptr;
 	struct indegree_slab indegree;
+	struct commit_queue queue;
+	struct commit *commit;
 
 	if (!orig)
 		return;
 	*list = NULL;
 
 	init_indegree_slab(&indegree);
+	memset(&queue, '\0', sizeof(queue));
+	switch (sort_order) {
+	default: /* REV_SORT_IN_GRAPH_ORDER */
+		queue.compare = NULL;
+		break;
+	case REV_SORT_BY_COMMIT_DATE:
+		queue.compare = compare_commits_by_commit_date;
+		break;
+	}
 
 	/* Mark them and clear the indegree */
 	for (next = orig; next; next = next->next) {
@@ -533,7 +554,7 @@ void sort_in_topological_order(struct commit_list ** list, enum rev_sort_order s
 
 	/* update the indegree */
 	for (next = orig; next; next = next->next) {
-		struct commit_list * parents = next->item->parents;
+		struct commit_list *parents = next->item->parents;
 		while (parents) {
 			struct commit *parent = parents->item;
 			int *pi = indegree_slab_at(&indegree, parent);
@@ -551,30 +572,28 @@ void sort_in_topological_order(struct commit_list ** list, enum rev_sort_order s
 	 *
 	 * the tips serve as a starting set for the work queue.
 	 */
-	work = NULL;
-	insert = &work;
 	for (next = orig; next; next = next->next) {
 		struct commit *commit = next->item;
 
 		if (*(indegree_slab_at(&indegree, commit)) == 1)
-			insert = &commit_list_insert(commit, insert)->next;
+			commit_queue_put(&queue, commit);
 	}
 
-	/* process the list in topological order */
-	if (sort_order != REV_SORT_IN_GRAPH_ORDER)
-		commit_list_sort_by_date(&work);
+	/*
+	 * This is unfortunate; the initial tips need to be shown
+	 * in the order given from the revision traversal machinery.
+	 */
+	if (sort_order == REV_SORT_IN_GRAPH_ORDER)
+		commit_queue_reverse(&queue);
+
+	/* We no longer need the commit list */
+	free_commit_list(orig);
 
 	pptr = list;
 	*list = NULL;
-	while (work) {
-		struct commit *commit;
-		struct commit_list *parents, *work_item;
-
-		work_item = work;
-		work = work_item->next;
-		work_item->next = NULL;
+	while ((commit = commit_queue_get(&queue)) != NULL) {
+		struct commit_list *parents;
 
-		commit = work_item->item;
 		for (parents = commit->parents; parents ; parents = parents->next) {
 			struct commit *parent = parents->item;
 			int *pi = indegree_slab_at(&indegree, parent);
@@ -587,27 +606,20 @@ void sort_in_topological_order(struct commit_list ** list, enum rev_sort_order s
 			 * when all their children have been emitted thereby
 			 * guaranteeing topological order.
 			 */
-			if (--(*pi) == 1) {
-				switch (sort_order) {
-				case REV_SORT_BY_COMMIT_DATE:
-					commit_list_insert_by_date(parent, &work);
-					break;
-				default: /* REV_SORT_IN_GRAPH_ORDER */
-					commit_list_insert(parent, &work);
-					break;
-				}
-			}
+			if (--(*pi) == 1)
+				commit_queue_put(&queue, parent);
 		}
 		/*
-		 * work_item is a commit all of whose children
-		 * have already been emitted. we can emit it now.
+		 * all children of commit have already been
+		 * emitted. we can emit it now.
 		 */
 		*(indegree_slab_at(&indegree, commit)) = 0;
-		*pptr = work_item;
-		pptr = &work_item->next;
+
+		pptr = &commit_list_insert(commit, pptr)->next;
 	}
 
 	clear_indegree_slab(&indegree);
+	clear_commit_queue(&queue);
 }
 
 /* merge-base stuff */
-- 
1.8.3-451-gb703ddf

  parent reply	other threads:[~2013-06-09 23:24 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-04 18:08 [PATCH/RFC] add --authorship-order flag to git log / rev-list elliottcable
2013-06-04 18:08 ` [PATCH/RFC] rev-list: add --authorship-order alternative ordering elliottcable
2013-06-04 19:14   ` Junio C Hamano
2013-06-04 21:20     ` Junio C Hamano
2013-06-06 19:03       ` Elliott Cable
2013-06-06 19:29         ` Junio C Hamano
2013-06-06 19:32           ` Elliott Cable
2013-06-06 19:40         ` Junio C Hamano
2013-06-06 22:48           ` Junio C Hamano
2013-06-06 23:25             ` [PATCH] toposort: rename "lifo" field Junio C Hamano
2013-06-07  1:25               ` Junio C Hamano
2013-06-07  5:11                 ` [PATCH 0/3] Preparing for --date-order=author Junio C Hamano
2013-06-07  5:11                   ` [PATCH 1/3] toposort: rename "lifo" field Junio C Hamano
2013-06-07  5:18                     ` Eric Sunshine
2013-06-07  5:21                       ` Junio C Hamano
2013-06-07  5:11                   ` [PATCH 2/3] commit-queue: LIFO or priority queue of commits Junio C Hamano
2013-06-07  5:29                     ` Eric Sunshine
2013-06-07  5:11                   ` [PATCH 3/3] sort-in-topological-order: use commit-queue Junio C Hamano
2013-06-09 23:24                   ` [PATCH v2 0/4] log --author-date-order Junio C Hamano
2013-06-09 23:24                     ` [PATCH v2 1/4] toposort: rename "lifo" field Junio C Hamano
2013-06-10  2:12                       ` Eric Sunshine
2013-06-10  5:05                       ` Jeff King
2013-06-09 23:24                     ` [PATCH v2 2/4] commit-queue: LIFO or priority queue of commits Junio C Hamano
2013-06-10  5:25                       ` Jeff King
2013-06-10  7:21                         ` Junio C Hamano
2013-06-10 18:15                           ` Jeff King
2013-06-10 18:56                             ` Junio C Hamano
2013-06-10 18:59                               ` Jeff King
2013-06-10 23:23                                 ` Junio C Hamano
2013-06-11  6:36                                   ` Jeff King
2013-06-11 17:02                                     ` Junio C Hamano
2013-06-11 22:19                                     ` [PATCH v3 0/4] log --author-date-order Junio C Hamano
2013-06-11 22:19                                       ` [PATCH v3 1/4] toposort: rename "lifo" field Junio C Hamano
2013-06-11 22:19                                       ` [PATCH v3 2/4] prio-queue: priority queue of pointers to structs Junio C Hamano
2013-06-11 22:19                                       ` [PATCH v3 3/4] sort-in-topological-order: use prio-queue Junio C Hamano
2013-06-11 22:19                                       ` [PATCH v3 4/4] log: --author-date-order Junio C Hamano
2013-06-09 23:24                     ` Junio C Hamano [this message]
2013-06-09 23:37                       ` [PATCH v2 3/4] sort-in-topological-order: use commit-queue Junio C Hamano
2013-06-10  5:31                         ` Jeff King
2013-06-10  7:27                           ` Junio C Hamano
2013-06-10 18:24                             ` Jeff King
2013-06-09 23:24                     ` [PATCH v2 4/4] log: --author-date-order Junio C Hamano
2013-06-10  5:50                       ` Jeff King
2013-06-10  7:39                         ` Junio C Hamano
2013-06-10 18:49                           ` Jeff King
2013-06-20 19:36                             ` Junio C Hamano
2013-06-20 20:16                               ` Jeff King
2013-06-07  5:09               ` [PATCH] toposort: rename "lifo" field Eric Sunshine
2013-06-04 21:22     ` [PATCH/RFC] rev-list: add --authorship-order alternative ordering Jeff King
2013-06-04 18:53 ` [PATCH/RFC] add --authorship-order flag to git log / rev-list Junio C Hamano
2013-06-06 18:06   ` Elliott Cable

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=1370820277-30158-4-git-send-email-gitster@pobox.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    --cc=me@ell.io \
    --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.