git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 1/2] Add a generic "object decorator" interface, and make object refs use it
@ 2007-04-16 23:03 Linus Torvalds
  2007-04-16 23:05 ` [PATCH 2/2] Add support for "commit name decorations" to log family of commands Linus Torvalds
  0 siblings, 1 reply; 2+ messages in thread
From: Linus Torvalds @ 2007-04-16 23:03 UTC (permalink / raw
  To: Junio C Hamano, Theodore Ts'o, Git Mailing List


This allows you to add an arbitrary "decoration" of your choice to any
object.  It's a space- and time-efficient way to add information to
arbitrary objects, especially if most objects probably do not have the
decoration.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---

This shouldn't change any behaviour, just re-implements the object-refs 
hashing as a new generic "decorator".

 Makefile      |    4 +-
 decorate.c    |   89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 decorate.h    |   18 +++++++++++
 object-refs.c |   69 ++++---------------------------------------
 object.h      |    1 -
 5 files changed, 116 insertions(+), 65 deletions(-)
 create mode 100644 decorate.c
 create mode 100644 decorate.h

diff --git a/Makefile b/Makefile
index b8e6030..251fc31 100644
--- a/Makefile
+++ b/Makefile
@@ -283,7 +283,7 @@ LIB_H = \
 	diff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.h \
 	run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
 	tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
-	utf8.h reflog-walk.h patch-ids.h
+	utf8.h reflog-walk.h patch-ids.h decorate.h
 
 DIFF_OBJS = \
 	diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -305,7 +305,7 @@ LIB_OBJS = \
 	write_or_die.o trace.o list-objects.o grep.o match-trees.o \
 	alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
 	color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
-	convert.o
+	convert.o decorate.o
 
 BUILTIN_OBJS = \
 	builtin-add.o \
diff --git a/decorate.c b/decorate.c
new file mode 100644
index 0000000..721bcd1
--- /dev/null
+++ b/decorate.c
@@ -0,0 +1,89 @@
+/*
+ * decorate.c - decorate a git object with some arbitrary
+ * data.
+ */
+#include "cache.h"
+#include "object.h"
+#include "decorate.h"
+
+static unsigned int hash_obj(struct object *obj, unsigned int n)
+{
+	unsigned int hash = *(unsigned int *)obj->sha1;
+	return hash % n;
+}
+
+static void *insert_decoration(struct decoration *n, struct object *base, void *decoration)
+{
+	int size = n->size;
+	struct object_decoration *hash = n->hash;
+	int j = hash_obj(base, size);
+
+	while (hash[j].base) {
+		if (hash[j].base == base) {
+			void *old = hash[j].decoration;
+			hash[j].decoration = decoration;
+			return old;
+		}
+		j++;
+		if (++j >= size)
+			j = 0;
+	}
+	hash[j].base = base;
+	hash[j].decoration = decoration;
+	n->nr++;
+	return NULL;
+}
+
+static void grow_decoration(struct decoration *n)
+{
+	int i;
+	int old_size = n->size;
+	struct object_decoration *old_hash;
+
+	old_size = n->size;
+	old_hash = n->hash;
+	
+	n->size = (old_size + 1000) * 3 / 2;
+	n->hash = xcalloc(n->size, sizeof(struct object_decoration));
+	n->nr = 0;
+	
+	for (i = 0; i < old_size; i++) {
+		struct object *base = old_hash[i].base;
+		void *decoration = old_hash[i].decoration;
+
+		if (!base)
+			continue;
+		insert_decoration(n, base, decoration);
+	}
+	free(old_hash);
+}
+
+/* Add a decoration pointer, return any old one */
+void *add_decoration(struct decoration *n, struct object *obj, void *decoration)
+{
+	int nr = n->nr + 1;
+
+	if (nr > n->size * 2 / 3)
+		grow_decoration(n);
+	return insert_decoration(n, obj, decoration);
+}
+
+/* Lookup a decoration pointer */
+void *lookup_decoration(struct decoration *n, struct object *obj)
+{
+	int j;
+
+	/* nothing to lookup */
+	if (!n->size)
+		return NULL;
+	j = hash_obj(obj, n->size);
+	for (;;) {
+		struct object_decoration *ref = n->hash + j;
+		if (ref->base == obj)
+			return ref->decoration;
+		if (!ref->base)
+			return NULL;
+		if (++j == n->size)
+			j = 0;
+	}
+}
diff --git a/decorate.h b/decorate.h
new file mode 100644
index 0000000..1fa4ad9
--- /dev/null
+++ b/decorate.h
@@ -0,0 +1,18 @@
+#ifndef DECORATE_H
+#define DECORATE_H
+
+struct object_decoration {
+	struct object *base;
+	void *decoration;
+};
+
+struct decoration {
+	const char *name;
+	unsigned int size, nr;
+	struct object_decoration *hash;
+};
+
+extern void *add_decoration(struct decoration *n, struct object *obj, void *decoration);
+extern void *lookup_decoration(struct decoration *n, struct object *obj);
+
+#endif
diff --git a/object-refs.c b/object-refs.c
index 98ea100..022e8d8 100644
--- a/object-refs.c
+++ b/object-refs.c
@@ -1,75 +1,20 @@
 #include "cache.h"
 #include "object.h"
+#include "decorate.h"
 
 int track_object_refs = 0;
 
-static unsigned int refs_hash_size, nr_object_refs;
-static struct object_refs **refs_hash;
+static struct decoration ref_decorate;
 
-static unsigned int hash_obj(struct object *obj, unsigned int n)
+struct object_refs *lookup_object_refs(struct object *base)
 {
-	unsigned int hash = *(unsigned int *)obj->sha1;
-	return hash % n;
+	return lookup_decoration(&ref_decorate, base);
 }
 
-static void insert_ref_hash(struct object_refs *ref, struct object_refs **hash, unsigned int size)
+static void add_object_refs(struct object *obj, struct object_refs *refs)
 {
-	int j = hash_obj(ref->base, size);
-
-	while (hash[j]) {
-		j++;
-		if (j >= size)
-			j = 0;
-	}
-	hash[j] = ref;
-}
-
-static void grow_refs_hash(void)
-{
-	int i;
-	int new_hash_size = (refs_hash_size + 1000) * 3 / 2;
-	struct object_refs **new_hash;
-
-	new_hash = xcalloc(new_hash_size, sizeof(struct object_refs *));
-	for (i = 0; i < refs_hash_size; i++) {
-		struct object_refs *ref = refs_hash[i];
-		if (!ref)
-			continue;
-		insert_ref_hash(ref, new_hash, new_hash_size);
-	}
-	free(refs_hash);
-	refs_hash = new_hash;
-	refs_hash_size = new_hash_size;
-}
-
-static void add_object_refs(struct object *obj, struct object_refs *ref)
-{
-	int nr = nr_object_refs + 1;
-
-	if (nr > refs_hash_size * 2 / 3)
-		grow_refs_hash();
-	ref->base = obj;
-	insert_ref_hash(ref, refs_hash, refs_hash_size);
-	nr_object_refs = nr;
-}
-
-struct object_refs *lookup_object_refs(struct object *obj)
-{
-	struct object_refs *ref;
-	int j;
-
-	/* nothing to lookup */
-	if (!refs_hash_size)
-		return NULL;
-	j = hash_obj(obj, refs_hash_size);
-	while ((ref = refs_hash[j]) != NULL) {
-		if (ref->base == obj)
-			break;
-		j++;
-		if (j >= refs_hash_size)
-			j = 0;
-	}
-	return ref;
+	if (add_decoration(&ref_decorate, obj, refs))
+		die("object %s tried to add refs twice!", sha1_to_hex(obj->sha1));
 }
 
 struct object_refs *alloc_object_refs(unsigned count)
diff --git a/object.h b/object.h
index bdbf0fa..bdbbc18 100644
--- a/object.h
+++ b/object.h
@@ -8,7 +8,6 @@ struct object_list {
 
 struct object_refs {
 	unsigned count;
-	struct object *base;
 	struct object *ref[FLEX_ARRAY]; /* more */
 };
 
-- 
1.5.1.1.107.g7a15

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

* [PATCH 2/2] Add support for "commit name decorations" to log family of commands
  2007-04-16 23:03 [PATCH 1/2] Add a generic "object decorator" interface, and make object refs use it Linus Torvalds
@ 2007-04-16 23:05 ` Linus Torvalds
  0 siblings, 0 replies; 2+ messages in thread
