Git development
 help / color / mirror / Atom feed
* Re: [PATCH] "checkout-cache -m" writes unmerged contents for each stage.
From: Linus Torvalds @ 2005-04-18  2:56 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfyxovm6j.fsf@assigned-by-dhcp.cox.net>



On Sun, 17 Apr 2005, Junio C Hamano wrote:
> 
> One small detail.  What about the "-x" bit?

You'll need to merge those kinds of changes separately for now. We'll have 
to resolve that too, right now I think the -x bit gets lost on a merge 
simply because we just write the temp-files, something merges them, and 
does an "update-cache" on the merged result, and we'll pick up the -x bit 
(or rather, lack of one) at that point.

		Linus

^ permalink raw reply

* Re: [PATCH] "checkout-cache -m" writes unmerged contents for each stage.
From: Junio C Hamano @ 2005-04-18  2:44 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0504171833450.7211@ppc970.osdl.org>

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> I'm actually thinking that maybe the _right_ interface is to do something 
LT> like this:

LT> 	merge-cache <program> <filename>

LT> and what that does is to look up the <filename> in the cache, and if it 
LT> has any merge entries, unpack all of them (which may be just one file, of 
LT> course) into up to three separate files (mkstemp()), and then execve the 
LT> supplied program name with those three files as arguments 1,2,3 (empty 
LT> argument if no file), and "filename" as argument 4.

LT> What do you think? I can whip up a "merge-cache" program like that in five 
LT> minutes, and it _seems_ like the right interface..

One small detail.  What about the "-x" bit?

In case 2 and 3 in your sample merge script, the "merge script"
needs to know what the preferred mode bits are before running
"update-cache --add".

Yes, it can figure that out by running "show-files --unmerged"
and grepping for "$4" by itself, but then it can figure out the
information in "$1" through "$3" by itself as well, so that
makes having merge-cache wrapper less useful to begin with.

I do not think it is realistic for these three related trees to
have files that differ in -x bit, so it would not be that useful
to give the "merge script" the flexibility to pick -x bit value
among three parents --- it would be fine for the merge-cache
wrapper to dictate the value of the -x bit for the resulting
file.  So I'd suggest to add an extra parameter to the "merge
script" when merge-cache wrapper calls it.


^ permalink raw reply

* Re: SHA1 hash safety
From: Theodore Ts'o @ 2005-04-18  0:09 UTC (permalink / raw)
  To: David A. Wheeler; +Cc: Paul Jackson, David Lang, cscott, pasky, omb, mingo, git
In-Reply-To: <4261E84D.6040208@dwheeler.com>

On Sun, Apr 17, 2005 at 12:38:37AM -0400, David A. Wheeler wrote:
> The probability of an accidental overlap for SHA-1 for two
> different files is absurdly remote; it's just not worth worrying about.
> 
> However, the possibility of an INTENTIONAL overlap is a completely
> different matter.  I think the hash algorithm should change in the
> future; I have a proposal below.
> 
> Someone has ALREADY broken into a server to modify the Linux kernel
> code already, so the idea of an attack on kernel code
> is not an idle fantasy. MD5 is dead, and SHA-1's work factor has
> already been sufficiently broken that people have already been told
> "walk to the exits" (i.e., DO NOT USE SHA-1 for new programs like git).

We're very clearly going to need a FAQ for git.

SHA-1's work factor has been decreased to 2**69 from 2**80 for
generating two messages that have the same hash value, WHERE THE HASH
VALUE AND THE MESSAGES ARE NOT UNDER THE ATTACKER'S CONTROL.  This is
not the same as a pre-image attack, where given a message M1 which
hashes to value H, the attacker can find another message M2 which also
hashes to value H.  In even if the attacker can do this, the result
has to have valid git metadata format, and also be valid C code.

So the the recent result which has weakened (but not broken) SHA-1's
use in digital signatures, and which has resulted in the advice to
"walk not run" for the exits, do not apply to git.

Can we guarantee that there won't be further innovations that may
break SHA-1?  Of course not.  But an attacker who wants to introduced
a trojan into the Linux kernel would have a much easier time doing a
"black bag job" --- i.e., breaking into Linus's house in Portland, and
then inserting a buggered patch into his master source tree.

If you're going to be a professional paranoid, it's best to worry
about the realistic attacks before stressing out over the unrealistic
ones.

						- Ted

^ permalink raw reply

* [5/5] Switch implementations of merge-base, port to parsing
From: Daniel Barkalow @ 2005-04-18  2:42 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git
In-Reply-To: <Pine.LNX.4.21.0504172229240.30848-100000@iabervon.org>

