git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* git-rev-list  in local commit order
@ 2005-05-14 21:44 Sean
  2005-05-15 19:48 ` Thomas Gleixner
  0 siblings, 1 reply; 17+ messages in thread
From: Sean @ 2005-05-14 21:44 UTC (permalink / raw)
  To: git

[-- Attachment #1: Type: text/plain, Size: 1317 bytes --]

Attached is a preliminary hackish patch to sort git-rev-list in local
commit order.   While I don't know how useful this really is, it's
presented as an alternative to the repo-id proposal.  This will work even
if the branch happens to be from a single repository, where repo-id will
not.  However, shared commit objects can cause problems so for best
results use private commit objects for each repository.

For purposes of testing, this patch changes the Cogito default of linking
objects to copying, for local repository pull operations.   This patch
will work with _existing_ repositories where local commit times have been
maintained.

Also attached, is a little test script that demonstrates the local commit
time order.  After running the test script, you can use the cg-log command
in each of the M and R directories to see the difference even though the
two repositories share a head commit.

This patch is not nearly ready for inclusion anywhere just meant for
comment.  It is based off Petr's cogito tree (commit
fa6e9eb368e949e78c4e66217461cf624b52b0a2).

 cache.h     |    1
 cg-pull     |    4 -
 commit.c    |  121
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 commit.h    |    6 ++
 rev-list.c  |    2
 sha1_file.c |    8 +++
 6 files changed, 137 insertions(+), 5 deletions(-)

Sean


[-- Attachment #2: local-rev-list-v1.patch --]
[-- Type: application/octet-stream, Size: 6552 bytes --]

Index: cache.h
===================================================================
--- a/cache.h  (mode:100644)
+++ b/cache.h  (mode:100644)
@@ -157,6 +157,7 @@
 extern int write_sha1_from_fd(const unsigned char *sha1, int fd);
 
 extern int has_sha1_file(const unsigned char *sha1);
+extern unsigned long sha1_local_date(const unsigned char *sha1);
 
 /* Convert to/from hex/sha1 representation */
 extern int get_sha1(const char *str, unsigned char *sha1);
Index: cg-pull
===================================================================
--- a/cg-pull  (mode:100755)
+++ b/cg-pull  (mode:100755)
@@ -143,7 +143,7 @@
 	[ "$1" = "-i" ] && shift
 	[ "$1" = "-s" ] && shift
 
-	cp_flags_l="-va"
+	cp_flags_l="-vdR"
 	if [ "$1" = "-u" ]; then
 		cp_flags_l="$cp_flags_l -lu"
 		shift
@@ -163,7 +163,7 @@
 }
 
 pull_local () {
-	git-local-pull -a -l -v "$(cat "$_git/refs/heads/$1")" "$2"
+	git-local-pull -a -v "$(cat "$_git/refs/heads/$1")" "$2"
 }
 
 if echo "$uri" | grep -q "^http://"; then
Index: commit.c
===================================================================
--- a/commit.c  (mode:100644)
+++ b/commit.c  (mode:100644)
@@ -2,6 +2,7 @@
 #include "cache.h"
 #include <string.h>
 #include <limits.h>
+#include <stdlib.h>
 
 const char *commit_type = "commit";
 
@@ -13,6 +14,7 @@
 		memset(ret, 0, sizeof(struct commit));
 		created_object(sha1, &ret->object);
 		ret->object.type = commit_type;
+		ret->local_date = sha1_local_date(sha1);
 		return ret;
 	}
 	if (obj->type != commit_type) {
@@ -41,6 +43,18 @@
 	return date;
 }
 
+static void insert_by_local_date(struct commit_list **list, struct commit *item)
+{
+	struct commit_list **pp = list;
+	struct commit_list *p;
+	while ((p = *pp) != NULL) {
+		if (p->item->local_date > item->local_date) 
+			break;
+		pp = &p->next;
+	}
+	commit_list_insert(item, pp);
+}
+
 int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
 {
 	void *bufptr = buffer;
@@ -58,12 +72,13 @@
 	       !get_sha1_hex(bufptr + 7, parent)) {
 		struct commit *new_parent = lookup_commit(parent);
 		if (new_parent) {
-			commit_list_insert(new_parent, &item->parents);
+ 			insert_by_local_date(&item->parents, new_parent);
 			add_ref(&item->object, &new_parent->object);
 		}
 		bufptr += 48;
 	}
 	item->date = parse_commit_date(bufptr);
+	item->merge_nodes = NULL;
 	return 0;
 }
 
@@ -152,3 +167,107 @@
 	}
 	return ret;
 }
+
+struct commit_list *copy_commit_list(struct commit_list *list)
+{
+	struct commit_list *copy = NULL;
+	while (list) {
+		commit_list_insert(list->item, &copy); 
+		list = list->next;
+	}
+	return copy;
+}
+
+int found_on_list(struct commit *item, struct commit_list *list)
+{
+	while (list) {
+		if (list->item == item)
+			return 1;
+		list = list->next;
+	}
+	return 0;
+}
+
+static struct commit *process_local_list(struct commit_list **list_p, 
+					int this_mark, int other_mark)
+{
+	struct commit *item = (*list_p)->item;
+
+	if (item->object.flags & other_mark) {
+		return item;
+	} else {
+		pop_most_recent_commit(list_p, this_mark);
+	}
+	return NULL;
+}
+
+struct commit *common_local_ancestor(struct commit *rev1, struct commit *rev2)
+{
+	struct commit_list *rev1list = NULL;
+	struct commit_list *rev2list = NULL;
+
+	commit_list_insert(rev1, &rev1list); rev1->object.flags |= 0x1;
+	commit_list_insert(rev2, &rev2list); rev2->object.flags |= 0x2;
+	parse_commit(rev1); parse_commit(rev2);
+
+	while (rev1list || rev2list) {
+		struct commit *ret;
+		if (!rev1list) {
+			// process 2
+			ret = process_local_list(&rev2list, 0x2, 0x1);
+		} else if (!rev2list) {
+			// process 1
+			ret = process_local_list(&rev1list, 0x1, 0x2);
+		} else if (rev1list->item->local_date 
+				< rev2list->item->local_date) {
+			// process 2
+			ret = process_local_list(&rev2list, 0x2, 0x1);
+		} else {
+			// process 1
+			ret = process_local_list(&rev1list, 0x1, 0x2);
+		}
+		if (ret) {
+			free_commit_list(rev1list);
+			free_commit_list(rev2list);
+			return ret;
+		}
+	}
+	return NULL;
+}
+
+void insert_merge_nodes(struct commit_list *plist,
+			struct commit_list *stop,
+			struct commit *node)
+{
+	struct commit_list *p;
+	for (p=plist; p != stop; p=p->next)
+		commit_list_insert(	common_local_ancestor(node, p->item),
+					&node->merge_nodes);
+}
+
+struct commit *pop_newest_local_commit(	struct commit_list **list,
+					unsigned int mark)
+{
+	struct commit *ret = (*list)->item;
+	struct commit_list *parents = ret->parents;
+	struct commit_list *old = *list;
+	struct commit_list *prev = ret->merge_nodes;
+
+	*list = (*list)->next;
+	free(old);
+
+	/* Loop expects parents to be ordered oldest to newest on local time */
+	while (parents) {
+		struct commit *commit = parents->item;
+		parse_commit(commit);
+		if (!((commit->object.flags & mark) | 
+                       found_on_list(commit, ret->merge_nodes))) {
+			commit->object.flags |= mark;
+			prev = commit->merge_nodes = copy_commit_list(prev);
+			insert_merge_nodes(ret->parents, parents, commit);
+			commit_list_insert(commit, list);
+		}
+		parents = parents->next;
+	}
+	return ret;
+}
Index: commit.h
===================================================================
--- a/commit.h  (mode:100644)
+++ b/commit.h  (mode:100644)
@@ -11,8 +11,9 @@
 
 struct commit {
 	struct object object;
-	unsigned long date;
+	unsigned long date, local_date;
 	struct commit_list *parents;
+	struct commit_list *merge_nodes;
 	struct tree *tree;
 };
 
@@ -36,4 +37,7 @@
 struct commit *pop_most_recent_commit(struct commit_list **list, 
 				      unsigned int mark);
 
+struct commit *pop_newest_local_commit(	struct commit_list **list,
+					unsigned int mark);
+
 #endif /* COMMIT_H */
Index: rev-list.c
===================================================================
--- a/rev-list.c  (mode:100644)
+++ b/rev-list.c  (mode:100644)
@@ -38,7 +38,7 @@
 
 	commit_list_insert(commit, &list);
 	do {
-		struct commit *commit = pop_most_recent_commit(&list, 0x1);
+		struct commit *commit = pop_newest_local_commit(&list, 0x4);
 
 		if (min_age != -1 && (commit->date > min_age))
 			continue;
Index: sha1_file.c
===================================================================
--- a/sha1_file.c  (mode:100644)
+++ b/sha1_file.c  (mode:100644)
@@ -577,6 +577,14 @@
 	return !!find_sha1_file(sha1, &st);
 }
 
+unsigned long sha1_local_date(const unsigned char *sha1)
+{
+	struct stat st;
+	if (find_sha1_file(sha1, &st))
+		return st.st_mtime;
+	return 0;
+}
+
 int index_fd(unsigned char *sha1, int fd, struct stat *st)
 {
 	unsigned long size = st->st_size;

[-- Attachment #3: test-local-rev-list-v1.sh --]
[-- Type: application/octet-stream, Size: 921 bytes --]

#!/bin/bash
die() { echo "death: $*" ; exit 1; }
mkdir R && cd R || die "on mkdir R"
cg-init < /dev/null || die "R init"

touch one ; cg-add one || die "adding Rn-3"
echo "Rn-3" | cg-commit || die "committing Rn-3"

cd .. || die "cd base"
cg-clone R M || die "cloning"

cd M || die "cd M"
touch two; cg-add two || die "adding Mn-1"
echo "Mn-1" | cg-commit || die "committing Mn-1"

cd ../R || die "cd ../R"
touch three; cg-add three || die "adding Rn-2"
echo "Rn-2" | cg-commit || die "committing Rn-2"

cd ../M || die "cd ../M"
touch four; cg-add four || die "adding Mn"
echo "Mn" | cg-commit || die "committing Mn"

cd ../R || die "cd ../R"
touch five; cg-add five || die "adding Rn-1"
echo "Rn-1" | cg-commit || die "committing Rn-1"

sleep 1
cg-branch-add M ../M/.git || die "adding M branch"
echo "Rn" | cg-update M || die "merging M"

sleep 1
cd ../M || die "cd ../M"
cg-update origin || die "fast forwarding to R"

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2005-05-18  5:16 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-14 21:44 git-rev-list in local commit order Sean
2005-05-15 19:48 ` Thomas Gleixner
2005-05-15 19:57   ` Sean
2005-05-15 20:44     ` Thomas Gleixner
2005-05-15 20:45       ` Sean
2005-05-15 21:13         ` Thomas Gleixner
2005-05-15 21:21           ` Sean
2005-05-15 21:30             ` Thomas Gleixner
2005-05-15 21:43               ` Sean
2005-05-15 22:13                 ` Thomas Gleixner
2005-05-16 21:25                   ` Sean
2005-05-16 23:46                     ` Linus Torvalds
2005-05-17  9:52                       ` Thomas Gleixner
2005-05-17 15:43                         ` Linus Torvalds
2005-05-17 17:05                           ` Thomas Gleixner
2005-05-17 17:44                             ` Linus Torvalds
2005-05-18  5:16                               ` Jon Seymour

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).