From: Linus Torvalds @ 2007-04-16 23:05 UTC (permalink / raw
  To: Junio C Hamano, Theodore Ts'o, Git Mailing List


This adds "--decorate" as a log option, which prints out the ref names 
of any commits that are shown.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---

I'm not married to the exact format, but if people prefer some other 
setup it should be easy to change. The code is fairly simple and obvious.

 builtin-log.c |   34 ++++++++++++++++++++++++++++++++--
 commit.h      |    8 ++++++++
 log-tree.c    |   21 +++++++++++++++++++++
 3 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/builtin-log.c b/builtin-log.c
index 4699494..38bf52f 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -13,16 +13,43 @@
 #include "tag.h"
 #include "reflog-walk.h"
 #include "patch-ids.h"
+#include "refs.h"
 
 static int default_show_root = 1;
 
 /* this is in builtin-diff.c */
 void add_head(struct rev_info *revs);
 
+static void add_name_decoration(const char *prefix, const char *name, struct object *obj)
+{
+	int plen = strlen(prefix);
+	int nlen = strlen(name);
+	struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen);
+	memcpy(res->name, prefix, plen);
+	memcpy(res->name + plen, name, nlen + 1);
+	res->next = add_decoration(&name_decoration, obj, res);
+}
+
+static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
+{
+	struct object *obj = parse_object(sha1);
+	if (!obj)
+		return 0;
+	add_name_decoration("", refname, obj);
+	while (obj->type == OBJ_TAG) {
+		obj = ((struct tag *)obj)->tagged;
+		if (!obj)
+			break;
+		add_name_decoration("tag: ", refname, obj);
+	}
+	return 0;
+}
+
 static void cmd_log_init(int argc, const char **argv, const char *prefix,
 		      struct rev_info *rev)
 {
 	int i;
+	int decorate = 0;
 
 	rev->abbrev = DEFAULT_ABBREV;
 	rev->commit_format = CMIT_FMT_DEFAULT;
@@ -39,8 +66,11 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
 				git_log_output_encoding = xstrdup(arg);
 			else
 				git_log_output_encoding = "";
-		}
-		else
+		} else if (!strcmp(arg, "--decorate")) {
+			if (!decorate)
+				for_each_ref(add_ref_decoration, NULL);
+			decorate = 1;
+		} else
 			die("unrecognized argument: %s", arg);
 	}
 }