This switches to my implementation of merge-base, but with the new parsing
library.

Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>
Index: Makefile
===================================================================
--- 108bfb69c14c55c3c6e30a298307390c82cf1b3b/Makefile  (mode:100644 sha1:affc0e96030d4514f8306ee29020ca6bb320648f)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/Makefile  (mode:100644 sha1:c8908268d3c2253d3905671de5cabe4c84674128)
@@ -64,8 +64,8 @@
 ls-tree: ls-tree.o read-cache.o
 	$(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
 
-merge-base: merge-base.o read-cache.o
-	$(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+	$(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
 
 read-cache.o: cache.h
 show-diff.o: cache.h
Index: merge-base.c
===================================================================
--- 108bfb69c14c55c3c6e30a298307390c82cf1b3b/merge-base.c  (mode:100644 sha1:c98cad0befcf7e04fcc329d9bb7cb550506a4574)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/merge-base.c  (mode:100644 sha1:414ff419c679dba122b2f21b698c1e2c8abdd965)
@@ -1,57 +1,95 @@
+#include <stdlib.h>
 #include "cache.h"
-#include "revision.h"
+#include "commit.h"
 
-/*
- * This is stupid. We could have much better heurstics, I bet.
- */
-static int better(struct revision *new, struct revision *old)
+static struct commit *process_list(struct commit_list **list_p, int this_mark,
+				   int other_mark)
 {
-	return new->date > old->date;
+	struct commit_list *parent, *temp;
+	struct commit_list *posn = *list_p;
+	*list_p = NULL;
+	while (posn) {
+		parse_commit(posn->item);
+		if (posn->item->object.flags & this_mark) {
+			/*
+			  printf("%d already seen %s %x\n",
+			  this_mark
+			  sha1_to_hex(posn->parent->sha1),
+			  posn->parent->flags);
+			*/
+			/* do nothing; this indicates that this side
+			 * split and reformed, and we only need to
+			 * mark it once.
+			 */
+		} else if (posn->item->object.flags & other_mark) {
+			return posn->item;
+		} else {
+			/*
+			  printf("%d based on %s\n",
+			  this_mark,
+			  sha1_to_hex(posn->parent->sha1));
+			*/
+			posn->item->object.flags |= this_mark;
+			
+			parent = posn->item->parents;
+			while (parent) {
+				temp = malloc(sizeof(struct commit_list));
+				temp->next = *list_p;
+				temp->item = parent->item;
+				*list_p = temp;
+				parent = parent->next;
+			}
+		}
+		posn = posn->next;
+	}
+	return NULL;
 }
 
-static struct revision *common_parent(struct revision *rev1, struct revision *rev2)
+struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
 {
-	int i;
-	struct revision *best = NULL;
+	struct commit_list *rev1list = malloc(sizeof(struct commit_list));
+	struct commit_list *rev2list = malloc(sizeof(struct commit_list));
+
+	rev1list->item = rev1;
+	rev1list->next = NULL;
+
+	rev2list->item = rev2;
+	rev2list->next = NULL;
 
-	mark_reachable(rev1, 1);
-	mark_reachable(rev2, 2);
-	for (i = 0; i < nr_revs ;i++) {
-		struct revision *rev = revs[i];
-		if ((rev->flags & 3) != 3)
-			continue;
-		if (!best) {
-			best = rev;
-			continue;
+	while (rev1list || rev2list) {
+		struct commit *ret;
+		ret = process_list(&rev1list, 0x1, 0x2);
+		if (ret) {
+			/* XXXX free lists */
+			return ret;
+		}
+		ret = process_list(&rev2list, 0x2, 0x1);
+		if (ret) {
+			/* XXXX free lists */
+			return ret;
 		}
-		if (better(rev, best))
-			best = rev;
 	}
-	return best;
+	return NULL;
 }
 
 int main(int argc, char **argv)
 {
-	unsigned char rev1[20], rev2[20];
-	struct revision *common;
-
-	if (argc != 3 || get_sha1_hex(argv[1], rev1) || get_sha1_hex(argv[2], rev2))
-		usage("merge-base <commit1> <commit2>");
+	struct commit *rev1, *rev2, *ret;
+	unsigned char rev1key[20], rev2key[20];
 
-	/*
-	 * We will eventually want to include a revision cache file
-	 * that "rev-tree.c" has generated, since this is going to
-	 * otherwise be quite expensive for big trees..
-	 *
-	 * That's some time off, though, and in the meantime we know
-	 * that we have a solution to the eventual expense.
-	 */
-	parse_commit(rev1);
-	parse_commit(rev2);
-
-	common = common_parent(lookup_rev(rev1), lookup_rev(rev2));
-	if (!common)
-		die("no common parent found");
-	printf("%s\n", sha1_to_hex(common->sha1));
-	return 0;
+	if (argc != 3 ||
+	    get_sha1_hex(argv[1], rev1key) ||
+	    get_sha1_hex(argv[2], rev2key)) {
+		usage("merge-base <commit-id> <commit-id>");
+	}
+	rev1 = lookup_commit(rev1key);
+	rev2 = lookup_commit(rev2key);
+	ret = common_ancestor(rev1, rev2);
+	if (ret) {
+		printf("%s\n", sha1_to_hex(ret->object.sha1));
+		return 0;
+	} else {
+		return 1;
+	}
+	
 }


^ permalink raw reply

* [4/5] Port fsck-cache to use parsing functions
From: Daniel Barkalow @ 2005-04-18  2:40 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git
In-Reply-To: <Pine.LNX.4.21.0504172229240.30848-100000@iabervon.org>

This ports fsck-cache to use parsing functions. Note that performance
could be improved here by only reading each object once, but this requires
somewhat more complicated flow control.

Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>
Index: Makefile
===================================================================
--- 499f6cf77edad6935da0106cca4472e50fdbde34/Makefile  (mode:100644 sha1:f00a9c3c1cdbfef7e96cfa98256aad35e63131e7)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/Makefile  (mode:100644 sha1:c8908268d3c2253d3905671de5cabe4c84674128)
@@ -43,8 +43,8 @@
 cat-file: cat-file.o read-cache.o
 	$(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
 
-fsck-cache: fsck-cache.o read-cache.o
-	$(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+	$(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
 
 checkout-cache: checkout-cache.o read-cache.o
 	$(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
Index: fsck-cache.c
===================================================================
--- 499f6cf77edad6935da0106cca4472e50fdbde34/fsck-cache.c  (mode:100644 sha1:cff04ce34e9445cd57db9c1026040d56f045e5e7)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/fsck-cache.c  (mode:100644 sha1:2000f16efc84911a51a40664fef8a637c90e2dcc)
@@ -3,7 +3,11 @@
 #include <sys/types.h>
 #include <dirent.h>
 
-#include "revision.h"
+#include "commit.h"
+#include "tree.h"
+#include "blob.h"
+
+#define REACHABLE 0x0001
 
 static int show_unreachable = 0;
 static unsigned char head_sha1[20];
@@ -13,96 +17,54 @@
 	int i;
 
 	/* Look up all the requirements, warn about missing objects.. */
-	for (i = 0; i < nr_revs; i++) {
-		struct revision *rev = revs[i];
+	for (i = 0; i < nr_objs; i++) {
+		struct object *obj = objs[i];
 
-		if (show_unreachable && !(rev->flags & REACHABLE)) {
-			printf("unreachable %s\n", sha1_to_hex(rev->sha1));
+		if (show_unreachable && !(obj->flags & REACHABLE)) {
+			printf("unreachable %s\n", sha1_to_hex(obj->sha1));
 			continue;
 		}
 
-		switch (rev->flags & (SEEN | USED)) {
-		case 0:
-			printf("bad %s\n", sha1_to_hex(rev->sha1));
-			break;
-		case USED:
-			printf("missing %s\n", sha1_to_hex(rev->sha1));
-			break;
-		case SEEN:
-			printf("dangling %s\n", sha1_to_hex(rev->sha1));
-			break;
+		if (!obj->parsed) {
+			printf("missing %s %s\n", obj->type, 
+			       sha1_to_hex(obj->sha1));
+		}
+		if (!obj->used) {
+			printf("dangling %s %s\n", obj->type, 
+			       sha1_to_hex(obj->sha1));
 		}
 	}
 }
 
-static void mark_needs_sha1(unsigned char *parent, const char * tag, unsigned char *child)
-{
-	struct revision * child_rev = add_relationship(lookup_rev(parent), child);
-	child_rev->flags |= USED;
-}
-
-static int mark_sha1_seen(unsigned char *sha1, char *tag)
-{
-	struct revision *rev = lookup_rev(sha1);
-
-	rev->flags |= SEEN;
-	return 0;
-}
-
 static int fsck_tree(unsigned char *sha1, void *data, unsigned long size)
 {
-	int warn_old_tree = 1;
-
-	while (size) {
-		int len = 1+strlen(data);
-		unsigned char *file_sha1 = data + len;
-		char *path = strchr(data, ' ');
-		unsigned int mode;
-		if (size < len + 20 || !path || sscanf(data, "%o", &mode) != 1)
-			return -1;
-
-		/* Warn about trees that don't do the recursive thing.. */
-		if (warn_old_tree && strchr(path, '/')) {
-			fprintf(stderr, "warning: fsck-cache: tree %s has full pathnames in it\n", sha1_to_hex(sha1));
-			warn_old_tree = 0;
-		}
-
-		data += len + 20;
-		size -= len + 20;
-		mark_needs_sha1(sha1, S_ISDIR(mode) ? "tree" : "blob", file_sha1);
+	struct tree *item = lookup_tree(sha1);
+	if (parse_tree(item))
+		return -1;
+	if (item->has_full_path) {
+		fprintf(stderr, "warning: fsck-cache: tree %s "
+			"has full pathnames in it\n", sha1_to_hex(sha1));
 	}
 	return 0;
 }
 
 static int fsck_commit(unsigned char *sha1, void *data, unsigned long size)
 {
-	int parents;
-	unsigned char tree_sha1[20];
-	unsigned char parent_sha1[20];
-
-	if (memcmp(data, "tree ", 5))
+	struct commit *commit = lookup_commit(sha1);
+	if (parse_commit(commit))
 		return -1;
-	if (get_sha1_hex(data + 5, tree_sha1) < 0)
+	if (!commit->tree)
 		return -1;
-	mark_needs_sha1(sha1, "tree", tree_sha1);
-	data += 5 + 40 + 1;	/* "tree " + <hex sha1> + '\n' */
-	parents = 0;
-	while (!memcmp(data, "parent ", 7)) {
-		if (get_sha1_hex(data + 7, parent_sha1) < 0)
-			return -1;
-		mark_needs_sha1(sha1, "commit", parent_sha1);
-		data += 7 + 40 + 1; 	/* "parent " + <hex sha1> + '\n' */
-		parents++;
-	}
-	if (!parents)
+	if (!commit->parents)
 		printf("root %s\n", sha1_to_hex(sha1));
 	return 0;
 }
 
-static int fsck_entry(unsigned char *sha1, char *tag, void *data, unsigned long size)
+static int fsck_entry(unsigned char *sha1, char *tag, void *data, 
+		      unsigned long size)
 {
 	if (!strcmp(tag, "blob")) {
-		/* Nothing to check */;
+		lookup_blob(sha1); /* Nothing to check; but notice it. */
 	} else if (!strcmp(tag, "tree")) {
 		if (fsck_tree(sha1, data, size) < 0)
 			return -1;
@@ -111,7 +73,7 @@
 			return -1;
 	} else
 		return -1;
-	return mark_sha1_seen(sha1, tag);
+	return 0;
 }
 
 static int fsck_name(char *hex)
@@ -125,7 +87,8 @@
 			unsigned long size;
 			void *buffer = NULL;
 			if (!check_sha1_signature(sha1, map, mapsize))
-				buffer = unpack_sha1_file(map, mapsize, type, &size);
+				buffer = unpack_sha1_file(map, mapsize, type,
+							  &size);
 			munmap(map, mapsize);
 			if (buffer && !fsck_entry(sha1, type, buffer, size))
 				return 0;
@@ -186,7 +149,10 @@
 			continue;
 		}
 		if (!get_sha1_hex(argv[i], head_sha1)) {
-			mark_reachable(lookup_rev(head_sha1), REACHABLE);
+			struct object *obj =
+				&lookup_commit(head_sha1)->object;
+			obj->used = 1;
+			mark_reachable(obj, REACHABLE);
 			heads++;
 			continue;
 		}


^ permalink raw reply

* [3/5] Port rev-tree to parsing functions
From: Daniel Barkalow @ 2005-04-18  2:37 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git
In-Reply-To: <Pine.LNX.4.21.0504172229240.30848-100000@iabervon.org>

This ports rev-tree to use the parsing functions introduced in the
previous patches.

Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>
Index: Makefile
===================================================================
--- 5ca133e1b74aee39b2124c0ec9fd51539babb5e0/Makefile  (mode:100644 sha1:773166a462f88b1c69930ce36d336d3d7badc319)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/Makefile  (mode:100644 sha1:c8908268d3c2253d3905671de5cabe4c84674128)
@@ -52,8 +52,8 @@
 diff-tree: diff-tree.o read-cache.o
 	$(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
 
-rev-tree: rev-tree.o read-cache.o
-	$(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS)
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+	$(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
 
 show-files: show-files.o read-cache.o
 	$(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
Index: rev-tree.c
===================================================================
--- 5ca133e1b74aee39b2124c0ec9fd51539babb5e0/rev-tree.c  (mode:100644 sha1:2d331b04c8243baab9546611ced07ba3439ab8ae)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/rev-tree.c  (mode:100644 sha1:38e992ac027c733f38b18932caa4032849936d05)
@@ -4,7 +4,7 @@
 #include <ctype.h>
 
 #include "cache.h"
-#include "revision.h"
+#include "commit.h"
 
 /*
  * revision.h leaves the low 16 bits of the "flags" field of the
@@ -18,38 +18,7 @@
 
 static void read_cache_file(const char *path)
 {
-	FILE *file = fopen(path, "r");
-	char line[500];
-
-	if (!file)
-		die("bad revtree cache file (%s)", path);
-
-	while (fgets(line, sizeof(line), file)) {
-		unsigned long date;
-		unsigned char sha1[20];
-		struct revision *rev;
-		const char *buf;
-
-		if (sscanf(line, "%lu", &date) != 1)
-			break;
-		buf = strchr(line, ' ');
-		if (!buf)
-			break;
-		if (get_sha1_hex(buf+1, sha1))
-			break;
-		rev = lookup_rev(sha1);
-		rev->flags |= SEEN;
-		rev->date = date;
-
-		/* parents? */
-		while ((buf = strchr(buf+1, ' ')) != NULL) {
-			unsigned char parent[20];
-			if (get_sha1_hex(buf + 1, parent))
-				break;
-			add_relationship(rev, parent);
-		}
-	}
-	fclose(file);
+	die("no revtree cache file yet");
 }
 
 /*
@@ -61,16 +30,16 @@
  * And sometimes we're only interested in "edge" commits, ie
  * places where the marking changes between parent and child.
  */
-static int interesting(struct revision *rev)
+static int interesting(struct commit *rev)
 {
-	unsigned mask = marked(rev);
+	unsigned mask = rev->object.flags;
 
 	if (!mask)
 		return 0;
 	if (show_edges) {
-		struct parent *p = rev->parent;
+		struct commit_list *p = rev->parents;
 		while (p) {
-			if (mask != marked(p->parent))
+			if (mask != p->item->object.flags)
 				return 1;
 			p = p->next;
 		}
@@ -82,6 +51,18 @@
 	return 1;
 }
 
+void process_commit(unsigned char *sha1) {
+	struct commit_list *parents;
+	struct commit *obj = lookup_commit(sha1);
+	parse_commit(obj);
+	
+	parents = obj->parents;
+	while (parents) {
+		process_commit(parents->item->object.sha1);
+		parents = parents->next;
+	}
+}
+
 /*
  * Usage: rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id2>]
  *
@@ -119,7 +100,7 @@
 		}
 		if (nr >= MAX_COMMITS || get_sha1_hex(arg, sha1[nr]))
 			usage("rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id>]");
-		parse_commit(sha1[nr]);
+		process_commit(sha1[nr]);
 		nr++;
 	}
 
@@ -127,22 +108,30 @@
 	 * Now we have the maximal tree. Walk the different sha files back to the root.
 	 */
 	for (i = 0; i < nr; i++)
-		mark_reachable(lookup_rev(sha1[i]), 1 << i);
+		mark_reachable(&lookup_commit(sha1[i])->object, 1 << i);
 
 	/*
 	 * Now print out the results..
 	 */
-	for (i = 0; i < nr_revs; i++) {
-		struct revision *rev = revs[i];
-		struct parent *p;
+	for (i = 0; i < nr_objs; i++) {
+		struct object *obj = objs[i];
+		struct commit *commit;
+		struct commit_list *p;
+
+		if (obj->type != commit_type)
+			continue;
+
+		commit = (struct commit *) obj;
 
-		if (!interesting(rev))
+		if (!interesting(commit))
 			continue;
 
-		printf("%lu %s:%d", rev->date, sha1_to_hex(rev->sha1), marked(rev));
-		p = rev->parent;
+		printf("%lu %s:%d", commit->date, sha1_to_hex(obj->sha1), 
+		       obj->flags);
+		p = commit->parents;
 		while (p) {
-			printf(" %s:%d", sha1_to_hex(p->parent->sha1), marked(p->parent));
+			printf(" %s:%d", sha1_to_hex(p->item->object.sha1), 
+			       p->item->object.flags);
 			p = p->next;
 		}
 		printf("\n");


^ permalink raw reply

* [2/5] Implementations of parsing functions
From: Daniel Barkalow @ 2005-04-18  2:36 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git
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;
+}


^ permalink raw reply

* [1/5] Header files for object parsing
From: Daniel Barkalow @ 2005-04-18  2:35 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git
In-Reply-To: <Pine.LNX.4.21.0504172229240.30848-100000@iabervon.org>

This adds the structs and function declarations for parsing git objects.

Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>
Index: blob.h
===================================================================
--- /dev/null  (tree:5ca133e1b74aee39b2124c0ec9fd51539babb5e0)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/blob.h  (mode:100644 sha1:9a23db3a7deca67981b67ceb768411e31f723715)
@@ -0,0 +1,14 @@
+#ifndef BLOB_H
+#define BLOB_H
+
+#include "object.h"
+
+extern const char *blob_type;
+
+struct blob {
+	struct object object;
+};
+
+struct blob *lookup_blob(unsigned char *sha1);
+
+#endif /* BLOB_H */
Index: commit.h
===================================================================
--- /dev/null  (tree:5ca133e1b74aee39b2124c0ec9fd51539babb5e0)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/commit.h  (mode:100644 sha1:8cd20b046875f5f7e534b0607fdd97f330f53272)
@@ -0,0 +1,27 @@
+#ifndef COMMIT_H
+#define COMMIT_H
+
+#include "object.h"
+#include "tree.h"
+
+struct commit_list {
+	struct commit *item;
+	struct commit_list *next;
+};
+
+struct commit {
+	struct object object;
+	unsigned long date;
+	struct commit_list *parents;
+	struct tree *tree;
+};
+
+extern const char *commit_type;
+
+struct commit *lookup_commit(unsigned char *sha1);
+
+int parse_commit(struct commit *item);
+
+void free_commit_list(struct commit_list *list);
+
+#endif /* COMMIT_H */
Index: object.h
===================================================================
--- /dev/null  (tree:5ca133e1b74aee39b2124c0ec9fd51539babb5e0)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/object.h  (mode:100644 sha1:20f879e0867b8d6a052c458d9230fbc7786d2864)
@@ -0,0 +1,29 @@
+#ifndef OBJECT_H
+#define OBJECT_H
+
+struct object_list {
+	struct object *item;
+	struct object_list *next;
+};
+
+struct object {
+	unsigned parsed : 1;
+	unsigned used : 1;
+	unsigned int flags;
+	unsigned char sha1[20];
+	const char *type;
+	struct object_list *refs;
+};
+
+int nr_objs;
+struct object **objs;
+
+struct object *lookup_object(unsigned char *sha1);
+
+void created_object(unsigned char *sha1, struct object *obj);
+
+void add_ref(struct object *refer, struct object *target);
+
+void mark_reachable(struct object *obj, unsigned int mask);
+
+#endif /* OBJECT_H */
Index: tree.h
===================================================================
--- /dev/null  (tree:5ca133e1b74aee39b2124c0ec9fd51539babb5e0)
+++ 1172a9b8f45b2fd640985595cc5258db3b027828/tree.h  (mode:100644 sha1:14ebbacded09d5e058c7f94652dcb9e12bc31cae)
@@ -0,0 +1,17 @@
+#ifndef TREE_H
+#define TREE_H
+
+#include "object.h"
+
+extern const char *tree_type;
+
+struct tree {
+	struct object object;
+	unsigned has_full_path : 1;
+};
+
+struct tree *lookup_tree(unsigned char *sha1);
+
+int parse_tree(struct tree *tree);
+
+#endif /* TREE_H */


^ permalink raw reply

* [0/5] Parsers for git objects, porting some programs
From: Daniel Barkalow @ 2005-04-18  2:33 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git
In-Reply-To: <Pine.LNX.4.21.0504172206460.30848-100000@iabervon.org>

This series introduces common parsers for objects, and ports the programs
that currently use revision.h to them.

 1: the header files
 2: the implementations
 3: port rev-tree
 4: port fsck-cache
 5: port merge-base

	-Daniel
*This .sig left intentionally blank*


^ permalink raw reply

* Re: [PATCH] "checkout-cache -m" writes unmerged contents for each stage.
From: Junio C Hamano @ 2005-04-18  2:19 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0504171833450.7211@ppc970.osdl.org>

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> On Sun, 17 Apr 2005, Junio C Hamano wrote:
>> 
>> This is the alternative strategy I mentioned in my previous
>> message.  A new -m option to checkout-cache causes it to store
>> contents of unmerged paths in path~1~, path~2~, and path~3~.

LT> I don't think this is wrong, but it all seems a bit hacky. The reason I 
LT> didn't apply your other patch was that I just don't feel quite comfortable 
LT> with what is the RightThing(tm) to do yet.

I do not personally like that '-m' thing either so please feel
free to drop it.  I was just toying with the idea.  I knew you
would not use "-m" yourself (and I would not myself either).
The patch was primarily meant for Pasky to raise his opinion.
If having something like this helps Cogito then he can keep it.
If Cogito will be doing the "show-files --unmerged" with
"cat-file blob" itself and this "checkout-cache -m" does not
help it that much then there is no point having this hack.

LT> I'm actually fairly certain that the right thing to do is to silently 
LT> ignore all unmerged entries. They just aren't "interesting" from a 
LT> checkout-cache perspective, least of all when given the "-a" flag. So even 
LT> warning about them seems to be pointless.

I do not mind your dropping the "warning" bit, but please keep
the skipping bit for "-a".  Dropping that TT from stage 1 into
the working directory and then complaining that TT exists when
it then tries to extract stage 2 and stage 3 is simply madness.

LT> What do you think? I can whip up a "merge-cache" program like that in five 
LT> minutes, and it _seems_ like the right interface..

Yes.  I think that is the right thing to do.  In fact the idea
is quite similar to what I've been working on, which is a
rewrite of that perl thing to use "read-tree -m O A B".


^ permalink raw reply

* Re: [RFC] General object parsing
From: Daniel Barkalow @ 2005-04-18  2:15 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git
In-Reply-To: <Pine.LNX.4.58.0504171807590.7211@ppc970.osdl.org>

On Sun, 17 Apr 2005, Linus Torvalds wrote:

> On Sun, 17 Apr 2005, Daniel Barkalow wrote:
> > 
> > Any comment on the design, or should I send my implementation?
> 
> Show the patches, and maybe I (and others) can make comments on the 
> thing.. It doesn't sound broken by design, the only question is how much 
> harder (if any) it is to use than the rather trivial "revision.h" which 
> gets us really small files.

I don't think it's much different in difficulty, plus it handles more
(parsing the objects more completely). They'll follow.

> In particular, is there some easy way to walk backwards by time? "git log"  
> definitely needs that, and merge-base clearly wants something similar. I
> also pretty much guarantee that visualization tools want that - creating a
> visual representation of the dag by time.

I think that should be easy, although I haven't written code to do it. If
you output the whole history, sorted by date, you obviously need to get 
the whole history, but I expect people will have some sort of pruning to
keep it down to a size they care about.

> But if there are simple helper functions to get the "next backwards in 
> time" case (by looking at the parent dates in a merge), then that should 
> be ok to do incrementally.

Haven't written that yet, but I can do so.

	-Daniel
*This .sig left intentionally blank*


^ permalink raw reply

* Re: SHA1 hash safety
From: Brian O'Mahoney @ 2005-04-18  2:07 UTC (permalink / raw)
  To: Horst von Brand; +Cc: ross, C. Scott Ananian, omb, David Lang, Ingo Molnar, git
In-Reply-To: <200504170635.j3H6Z0Ga005661@laptop11.inf.utfsm.cl>

Linus wants to drive ahead, and ignore the collision issue for now,
and has been dismissive of the risks, he wants a result not heart
searching, and the list comments exhibit a confusion with the
engineering problem of avoiding accidental collisions v deliberate sabotage.

Since this is not a show-stopper, and getting the BK replacement in place
is time critical, and if you look at the code it is easy to extend the
content key, LET US just leave this issue for now.

Horst von Brand wrote:
> ross@jose.lug.udel.edu said:
> 
> [...]
> 
> 
>>Linus has already weighed in that he doesn't give a crap.  All the
>>crypto-babble about collision whitepapers is uninteresting without a
>>repo that has real collisions.  git is far too cool as is - prove I
>>should be concerned.
> 
> 
> Just copy over a file (might be the first step in splitting it, or a
> header file that is duplicated for convenience, ...)

-- 
mit freundlichen Grüßen, Brian.

Dr. Brian O'Mahoney
Mobile +41 (0)79 334 8035 Email: omb@bluewin.ch
Bleicherstrasse 25, CH-8953 Dietikon, Switzerland
PGP Key fingerprint = 33 41 A2 DE 35 7C CE 5D  F5 14 39 C9 6D 38 56 D5

^ permalink raw reply

* Re: [PATCH] "checkout-cache -m" writes unmerged contents for each stage.
From: Linus Torvalds @ 2005-04-18  2:05 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v1x99vwdg.fsf@assigned-by-dhcp.cox.net>



On Sun, 17 Apr 2005, Junio C Hamano wrote:
>
> This is the alternative strategy I mentioned in my previous
> message.  A new -m option to checkout-cache causes it to store
> contents of unmerged paths in path~1~, path~2~, and path~3~.

I don't think this is wrong, but it all seems a bit hacky. The reason I 
didn't apply your other patch was that I just don't feel quite comfortable 
with what is the RightThing(tm) to do yet.

I'm actually fairly certain that the right thing to do is to silently 
ignore all unmerged entries. They just aren't "interesting" from a 
checkout-cache perspective, least of all when given the "-a" flag. So even 
warning about them seems to be pointless.

The other issue is that obviously we _do_ need to have some way to merge
them, but as far as I can tell, we've really got that already in
"show-files --unmerged"  together with "cat-file blob xxxx". I do believe 
that it's a damn ugly script, and that maybe we could create some helper 
plumbing to make it more obvious, but I haven't quite decided what the 
right helper interface would be.

Writing files to the current working directory I don't like, especially as
we don't even necessarily write all three files (so with your example
code, if there was a left-over xxx~1~ file from a previous merge, your
merger would really get confused now since it thinks it has an original
file that didn't actually really exist). So I'd much rather write them to
a /tmp directory instead, let the user merge them some way.

I'm actually thinking that maybe the _right_ interface is to do something 
like this:

	merge-cache <program> <filename>

and what that does is to look up the <filename> in the cache, and if it 
has any merge entries, unpack all of them (which may be just one file, of 
course) into up to three separate files (mkstemp()), and then execve the 
supplied program name with those three files as arguments 1,2,3 (empty 
argument if no file), and "filename" as argument 4.

So now the program could be a simple script:

	#!/bin/sh
	#
	# This is the git merge script, called with
	#
	#   $1 - original file (or empty string)
	#   $2 - file in branch1 (or empty string)
	#   $3 - file in branch2 (or empty string)
	#   $4 - pathname in repository
	#
	#
	# Case 1: file removed in both
	#
	if [ -z "$2" && -z "$3" ]; then
		rm -- "$4"
		update-cache --remove -- "$4"
		exit 0
	fi
	#
	# Case 2: file exists in just one
	#
	if [ -z "$2" || -z "$3" ] then
		cat "$2""$3" > "$4"
		update-cache --add -- "$4"
		exit 0
	fi
	#
	# Case 3: file exists in both
	#
	src="$1"
	if [ -z "$1" ]; then
		src=/den/null
	fi	
	merge "$3" "$src" "$2" && cp "$3" "$4" && update-cache --add -- "$4"

or you could so something fancier.

This would _seem_ to be a very simple way to generate a nice merge (the 
merge script can obviously be a lot smarter than the above thing, 
including doing nice graphical merge interfaces).

An extension of this might be to make "merge-cache" take several 
filenames, and merge them one at a time (stopping if the merge program 
returns a failure code). And obviously this also expands trivially to the 
normal "-a" case, which would do the same, except it would just call the 
merge program for any file it finds that needs merging)

What do you think? I can whip up a "merge-cache" program like that in five 
minutes, and it _seems_ like the right interface..

		Linus

^ permalink raw reply

* Re: [patch] fork optional branch point normazilation
From: Brad Roberts @ 2005-04-18  2:01 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git
In-Reply-To: <Pine.LNX.4.58.0504171806230.7211@ppc970.osdl.org>

The patch needed some tweaking, but not in the way you thought. :)

commit a6aa192641e9ea242332fee4916abf5ad2640d75
tree c69878b009ec2f505d75aa7d99e9ee30cd21ab02
parent 60e1274460f50bcecdc3f162b4fced9e5ebf2dfb
author Brad Roberts <braddr@puremagic.com> 1113789519 -0700
committer Brad Roberts <braddr@gameboy2> 1113789519 -0700

Fix remove_specials for real.  The second half logic needs the original
head of the string.

Signed-off-by: Brad Roberts <braddr@puremagic.com>

Index: commit-tree.c
===================================================================
--- 02cf6917da6297ff4f9172f7af174ba329f01b3d/commit-tree.c  (mode:100644 sha1:ec53a4565ec0033aaf6df2a48d233ccf4823e8b0)
+++ c69878b009ec2f505d75aa7d99e9ee30cd21ab02/commit-tree.c  (mode:100644 sha1:f41cda6f9496b9e33cb95305ef1093f846c663ae)
@@ -83,11 +83,11 @@
 static void remove_special(char *p)
 {
        char c;
-       char *dst = p;
+       char *dst = p, *src = p;

        for (;;) {
-               c = *p;
-               p++;
+               c = *src;
+               src++;
                switch(c) {
                case '\n': case '<': case '>':
                        continue;


Later,
Brad


^ permalink raw reply

* Re: using git directory cache code in darcs?
From: Paul Jackson @ 2005-04-18  2:00 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: lkml, git
In-Reply-To: <7vvf6lugw7.fsf@assigned-by-dhcp.cox.net>

Junio wrote:
> What Linus is saying is that he wants you to talk with git
> plumbing by invoking the executables he have, via system(3),
> popen(3), etc.

Hopefully, Linus didn't specify system(3) or popen(3) for production
software.

They are a rich source of security holes.  Inefficient, too, since they
invoke a shell process to interpret the command.

Use execve(2), or exevl(3), execle(3), execv(3).

Or if you really enjoy the path search, use execlp or execvp, but with
your own $PATH, not trusting the one passed in via the environment any
further than you can throw it.

However, on further consideration, I think Linus is wrong to recommend
that the git executables, not a libgit library, be the 'basic user level
on which all else is based."

I will reply to a Linus post, expounding on that thought further.

-- 
                  I won't rest till it's the best ...
                  Programmer, Linux Scalability
                  Paul Jackson <pj@engr.sgi.com> 1.650.933.1373, 1.925.600.0401

^ permalink raw reply

* [PATCH] remove_special() tentative fix.
From: Junio C Hamano @ 2005-04-18  1:51 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, Brad Roberts, git
In-Reply-To: <Pine.LNX.4.58.0504171806230.7211@ppc970.osdl.org>

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> On Mon, 18 Apr 2005, Petr Baudis wrote:
>> 
>> Am I just slow or does the first dst-- make it miss the last trailing
>> /[,;.]/?

LT> Hopefully not. It _should_ make it miss the last '\0', but hey, it got my
LT> usual amount of testing (ie none). I'm sure Brad can tell us whether it
LT> makes any difference..

No, you are both slow ;-)  At that point p is not the beginning
of the input anymore.  This is a *tentative* fix to implement
your intended solution.

I have a suspicion that your intended solution would not work on
systems that really use these GECOS subfields, though.  These
commas are there to separate subfields and your intended
solution would keep the office numbers etc. as part of commiter
name.  Honestly, I think your COMMITTER_* environment variable
idea is far better than playing games like this, although at the
same time I sympathize your not wanting to encourage people to
lie about the committer identity.

Signed-off-by: Junio C Hamano <junkio@cox.net> 
---

cd /opt/packrat/playpen/public/in-place/git/git/
show-diff commit-tree.c
commit-tree.c: ec53a4565ec0033aaf6df2a48d233ccf4823e8b0
--- commit-tree.c
+++ commit-tree.c	2005-04-17 18:43:39.000000000 -0700
@@ -83,6 +83,7 @@ static void finish_buffer(char *tag, cha
 static void remove_special(char *p)
 {
 	char c;
+	char *begin = p;
 	char *dst = p;
 
 	for (;;) {
@@ -102,7 +103,7 @@ static void remove_special(char *p)
 	 * have commas etc in their gecos field
 	 */
 	dst--;
-	while (--dst >= p) {
+	while (--dst >= begin) {
 		unsigned char c = *dst;
 		switch (c) {
 		case ',': case ';': case '.':

Compilation finished at Sun Apr 17 18:44:55


^ permalink raw reply

* Re: [4/5] Add option for hardlinkable cache of extracted blobs
From: Petr Baudis @ 2005-04-18  1:48 UTC (permalink / raw)
  To: Paul Jackson; +Cc: barkalow, git
In-Reply-To: <20050417183508.15beb1fd.pj@sgi.com>

Dear diary, on Mon, Apr 18, 2005 at 03:35:08AM CEST, I got a letter
where Paul Jackson <pj@sgi.com> told me that...
> Petr wrote:
> > The documentation I've got says:
> > 
> > "R_OK,  W_OK  and  X_OK request checking whether the file exists and has
> >  read, write and execute permissions, respectively.  F_OK just requests
> >  checking for the existence of the file."
> 
> You don't exactly say it, but I'm guessing that you think that this
> documentation is stating that F_OK checks for the existance of the file
> _regardless_ of path access permissions.
> 
> No so.  Write your own little test program, and/or read the kernel source.
> 
> Even if the file exists, if its directory entry is not accessible to the
> _real_ uid/gid, access F_OK will fail.  If the problem is a lack of
> seach permissions on some directory in the path, the errno will be
> EACCES.

Ok, I stand corrected; and when giving the access(2) manual page a
second look, it could imply that too. It has some room for more
crystal-clearness, though. ;-)

Thanks,

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: full kernel history, in patchset format
From: David Woodhouse @ 2005-04-18  1:36 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, Ingo Molnar, git
In-Reply-To: <Pine.LNX.4.58.0504171816040.7211@ppc970.osdl.org>

On Sun, 2005-04-17 at 18:16 -0700, Linus Torvalds wrote:
> Alternatively, you can have just the rev-tree cache of them. That's what
> it was designed for (along with avoiding to have to read 60,000 commits).

Purely from a conceptual POV I'd be a little happier with the history
just ending with a parent pointer to a commit object which is absent,
rather than having commit objects which point to _trees_ which are
absent. But I suppose I can't really justify that, and I'm not overly
bothered about it either.

The important thing to get right at this point is that the tree we all
work with should refer to the history, regardless of how we choose to
prune it. The current linux-2.6.git tree has a parentless commit for the
2.6.12-rc2 import, which is bad. We should start with Thomas' git tree
representing the real history, and work from that. You don't even need
to see his tree; you only need the final sha1 hash of the commit in his
tree which matches 2.6.12-rc2, so you can use that as the 'parent' of
the first change you import yourself.

-- 
dwmw2


^ permalink raw reply

* Re: [4/5] Add option for hardlinkable cache of extracted blobs
From: Paul Jackson @ 2005-04-18  1:35 UTC (permalink / raw)
  To: Petr Baudis; +Cc: barkalow, git
In-Reply-To: <20050417201856.GJ1461@pasky.ji.cz>

Petr wrote:
> The documentation I've got says:
> 
> "R_OK,  W_OK  and  X_OK request checking whether the file exists and has
>  read, write and execute permissions, respectively.  F_OK just requests
>  checking for the existence of the file."

You don't exactly say it, but I'm guessing that you think that this
documentation is stating that F_OK checks for the existance of the file
_regardless_ of path access permissions.

No so.  Write your own little test program, and/or read the kernel source.

Even if the file exists, if its directory entry is not accessible to the
_real_ uid/gid, access F_OK will fail.  If the problem is a lack of
seach permissions on some directory in the path, the errno will be
EACCES.

-- 
                  I won't rest till it's the best ...
                  Programmer, Linux Scalability
                  Paul Jackson <pj@engr.sgi.com> 1.650.933.1373, 1.925.600.0401

^ permalink raw reply

* Re: Re-done kernel archive - real one?
From: randy_dunlap @ 2005-04-18  1:33 UTC (permalink / raw)
  To: David Woodhouse; +Cc: torvalds, git, hpa
In-Reply-To: <1113780105.11910.4.camel@localhost.localdomain>

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

On Mon, 18 Apr 2005 09:21:45 +1000 David Woodhouse wrote:

| On Sun, 2005-04-17 at 15:22 -0700, randy_dunlap wrote:
| > David did the commits-mailing-list script and I'm working on a
| > commits web-page like what was formerly seen at:
| > http://www.kernel.org/pub/linux/kernel/v2.6/testing/cset/
| > (with daily tarball)
| > 
| > based on some older scripts from David, however I'm wondering if
| > a variant of the gitlog.sh script wouldn't be a better starting
| > point for it.
| 
| My commits-list script is in fact based on gitlog.sh. You'll probably
| find useful things to crib from in both that and the original
| bkexport.sh script.

Yep, already had all of that in progress.

| The commits script also wants updating to print the date properly now
| that we've changed how it's stored -- I'll try to find some time this
| week to update it and set it running on master.kernel.org again, but it
| may end up waiting till after LCA.

Here's a working gitgenwebpage.sh script, although it may be possible
to do it better/faster, and merge it with the commits mail script
(as you mentioned).


---
~Randy

[-- Attachment #2: gitgenwebpage.sh --]
[-- Type: application/x-sh, Size: 4282 bytes --]

^ permalink raw reply

* Re: [4/5] Add option for hardlinkable cache of extracted blobs
From: Paul Jackson @ 2005-04-18  1:24 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: pasky, git
In-Reply-To: <Pine.LNX.4.21.0504171600310.30848-100000@iabervon.org>

> So it shouldn't complain about a filename which you're allowed to try to
> stat, even if there's nothing there.

I'm not sure what 'nothing there' means to you.

To me, it means 'no file there', so no you would not be allowed
to stat it - and should fail ENOENT.

> And it would depend on the privs of
> the wrong user in looking at the path.

Yup.

-- 
                  I won't rest till it's the best ...
                  Programmer, Linux Scalability
                  Paul Jackson <pj@engr.sgi.com> 1.650.933.1373, 1.925.600.0401

^ permalink raw reply

* Re: [4/5] Add option for hardlinkable cache of extracted blobs
From: Paul Jackson @ 2005-04-18  1:20 UTC (permalink / raw)
  To: Petr Baudis; +Cc: barkalow, git
In-Reply-To: <20050417195935.GI1461@pasky.ji.cz>

Petr wrote:
> Does this distinction have any effect when doing F_OK?

Well, yeah.  If only one of real or effective id's could traverse the
path (execute perm on directories), then you'd get the wrong answer.

-- 
                  I won't rest till it's the best ...
                  Programmer, Linux Scalability
                  Paul Jackson <pj@engr.sgi.com> 1.650.933.1373, 1.925.600.0401

^ permalink raw reply

* Re: full kernel history, in patchset format
From: Linus Torvalds @ 2005-04-18  1:16 UTC (permalink / raw)
  To: Petr Baudis; +Cc: David Woodhouse, Ingo Molnar, git
In-Reply-To: <20050418003526.GD1461@pasky.ji.cz>



On Mon, 18 Apr 2005, Petr Baudis wrote:

> Dear diary, on Mon, Apr 18, 2005 at 02:06:43AM CEST, I got a letter
> where David Woodhouse <dwmw2@infradead.org> told me that...
> > On Mon, 2005-04-18 at 01:39 +0200, Petr Baudis wrote:
> > > Of course an entirely different thing are _trees_ associated with those
> > > commits. As long as you stay with a simple three-way merge, you
> > > basically never want to look at trees which aren't heads and which you
> > > don't specifically request to look at. And the trees and what they carry
> > > inside is the main bulk of data.
> > 
> > If the trees are absent and you're trying to merge, what do you gain
> > from having the commit objects?
> 
> merge-base

Alternatively, you can have just the rev-tree cache of them. That's what
it was designed for (along with avoiding to have to read 60,000 commits).

		Linus

^ permalink raw reply

* Re: [RFC] General object parsing
From: Linus Torvalds @ 2005-04-18  1:15 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: Petr Baudis, git
In-Reply-To: <Pine.LNX.4.21.0504171958520.30848-100000@iabervon.org>



On Sun, 17 Apr 2005, Daniel Barkalow wrote:
> 
> Any comment on the design, or should I send my implementation?

Show the patches, and maybe I (and others) can make comments on the 
thing.. It doesn't sound broken by design, the only question is how much 
harder (if any) it is to use than the rather trivial "revision.h" which 
gets us really small files.

In particular, is there some easy way to walk backwards by time? "git log"  
definitely needs that, and merge-base clearly wants something similar. I
also pretty much guarantee that visualization tools want that - creating a
visual representation of the dag by time.

If you need to read the whole thing to get that representation, then 
trying to be clever isn't even worth it - it's such a common thing that I 
bet rev-tree + caches is actually way superior.

But if there are simple helper functions to get the "next backwards in 
time" case (by looking at the parent dates in a merge), then that should 
be ok to do incrementally.

			Linus

^ permalink raw reply

* Re: SHA1 hash safety
From: Horst von Brand @ 2005-04-17  6:35 UTC (permalink / raw)
  To: ross; +Cc: C. Scott Ananian, omb, David Lang, Ingo Molnar, git
In-Reply-To: <20050416154951.GB13373@jose.lug.udel.edu>

ross@jose.lug.udel.edu said:

[...]

> Linus has already weighed in that he doesn't give a crap.  All the
> crypto-babble about collision whitepapers is uninteresting without a
> repo that has real collisions.  git is far too cool as is - prove I
> should be concerned.

Just copy over a file (might be the first step in splitting it, or a
header file that is duplicated for convenience, ...)
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox