{"thread":{"id":"275","subject":"[PATCH 0/5] Better merge-base, alternative transport programs","startedAt":"2005-04-24T00:03:13Z","lastAt":"2005-04-24T12:43:18Z","messageCount":12,"participants":["Daniel Barkalow","Linus Torvalds","Andreas Gal","Petr Baudis"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"1440","messageId":"Pine.LNX.4.21.0504231953490.30848-100000@iabervon.org","threadId":"275","inReplyTo":null,"subject":"[PATCH 0/5] Better merge-base, alternative transport programs","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-24T00:03:13Z","receivedAt":"2005-04-24T00:03:13Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This series contains three patches to add functionality to the library\nroutines necessary for the rest of the series, a patch to change the\nmerge-base implementation such that it always returns one of its arguments\nwhen possible (by way of using the date-based algorithm), and a patch to\nsupport fetching what is needed from a repository by HTTP, and both\npushing and pulling by ssh.\n\n 1: Add some functions for commit lists\n 2: Parse tree objects completely\n 3: Add some functions related to files\n 4: Replace merge-base\n 5: Add push and pull programs\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"1441","messageId":"Pine.LNX.4.21.0504232003490.30848-100000@iabervon.org","threadId":"275","inReplyTo":"Pine.LNX.4.21.0504231953490.30848-100000@iabervon.org","subject":"[PATCH 1/5] Add some functions for commit lists","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-24T00:07:09Z","receivedAt":"2005-04-24T00:07:09Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This adds a function for inserting an item in a commit list, a function\nfor sorting a commit list by date, and a function for progressively\nscanning a commit history from most recent to least recent.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: commit.c\n===================================================================\n--- 329aca984ad6d06eb6d2dffae3933f00ccb8df5a/commit.c  (mode:100644 sha1:9f0668eb68cec56a738a58fe930ae0ae2960e2b2)\n+++ e09a6d73a7c6c7a8bfb7e7003a34a507ed97a3b6/commit.c  (mode:100644 sha1:911f6435a74b93f6d25c6852d1814fa8dbaf626e)\n@@ -63,12 +63,9 @@\n \tbufptr += 46; /* \"tree \" + \"hex sha1\" + \"\\n\" */\n \twhile (!memcmp(bufptr, \"parent \", 7) &&\n \t       !get_sha1_hex(bufptr + 7, parent)) {\n-\t\tstruct commit_list *new_parent = \n-\t\t\tmalloc(sizeof(struct commit_list));\n-\t\tnew_parent->next = item->parents;\n-\t\tnew_parent->item = lookup_commit(parent);\n-\t\tadd_ref(&item->object, &new_parent->item->object);\n-\t\titem->parents = new_parent;\n+\t\tstruct commit *new_parent = lookup_commit(parent);\n+\t\tcommit_list_insert(new_parent, &item->parents);\n+\t\tadd_ref(&item->object, &new_parent->object);\n \t\tbufptr += 48;\n \t}\n \titem->date = parse_commit_date(bufptr);\n@@ -76,6 +73,14 @@\n \treturn 0;\n }\n \n+void commit_list_insert(struct commit *item, struct commit_list **list_p)\n+{\n+\tstruct commit_list *new_list = malloc(sizeof(struct commit_list));\n+\tnew_list->item = item;\n+\tnew_list->next = *list_p;\n+\t*list_p = new_list;\n+}\n+\n void free_commit_list(struct commit_list *list)\n {\n \twhile (list) {\n@@ -84,3 +89,44 @@\n \t\tfree(temp);\n \t}\n }\n+\n+static void insert_by_date(struct commit_list **list, struct commit *item)\n+{\n+\tstruct commit_list **pp = list;\n+\tstruct commit_list *p;\n+\twhile ((p = *pp) != NULL) {\n+\t\tif (p->item->date < item->date) {\n+\t\t\tbreak;\n+\t\t}\n+\t\tpp = &p->next;\n+\t}\n+\tcommit_list_insert(item, pp);\n+}\n+\n+\t\n+void sort_by_date(struct commit_list **list)\n+{\n+\tstruct commit_list *ret = NULL;\n+\twhile (*list) {\n+\t\tinsert_by_date(&ret, (*list)->item);\n+\t\t*list = (*list)->next;\n+\t}\n+\t*list = ret;\n+}\n+\n+struct commit *pop_most_recent_commit(struct commit_list **list)\n+{\n+\tstruct commit *ret = (*list)->item;\n+\tstruct commit_list *parents = ret->parents;\n+\tstruct commit_list *old = *list;\n+\n+\t*list = (*list)->next;\n+\tfree(old);\n+\n+\twhile (parents) {\n+\t\tparse_commit(parents->item);\n+\t\tinsert_by_date(list, parents->item);\n+\t\tparents = parents->next;\n+\t}\n+\treturn ret;\n+}\nIndex: commit.h\n===================================================================\n--- 329aca984ad6d06eb6d2dffae3933f00ccb8df5a/commit.h  (mode:100644 sha1:4afd27b1095cf9f9203c96db2b9f2b0bba5063d8)\n+++ e09a6d73a7c6c7a8bfb7e7003a34a507ed97a3b6/commit.h  (mode:100644 sha1:c8684d1cd07d7c9ed0af06a3f3d9e7b49fbed0a2)\n@@ -22,6 +22,15 @@\n \n int parse_commit(struct commit *item);\n \n+void commit_list_insert(struct commit *item, struct commit_list **list_p);\n+\n void free_commit_list(struct commit_list *list);\n \n+void sort_by_date(struct commit_list **list);\n+\n+/** Removes the first commit from a list sorted by date, and adds all\n+ * of its parents.\n+ **/\n+struct commit *pop_most_recent_commit(struct commit_list **list);\n+\n #endif /* COMMIT_H */\n\n"},{"id":"1442","messageId":"Pine.LNX.4.21.0504232007150.30848-100000@iabervon.org","threadId":"275","inReplyTo":"Pine.LNX.4.21.0504231953490.30848-100000@iabervon.org","subject":"[PATCH 2/5] Parse tree objects completely","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-24T00:10:33Z","receivedAt":"2005-04-24T00:10:33Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This adds the contents of trees to struct tree.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\ncommit af03ca2bdc01fdc2565c2914285d9c3ccb1205d3\ntree 144a13fb75a39538ec4578792d2c374c6ef50f46\nparent fda07b139124925a8000207fb1d91feec1fe675d\nauthor Daniel Barkalow <barkalow@iabervon.org> 1114296377 -0400\ncommitter Daniel Barkalow <barkalow@silva-tulga.(none)> 1114296377 -0400\n\n    Parse tree objects completely\n\nIndex: tree.c\n===================================================================\n--- e09a6d73a7c6c7a8bfb7e7003a34a507ed97a3b6/tree.c  (mode:100644 sha1:e988aed6a85d15568dcb93b69035b97a24e30cc9)\n+++ 144a13fb75a39538ec4578792d2c374c6ef50f46/tree.c  (mode:100644 sha1:79b9625855c017ce0298f62cc398ed4d16964cb1)\n@@ -92,6 +92,7 @@\n \tchar type[20];\n \tvoid *buffer, *bufptr;\n \tunsigned long size;\n+\tstruct tree_entry_list **list_p;\n \tif (item->object.parsed)\n \t\treturn 0;\n \titem->object.parsed = 1;\n@@ -103,8 +104,10 @@\n \tif (strcmp(type, tree_type))\n \t\treturn error(\"Object %s not a tree\",\n \t\t\t     sha1_to_hex(item->object.sha1));\n+\tlist_p = &item->entries;\n \twhile (size) {\n \t\tstruct object *obj;\n+\t\tstruct tree_entry_list *entry;\n \t\tint len = 1+strlen(bufptr);\n \t\tunsigned char *file_sha1 = bufptr + len;\n \t\tchar *path = strchr(bufptr, ' ');\n@@ -113,6 +116,12 @@\n \t\t    sscanf(bufptr, \"%o\", &mode) != 1)\n \t\t\treturn -1;\n \n+\t\tentry = malloc(sizeof(struct tree_entry_list));\n+\t\tentry->name = strdup(path + 1);\n+\t\tentry->directory = S_ISDIR(mode);\n+\t\tentry->executable = mode & S_IXUSR;\n+\t\tentry->next = NULL;\n+\n \t\t/* Warn about trees that don't do the recursive thing.. */\n \t\tif (strchr(path, '/')) {\n \t\t\titem->has_full_path = 1;\n@@ -121,12 +130,17 @@\n \t\tbufptr += len + 20;\n \t\tsize -= len + 20;\n \n-\t\tif (S_ISDIR(mode)) {\n-\t\t\tobj = &lookup_tree(file_sha1)->object;\n+\t\tif (entry->directory) {\n+\t\t\tentry->item.tree = lookup_tree(file_sha1);\n+\t\t\tobj = &entry->item.tree->object;\n \t\t} else {\n-\t\t\tobj = &lookup_blob(file_sha1)->object;\n+\t\t\tentry->item.blob = lookup_blob(file_sha1);\n+\t\t\tobj = &entry->item.blob->object;\n \t\t}\n \t\tadd_ref(&item->object, obj);\n+\n+\t\t*list_p = entry;\n+\t\tlist_p = &entry->next;\n \t}\n \treturn 0;\n }\nIndex: tree.h\n===================================================================\n--- e09a6d73a7c6c7a8bfb7e7003a34a507ed97a3b6/tree.h  (mode:100644 sha1:4d5496de307999f5ada8412259e0e86d2c8092de)\n+++ 144a13fb75a39538ec4578792d2c374c6ef50f46/tree.h  (mode:100644 sha1:19b190565957a7a03c34f7efa68a7fe0c6783d04)\n@@ -5,9 +5,21 @@\n \n extern const char *tree_type;\n \n+struct tree_entry_list {\n+\tstruct tree_entry_list *next;\n+\tunsigned directory : 1;\n+\tunsigned executable : 1;\n+\tchar *name;\n+\tunion {\n+\t\tstruct tree *tree;\n+\t\tstruct blob *blob;\n+\t} item;\n+};\n+\n struct tree {\n \tstruct object object;\n \tunsigned has_full_path : 1;\n+\tstruct tree_entry_list *entries;\n };\n \n struct tree *lookup_tree(unsigned char *sha1);\n\n"},{"id":"1445","messageId":"Pine.LNX.4.21.0504232010360.30848-100000@iabervon.org","threadId":"275","inReplyTo":"Pine.LNX.4.21.0504231953490.30848-100000@iabervon.org","subject":"[PATCH 3/5] Additional functions for the objects database","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-24T00:15:54Z","receivedAt":"2005-04-24T00:15:54Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This adds two functions: one to check if an object is present in the local\ndatabase, and one to add an object to the local database by reading it\nfrom a file descriptor and checking its hash.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: cache.h\n===================================================================\n--- 144a13fb75a39538ec4578792d2c374c6ef50f46/cache.h  (mode:100644 sha1:bf30ac4741d2eeeb483079f566182505898082f3)\n+++ cae140a16189361d8c9f1f7e68ef519956fd26d9/cache.h  (mode:100644 sha1:794d676a5cf5c9a03309c4b368840f8707cfcf46)\n@@ -122,11 +122,16 @@\n extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);\n extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);\n extern int write_sha1_file(char *buf, unsigned len, unsigned char *return_sha1);\n+\n extern int check_sha1_signature(unsigned char *sha1, void *buf, unsigned long size, const char *type);\n \n /* Read a tree into the cache */\n extern int read_tree(void *buffer, unsigned long size, int stage);\n \n+extern int write_sha1_from_fd(const unsigned char *sha1, int fd);\n+\n+extern int has_sha1_file(const unsigned char *sha1);\n+\n /* Convert to/from hex/sha1 representation */\n extern int get_sha1_hex(const char *hex, unsigned char *sha1);\n extern char *sha1_to_hex(const unsigned char *sha1);\t/* static buffer result! */\nIndex: sha1_file.c\n===================================================================\n--- 144a13fb75a39538ec4578792d2c374c6ef50f46/sha1_file.c  (mode:100644 sha1:66308ede85c2dad6b184fb74a7215b06a173d8f7)\n+++ cae140a16189361d8c9f1f7e68ef519956fd26d9/sha1_file.c  (mode:100644 sha1:97a515a073fec5870dfaaa279868ce9330853d3d)\n@@ -328,3 +328,75 @@\n \tclose(fd);\n \treturn 0;\n }\n+\n+int write_sha1_from_fd(const unsigned char *sha1, int fd)\n+{\n+\tchar *filename = sha1_file_name(sha1);\n+\n+\tint local;\n+\tz_stream stream;\n+\tunsigned char real_sha1[20];\n+\tchar buf[4096];\n+\tchar discard[4096];\n+\tint ret;\n+\tSHA_CTX c;\n+\n+\tlocal = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);\n+\n+\tif (local < 0)\n+\t\treturn error(\"Couldn't open %s\\n\", filename);\n+\n+\tmemset(&stream, 0, sizeof(stream));\n+\n+\tinflateInit(&stream);\n+\n+\tSHA1_Init(&c);\n+\n+\tdo {\n+\t\tssize_t size;\n+\t\tsize = read(fd, buf, 4096);\n+\t\tif (size <= 0) {\n+\t\t\tclose(local);\n+\t\t\tunlink(filename);\n+\t\t\tif (!size)\n+\t\t\t\treturn error(\"Connection closed?\");\n+\t\t\tperror(\"Reading from connection\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\twrite(local, buf, size);\n+\t\tstream.avail_in = size;\n+\t\tstream.next_in = buf;\n+\t\tdo {\n+\t\t\tstream.next_out = discard;\n+\t\t\tstream.avail_out = sizeof(discard);\n+\t\t\tret = inflate(&stream, Z_SYNC_FLUSH);\n+\t\t\tSHA1_Update(&c, discard, sizeof(discard) -\n+\t\t\t\t    stream.avail_out);\n+\t\t} while (stream.avail_in && ret == Z_OK);\n+\t\t\n+\t} while (ret == Z_OK);\n+\tinflateEnd(&stream);\n+\n+\tclose(local);\n+\tSHA1_Final(real_sha1, &c);\n+\tif (ret != Z_STREAM_END) {\n+\t\tunlink(filename);\n+\t\treturn error(\"File %s corrupted\", sha1_to_hex(sha1));\n+\t}\n+\tif (memcmp(sha1, real_sha1, 20)) {\n+\t\tunlink(filename);\n+\t\treturn error(\"File %s has bad hash\\n\", sha1_to_hex(sha1));\n+\t}\n+\t\n+\treturn 0;\n+}\n+\n+int has_sha1_file(const unsigned char *sha1)\n+{\n+\tchar *filename = sha1_file_name(sha1);\n+\tstruct stat st;\n+\n+\tif (!stat(filename, &st))\n+\t\treturn 1;\n+\treturn 0;\n+}\n\n"},{"id":"1446","messageId":"Pine.LNX.4.21.0504232016010.30848-100000@iabervon.org","threadId":"275","inReplyTo":"Pine.LNX.4.21.0504231953490.30848-100000@iabervon.org","subject":"[PATCH 4/5] Replace merge-base implementation","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-24T00:18:28Z","receivedAt":"2005-04-24T00:18:28Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"The old implementation was a nice algorithm, but, unfortunately, it could\nbe confused in some cases and would not necessarily do the obvious thing\nif one argument was decended from the other. This version fixes that by\nchanging the criterion to the most recent common ancestor.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: merge-base.c\n===================================================================\n--- cae140a16189361d8c9f1f7e68ef519956fd26d9/merge-base.c  (mode:100644 sha1:ac1153bc5646cb2d515ff206b759f4a79e90273a)\n+++ 9b75904eab1300d83264a1840d396160482fee88/merge-base.c  (mode:100644 sha1:0e4c58ede915aca5719bbd12ecd1945f2f300590)\n@@ -5,67 +5,63 @@\n static struct commit *process_list(struct commit_list **list_p, int this_mark,\n \t\t\t\t   int other_mark)\n {\n-\tstruct commit_list *parent, *temp;\n-\tstruct commit_list *posn = *list_p;\n-\t*list_p = NULL;\n-\twhile (posn) {\n-\t\tparse_commit(posn->item);\n-\t\tif (posn->item->object.flags & this_mark) {\n-\t\t\t/*\n-\t\t\t  printf(\"%d already seen %s %x\\n\",\n-\t\t\t  this_mark\n-\t\t\t  sha1_to_hex(posn->parent->sha1),\n-\t\t\t  posn->parent->flags);\n-\t\t\t*/\n-\t\t\t/* do nothing; this indicates that this side\n-\t\t\t * split and reformed, and we only need to\n-\t\t\t * mark it once.\n-\t\t\t */\n-\t\t} else if (posn->item->object.flags & other_mark) {\n-\t\t\treturn posn->item;\n-\t\t} else {\n-\t\t\t/*\n-\t\t\t  printf(\"%d based on %s\\n\",\n-\t\t\t  this_mark,\n-\t\t\t  sha1_to_hex(posn->parent->sha1));\n-\t\t\t*/\n-\t\t\tposn->item->object.flags |= this_mark;\n-\t\t\t\n-\t\t\tparent = posn->item->parents;\n-\t\t\twhile (parent) {\n-\t\t\t\ttemp = malloc(sizeof(struct commit_list));\n-\t\t\t\ttemp->next = *list_p;\n-\t\t\t\ttemp->item = parent->item;\n-\t\t\t\t*list_p = temp;\n-\t\t\t\tparent = parent->next;\n-\t\t\t}\n-\t\t}\n-\t\tposn = posn->next;\n+\tstruct commit *item = (*list_p)->item;\n+\t\n+\tif (item->object.flags & this_mark) {\n+\t\t/*\n+\t\t  printf(\"%d already seen %s %x\\n\",\n+\t\t  this_mark\n+\t\t  sha1_to_hex(posn->parent->sha1),\n+\t\t  posn->parent->flags);\n+\t\t*/\n+\t\t/* do nothing; this indicates that this side\n+\t\t * split and reformed, and we only need to\n+\t\t * mark it once.\n+\t\t */\n+\t\t*list_p = (*list_p)->next;\n+\t} else if (item->object.flags & other_mark) {\n+\t\treturn item;\n+\t} else {\n+\t\t/*\n+\t\t  printf(\"%d based on %s\\n\",\n+\t\t  this_mark,\n+\t\t  sha1_to_hex(posn->parent->sha1));\n+\t\t*/\n+\t\tpop_most_recent_commit(list_p);\n+\t\titem->object.flags |= this_mark;\n \t}\n \treturn NULL;\n }\n \n struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)\n {\n-\tstruct commit_list *rev1list = malloc(sizeof(struct commit_list));\n-\tstruct commit_list *rev2list = malloc(sizeof(struct commit_list));\n+\tstruct commit_list *rev1list = NULL;\n+\tstruct commit_list *rev2list = NULL;\n \n-\trev1list->item = rev1;\n-\trev1list->next = NULL;\n+\tcommit_list_insert(rev1, &rev1list);\n+\tcommit_list_insert(rev2, &rev2list);\n \n-\trev2list->item = rev2;\n-\trev2list->next = NULL;\n+\tparse_commit(rev1);\n+\tparse_commit(rev2);\n \n \twhile (rev1list || rev2list) {\n \t\tstruct commit *ret;\n-\t\tret = process_list(&rev1list, 0x1, 0x2);\n-\t\tif (ret) {\n-\t\t\t/* XXXX free lists */\n-\t\t\treturn ret;\n+\t\tif (!rev1list) {\n+\t\t\t// process 2\n+\t\t\tret = process_list(&rev2list, 0x2, 0x1);\n+\t\t} else if (!rev2list) {\n+\t\t\t// process 1\n+\t\t\tret = process_list(&rev1list, 0x1, 0x2);\n+\t\t} else if (rev1list->item->date < rev2list->item->date) {\n+\t\t\t// process 2\n+\t\t\tret = process_list(&rev2list, 0x2, 0x1);\n+\t\t} else {\n+\t\t\t// process 1\n+\t\t\tret = process_list(&rev1list, 0x1, 0x2);\n \t\t}\n-\t\tret = process_list(&rev2list, 0x2, 0x1);\n \t\tif (ret) {\n-\t\t\t/* XXXX free lists */\n+\t\t\tfree_commit_list(rev1list);\n+\t\t\tfree_commit_list(rev2list);\n \t\t\treturn ret;\n \t\t}\n \t}\n\n"},{"id":"1448","messageId":"Pine.LNX.4.21.0504232018330.30848-100000@iabervon.org","threadId":"275","inReplyTo":"Pine.LNX.4.21.0504231953490.30848-100000@iabervon.org","subject":"[PATCH 5/5] Various transport programs","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-24T00:24:39Z","receivedAt":"2005-04-24T00:24:39Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This patch adds three similar and related programs. http-pull downloads\nobjects from an HTTP server; rpull downloads objects by using ssh and\nrpush on the other side; and rpush uploads objects by using ssh and rpull\non the other side.\n\nThe algorithm should be sufficient to make the network throughput required\ndepend only on how much content is new, not at all on how much content the\nrepository contains.\n\nThe combination should enable people to have remote repositories by way of\nssh login for authenticated users and HTTP for anonymous access.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: Makefile\n===================================================================\n--- 9b75904eab1300d83264a1840d396160482fee88/Makefile  (mode:100644 sha1:57e70239503466fb3a77f1f2618ee64377e8e04b)\n+++ a56d8adaecc49ce7f26536f9f5d54ec813072e4f/Makefile  (mode:100644 sha1:b60d8eb691f4edd56d5b310b0dd670e98c852228)\n@@ -16,7 +16,7 @@\n PROG=   update-cache show-diff init-db write-tree read-tree commit-tree \\\n \tcat-file fsck-cache checkout-cache diff-tree rev-tree show-files \\\n \tcheck-files ls-tree merge-base merge-cache unpack-file git-export \\\n-\tdiff-cache convert-cache\n+\tdiff-cache convert-cache http-pull rpush rpull\n \n all: $(PROG)\n \n@@ -51,7 +51,13 @@\n init-db: init-db.o\n \n %: %.o $(LIB_FILE)\n-\t$(CC) $(CFLAGS) -o $@ $< $(LIBS)\n+\t$(CC) $(CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)\n+\n+rpush: rsh.o\n+\n+rpull: rsh.o\n+\n+http-pull: LIBS += -lcurl\n \n blob.o: $(LIB_H)\n cat-file.o: $(LIB_H)\n@@ -80,6 +86,9 @@\n usage.o: $(LIB_H)\n unpack-file.o: $(LIB_H)\n write-tree.o: $(LIB_H)\n+http-pull.o: $(LIB_H)\n+rpull.o: $(LIB_H)\n+rpush.o: $(LIB_H)\n \n clean:\n \trm -f *.o mozilla-sha1/*.o ppc/*.o $(PROG) $(LIB_FILE)\nIndex: http-pull.c\n===================================================================\n--- /dev/null  (tree:9b75904eab1300d83264a1840d396160482fee88)\n+++ a56d8adaecc49ce7f26536f9f5d54ec813072e4f/http-pull.c  (mode:100644 sha1:a17225719c53508a37905618c624ad8c4d0372ec)\n@@ -0,0 +1,204 @@\n+#include <fcntl.h>\n+#include <unistd.h>\n+#include <string.h>\n+#include <stdlib.h>\n+#include \"cache.h\"\n+#include \"commit.h\"\n+#include <errno.h>\n+#include <stdio.h>\n+\n+#include <curl/curl.h>\n+#include <curl/easy.h>\n+\n+static CURL *curl;\n+\n+static char *base;\n+\n+static int tree = 0;\n+static int commits = 0;\n+static int all = 0;\n+\n+static SHA_CTX c;\n+static z_stream stream;\n+\n+static int local;\n+static int zret;\n+\n+static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, \n+\t\t\t       void *data) {\n+\tchar expn[4096];\n+\tsize_t size = eltsize * nmemb;\n+\tint posn = 0;\n+\tdo {\n+\t\tssize_t retval = write(local, ptr + posn, size - posn);\n+\t\tif (retval < 0)\n+\t\t\treturn posn;\n+\t\tposn += retval;\n+\t} while (posn < size);\n+\n+\tstream.avail_in = size;\n+\tstream.next_in = ptr;\n+\tdo {\n+\t\tstream.next_out = expn;\n+\t\tstream.avail_out = sizeof(expn);\n+\t\tzret = inflate(&stream, Z_SYNC_FLUSH);\n+\t\tSHA1_Update(&c, expn, sizeof(expn) - stream.avail_out);\n+\t} while (stream.avail_in && zret == Z_OK);\n+\treturn size;\n+}\n+\n+static int fetch(unsigned char *sha1)\n+{\n+\tchar *hex = sha1_to_hex(sha1);\n+\tchar *filename = sha1_file_name(sha1);\n+\tchar real_sha1[20];\n+\tchar *url;\n+\tchar *posn;\n+\n+\tif (has_sha1_file(sha1)) {\n+\t\treturn 0;\n+\t}\n+\n+\tlocal = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);\n+\n+\tif (local < 0)\n+\t\treturn error(\"Couldn't open %s\\n\", filename);\n+\n+\tmemset(&stream, 0, sizeof(stream));\n+\n+\tinflateInit(&stream);\n+\n+\tSHA1_Init(&c);\n+\n+\tcurl_easy_setopt(curl, CURLOPT_FILE, NULL);\n+\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);\n+\n+\turl = malloc(strlen(base) + 50);\n+\tstrcpy(url, base);\n+\tposn = url + strlen(base);\n+\tstrcpy(posn, \"objects/\");\n+\tposn += 8;\n+\tmemcpy(posn, hex, 2);\n+\tposn += 2;\n+\t*(posn++) = '/';\n+\tstrcpy(posn, hex + 2);\n+\n+\tcurl_easy_setopt(curl, CURLOPT_URL, url);\n+\n+\t/*printf(\"Getting %s\\n\", hex);*/\n+\n+\tif (curl_easy_perform(curl))\n+\t\treturn error(\"Couldn't get %s for %s\\n\", url, hex);\n+\n+\tclose(local);\n+\tinflateEnd(&stream);\n+\tSHA1_Final(real_sha1, &c);\n+\tif (zret != Z_STREAM_END) {\n+\t\tunlink(filename);\n+\t\treturn error(\"File %s (%s) corrupt\\n\", hex, url);\n+\t}\n+\tif (memcmp(sha1, real_sha1, 20)) {\n+\t\tunlink(filename);\n+\t\treturn error(\"File %s has bad hash\\n\", hex);\n+\t}\n+\t\n+\treturn 0;\n+}\n+\n+static int process_tree(unsigned char *sha1)\n+{\n+\tstruct tree *tree = lookup_tree(sha1);\n+\tstruct tree_entry_list *entries;\n+\n+\tif (parse_tree(tree))\n+\t\treturn -1;\n+\n+\tfor (entries = tree->entries; entries; entries = entries->next) {\n+\t\tif (fetch(entries->item.tree->object.sha1))\n+\t\t\treturn -1;\n+\t\tif (entries->directory) {\n+\t\t\tif (process_tree(entries->item.tree->object.sha1))\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int process_commit(unsigned char *sha1)\n+{\n+\tstruct commit *obj = lookup_commit(sha1);\n+\n+\tif (fetch(sha1))\n+\t\treturn -1;\n+\n+\tif (parse_commit(obj))\n+\t\treturn -1;\n+\n+\tif (tree) {\n+\t\tif (fetch(obj->tree->object.sha1))\n+\t\t\treturn -1;\n+\t\tif (process_tree(obj->tree->object.sha1))\n+\t\t\treturn -1;\n+\t\tif (!all)\n+\t\t\ttree = 0;\n+\t}\n+\tif (commits) {\n+\t\tstruct commit_list *parents = obj->parents;\n+\t\tfor (; parents; parents = parents->next) {\n+\t\t\tif (has_sha1_file(parents->item->object.sha1))\n+\t\t\t\tcontinue;\n+\t\t\tif (fetch(parents->item->object.sha1)) {\n+\t\t\t\t/* The server might not have it, and\n+\t\t\t\t * we don't mind. \n+\t\t\t\t */\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (process_commit(parents->item->object.sha1))\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tchar *commit_id;\n+\tchar *url;\n+\tint arg = 1;\n+\tunsigned char sha1[20];\n+\n+\twhile (arg < argc && argv[arg][0] == '-') {\n+\t\tif (argv[arg][1] == 't') {\n+\t\t\ttree = 1;\n+\t\t} else if (argv[arg][1] == 'c') {\n+\t\t\tcommits = 1;\n+\t\t} else if (argv[arg][1] == 'a') {\n+\t\t\tall = 1;\n+\t\t\ttree = 1;\n+\t\t\tcommits = 1;\n+\t\t}\n+\t\targ++;\n+\t}\n+\tif (argc < arg + 2) {\n+\t\tusage(\"http-pull [-c] [-t] [-a] commit-id url\");\n+\t\treturn 1;\n+\t}\n+\tcommit_id = argv[arg];\n+\turl = argv[arg + 1];\n+\n+\tget_sha1_hex(commit_id, sha1);\n+\n+\tcurl_global_init(CURL_GLOBAL_ALL);\n+\n+\tcurl = curl_easy_init();\n+\n+\tbase = url;\n+\n+\tif (fetch(sha1))\n+\t\treturn 1;\n+\tif (process_commit(sha1))\n+\t\treturn 1;\n+\n+\tcurl_global_cleanup();\n+\treturn 0;\n+}\nIndex: rpull.c\n===================================================================\n--- /dev/null  (tree:9b75904eab1300d83264a1840d396160482fee88)\n+++ a56d8adaecc49ce7f26536f9f5d54ec813072e4f/rpull.c  (mode:100644 sha1:c27af2c2464de28732b8ad1fff3ed8a0804250d6)\n@@ -0,0 +1,128 @@\n+#include <fcntl.h>\n+#include <unistd.h>\n+#include <string.h>\n+#include <stdlib.h>\n+#include \"cache.h\"\n+#include \"commit.h\"\n+#include <errno.h>\n+#include <stdio.h>\n+#include \"rsh.h\"\n+\n+static int tree = 0;\n+static int commits = 0;\n+static int all = 0;\n+\n+static int fd_in;\n+static int fd_out;\n+\n+static int fetch(unsigned char *sha1)\n+{\n+\tif (has_sha1_file(sha1))\n+\t\treturn 0;\n+\twrite(fd_out, sha1, 20);\n+\treturn write_sha1_from_fd(sha1, fd_in);\n+}\n+\n+static int process_tree(unsigned char *sha1)\n+{\n+\tstruct tree *tree = lookup_tree(sha1);\n+\tstruct tree_entry_list *entries;\n+\n+\tif (parse_tree(tree))\n+\t\treturn -1;\n+\n+\tfor (entries = tree->entries; entries; entries = entries->next) {\n+\t\t/*\n+\t\t  fprintf(stderr, \"Tree %s \", sha1_to_hex(sha1));\n+\t\t  fprintf(stderr, \"needs %s\\n\", \n+\t\t  sha1_to_hex(entries->item.tree->object.sha1));\n+\t\t*/\n+\t\tif (fetch(entries->item.tree->object.sha1)) {\n+\t\t\treturn error(\"Missing item %s\",\n+\t\t\t\t     sha1_to_hex(entries->item.tree->object.sha1));\n+\t\t}\n+\t\tif (entries->directory) {\n+\t\t\tif (process_tree(entries->item.tree->object.sha1))\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int process_commit(unsigned char *sha1)\n+{\n+\tstruct commit *obj = lookup_commit(sha1);\n+\n+\tif (fetch(sha1)) {\n+\t\treturn error(\"Fetching %s\", sha1_to_hex(sha1));\n+\t}\n+\n+\tif (parse_commit(obj))\n+\t\treturn -1;\n+\n+\tif (tree) {\n+\t\tif (fetch(obj->tree->object.sha1))\n+\t\t\treturn -1;\n+\t\tif (process_tree(obj->tree->object.sha1))\n+\t\t\treturn -1;\n+\t\tif (!all)\n+\t\t\ttree = 0;\n+\t}\n+\tif (commits) {\n+\t\tstruct commit_list *parents = obj->parents;\n+\t\tfor (; parents; parents = parents->next) {\n+\t\t\tif (has_sha1_file(parents->item->object.sha1))\n+\t\t\t\tcontinue;\n+\t\t\tif (fetch(parents->item->object.sha1)) {\n+\t\t\t\t/* The server might not have it, and\n+\t\t\t\t * we don't mind. \n+\t\t\t\t */\n+\t\t\t\terror(\"Missing tree %s; continuing\", \n+\t\t\t\t      sha1_to_hex(parents->item->object.sha1));\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (process_commit(parents->item->object.sha1))\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tchar *commit_id;\n+\tchar *url;\n+\tint arg = 1;\n+\tunsigned char sha1[20];\n+\n+\twhile (arg < argc && argv[arg][0] == '-') {\n+\t\tif (argv[arg][1] == 't') {\n+\t\t\ttree = 1;\n+\t\t} else if (argv[arg][1] == 'c') {\n+\t\t\tcommits = 1;\n+\t\t} else if (argv[arg][1] == 'a') {\n+\t\t\tall = 1;\n+\t\t\ttree = 1;\n+\t\t\tcommits = 1;\n+\t\t}\n+\t\targ++;\n+\t}\n+\tif (argc < arg + 2) {\n+\t\tusage(\"rpull [-c] [-t] [-a] commit-id url\");\n+\t\treturn 1;\n+\t}\n+\tcommit_id = argv[arg];\n+\turl = argv[arg + 1];\n+\n+\tif (setup_connection(&fd_in, &fd_out, \"rpush\", url, arg, argv + 1))\n+\t\treturn 1;\n+\n+\tget_sha1_hex(commit_id, sha1);\n+\n+\tif (fetch(sha1))\n+\t\treturn 1;\n+\tif (process_commit(sha1))\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\nIndex: rpush.c\n===================================================================\n--- /dev/null  (tree:9b75904eab1300d83264a1840d396160482fee88)\n+++ a56d8adaecc49ce7f26536f9f5d54ec813072e4f/rpush.c  (mode:100644 sha1:0293a1a46311d7e20b13177143741ab9d6d0d201)\n@@ -0,0 +1,69 @@\n+#include \"cache.h\"\n+#include \"rsh.h\"\n+#include <sys/socket.h>\n+#include <errno.h>\n+\n+void service(int fd_in, int fd_out) {\n+\tssize_t size;\n+\tint posn;\n+\tchar sha1[20];\n+\tunsigned long objsize;\n+\tvoid *buf;\n+\tdo {\n+\t\tposn = 0;\n+\t\tdo {\n+\t\t\tsize = read(fd_in, sha1 + posn, 20 - posn);\n+\t\t\tif (size < 0) {\n+\t\t\t\tperror(\"rpush: read \");\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tif (!size)\n+\t\t\t\treturn;\n+\t\t\tposn += size;\n+\t\t} while (posn < 20);\n+\n+\t\t/* fprintf(stderr, \"Serving %s\\n\", sha1_to_hex(sha1)); */\n+\n+\t\tbuf = map_sha1_file(sha1, &objsize);\n+\t\tif (!buf) {\n+\t\t\tfprintf(stderr, \"rpush: could not find %s\\n\", \n+\t\t\t\tsha1_to_hex(sha1));\n+\t\t\treturn;\n+\t\t}\n+\t\tposn = 0;\n+\t\tdo {\n+\t\t\tsize = write(fd_out, buf + posn, objsize - posn);\n+\t\t\tif (size <= 0) {\n+\t\t\t\tif (!size) {\n+\t\t\t\t\tfprintf(stderr, \"rpush: write closed\");\n+\t\t\t\t} else {\n+\t\t\t\t\tperror(\"rpush: write \");\n+\t\t\t\t}\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tposn += size;\n+\t\t} while (posn < objsize);\n+\t} while (1);\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tint arg = 1;\n+        char *commit_id;\n+        char *url;\n+\tint fd_in, fd_out;\n+\twhile (arg < argc && argv[arg][0] == '-') {\n+                arg++;\n+        }\n+        if (argc < arg + 2) {\n+                usage(\"rpush [-c] [-t] [-a] commit-id url\");\n+                return 1;\n+        }\n+\tcommit_id = argv[arg];\n+\turl = argv[arg + 1];\n+\tif (setup_connection(&fd_in, &fd_out, \"rpull\", url, arg, argv + 1))\n+\t\treturn 1;\n+\n+\tservice(fd_in, fd_out);\n+\treturn 0;\n+}\nIndex: rsh.c\n===================================================================\n--- /dev/null  (tree:9b75904eab1300d83264a1840d396160482fee88)\n+++ a56d8adaecc49ce7f26536f9f5d54ec813072e4f/rsh.c  (mode:100644 sha1:4d6a90bf6c1b290975fb2ac22f25979be56cb476)\n@@ -0,0 +1,63 @@\n+#include \"rsh.h\"\n+\n+#include <string.h>\n+#include <sys/socket.h>\n+\n+#include \"cache.h\"\n+\n+#define COMMAND_SIZE 4096\n+\n+int setup_connection(int *fd_in, int *fd_out, char *remote_prog, \n+\t\t     char *url, int rmt_argc, char **rmt_argv)\n+{\n+\tchar *host;\n+\tchar *path;\n+\tint sv[2];\n+\tchar command[COMMAND_SIZE];\n+\tchar *posn;\n+\tint i;\n+\n+\tif (!strcmp(url, \"-\")) {\n+\t\t*fd_in = 0;\n+\t\t*fd_out = 1;\n+\t\treturn 0;\n+\t}\n+\n+\thost = strstr(url, \"//\");\n+\tif (!host) {\n+\t\treturn error(\"Bad URL: %s\", url);\n+\t}\n+\thost += 2;\n+\tpath = strchr(host, '/');\n+\tif (!path) {\n+\t\treturn error(\"Bad URL: %s\", url);\n+\t}\n+\t*(path++) = '\\0';\n+\t/* ssh <host> 'cd /<path>; stdio-pull <arg...> <commit-id>' */\n+\tsnprintf(command, COMMAND_SIZE, \n+\t\t \"cd /%s; SHA1_FILE_DIRECTORY=objects %s\",\n+\t\t path, remote_prog);\n+\tposn = command + strlen(command);\n+\tfor (i = 0; i < rmt_argc; i++) {\n+\t\t*(posn++) = ' ';\n+\t\tstrncpy(posn, rmt_argv[i], COMMAND_SIZE - (posn - command));\n+\t\tposn += strlen(rmt_argv[i]);\n+\t\tif (posn - command + 4 >= COMMAND_SIZE) {\n+\t\t\treturn error(\"Command line too long\");\n+\t\t}\n+\t}\n+\tstrcpy(posn, \" -\");\n+\tif (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {\n+\t\treturn error(\"Couldn't create socket\");\n+\t}\n+\tif (!fork()) {\n+\t\tclose(sv[1]);\n+\t\tdup2(sv[0], 0);\n+\t\tdup2(sv[0], 1);\n+\t\texeclp(\"ssh\", \"ssh\", host, command, NULL);\n+\t}\n+\tclose(sv[0]);\n+\t*fd_in = sv[1];\n+\t*fd_out = sv[1];\n+\treturn 0;\n+}\nIndex: rsh.h\n===================================================================\n--- /dev/null  (tree:9b75904eab1300d83264a1840d396160482fee88)\n+++ a56d8adaecc49ce7f26536f9f5d54ec813072e4f/rsh.h  (mode:100644 sha1:97e4f20b2b80662269827d77f3104025143087e7)\n@@ -0,0 +1,7 @@\n+#ifndef RSH_H\n+#define RSH_H\n+\n+int setup_connection(int *fd_in, int *fd_out, char *remote_prog, \n+\t\t     char *url, int rmt_argc, char **rmt_argv);\n+\n+#endif\n\n"},{"id":"1462","messageId":"Pine.LNX.4.58.0504231906110.2344@ppc970.osdl.org","threadId":"275","inReplyTo":"Pine.LNX.4.21.0504232003490.30848-100000@iabervon.org","subject":"Re: [PATCH 1/5] Add some functions for commit lists","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-04-24T02:12:38Z","receivedAt":"2005-04-24T02:12:38Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 23 Apr 2005, Daniel Barkalow wrote:\n>\n> This adds a function for inserting an item in a commit list, a function\n> for sorting a commit list by date, and a function for progressively\n> scanning a commit history from most recent to least recent.\n\nOk. This is more in like with what I was hoping for, looks good.\n\nAll patches applied and pushed out, and I wrote a trivial \"rev-list\" thing \nthat is kind of a cut-down rev-tree which just lists the commits in the \norder the \"fake time order\".\n\nThe \"fake time order\" just uses this progressive commit history scan, \nwhich is different from the old \"sort by date\" in that it still takes \nparenthood into account, and always shows the child first.\n\nIt turns out that since git is so damn fast, when I commit a mbox of \npatches, they often all get the same date, since we \"only\" do dates with a \none-second granularity. So sorting by date ends up doing strange things, \nwhen some of the entries have no sort order.\n\nDaniel's date-based incremental scanning solves this problem, and also \nmeans that we get output immediately without having to parse the whole \ntree down to the root.\n\nSo with this, git-pasky should probably do the following..\n\n\t\t\tLinus\n\n-\nMake gitlog.sh use the new simple time-based commit traversal\nhelpers.\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n\ngitlog.sh: a496a864f9586e47a4d7bd3ae0af0b3e07b7deb8\n--- a/gitlog.sh\n+++ b/gitlog.sh\n@@ -11,7 +11,7 @@\n \n base=$(gitXnormid.sh -c $1) || exit 1\n \n-rev-tree $base | sort -rn | while read time commit parents; do\n+rev-list $base | while read commit; do\n \techo commit ${commit%:*};\n \tcat-file commit $commit | \\\n \t\twhile read key rest; do\n"},{"id":"1464","messageId":"Pine.LNX.4.58.0504231916300.2344@ppc970.osdl.org","threadId":"275","inReplyTo":"Pine.LNX.4.58.0504231906110.2344@ppc970.osdl.org","subject":"Re: [PATCH 1/5] Add some functions for commit lists","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-04-24T02:20:55Z","receivedAt":"2005-04-24T02:20:55Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 23 Apr 2005, Linus Torvalds wrote:\n> \n> Ok. This is more in like with what I was hoping for, looks good.\n\nOh, Daniel, I notice that you have the same old bug: it will happily add \nthe same parent to the list several times. You need to prune them out, and \nignore things you've seen.\n\nI pushed out the fix (don't parse and add parents to the list that were \nalready parsed).\n\n\t\tLinus\n"},{"id":"1465","messageId":"Pine.LNX.4.21.0504232230080.30848-100000@iabervon.org","threadId":"275","inReplyTo":"Pine.LNX.4.58.0504231916300.2344@ppc970.osdl.org","subject":"Re: [PATCH 1/5] Add some functions for commit lists","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-24T02:40:40Z","receivedAt":"2005-04-24T02:40:40Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 23 Apr 2005, Linus Torvalds wrote:\n\n> \n> \n> On Sat, 23 Apr 2005, Linus Torvalds wrote:\n> > \n> > Ok. This is more in like with what I was hoping for, looks good.\n> \n> Oh, Daniel, I notice that you have the same old bug: it will happily add \n> the same parent to the list several times. You need to prune them out, and \n> ignore things you've seen.\n>\n> I pushed out the fix (don't parse and add parents to the list that were \n> already parsed).\n\nThis won't actually work for merge-base, which wants to run two of these,\none for each head, in parallel, and find the first commit on both lists. I\nthink making insert_by_date() ignore items already in the list is a better\nsolution, although that might run into problems if there's a complicated\ngraph of commits all with the same time.\n\nAnother option is to specify a object.flags bit to mark for each commit\nand ignore commits that are already marked.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"1468","messageId":"Pine.LNX.4.21.0504232257390.30848-100000@iabervon.org","threadId":"275","inReplyTo":"Pine.LNX.4.21.0504232230080.30848-100000@iabervon.org","subject":"[PATCH] Allow multiple date-ordered lists","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-24T02:59:46Z","receivedAt":"2005-04-24T02:59:46Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"Make pop_most_recent_commit() return the same objects multiple times, but only\nif called with different bits to mark.\n\nThis is necessary to make merge-base work again.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\n\n---\ncommit 58ec99a22e3a8dac158d9949b0a704752991ac8a\ntree 6f24c9b481d76e067d64bac1a8dbd5cf5d0dfb05\nparent f4adf2687593e8d6e58ac1c4710e0385a82500e5\nauthor Daniel Barkalow <barkalow@iabervon.org> 1114311416 -0400\ncommitter Daniel Barkalow <barkalow@silva-tulga.(none)> 1114311416 -0400\n\nIndex: commit.c\n===================================================================\n--- 34933617a2e8284ffca6ab2a1b2f00d6996a58e7/commit.c  (mode:100644 sha1:0243e77cb8e839e2972a2882bb1d0719f6e3cff1)\n+++ 6f24c9b481d76e067d64bac1a8dbd5cf5d0dfb05/commit.c  (mode:100644 sha1:2502688262819033f5b8ed60a7bef5eed0aa2d6a)\n@@ -114,7 +114,8 @@\n \t*list = ret;\n }\n \n-struct commit *pop_most_recent_commit(struct commit_list **list)\n+struct commit *pop_most_recent_commit(struct commit_list **list,\n+\t\t\t\t      unsigned int mark)\n {\n \tstruct commit *ret = (*list)->item;\n \tstruct commit_list *parents = ret->parents;\n@@ -125,8 +126,9 @@\n \n \twhile (parents) {\n \t\tstruct commit *commit = parents->item;\n-\t\tif (!commit->object.parsed) {\n-\t\t\tparse_commit(commit);\n+\t\tparse_commit(commit);\n+\t\tif (!(commit->object.flags & mark)) {\n+\t\t\tcommit->object.flags |= mark;\n \t\t\tinsert_by_date(list, commit);\n \t\t}\n \t\tparents = parents->next;\nIndex: commit.h\n===================================================================\n--- 34933617a2e8284ffca6ab2a1b2f00d6996a58e7/commit.h  (mode:100644 sha1:c8684d1cd07d7c9ed0af06a3f3d9e7b49fbed0a2)\n+++ 6f24c9b481d76e067d64bac1a8dbd5cf5d0dfb05/commit.h  (mode:100644 sha1:d61d084c89c72f4fe79c654db721df31c4f04224)\n@@ -31,6 +31,7 @@\n /** Removes the first commit from a list sorted by date, and adds all\n  * of its parents.\n  **/\n-struct commit *pop_most_recent_commit(struct commit_list **list);\n+struct commit *pop_most_recent_commit(struct commit_list **list, \n+\t\t\t\t      unsigned int mark);\n \n #endif /* COMMIT_H */\nIndex: merge-base.c\n===================================================================\n--- 34933617a2e8284ffca6ab2a1b2f00d6996a58e7/merge-base.c  (mode:100644 sha1:0e4c58ede915aca5719bbd12ecd1945f2f300590)\n+++ 6f24c9b481d76e067d64bac1a8dbd5cf5d0dfb05/merge-base.c  (mode:100644 sha1:2c40881302e586366f03ae6ac6e7c0035847e2f0)\n@@ -6,29 +6,11 @@\n \t\t\t\t   int other_mark)\n {\n \tstruct commit *item = (*list_p)->item;\n-\t\n-\tif (item->object.flags & this_mark) {\n-\t\t/*\n-\t\t  printf(\"%d already seen %s %x\\n\",\n-\t\t  this_mark\n-\t\t  sha1_to_hex(posn->parent->sha1),\n-\t\t  posn->parent->flags);\n-\t\t*/\n-\t\t/* do nothing; this indicates that this side\n-\t\t * split and reformed, and we only need to\n-\t\t * mark it once.\n-\t\t */\n-\t\t*list_p = (*list_p)->next;\n-\t} else if (item->object.flags & other_mark) {\n+\n+\tif (item->object.flags & other_mark) {\n \t\treturn item;\n \t} else {\n-\t\t/*\n-\t\t  printf(\"%d based on %s\\n\",\n-\t\t  this_mark,\n-\t\t  sha1_to_hex(posn->parent->sha1));\n-\t\t*/\n-\t\tpop_most_recent_commit(list_p);\n-\t\titem->object.flags |= this_mark;\n+\t\tpop_most_recent_commit(list_p, this_mark);\n \t}\n \treturn NULL;\n }\n@@ -39,7 +21,9 @@\n \tstruct commit_list *rev2list = NULL;\n \n \tcommit_list_insert(rev1, &rev1list);\n+\trev1->object.flags |= 0x1;\n \tcommit_list_insert(rev2, &rev2list);\n+\trev2->object.flags |= 0x2;\n \n \tparse_commit(rev1);\n \tparse_commit(rev2);\nIndex: rev-list.c\n===================================================================\n--- 34933617a2e8284ffca6ab2a1b2f00d6996a58e7/rev-list.c  (mode:100644 sha1:1c797d24a91b44994dc11180dd61c3ecf8f93349)\n+++ 6f24c9b481d76e067d64bac1a8dbd5cf5d0dfb05/rev-list.c  (mode:100644 sha1:77bfc29db1aad08ba9d7d87ce08d33d4a88e74e3)\n@@ -16,7 +16,7 @@\n \n \tcommit_list_insert(commit, &list);\n \tdo {\n-\t\tstruct commit *commit = pop_most_recent_commit(&list);\n+\t\tstruct commit *commit = pop_most_recent_commit(&list, 0x1);\n \t\tprintf(\"%s\\n\", sha1_to_hex(commit->object.sha1));\n \t} while (list);\n \treturn 0;\n\n"},{"id":"1470","messageId":"Pine.LNX.4.58.0504232022180.4690@sam.ics.uci.edu","threadId":"275","inReplyTo":"Pine.LNX.4.58.0504231906110.2344@ppc970.osdl.org","subject":"[PATCH] Add -u option to diff-cache to show UNCHANGED files","fromName":"Andreas Gal","fromEmail":"gal@uci.edu","sentAt":"2005-04-24T03:28:17Z","receivedAt":"2005-04-24T03:28:17Z","isPatch":true,"sender":{"key":"gal@uci.edu","avatar":null},"body":"\nWith -u diff-cache shows unchanged files, instead of files that changed. \nThis is useful to implement a \"git clean\" command that throws away all \nchecked out files that have not changed (yes, I really would like to \nhave that). One could also do show-files and then substract the \ndiff-cache output from it, but thats slow and clumsy. \n\nSigned-off-by: Andreas Gal <gal@uci.edu>\n\n--- b407d753e520fa0b1523d770d98b3015af197275/diff-cache.c\n+++ diff-cache.c\n@@ -2,6 +2,7 @@\n \n static int cached_only = 0;\n static int line_termination = '\\n';\n+static int show_unchanged = 0;\n \n /* A file entry went away or appeared */\n static void show_file(const char *prefix, struct cache_entry *ce)\n@@ -32,7 +33,7 @@\n \t}\n \n \toldmode = ntohl(old->ce_mode);\n-\tif (mode == oldmode && !memcmp(sha1, old->sha1, 20))\n+\tif ((mode == oldmode && !memcmp(sha1, old->sha1, 20)) != show_unchanged)\n \t\treturn 0;\n \n \tstrcpy(old_sha1_hex, sha1_to_hex(old->sha1));\n@@ -85,7 +86,7 @@\n \t}\n }\n \n-static char *diff_cache_usage = \"diff-cache [-r] [-z] [--cached] <tree sha1>\";\n+static char *diff_cache_usage = \"diff-cache [-r] [-u] [-z] [--cached] <tree sha1>\";\n \n int main(int argc, char **argv)\n {\n@@ -102,6 +103,10 @@\n \t\t\t/* We accept the -r flag just to look like diff-tree */\n \t\t\tcontinue;\n \t\t}\n+\t\tif (!strcmp(arg, \"-u\")) {\n+\t\t\tshow_unchanged = 1;\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (!strcmp(arg, \"-z\")) {\n \t\t\tline_termination = '\\0';\n \t\t\tcontinue;\n"},{"id":"1513","messageId":"20050424124318.GD1507@pasky.ji.cz","threadId":"275","inReplyTo":"Pine.LNX.4.58.0504232022180.4690@sam.ics.uci.edu","subject":"Re: [PATCH] Add -u option to diff-cache to show UNCHANGED files","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-24T12:43:18Z","receivedAt":"2005-04-24T12:43:18Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, Apr 24, 2005 at 05:28:17AM CEST, I got a letter\nwhere Andreas Gal <gal@uci.edu> told me that...\n> With -u diff-cache shows unchanged files, instead of files that changed. \n> This is useful to implement a \"git clean\" command that throws away all \n> checked out files that have not changed (yes, I really would like to \n> have that). One could also do show-files and then substract the \n> diff-cache output from it, but thats slow and clumsy. \n> \n> Signed-off-by: Andreas Gal <gal@uci.edu>\n\nI don't think this fits to diff-cache (since the output is basically\nnonsensical apart of the filename, right?). Maybe rather show-files?\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"}]}