diff --git a/commit.h b/commit.h
index 83507a0..59de17e 100644
--- a/commit.h
+++ b/commit.h
@@ -3,6 +3,7 @@
 
 #include "object.h"
 #include "tree.h"
+#include "decorate.h"
 
 struct commit_list {
 	struct commit *item;
@@ -21,6 +22,13 @@ struct commit {
 extern int save_commit_buffer;
 extern const char *commit_type;
 
+/* While we can decorate any object with a name, it's only used for commits.. */
+extern struct decoration name_decoration;
+struct name_decoration {
+	struct name_decoration *next;
+	char name[1];
+};
+
 struct commit *lookup_commit(const unsigned char *sha1);
 struct commit *lookup_commit_reference(const unsigned char *sha1);
 struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
diff --git a/log-tree.c b/log-tree.c
index dad5513..300b733 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -4,6 +4,8 @@
 #include "log-tree.h"
 #include "reflog-walk.h"
 
+struct decoration name_decoration = { "object names" };
+
 static void show_parents(struct commit *commit, int abbrev)
 {
 	struct commit_list *p;
@@ -13,6 +15,23 @@ static void show_parents(struct commit *commit, int abbrev)
 	}
 }
 
+static void show_decorations(struct commit *commit)
+{
+	const char *prefix;
+	struct name_decoration *decoration;
+
+	decoration = lookup_decoration(&name_decoration, &commit->object);
+	if (!decoration)
+		return;
+	prefix = " (";
+	while (decoration) {
+		printf("%s%s", prefix, decoration->name);
+		prefix = ", ";
+		decoration = decoration->next;
+	}
+	putchar(')');
+}
+
 /*
  * Search for "^[-A-Za-z]+: [^@]+@" pattern. It usually matches
  * Signed-off-by: and Acked-by: lines.
@@ -136,6 +155,7 @@ void show_log(struct rev_info *opt, const char *sep)
 		fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), stdout);
 		if (opt->parents)
 			show_parents(commit, abbrev_commit);
+		show_decorations(commit);
 		putchar(opt->diffopt.line_termination);
 		return;
 	}
@@ -240,6 +260,7 @@ void show_log(struct rev_info *opt, const char *sep)
 			printf(" (from %s)",
 			       diff_unique_abbrev(parent->object.sha1,
 						  abbrev_commit));
+		show_decorations(commit);
 		printf("%s",
 		       diff_get_color(opt->diffopt.color_diff, DIFF_RESET));
 		putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n');
-- 
1.5.1.1.107.g7a15

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

end of thread, other threads:[~2007-04-16 23:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-16 23:03 [PATCH 1/2] Add a generic "object decorator" interface, and make object refs use it Linus Torvalds
2007-04-16 23:05 ` [PATCH 2/2] Add support for "commit name decorations" to log family of commands Linus Torvalds

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).