git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[2/5] Implementations of parsing functions

From
Daniel Barkalow <barkalow@iabervon.org>
Date
Apr 18, 2005, 02:36 UTC
Message-ID
<Pine.LNX.4.21.0504172235260.30848-100000@iabervon.org>
In-Reply-To
<Pine.LNX.4.21.0504172229240.30848-100000@iabervon.org>
This implements the parsing functions.
Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>
Index: blob.c
===================================================================
--- /dev/null  (tree:5ca133e1b74aee39b2124c0ec9fd51539babb5e0)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/blob.c  (mode:100644 sha1:04e0c1da9b1f4cdb1d1c5881b785babd3b0ceb09)
@@ -0,0 +1,24 @@
+#include "blob.h"
+#include "cache.h"
+#include <stdlib.h>
+
+const char *blob_type = "blob";
+
+struct blob *lookup_blob(unsigned char *sha1)
+{
+	struct object *obj = lookup_object(sha1);
+	if (!obj) {
+		struct blob *ret = malloc(sizeof(struct blob));
+		bzero(ret, sizeof(struct blob));
+		created_object(sha1, &ret->object);
+		ret->object.type = blob_type;
+		ret->object.parsed = 1;
+		return ret;
+	}
+	if (obj->parsed && obj->type != blob_type) {
+		error("Object %s is a %s, not a blob", 
+		      sha1_to_hex(sha1), obj->type);
+		return NULL;
+	}
+	return (struct blob *) obj;
+}
Index: commit.c
===================================================================
--- /dev/null  (tree:5ca133e1b74aee39b2124c0ec9fd51539babb5e0)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/commit.c  (mode:100644 sha1:0099baa63971d86ee30ef2a7da25057f0f45a964)
@@ -0,0 +1,85 @@
+#include "commit.h"
+#include "cache.h"
+#include <string.h>
+
+const char *commit_type = "commit";
+
+struct commit *lookup_commit(unsigned char *sha1)
+{
+	struct object *obj = lookup_object(sha1);
+	if (!obj) {
+		struct commit *ret = malloc(sizeof(struct commit));
+		bzero(ret, sizeof(struct commit));
+		created_object(sha1, &ret->object);
+		return ret;
+	}
+	if (obj->parsed && obj->type != commit_type) {
+		error("Object %s is a %s, not a commit", 
+		      sha1_to_hex(sha1), obj->type);
+		return NULL;
+	}
+	return (struct commit *) obj;
+}
+
+static unsigned long parse_commit_date(const char *buf)
+{
+	unsigned long date;
+
+	if (memcmp(buf, "author", 6))
+		return 0;
+	while (*buf++ != '\n')
+		/* nada */;
+	if (memcmp(buf, "committer", 9))
+		return 0;
+	while (*buf++ != '>')
+		/* nada */;
+	date = strtoul(buf, NULL, 10);
+	if (date == ULONG_MAX)
+		date = 0;
+	return date;
+}
+
+int parse_commit(struct commit *item)
+{
+	char type[20];
+	void * buffer, *bufptr;
+	unsigned long size;
+	unsigned char parent[20];
+	if (item->object.parsed)
+		return 0;
+	item->object.parsed = 1;
+	buffer = bufptr = read_sha1_file(item->object.sha1, type, &size);
+	if (!buffer)
+		return error("Could not read %s",
+			     sha1_to_hex(item->object.sha1));
+	if (strcmp(type, commit_type))
+		return error("Object %s not a commit",
+			     sha1_to_hex(item->object.sha1));
+	item->object.type = commit_type;
+	get_sha1_hex(bufptr + 5, parent);
+	item->tree = lookup_tree(parent);
+	add_ref(&item->object, &item->tree->object);
+	bufptr += 46; /* "tree " + "hex sha1" + "\n" */
+	while (!memcmp(bufptr, "parent ", 7) &&
+	       !get_sha1_hex(bufptr + 7, parent)) {
+		struct commit_list *new_parent = 
+			malloc(sizeof(struct commit_list));
+		new_parent->next = item->parents;
+		new_parent->item = lookup_commit(parent);
+		add_ref(&item->object, &new_parent->item->object);
+		item->parents = new_parent;
+		bufptr += 48;
+	}
+	item->date = parse_commit_date(bufptr);
+	free(buffer);
+	return 0;
+}
+
+void free_commit_list(struct commit_list *list)
+{
+	while (list) {
+		struct commit_list *temp = list;
+		list = temp->next;
+		free(temp);
+	}
+}
Index: object.c
===================================================================
--- /dev/null  (tree:5ca133e1b74aee39b2124c0ec9fd51539babb5e0)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/object.c  (mode:100644 sha1:986624ac7a7fd9229e05e1f181fd500640298d9e)
@@ -0,0 +1,96 @@
+#include "object.h"
+#include "cache.h"
+#include <stdlib.h>
+#include <string.h>
+
+struct object **objs;
+int nr_objs;
+static int obj_allocs;
+
+static int find_object(unsigned char *sha1)
+{
+	int first = 0, last = nr_objs;
+
+        while (first < last) {
+                int next = (first + last) / 2;
+                struct object *obj = objs[next];
+                int cmp;
+
+                cmp = memcmp(sha1, obj->sha1, 20);
+                if (!cmp)
+                        return next;
+                if (cmp < 0) {
+                        last = next;
+                        continue;
+                }
+                first = next+1;
+        }
+        return -first-1;
+}
+
+struct object *lookup_object(unsigned char *sha1)
+{
+	int pos = find_object(sha1);
+	if (pos >= 0)
+		return objs[pos];
+	return NULL;
+}
+
+void created_object(unsigned char *sha1, struct object *obj)
+{
+	int pos = find_object(sha1);
+
+	obj->parsed = 0;
+	memcpy(obj->sha1, sha1, 20);
+	obj->type = NULL;
+	obj->refs = NULL;
+	obj->used = 0;
+
+	if (pos >= 0)
+		die("Inserting %s twice\n", sha1_to_hex(sha1));
+	pos = -pos-1;
+
+	if (obj_allocs == nr_objs) {
+		obj_allocs = alloc_nr(obj_allocs);
+		objs = realloc(objs, obj_allocs * sizeof(struct object *));
+	}
+
+	/* Insert it into the right place */
+	memmove(objs + pos + 1, objs + pos, (nr_objs - pos) * 
+		sizeof(struct object *));
+
+	objs[pos] = obj;
+	nr_objs++;
+}
+
+void add_ref(struct object *refer, struct object *target)
+{
+	struct object_list **pp = &refer->refs;
+	struct object_list *p;
+	
+	while ((p = *pp) != NULL) {
+		if (p->item == target)
+			return;
+		pp = &p->next;
+	}
+
+	target->used = 1;
+	p = malloc(sizeof(*p));
+	p->item = target;
+	p->next = NULL;
+	*pp = p;
+}
+
+void mark_reachable(struct object *obj, unsigned int mask)
+{
+	struct object_list *p = obj->refs;
+
+	/* If we've been here already, don't bother */
+	if (obj->flags & mask)
+		return;
+	obj->flags |= mask;
+	while (p) {
+		mark_reachable(p->item, mask);
+		p = p->next;
+	}
+}
Index: tree.c
===================================================================
--- /dev/null  (tree:5ca133e1b74aee39b2124c0ec9fd51539babb5e0)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/tree.c  (mode:100644 sha1:7c5e5e46f4967b0812b06c0114946c3a6432c8d8)
@@ -0,0 +1,67 @@
+#include "tree.h"
+#include "blob.h"
+#include "cache.h"
+#include <stdlib.h>
+
+const char *tree_type = "tree";
+
+struct tree *lookup_tree(unsigned char *sha1)
+{
+	struct object *obj = lookup_object(sha1);
+	if (!obj) {
+		struct tree *ret = malloc(sizeof(struct tree));
+		bzero(ret, sizeof(struct tree));
+		created_object(sha1, &ret->object);
+		return ret;
+	}
+	if (obj->parsed && obj->type != tree_type) {
+		error("Object %s is a %s, not a tree", 
+		      sha1_to_hex(sha1), obj->type);
+		return NULL;
+	}
+	return (struct tree *) obj;
+}
+
+int parse_tree(struct tree *item)
+{
+	char type[20];
+	void *buffer, *bufptr;
+	unsigned long size;
+	if (item->object.parsed)
+		return 0;
+	item->object.parsed = 1;
+	item->object.type = tree_type;
+	buffer = bufptr = read_sha1_file(item->object.sha1, type, &size);
+	if (!buffer)
+		return error("Could not read %s",
+			     sha1_to_hex(item->object.sha1));
+	if (strcmp(type, tree_type))
+		return error("Object %s not a tree",
+			     sha1_to_hex(item->object.sha1));
+	while (size) {
+		struct object *obj;
+		int len = 1+strlen(bufptr);
+		unsigned char *file_sha1 = bufptr + len;
+		char *path = strchr(bufptr, ' ');
+		unsigned int mode;
+		if (size < len + 20 || !path || 
+		    sscanf(bufptr, "%o", &mode) != 1)
+			return -1;
+
+		/* Warn about trees that don't do the recursive thing.. */
+		if (strchr(path, '/')) {
+			item->has_full_path = 1;
+		}
+
+		bufptr += len + 20;
+		size -= len + 20;
+
+		if (S_ISDIR(mode)) {
+			obj = &lookup_tree(file_sha1)->object;
+		} else {
+			obj = &lookup_blob(file_sha1)->object;
+		}
+		add_ref(&item->object, obj);
+	}
+	return 0;
+}
Previous: Daniel BarkalowNext: Daniel Barkalow
Message 6 of 16 in “[RFC] General object parsing”
  1. Daniel BarkalowApr 18, 2005
  2. Linus TorvaldsApr 18, 2005
  3. Daniel BarkalowApr 18, 2005
  4. 0/5 Parsers for git objects, porting some programsDaniel Barkalow, Apr 18, 2005
  5. 1/5 Header files for object parsingDaniel Barkalow, Apr 18, 2005
  6. 2/5 Implementations of parsing functionsDaniel Barkalow, Apr 18, 2005
  7. 3/5 Port rev-tree to parsing functionsDaniel Barkalow, Apr 18, 2005
  8. 4/5 Port fsck-cache to use parsing functionsDaniel Barkalow, Apr 18, 2005
  9. 5/5 Switch implementations of merge-base, port to parsingDaniel Barkalow, Apr 18, 2005
  10. Linus TorvaldsApr 18, 2005
  11. Daniel BarkalowApr 18, 2005
  12. Junio C HamanoApr 19, 2005
  13. Daniel BarkalowApr 19, 2005
  14. Daniel BarkalowApr 19, 2005
  15. Daniel BarkalowApr 18, 2005
  16. David WoodhouseApr 18, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.