{"thread":{"id":"86","subject":"[0/5] Patch set for various things","startedAt":"2005-04-17T15:20:26Z","lastAt":"2005-04-22T23:24:42Z","messageCount":37,"participants":["Daniel Barkalow","Petr Baudis","Linus Torvalds","Paul Jackson","Brad Roberts","tony.luck@intel.com","Martin Schlemmer"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"478","messageId":"Pine.LNX.4.21.0504171108060.30848-100000@iabervon.org","threadId":"86","inReplyTo":"20050417144947.GG1487@pasky.ji.cz","subject":"[0/5] Patch set for various things","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T15:20:26Z","receivedAt":"2005-04-17T15:20:26Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"Here are a bunch of patches which I made first against linus, that I've\nrebased against pasky because they're mostly more version-control-like.\n\n 1: Add a parsing function to revision.h\n 2: Add merge-base\n 3: Add http-pull\n 4: Add option to make a hardlinkable cache of extracted options\n 5: Add commit id to version info\n\nThis also served as a test of cleaning up a patch series with git; I took\nmy current working directory, diffed it against its common ancestor with\npasky (no longer current), split the patch into logical pieces, and \napplied them in sequence against the current pasky, committing after each\none. This gives a history as if I'd actually written the code just like I\nwould have had I known what I was doing in advance and done it very\nquickly this morning. I think this should work in the future as a way to\navoid having the global revision control keeping developers' local \nmistakes while keeping history the way the mainline saw the development.\n\nA thought for future work: it would be nice if I could identify commits\nthat were used in creating a commit, but which should not be tracked down\nunless you were unfortunate enough to have been exposed to them (in which\ncase you'd like know to deal with them).\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"479","messageId":"Pine.LNX.4.21.0504171120400.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171108060.30848-100000@iabervon.org","subject":"[1/5] Parsing code in revision.h","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T15:24:20Z","receivedAt":"2005-04-17T15:24:20Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This adds support to revision.h for parsing commit records (but not going\nany further than parsing a single record). Something like this is needed\nby anything that uses revision.h, but older programs open-code it.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: revision.h\n===================================================================\n--- 45f926575d2c44072bfcf2317dbf3f0fbb513a4e/revision.h  (mode:100644 sha1:28d0de3261a61f68e4e0948a25a416a515cd2e83)\n+++ 37a0b01b85c2999243674d48bfc71cdba0e5518e/revision.h  (mode:100644 sha1:523bde6e14e18bb0ecbded8f83ad4df93fc467ab)\n@@ -24,6 +24,7 @@\n \tunsigned int flags;\n \tunsigned char sha1[20];\n \tunsigned long date;\n+\tunsigned char tree[20];\n \tstruct parent *parent;\n };\n \n@@ -111,4 +112,29 @@\n \t}\n }\n \n+static int parse_commit_object(struct revision *rev)\n+{\n+\tif (!(rev->flags & SEEN)) {\n+\t\tvoid *buffer, *bufptr;\n+\t\tunsigned long size;\n+\t\tchar type[20];\n+\t\tunsigned char parent[20];\n+\n+\t\trev->flags |= SEEN;\n+\t\tbuffer = bufptr = read_sha1_file(rev->sha1, type, &size);\n+\t\tif (!buffer || strcmp(type, \"commit\"))\n+\t\t\treturn -1;\n+\t\tget_sha1_hex(bufptr + 5, rev->tree);\n+\t\tbufptr += 46; /* \"tree \" + \"hex sha1\" + \"\\n\" */\n+\t\twhile (!memcmp(bufptr, \"parent \", 7) && \n+\t\t       !get_sha1_hex(bufptr+7, parent)) {\n+\t\t\tadd_relationship(rev, parent);\n+\t\t\tbufptr += 48;   /* \"parent \" + \"hex sha1\" + \"\\n\" */\n+\t\t}\n+\t\t//rev->date = parse_commit_date(bufptr);\n+\t\tfree(buffer);\n+\t}\n+\treturn 0;\n+}\n+\n #endif /* REVISION_H */\n\n"},{"id":"481","messageId":"Pine.LNX.4.21.0504171124340.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171108060.30848-100000@iabervon.org","subject":"[2/5] Add merge-base","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T15:27:13Z","receivedAt":"2005-04-17T15:27:13Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"merge-base finds one of the best common ancestors of a pair of commits. In\nparticular, it finds one of the ones which is fewest commits away from the\nfurther of the heads.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: Makefile\n===================================================================\n--- 37a0b01b85c2999243674d48bfc71cdba0e5518e/Makefile  (mode:100644 sha1:346e3850de026485802e41e16a1180be2df85e4a)\n+++ d662b707e11391f6cfe597fd4d0bf9c41d34d01a/Makefile  (mode:100644 sha1:b2ce7c5b63fffca59653b980d98379909f893d44)\n@@ -14,7 +14,7 @@\n \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\n+\tcheck-files ls-tree merge-base\n \n SCRIPT=\tparent-id tree-id git gitXnormid.sh gitadd.sh gitaddremote.sh \\\n \tgitcommit.sh gitdiff-do gitdiff.sh gitlog.sh gitls.sh gitlsobj.sh \\\nIndex: merge-base.c\n===================================================================\n--- /dev/null  (tree:37a0b01b85c2999243674d48bfc71cdba0e5518e)\n+++ d662b707e11391f6cfe597fd4d0bf9c41d34d01a/merge-base.c  (mode:100644 sha1:0f85e7d9e9a896d1142a54170ddf1159f11f9cdd)\n@@ -0,0 +1,108 @@\n+#include <stdlib.h>\n+#include \"cache.h\"\n+#include \"revision.h\"\n+\n+struct revision *common_ancestor(struct revision *rev1, struct revision *rev2)\n+{\n+\tstruct parent *parent;\n+\n+\tstruct parent *rev1list = malloc(sizeof(struct parent));\n+\tstruct parent *rev2list = malloc(sizeof(struct parent));\n+        \n+\tstruct parent *posn, *temp;\n+\n+\trev1list->parent = rev1;\n+\trev1list->next = NULL;\n+\n+\trev2list->parent = rev2;\n+\trev2list->next = NULL;\n+\n+\twhile (rev1list || rev2list) {\n+\t\tposn = rev1list;\n+\t\trev1list = NULL;\n+\t\twhile (posn) {\n+\t\t\tparse_commit_object(posn->parent);\n+\t\t\tif (posn->parent->flags & 0x0001) {\n+\t\t\t\t/*\n+\t\t\t\tprintf(\"1 already seen %s %x\\n\",\n+\t\t\t\t       sha1_to_hex(posn->parent->sha1),\n+\t\t\t\t       posn->parent->flags);\n+\t\t\t\t*/\n+                                // do nothing\n+\t\t\t} else if (posn->parent->flags & 0x0002) {\n+                                // XXXX free lists\n+\t\t\t\treturn posn->parent;\n+\t\t\t} else {\n+\t\t\t\t/*\n+\t\t\t\tprintf(\"1 based on %s\\n\",\n+\t\t\t\t       sha1_to_hex(posn->parent->sha1));\n+\t\t\t\t*/\n+\t\t\t\tposn->parent->flags |= 0x0001;\n+\n+\t\t\t\tparent = posn->parent->parent;\n+\t\t\t\twhile (parent) {\n+\t\t\t\t\ttemp = malloc(sizeof(struct parent));\n+\t\t\t\t\ttemp->next = rev1list;\n+\t\t\t\t\ttemp->parent = parent->parent;\n+\t\t\t\t\trev1list = temp;\n+\t\t\t\t\tparent = parent->next;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tposn = posn->next;\n+\t\t}\n+\t\tposn = rev2list;\n+\t\trev2list = NULL;\n+\t\twhile (posn) {\n+\t\t\tparse_commit_object(posn->parent);\n+\t\t\tif (posn->parent->flags & 0x0002) {\n+\t\t\t\t/*\n+\t\t\t\tprintf(\"2 already seen %s\\n\",\n+\t\t\t\t       sha1_to_hex(posn->parent->sha1));\n+\t\t\t\t*/\n+                                // do nothing\n+\t\t\t} else if (posn->parent->flags & 0x0001) {\n+                                // XXXX free lists\n+\t\t\t\treturn posn->parent;\n+\t\t\t} else {\n+\t\t\t\t/*\n+\t\t\t\tprintf(\"2 based on %s\\n\",\n+\t\t\t\t       sha1_to_hex(posn->parent->sha1));\n+\t\t\t\t*/\n+\t\t\t\tposn->parent->flags |= 0x0002;\n+\n+\t\t\t\tparent = posn->parent->parent;\n+\t\t\t\twhile (parent) {\n+\t\t\t\t\ttemp = malloc(sizeof(struct parent));\n+\t\t\t\t\ttemp->next = rev2list;\n+\t\t\t\t\ttemp->parent = parent->parent;\n+\t\t\t\t\trev2list = temp;\n+\t\t\t\t\tparent = parent->next;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tposn = posn->next;\n+\t\t}\n+\t}\n+\treturn NULL;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tstruct revision *rev1, *rev2, *ret;\n+\tunsigned char rev1key[20], rev2key[20];\n+\tif (argc != 3 ||\n+\t    get_sha1_hex(argv[1], rev1key) ||\n+\t    get_sha1_hex(argv[2], rev2key)) {\n+\t\tusage(\"mergebase <commit-id> <commit-id>\");\n+\t}\n+\trev1 = lookup_rev(rev1key);\n+\trev2 = lookup_rev(rev2key);\n+\tret = common_ancestor(rev1, rev2);\n+\tif (ret) {\n+\t\tprintf(\"%s\\n\", sha1_to_hex(ret->sha1));\n+\t\treturn 0;\n+\t} else {\n+\t\tprintf(\"Sorry.\\n\");\n+\t\treturn 1;\n+\t}\n+\t\n+}\n\n"},{"id":"483","messageId":"Pine.LNX.4.21.0504171127160.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171108060.30848-100000@iabervon.org","subject":"[3/5] Add http-pull","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T15:31:16Z","receivedAt":"2005-04-17T15:31:16Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"http-pull is a program that downloads from a (normal) HTTP server a commit\nand all of the tree and blob objects it refers to (but not other commits,\netc.). Options could be used to make it download a larger or different\nselection of objects. It depends on libcurl, which I forgot to mention in\nthe README again.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: Makefile\n===================================================================\n--- d662b707e11391f6cfe597fd4d0bf9c41d34d01a/Makefile  (mode:100644 sha1:b2ce7c5b63fffca59653b980d98379909f893d44)\n+++ 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/Makefile  (mode:100644 sha1:940ef8578cf469354002cd8feaec25d907015267)\n@@ -14,7 +14,7 @@\n \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\n+\tcheck-files ls-tree http-pull merge-base\n \n SCRIPT=\tparent-id tree-id git gitXnormid.sh gitadd.sh gitaddremote.sh \\\n \tgitcommit.sh gitdiff-do gitdiff.sh gitlog.sh gitls.sh gitlsobj.sh \\\n@@ -35,6 +35,7 @@\n \n LIBS= -lssl -lz\n \n+http-pull: LIBS += -lcurl\n \n $(PROG):%: %.o $(COMMON)\n \t$(CC) $(CFLAGS) -o $@ $^ $(LIBS)\nIndex: http-pull.c\n===================================================================\n--- /dev/null  (tree:d662b707e11391f6cfe597fd4d0bf9c41d34d01a)\n+++ 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/http-pull.c  (mode:100644 sha1:106ca31239e6afe6784e7c592234406f5c149e44)\n@@ -0,0 +1,126 @@\n+#include <fcntl.h>\n+#include <unistd.h>\n+#include <string.h>\n+#include <stdlib.h>\n+#include \"cache.h\"\n+#include \"revision.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 fetch(unsigned char *sha1)\n+{\n+\tchar *hex = sha1_to_hex(sha1);\n+\tchar *filename = sha1_file_name(sha1);\n+\n+\tchar *url;\n+\tchar *posn;\n+\tFILE *local;\n+\tstruct stat st;\n+\n+\tif (!stat(filename, &st)) {\n+\t\treturn 0;\n+\t}\n+\n+\tlocal = fopen(filename, \"w\");\n+\n+\tif (!local) {\n+\t\tfprintf(stderr, \"Couldn't open %s\\n\", filename);\n+\t\treturn -1;\n+\t}\n+\n+\tcurl_easy_setopt(curl, CURLOPT_FILE, local);\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+\tcurl_easy_perform(curl);\n+\n+\tfclose(local);\n+\t\n+\treturn 0;\n+}\n+\n+static int process_tree(unsigned char *sha1)\n+{\n+\tvoid *buffer;\n+        unsigned long size;\n+        char type[20];\n+\n+        buffer = read_sha1_file(sha1, type, &size);\n+\tif (!buffer)\n+\t\treturn -1;\n+\tif (strcmp(type, \"tree\"))\n+\t\treturn -1;\n+\twhile (size) {\n+\t\tint len = strlen(buffer) + 1;\n+\t\tunsigned char *sha1 = buffer + len;\n+\t\tunsigned int mode;\n+\t\tint retval;\n+\n+\t\tif (size < len + 20 || sscanf(buffer, \"%o\", &mode) != 1)\n+\t\t\treturn -1;\n+\n+\t\tbuffer = sha1 + 20;\n+\t\tsize -= len + 20;\n+\n+\t\tretval = fetch(sha1);\n+\t\tif (retval)\n+\t\t\treturn -1;\n+\n+\t\tif (S_ISDIR(mode)) {\n+\t\t\tretval = process_tree(sha1);\n+\t\t\tif (retval)\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 revision *rev = lookup_rev(sha1);\n+\tif (parse_commit_object(rev))\n+\t\treturn -1;\n+\t\n+\tfetch(rev->tree);\n+\tprocess_tree(rev->tree);\n+\treturn 0;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tchar *commit_id = argv[1];\n+\tchar *url = argv[2];\n+\n+\tunsigned char sha1[20];\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+\tfetch(sha1);\n+\tprocess_commit(sha1);\n+\n+\tcurl_global_cleanup();\n+\treturn 0;\n+}\n\n"},{"id":"484","messageId":"Pine.LNX.4.21.0504171131230.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171108060.30848-100000@iabervon.org","subject":"[4/5] Add option for hardlinkable cache of extracted blobs","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T15:35:19Z","receivedAt":"2005-04-17T15:35:19Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This adds an option (compile time, defined in the Makefile) to have a\ncache of extracted blobs so that different working directories can\nhardlink against them instead of creating new files for every\ncheckout. You should only use this if you're sure the programs you use\nbreak links on modification and you care about storing many large working\ndirectories with few changes at the same time.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: Makefile\n===================================================================\n--- 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/Makefile  (mode:100644 sha1:940ef8578cf469354002cd8feaec25d907015267)\n+++ 08f7700831e056ad710af69f91e3a8a705b6b2b1/Makefile  (mode:100644 sha1:a60fa46404c0487158d232bd021e4798bc8df8de)\n@@ -2,6 +2,9 @@\n # 1461501637330902918203684832716283019655932542976 hashes do not give you\n # enough guarantees about no collisions between objects ever hapenning.\n #\n+# -DUSE_HARDLINK_CACHE if you want a cache of files to be hardlinked\n+# to for unmodified checked out files.\n+#\n # -DNSEC if you want git to care about sub-second file mtimes and ctimes.\n # Note that you need some new glibc (at least >2.2.4) for this, and it will\n # BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly\nIndex: checkout-cache.c\n===================================================================\n--- 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/checkout-cache.c  (mode:100644 sha1:5d3028df0a45329e45fff2006719c9267adeb946)\n+++ 08f7700831e056ad710af69f91e3a8a705b6b2b1/checkout-cache.c  (mode:100644 sha1:338588259e17dd235fdc7db759d770004a760e15)\n@@ -34,6 +34,10 @@\n  */\n #include \"cache.h\"\n \n+#ifdef USE_HARDLINK_CACHE\n+#define HARDLINK_CACHE \".git/blobs\"\n+#endif /* USE_HARDLINK_CACHE */\n+\n static int force = 0, quiet = 0;\n \n static void create_directories(const char *path)\n@@ -67,6 +71,80 @@\n \treturn fd;\n }\n \n+#ifdef HARDLINK_CACHE\n+\n+/*\n+ * NOTE! This returns a statically allocated buffer, so you have to be\n+ * careful about using it. Do a \"strdup()\" if you need to save the\n+ * filename.\n+ */\n+char *sha1_blob_cache_file_name(const unsigned char *sha1)\n+{\n+\tint i;\n+\tstatic char *name, *base;\n+\n+\tif (!base) {\n+\t\tchar *sha1_file_directory = HARDLINK_CACHE;\n+\t\tint len = strlen(sha1_file_directory);\n+\t\tbase = malloc(len + 60);\n+\t\tmemcpy(base, sha1_file_directory, len);\n+\t\tmemset(base+len, 0, 60);\n+\t\tbase[len] = '/';\n+\t\tbase[len+3] = '/';\n+\t\tname = base + len + 1;\n+\t}\n+\tfor (i = 0; i < 20; i++) {\n+\t\tstatic char hex[] = \"0123456789abcdef\";\n+\t\tunsigned int val = sha1[i];\n+\t\tchar *pos = name + i*2 + (i > 0);\n+\t\t*pos++ = hex[val >> 4];\n+\t\t*pos = hex[val & 0xf];\n+\t}\n+\treturn base;\n+}\n+\n+static int write_entry(struct cache_entry *ce)\n+{\n+\tint fd;\n+\tvoid *new;\n+\tunsigned long size;\n+\tlong wrote;\n+\tchar type[20];\n+\tchar *cache_name;\n+\tstruct stat st;\n+\n+\tcache_name = sha1_blob_cache_file_name(ce->sha1);\n+\n+\tif (stat(cache_name, &st)) {\n+\t\tnew = read_sha1_file(ce->sha1, type, &size);\n+\t\tif (!new || strcmp(type, \"blob\")) {\n+\t\t\treturn error(\"checkout-cache: unable to read sha1 file of %s (%s)\",\n+\t\t\t\t     ce->name, sha1_to_hex(ce->sha1));\n+\t\t}\n+\t\tfd = create_file(cache_name, ntohl(ce->ce_mode));\n+\t\tif (fd < 0) {\n+\t\t\tfree(new);\n+\t\t\treturn error(\"checkout-cache: unable to create %s (%s)\",\n+\t\t\t\t     ce->name, strerror(errno));\n+\t\t}\n+\t\twrote = write(fd, new, size);\n+\t\tclose(fd);\n+\t\tfree(new);\n+\t\tif (wrote != size)\n+\t\t\treturn error(\"checkout-cache: unable to write %s\", \n+\t\t\t\t     ce->name);\n+\t}\n+\tif (link(cache_name, ce->name)) {\n+\t\tif (errno == ENOENT) {\n+\t\t\tcreate_directories(ce->name);\n+\t\t\tlink(cache_name, ce->name);\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+#else\n+\n static int write_entry(struct cache_entry *ce)\n {\n \tint fd;\n@@ -94,6 +172,8 @@\n \treturn 0;\n }\n \n+#endif\n+\n static int checkout_entry(struct cache_entry *ce)\n {\n \tstruct stat st;\n\n"},{"id":"485","messageId":"Pine.LNX.4.21.0504171135240.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171108060.30848-100000@iabervon.org","subject":"[5/5] Add commit-id to version","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T15:37:37Z","receivedAt":"2005-04-17T15:37:37Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"For people who run intermediate versions of git, it is useful to know\nexactly which post-release version you've installed. This adds the\ncommit-id to the version info, so you can tell exactly, provided you make\nsure to commit before installing.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: Makefile\n===================================================================\n--- 08f7700831e056ad710af69f91e3a8a705b6b2b1/Makefile  (mode:100644 sha1:a60fa46404c0487158d232bd021e4798bc8df8de)\n+++ 6467ed39f19b48563ff25782ebe2c6f951b0af3c/Makefile  (mode:100644 sha1:0e84e3cd12f836602b420c197e08fabefe975493)\n@@ -50,7 +50,7 @@\n \t@echo Generating gitversion.sh...\n \t@rm -f $@\n \t@echo \"#!/bin/sh\" > $@\n-\t@echo \"echo \\\"$(shell cat $(VERSION))\\\"\" >> $@\n+\t@echo \"echo \\\"$(shell cat $(VERSION)) $(shell commit-id)\\\"\" >> $@\n \t@chmod +x $@\n \n clean:\n\n"},{"id":"488","messageId":"20050417160106.GI1487@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171124340.30848-100000@iabervon.org","subject":"Re: Add merge-base","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-17T16:01:06Z","receivedAt":"2005-04-17T16:01:06Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, Apr 17, 2005 at 05:27:13PM CEST, I got a letter\nwhere Daniel Barkalow <barkalow@iabervon.org> told me that...\n> merge-base finds one of the best common ancestors of a pair of commits. In\n> particular, it finds one of the ones which is fewest commits away from the\n> further of the heads.\n\nWhat does it return when I have\n\n  A -- C\n    \\/   \\\n    /\\   /\n  B -- D\n\n? >:)\n\nI assume just either A or B, randomly?\n\nI think it would be best if it could list all the \"first-class\" matches\n(both A and B in this case), each on a separate line; this way the\noverlay tools could choose an algorithm to evaluate those further as\nthey see fit - e.g. sort them by time (you might aid that by listing the\ncommit time in front of them), then take the first n and try to diff\nthem all and take the one with least changes (as suggested by Linus).\n\nAnd if someone doesn't care, he just does | head -n 1 | cut -f 2.\n\n> Index: merge-base.c\n> ===================================================================\n> --- /dev/null  (tree:37a0b01b85c2999243674d48bfc71cdba0e5518e)\n> +++ d662b707e11391f6cfe597fd4d0bf9c41d34d01a/merge-base.c  (mode:100644 sha1:0f85e7d9e9a896d1142a54170ddf1159f11f9cdd)\n> @@ -0,0 +1,108 @@\n> +#include <stdlib.h>\n> +#include \"cache.h\"\n> +#include \"revision.h\"\n> +\n> +struct revision *common_ancestor(struct revision *rev1, struct revision *rev2)\n> +{\n> +\tstruct parent *parent;\n> +\n> +\tstruct parent *rev1list = malloc(sizeof(struct parent));\n> +\tstruct parent *rev2list = malloc(sizeof(struct parent));\n\nDid I overlook anything or you could have just a single revlist?\n\n> +        \n\nI smell trailing whitespaces!\n\n> +\tstruct parent *posn, *temp;\n> +\n> +\trev1list->parent = rev1;\n> +\trev1list->next = NULL;\n> +\n> +\trev2list->parent = rev2;\n> +\trev2list->next = NULL;\n> +\n> +\twhile (rev1list || rev2list) {\n> +\t\tposn = rev1list;\n> +\t\trev1list = NULL;\n> +\t\twhile (posn) {\n> +\t\t\tparse_commit_object(posn->parent);\n> +\t\t\tif (posn->parent->flags & 0x0001) {\n> +\t\t\t\t/*\n> +\t\t\t\tprintf(\"1 already seen %s %x\\n\",\n> +\t\t\t\t       sha1_to_hex(posn->parent->sha1),\n> +\t\t\t\t       posn->parent->flags);\n> +\t\t\t\t*/\n> +                                // do nothing\n\nMostly for consistency, I'd prefer you to use /* */ comments in general.\n\nI think a terrified squeak at stderr in this situation (possibly\nsuggesting fsck-cache) might be appropriate.\n\n> +\t\t\t} else if (posn->parent->flags & 0x0002) {\n> +                                // XXXX free lists\n\nHmm, so, why not free the lists?\n\n> +\t\t\t\treturn posn->parent;\n> +\t\t\t} else {\n> +\t\t\t\t/*\n> +\t\t\t\tprintf(\"1 based on %s\\n\",\n> +\t\t\t\t       sha1_to_hex(posn->parent->sha1));\n> +\t\t\t\t*/\n> +\t\t\t\tposn->parent->flags |= 0x0001;\n> +\n> +\t\t\t\tparent = posn->parent->parent;\n> +\t\t\t\twhile (parent) {\n> +\t\t\t\t\ttemp = malloc(sizeof(struct parent));\n> +\t\t\t\t\ttemp->next = rev1list;\n> +\t\t\t\t\ttemp->parent = parent->parent;\n> +\t\t\t\t\trev1list = temp;\n> +\t\t\t\t\tparent = parent->next;\n> +\t\t\t\t}\n> +\t\t\t}\n> +\t\t\tposn = posn->next;\n> +\t\t}\n> +\t\tposn = rev2list;\n> +\t\trev2list = NULL;\n> +\t\twhile (posn) {\n> +\t\t\tparse_commit_object(posn->parent);\n> +\t\t\tif (posn->parent->flags & 0x0002) {\n> +\t\t\t\t/*\n> +\t\t\t\tprintf(\"2 already seen %s\\n\",\n> +\t\t\t\t       sha1_to_hex(posn->parent->sha1));\n> +\t\t\t\t*/\n> +                                // do nothing\n> +\t\t\t} else if (posn->parent->flags & 0x0001) {\n> +                                // XXXX free lists\n> +\t\t\t\treturn posn->parent;\n> +\t\t\t} else {\n> +\t\t\t\t/*\n> +\t\t\t\tprintf(\"2 based on %s\\n\",\n> +\t\t\t\t       sha1_to_hex(posn->parent->sha1));\n> +\t\t\t\t*/\n> +\t\t\t\tposn->parent->flags |= 0x0002;\n> +\n> +\t\t\t\tparent = posn->parent->parent;\n> +\t\t\t\twhile (parent) {\n> +\t\t\t\t\ttemp = malloc(sizeof(struct parent));\n> +\t\t\t\t\ttemp->next = rev2list;\n> +\t\t\t\t\ttemp->parent = parent->parent;\n> +\t\t\t\t\trev2list = temp;\n> +\t\t\t\t\tparent = parent->next;\n> +\t\t\t\t}\n> +\t\t\t}\n> +\t\t\tposn = posn->next;\n> +\t\t}\n\nSymmetrical notes apply to this half. Actually, they are too similar.\nWhat about factoring them to a common function?\n\n> +\t}\n> +\treturn NULL;\n> +}\n> +\n> +int main(int argc, char **argv)\n> +{\n> +\tstruct revision *rev1, *rev2, *ret;\n> +\tunsigned char rev1key[20], rev2key[20];\n\nA newline here please.\n\n> +\tif (argc != 3 ||\n> +\t    get_sha1_hex(argv[1], rev1key) ||\n> +\t    get_sha1_hex(argv[2], rev2key)) {\n> +\t\tusage(\"mergebase <commit-id> <commit-id>\");\n> +\t}\n> +\trev1 = lookup_rev(rev1key);\n> +\trev2 = lookup_rev(rev2key);\n> +\tret = common_ancestor(rev1, rev2);\n> +\tif (ret) {\n> +\t\tprintf(\"%s\\n\", sha1_to_hex(ret->sha1));\n> +\t\treturn 0;\n> +\t} else {\n> +\t\tprintf(\"Sorry.\\n\");\n> +\t\treturn 1;\n\nPlease stay silent if you don't have anything useful to say.\n\n> +\t}\n> +\t\n> +}\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"},{"id":"491","messageId":"20050417160929.GJ1487@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171120400.30848-100000@iabervon.org","subject":"Re: Parsing code in revision.h","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-17T16:09:29Z","receivedAt":"2005-04-17T16:09:29Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, Apr 17, 2005 at 05:24:20PM CEST, I got a letter\nwhere Daniel Barkalow <barkalow@iabervon.org> told me that...\n> This adds support to revision.h for parsing commit records (but not going\n> any further than parsing a single record). Something like this is needed\n> by anything that uses revision.h, but older programs open-code it.\n> \n> Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>\n\nCould you please convert the current users (rev-tree.c and fsck-cache.c)\nto use this in the same patch?\n\n> Index: revision.h\n> ===================================================================\n> --- 45f926575d2c44072bfcf2317dbf3f0fbb513a4e/revision.h  (mode:100644 sha1:28d0de3261a61f68e4e0948a25a416a515cd2e83)\n> +++ 37a0b01b85c2999243674d48bfc71cdba0e5518e/revision.h  (mode:100644 sha1:523bde6e14e18bb0ecbded8f83ad4df93fc467ab)\n> @@ -24,6 +24,7 @@\n>  \tunsigned int flags;\n>  \tunsigned char sha1[20];\n>  \tunsigned long date;\n> +\tunsigned char tree[20];\n>  \tstruct parent *parent;\n>  };\n>  \n> @@ -111,4 +112,29 @@\n>  \t}\n>  }\n>  \n> +static int parse_commit_object(struct revision *rev)\n> +{\n> +\tif (!(rev->flags & SEEN)) {\n> +\t\tvoid *buffer, *bufptr;\n> +\t\tunsigned long size;\n> +\t\tchar type[20];\n> +\t\tunsigned char parent[20];\n> +\n> +\t\trev->flags |= SEEN;\n> +\t\tbuffer = bufptr = read_sha1_file(rev->sha1, type, &size);\n> +\t\tif (!buffer || strcmp(type, \"commit\"))\n> +\t\t\treturn -1;\n> +\t\tget_sha1_hex(bufptr + 5, rev->tree);\n> +\t\tbufptr += 46; /* \"tree \" + \"hex sha1\" + \"\\n\" */\n> +\t\twhile (!memcmp(bufptr, \"parent \", 7) && \n> +\t\t       !get_sha1_hex(bufptr+7, parent)) {\n> +\t\t\tadd_relationship(rev, parent);\n> +\t\t\tbufptr += 48;   /* \"parent \" + \"hex sha1\" + \"\\n\" */\n> +\t\t}\n> +\t\t//rev->date = parse_commit_date(bufptr);\n\nI don't like this.\n\n> +\t\tfree(buffer);\n> +\t}\n> +\treturn 0;\n> +}\n> +\n>  #endif /* REVISION_H */\n\nBTW, I think that in longer term having this stuffed in revision.h is a\nbad idea, we should have revision.c. I will accept patches putting the\nstuff to revision.h for now, though (unless it gets outrageous).\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"},{"id":"497","messageId":"Pine.LNX.4.21.0504171205190.30848-100000@iabervon.org","threadId":"86","inReplyTo":"20050417160106.GI1487@pasky.ji.cz","subject":"Re: Add merge-base","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T16:36:51Z","receivedAt":"2005-04-17T16:36:51Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sun, 17 Apr 2005, Petr Baudis wrote:\n\n> Dear diary, on Sun, Apr 17, 2005 at 05:27:13PM CEST, I got a letter\n> where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > merge-base finds one of the best common ancestors of a pair of commits. In\n> > particular, it finds one of the ones which is fewest commits away from the\n> > further of the heads.\n> \n> What does it return when I have\n> \n>   A -- C\n>     \\/   \\\n>     /\\   /\n>   B -- D\n> \n> ? >:)\n> \n> I assume just either A or B, randomly?\n\nEssentially, yes.\n\n> I think it would be best if it could list all the \"first-class\" matches\n> (both A and B in this case), each on a separate line; this way the\n> overlay tools could choose an algorithm to evaluate those further as\n> they see fit - e.g. sort them by time (you might aid that by listing the\n> commit time in front of them), then take the first n and try to diff\n> them all and take the one with least changes (as suggested by Linus).\n\nIt's actually kind of tricky to get all of the \"best\" ancestors without\ngetting any useless ancestors; the \"best\" criterion is maintained in the\ncurrent version by stopping as soon as possible.\n\nI think that the real solution would be to have a merge program that\ninteracts back and forth with the revision history processor, since I\nthink that merges for which the choice of ancestor matters (for whether it\ngives a conflict) would benefit most directly and clearly from figuring\nout the histories of the conflicting changes, not choosing different\nancestors.\n\nIf someone comes up with an algorithm that wants an alternative ancestor\nrather than more interactive stuff, I can work on getting a complete list.\n\n> > Index: merge-base.c\n> > ===================================================================\n> > --- /dev/null  (tree:37a0b01b85c2999243674d48bfc71cdba0e5518e)\n> > +++ d662b707e11391f6cfe597fd4d0bf9c41d34d01a/merge-base.c  (mode:100644 sha1:0f85e7d9e9a896d1142a54170ddf1159f11f9cdd)\n> > @@ -0,0 +1,108 @@\n> > +#include <stdlib.h>\n> > +#include \"cache.h\"\n> > +#include \"revision.h\"\n> > +\n> > +struct revision *common_ancestor(struct revision *rev1, struct revision *rev2)\n> > +{\n> > +\tstruct parent *parent;\n> > +\n> > +\tstruct parent *rev1list = malloc(sizeof(struct parent));\n> > +\tstruct parent *rev2list = malloc(sizeof(struct parent));\n> \n> Did I overlook anything or you could have just a single revlist?\n\nI tried with just one, but I couldn't keep it straight in my\nhead. rev1list holds the unmarked ancestors of rev1; rev2list holds the\nunmarked ancestors of rev2.\n\n> > +\tstruct parent *posn, *temp;\n> > +\n> > +\trev1list->parent = rev1;\n> > +\trev1list->next = NULL;\n> > +\n> > +\trev2list->parent = rev2;\n> > +\trev2list->next = NULL;\n> > +\n> > +\twhile (rev1list || rev2list) {\n> > +\t\tposn = rev1list;\n> > +\t\trev1list = NULL;\n> > +\t\twhile (posn) {\n> > +\t\t\tparse_commit_object(posn->parent);\n> > +\t\t\tif (posn->parent->flags & 0x0001) {\n> > +\t\t\t\t/*\n> > +\t\t\t\tprintf(\"1 already seen %s %x\\n\",\n> > +\t\t\t\t       sha1_to_hex(posn->parent->sha1),\n> > +\t\t\t\t       posn->parent->flags);\n> > +\t\t\t\t*/\n> > +                                // do nothing\n> \n> Mostly for consistency, I'd prefer you to use /* */ comments in general.\n\nSure.\n\n> I think a terrified squeak at stderr in this situation (possibly\n> suggesting fsck-cache) might be appropriate.\n\nNo, this is normal; it indicates that tree 1 has a recent little merge:\n\norig --------------- tree 2\n \\\n  --- X -- Y -- Z -- tree 1\n       \\       /\n        -- A --\n\nWhen we see X for A, we've already seen it for Y, but that's fine. I get\nthis case when I merge with you after you merge twice with Linus since I\nlast merged.\n\n> > +\t\t\t} else if (posn->parent->flags & 0x0002) {\n> > +                                // XXXX free lists\n> \n> Hmm, so, why not free the lists?\n\nAh, details; mainly, I want to wait until revision.h is cleaner before\nfixing this sort of thing.\n\n> Symmetrical notes apply to this half. Actually, they are too similar.\n> What about factoring them to a common function?\n\nSure.\n\nFixed version to follow.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"499","messageId":"Pine.LNX.4.21.0504171237200.30848-100000@iabervon.org","threadId":"86","inReplyTo":"20050417160929.GJ1487@pasky.ji.cz","subject":"Re: Parsing code in revision.h","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T16:44:38Z","receivedAt":"2005-04-17T16:44:38Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sun, 17 Apr 2005, Petr Baudis wrote:\n\n> Dear diary, on Sun, Apr 17, 2005 at 05:24:20PM CEST, I got a letter\n> where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > This adds support to revision.h for parsing commit records (but not going\n> > any further than parsing a single record). Something like this is needed\n> > by anything that uses revision.h, but older programs open-code it.\n> > \n> > Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>\n> \n> Could you please convert the current users (rev-tree.c and fsck-cache.c)\n> to use this in the same patch?\n\nThey do things somewhat differently, so it would be more intrusive. Could\nI send an extra patch to convert them instead of doing them here?\n\n> > Index: revision.h\n> > ===================================================================\n> > --- 45f926575d2c44072bfcf2317dbf3f0fbb513a4e/revision.h  (mode:100644 sha1:28d0de3261a61f68e4e0948a25a416a515cd2e83)\n> > +++ 37a0b01b85c2999243674d48bfc71cdba0e5518e/revision.h  (mode:100644 sha1:523bde6e14e18bb0ecbded8f83ad4df93fc467ab)\n> > @@ -24,6 +24,7 @@\n> >  \tunsigned int flags;\n> >  \tunsigned char sha1[20];\n> >  \tunsigned long date;\n> > +\tunsigned char tree[20];\n> >  \tstruct parent *parent;\n> >  };\n> >  \n> > @@ -111,4 +112,29 @@\n> >  \t}\n> >  }\n> >  \n> > +static int parse_commit_object(struct revision *rev)\n> > +{\n> > +\tif (!(rev->flags & SEEN)) {\n> > +\t\tvoid *buffer, *bufptr;\n> > +\t\tunsigned long size;\n> > +\t\tchar type[20];\n> > +\t\tunsigned char parent[20];\n> > +\n> > +\t\trev->flags |= SEEN;\n> > +\t\tbuffer = bufptr = read_sha1_file(rev->sha1, type, &size);\n> > +\t\tif (!buffer || strcmp(type, \"commit\"))\n> > +\t\t\treturn -1;\n> > +\t\tget_sha1_hex(bufptr + 5, rev->tree);\n> > +\t\tbufptr += 46; /* \"tree \" + \"hex sha1\" + \"\\n\" */\n> > +\t\twhile (!memcmp(bufptr, \"parent \", 7) && \n> > +\t\t       !get_sha1_hex(bufptr+7, parent)) {\n> > +\t\t\tadd_relationship(rev, parent);\n> > +\t\t\tbufptr += 48;   /* \"parent \" + \"hex sha1\" + \"\\n\" */\n> > +\t\t}\n> > +\t\t//rev->date = parse_commit_date(bufptr);\n> \n> I don't like this.\n\nYeah, that's left over from the not-quite the same parsing code in the\nother programs.\n\n> > +\t\tfree(buffer);\n> > +\t}\n> > +\treturn 0;\n> > +}\n> > +\n> >  #endif /* REVISION_H */\n> \n> BTW, I think that in longer term having this stuffed in revision.h is a\n> bad idea, we should have revision.c. I will accept patches putting the\n> stuff to revision.h for now, though (unless it gets outrageous).\n\nI'd actually like to make them commit.{c,h}, since the system calls the\nthings they actually deal in commits, not revisions. But this is getting\ninto stuff that's likely to cause painful divergance from Linus's repo,\nwhich is why I'm a bit leary of actually doing it now.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"502","messageId":"Pine.LNX.4.21.0504171251150.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171124340.30848-100000@iabervon.org","subject":"[2.1/5] Add merge-base","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T16:51:59Z","receivedAt":"2005-04-17T16:51:59Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"merge-base finds one of the best common ancestors of a pair of commits. In\nparticular, it finds one of the ones which is fewest commits away from the\nfurther of the heads.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: Makefile\n===================================================================\n--- 45f926575d2c44072bfcf2317dbf3f0fbb513a4e/Makefile  (mode:100644 sha1:346e3850de026485802e41e16a1180be2df85e4a)\n+++ 7d806c2d3be8f87d3d4d87e5254500d7fc24476b/Makefile  (mode:100644 sha1:0e84e3cd12f836602b420c197e08fabefe975493)\n@@ -14,7 +17,7 @@\n \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\n+\tcheck-files ls-tree merge-base\n \n SCRIPT=\tparent-id tree-id git gitXnormid.sh gitadd.sh gitaddremote.sh \\\n \tgitcommit.sh gitdiff-do gitdiff.sh gitlog.sh gitls.sh gitlsobj.sh \\\nIndex: merge-base.c\n===================================================================\n--- /dev/null  (tree:45f926575d2c44072bfcf2317dbf3f0fbb513a4e)\n+++ 7d806c2d3be8f87d3d4d87e5254500d7fc24476b/merge-base.c  (mode:100644 sha1:ee979c7532cbdf823e9930993b0dd8f97aadb21f)\n@@ -0,0 +1,95 @@\n+#include <stdlib.h>\n+#include \"cache.h\"\n+#include \"revision.h\"\n+\n+static struct revision *process_list(struct parent **list_p, int this_mark,\n+\t\t\t\t     int other_mark)\n+{\n+\tstruct parent *parent, *temp;\n+\tstruct parent *posn = *list_p;\n+\t*list_p = NULL;\n+\twhile (posn) {\n+\t\tparse_commit_object(posn->parent);\n+\t\tif (posn->parent->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->parent->flags & other_mark) {\n+\t\t\treturn posn->parent;\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->parent->flags |= this_mark;\n+\t\t\t\n+\t\t\tparent = posn->parent->parent;\n+\t\t\twhile (parent) {\n+\t\t\t\ttemp = malloc(sizeof(struct parent));\n+\t\t\t\ttemp->next = *list_p;\n+\t\t\t\ttemp->parent = parent->parent;\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+\t}\n+\treturn NULL;\n+}\n+\n+struct revision *common_ancestor(struct revision *rev1, struct revision *rev2)\n+{\n+\tstruct parent *rev1list = malloc(sizeof(struct parent));\n+\tstruct parent *rev2list = malloc(sizeof(struct parent));\n+\n+\trev1list->parent = rev1;\n+\trev1list->next = NULL;\n+\n+\trev2list->parent = rev2;\n+\trev2list->next = NULL;\n+\n+\twhile (rev1list || rev2list) {\n+\t\tstruct revision *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\t}\n+\t\tret = process_list(&rev2list, 0x2, 0x1);\n+\t\tif (ret) {\n+\t\t\t/* XXXX free lists */\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\treturn NULL;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tstruct revision *rev1, *rev2, *ret;\n+\tunsigned char rev1key[20], rev2key[20];\n+\n+\tif (argc != 3 ||\n+\t    get_sha1_hex(argv[1], rev1key) ||\n+\t    get_sha1_hex(argv[2], rev2key)) {\n+\t\tusage(\"merge-base <commit-id> <commit-id>\");\n+\t}\n+\trev1 = lookup_rev(rev1key);\n+\trev2 = lookup_rev(rev2key);\n+\tret = common_ancestor(rev1, rev2);\n+\tif (ret) {\n+\t\tprintf(\"%s\\n\", sha1_to_hex(ret->sha1));\n+\t\treturn 0;\n+\t} else {\n+\t\treturn 1;\n+\t}\n+\t\n+}\n\n"},{"id":"506","messageId":"20050417174736.GA1461@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171131230.30848-100000@iabervon.org","subject":"Re: [4/5] Add option for hardlinkable cache of extracted blobs","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-17T17:47:36Z","receivedAt":"2005-04-17T17:47:36Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, Apr 17, 2005 at 05:35:19PM CEST, I got a letter\nwhere Daniel Barkalow <barkalow@iabervon.org> told me that...\n> Index: checkout-cache.c\n> ===================================================================\n> --- 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/checkout-cache.c  (mode:100644 sha1:5d3028df0a45329e45fff2006719c9267adeb946)\n> +++ 08f7700831e056ad710af69f91e3a8a705b6b2b1/checkout-cache.c  (mode:100644 sha1:338588259e17dd235fdc7db759d770004a760e15)\n> @@ -67,6 +71,80 @@\n>  \treturn fd;\n>  }\n>  \n> +#ifdef HARDLINK_CACHE\n> +\n> +/*\n> + * NOTE! This returns a statically allocated buffer, so you have to be\n> + * careful about using it. Do a \"strdup()\" if you need to save the\n> + * filename.\n> + */\n> +char *sha1_blob_cache_file_name(const unsigned char *sha1)\n> +{\n..code basically identical with sha1_file_name()..\n> +}\n\nYou can guess what would I like you to do. ;-)\n\n> +\n> +static int write_entry(struct cache_entry *ce)\n> +{\n> +\tint fd;\n> +\tvoid *new;\n> +\tunsigned long size;\n> +\tlong wrote;\n> +\tchar type[20];\n> +\tchar *cache_name;\n> +\tstruct stat st;\n> +\n> +\tcache_name = sha1_blob_cache_file_name(ce->sha1);\n> +\n> +\tif (stat(cache_name, &st)) {\n..basically cut'n'paste of non-hardlinking write_entry()..\n\nBTW, I'd just use access(F_OK) instead of stat() it I don't care about\nthe file's stat at all anyway.\n\n> +\t}\n> +\tif (link(cache_name, ce->name)) {\n> +\t\tif (errno == ENOENT) {\n> +\t\t\tcreate_directories(ce->name);\n> +\t\t\tlink(cache_name, ce->name);\n> +\t\t}\n> +\t}\n> +\treturn 0;\n> +}\n\nI think it would be better to have this as hardlink_entry() and\nwrite_entry() to take the file name to write the entry to. Then you\nshould explicitly multiplex in checkout_cache() between what you do.\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"},{"id":"509","messageId":"20050417181054.GB1461@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171127160.30848-100000@iabervon.org","subject":"Re: [3/5] Add http-pull","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-17T18:10:54Z","receivedAt":"2005-04-17T18:10:54Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, Apr 17, 2005 at 05:31:16PM CEST, I got a letter\nwhere Daniel Barkalow <barkalow@iabervon.org> told me that...\n> http-pull is a program that downloads from a (normal) HTTP server a commit\n> and all of the tree and blob objects it refers to (but not other commits,\n> etc.). Options could be used to make it download a larger or different\n> selection of objects. It depends on libcurl, which I forgot to mention in\n> the README again.\n> \n> Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>\n\nSo, while you will be resending the patch, please update the README.\n\n> Index: Makefile\n> ===================================================================\n> --- d662b707e11391f6cfe597fd4d0bf9c41d34d01a/Makefile  (mode:100644 sha1:b2ce7c5b63fffca59653b980d98379909f893d44)\n> +++ 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/Makefile  (mode:100644 sha1:940ef8578cf469354002cd8feaec25d907015267)\n> @@ -35,6 +35,7 @@\n>  \n>  LIBS= -lssl -lz\n>  \n> +http-pull: LIBS += -lcurl\n>  \n>  $(PROG):%: %.o $(COMMON)\n>  \t$(CC) $(CFLAGS) -o $@ $^ $(LIBS)\n\nWhew. Looks like an awful trick, you say this works?! :-)\n\nAt times, I wouldn't want to be a GNU make parser.\n\n> Index: http-pull.c\n> ===================================================================\n> --- /dev/null  (tree:d662b707e11391f6cfe597fd4d0bf9c41d34d01a)\n> +++ 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/http-pull.c  (mode:100644 sha1:106ca31239e6afe6784e7c592234406f5c149e44)\n> @@ -0,0 +1,126 @@\n> +\tif (!stat(filename, &st)) {\n> +\t\treturn 0;\n> +\t}\n\naccess()\n\n> +\turl = malloc(strlen(base) + 50);\n\nOff-by-one. What about the trailing NUL?\n\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\n> +static int process_tree(unsigned char *sha1)\n> +{\n> +\tvoid *buffer;\n> +        unsigned long size;\n> +        char type[20];\n> +\n> +        buffer = read_sha1_file(sha1, type, &size);\n\nSomething with your whitespaces is wrong here. ;-)\n\n> +\tfetch(rev->tree);\n> +\tprocess_tree(rev->tree);\n\n> +\tfetch(sha1);\n> +\tprocess_commit(sha1);\n\nYou are ignoring return codes of own routines everywhere.\nYou should use error() instead of plain -1, BTW.\n\n\nI think you should have at least two disjunct modes - either you are\ndownloading everything related to the given commit, or you are\ndownloading all commit records for commit predecessors.\n\nEven if you might not want all the intermediate trees, you definitively\nwant the intermediate commits, to keep the history graph contignuous.\n\nSo in git pull, I'd imagine to do\n\n\thttp-pull -c $new_head\n\thttp-pull -t $(tree-id $new_head)\n\nSo, -c would fetch a given commit and all its predecessors until it hits\nwhat you already have on your side. -t would fetch a given tree with all\nfiles and subtrees and everything. http-pull shouldn't default on\neither, since they are mutually exclusive.\n\nWhat do you think?\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"},{"id":"512","messageId":"Pine.LNX.4.58.0504171114020.7211@ppc970.osdl.org","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171120400.30848-100000@iabervon.org","subject":"Re: [1/5] Parsing code in revision.h","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-04-17T18:18:47Z","receivedAt":"2005-04-17T18:18:47Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 17 Apr 2005, Daniel Barkalow wrote:\n>\n> --- 45f926575d2c44072bfcf2317dbf3f0fbb513a4e/revision.h  (mode:100644 sha1:28d0de3261a61f68e4e0948a25a416a515cd2e83)\n> +++ 37a0b01b85c2999243674d48bfc71cdba0e5518e/revision.h  (mode:100644 sha1:523bde6e14e18bb0ecbded8f83ad4df93fc467ab)\n> @@ -24,6 +24,7 @@\n>  \tunsigned int flags;\n>  \tunsigned char sha1[20];\n>  \tunsigned long date;\n> +\tunsigned char tree[20];\n>  \tstruct parent *parent;\n>  };\n>  \n\nI think this is really wrong.\n\nThe whole point of \"revision.h\" is that it's a generic framework for \nkeeping track of relationships between different objects. And those \nobjects are in no way just \"commit\" objects.\n\nFor example, fsck uses this \"struct revision\" to create a full free of \n_all_ the object dependencies, which means that a \"struct revision\" can be \nany object at all - it's not in any way limited to commit objects, and \nthere is no \"tree\" object that is associated with these things at all.\n\nBesides, why do you want the tree? There's really nothing you can do with \nthe tree to a first approximation - you need to _first_ do the \nreachability analysis entirely on the commit dependencies, and then when \nyou've selected a set of commits, you can just output those.\n\nLater phases will indeed look up what the tree is, but that's only after\nyou've decided on the commit object. There's no point in looking up (or\neven trying to just remember) _all_ the tree objects.\n\nHmm?\n\n\t\tLinus\n"},{"id":"515","messageId":"20050417183002.GE1461@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.58.0504171114020.7211@ppc970.osdl.org","subject":"Re: [1/5] Parsing code in revision.h","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-17T18:30:02Z","receivedAt":"2005-04-17T18:30:02Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, Apr 17, 2005 at 08:18:47PM CEST, I got a letter\nwhere Linus Torvalds <torvalds@osdl.org> told me that...\n> \n> \n> On Sun, 17 Apr 2005, Daniel Barkalow wrote:\n> >\n> > --- 45f926575d2c44072bfcf2317dbf3f0fbb513a4e/revision.h  (mode:100644 sha1:28d0de3261a61f68e4e0948a25a416a515cd2e83)\n> > +++ 37a0b01b85c2999243674d48bfc71cdba0e5518e/revision.h  (mode:100644 sha1:523bde6e14e18bb0ecbded8f83ad4df93fc467ab)\n> > @@ -24,6 +24,7 @@\n> >  \tunsigned int flags;\n> >  \tunsigned char sha1[20];\n> >  \tunsigned long date;\n> > +\tunsigned char tree[20];\n> >  \tstruct parent *parent;\n> >  };\n> >  \n> \n> I think this is really wrong.\n> \n> The whole point of \"revision.h\" is that it's a generic framework for \n> keeping track of relationships between different objects. And those \n> objects are in no way just \"commit\" objects.\n\nSomeone started the avalanche by adding date to the structure. Of\ncourse, date is smaller, but it leads people (including me) out of the\nway.\n\nPerhaps struct commit which will have struct revision (ugh - what about\nrather struct object?) as a member?\n\n> For example, fsck uses this \"struct revision\" to create a full free of \n> _all_ the object dependencies, which means that a \"struct revision\" can be \n> any object at all - it's not in any way limited to commit objects, and \n> there is no \"tree\" object that is associated with these things at all.\n\nThat's some really bad naming then.\n\n> Besides, why do you want the tree? There's really nothing you can do with \n> the tree to a first approximation - you need to _first_ do the \n> reachability analysis entirely on the commit dependencies, and then when \n> you've selected a set of commits, you can just output those.\n> \n> Later phases will indeed look up what the tree is, but that's only after\n> you've decided on the commit object. There's no point in looking up (or\n> even trying to just remember) _all_ the tree objects.\n\nThe goal was to have a commit record parser which would spit out this\nstructure containing all the relevant info, but I can agree that wasting\nmemory with it makes no sense. Perhaps it could take a possibly-NULL\nbuffer pointer where it would drop the tree ID, Daniel?\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"},{"id":"517","messageId":"Pine.LNX.4.21.0504171412350.30848-100000@iabervon.org","threadId":"86","inReplyTo":"20050417181054.GB1461@pasky.ji.cz","subject":"Re: [3/5] Add http-pull","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T18:49:11Z","receivedAt":"2005-04-17T18:49:11Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sun, 17 Apr 2005, Petr Baudis wrote:\n\n> > Index: Makefile\n> > ===================================================================\n> > --- d662b707e11391f6cfe597fd4d0bf9c41d34d01a/Makefile  (mode:100644 sha1:b2ce7c5b63fffca59653b980d98379909f893d44)\n> > +++ 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/Makefile  (mode:100644 sha1:940ef8578cf469354002cd8feaec25d907015267)\n> > @@ -35,6 +35,7 @@\n> >  \n> >  LIBS= -lssl -lz\n> >  \n> > +http-pull: LIBS += -lcurl\n> >  \n> >  $(PROG):%: %.o $(COMMON)\n> >  \t$(CC) $(CFLAGS) -o $@ $^ $(LIBS)\n> \n> Whew. Looks like an awful trick, you say this works?! :-)\n> \n> At times, I wouldn't want to be a GNU make parser.\n\nYup. GNU make is big on the features which do the obvious thing, even when\nyou can't believe they work. This is probably why nobody's managed to\nreplace it.\n\n> > Index: http-pull.c\n> > ===================================================================\n> > --- /dev/null  (tree:d662b707e11391f6cfe597fd4d0bf9c41d34d01a)\n> > +++ 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/http-pull.c  (mode:100644 sha1:106ca31239e6afe6784e7c592234406f5c149e44)\n> > +\turl = malloc(strlen(base) + 50);\n> \n> Off-by-one. What about the trailing NUL?\n\nI get length(base) + \"object/\"=8 + 40 SHA1 + 1 for '/' and 1 for NUL = 50.\n\n> I think you should have at least two disjunct modes - either you are\n> downloading everything related to the given commit, or you are\n> downloading all commit records for commit predecessors.\n> \n> Even if you might not want all the intermediate trees, you definitively\n> want the intermediate commits, to keep the history graph contignuous.\n> \n> So in git pull, I'd imagine to do\n> \n> \thttp-pull -c $new_head\n> \thttp-pull -t $(tree-id $new_head)\n> \n> So, -c would fetch a given commit and all its predecessors until it hits\n> what you already have on your side. -t would fetch a given tree with all\n> files and subtrees and everything. http-pull shouldn't default on\n> either, since they are mutually exclusive.\n> \n> What do you think?\n\nI think I'd rather keep the current behavior and add a -c for getting the\nhistory of commits, and maybe a -a for getting the history of commits and\ntheir tress.\n\nThere's some trickiness for the history of commits thing for stopping at\nthe point where you have everything, but also behaving appropriately if\nyou try once, fail partway through, and then try again. It's on my queue\nof things to think about.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"518","messageId":"Pine.LNX.4.21.0504171453260.30848-100000@iabervon.org","threadId":"86","inReplyTo":"20050417174736.GA1461@pasky.ji.cz","subject":"Re: [4/5] Add option for hardlinkable cache of extracted blobs","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T18:54:10Z","receivedAt":"2005-04-17T18:54:10Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"Drop this one for now; I'll revisit it once more important stuff is\nsettled down.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"519","messageId":"Pine.LNX.4.21.0504171457050.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171127160.30848-100000@iabervon.org","subject":"[3.1/5] Add http-pull","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T18:58:00Z","receivedAt":"2005-04-17T18:58:00Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"http-pull is a program that downloads from a (normal) HTTP server a commit\nand all of the tree and blob objects it refers to (but not other commits,\netc.). Options could be used to make it download a larger or different\nselection of objects.\n\nSigned-Off-By: Daniel Barkalow <barkalow@iabervon.org>\nIndex: Makefile\n===================================================================\n--- 45f926575d2c44072bfcf2317dbf3f0fbb513a4e/Makefile  (mode:100644 sha1:346e3850de026485802e41e16a1180be2df85e4a)\n+++ 3eae85f66143160a26f5545d197862c89e2a8fb8/Makefile  (mode:100644 sha1:0e84e3cd12f836602b420c197e08fabefe975493)\n@@ -14,7 +17,7 @@\n \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\n+\tcheck-files ls-tree http-pull merge-base\n \n SCRIPT=\tparent-id tree-id git gitXnormid.sh gitadd.sh gitaddremote.sh \\\n \tgitcommit.sh gitdiff-do gitdiff.sh gitlog.sh gitls.sh gitlsobj.sh \\\n@@ -35,6 +38,7 @@\n \n LIBS= -lssl -lz\n \n+http-pull: LIBS += -lcurl\n \n $(PROG):%: %.o $(COMMON)\n \t$(CC) $(CFLAGS) -o $@ $^ $(LIBS)\nIndex: README\n===================================================================\n--- 45f926575d2c44072bfcf2317dbf3f0fbb513a4e/README  (mode:100664 sha1:0170eafb60ad9009ca41c6536cecd6d1fdee5b86)\n+++ 3eae85f66143160a26f5545d197862c89e2a8fb8/README  (mode:100664 sha1:921d552d810394e665323ec82b4826914918689c)\n@@ -120,7 +120,7 @@\n \tdiff, patch\n \tlibssl\n \trsync\n-\n+\tcurl (later than 7.7, according to the docs)\n \n \n \tThe \"core GIT\"\nIndex: http-pull.c\n===================================================================\n--- /dev/null  (tree:45f926575d2c44072bfcf2317dbf3f0fbb513a4e)\n+++ 3eae85f66143160a26f5545d197862c89e2a8fb8/http-pull.c  (mode:100644 sha1:7ba4ad67f6dac34addb537ee147ae3de0550a484)\n@@ -0,0 +1,139 @@\n+#include <fcntl.h>\n+#include <unistd.h>\n+#include <string.h>\n+#include <stdlib.h>\n+#include \"cache.h\"\n+#include \"revision.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 fetch(unsigned char *sha1)\n+{\n+\tchar *hex = sha1_to_hex(sha1);\n+\tchar *filename = sha1_file_name(sha1);\n+\n+\tchar *url;\n+\tchar *posn;\n+\tFILE *local;\n+\n+\tif (!access(filename, R_OK)) {\n+\t\treturn 0;\n+\t}\n+\n+\tlocal = fopen(filename, \"w\");\n+\n+\tif (!local) {\n+\t\treturn error(\"Couldn't open %s\", filename);\n+\t}\n+\n+\tcurl_easy_setopt(curl, CURLOPT_FILE, local);\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+\tif (curl_easy_perform(curl)) {\n+\t\tfclose(local);\n+\t\tunlink(filename);\n+\t\treturn error(\"Error downloading %s from %s\",\n+\t\t\t     sha1_to_hex(sha1), url);\n+\t}\n+\n+\tfclose(local);\n+\t\n+\treturn 0;\n+}\n+\n+static int process_tree(unsigned char *sha1)\n+{\n+\tvoid *buffer;\n+\tunsigned long size;\n+\tchar type[20];\n+\n+\tbuffer = read_sha1_file(sha1, type, &size);\n+\tif (!buffer)\n+\t \treturn error(\"Couldn't read %s.\",\n+\t\t\t     sha1_to_hex(sha1));\n+\tif (strcmp(type, \"tree\"))\n+\t\treturn error(\"Expected %s to be a tree, but was a %s.\",\n+\t\t\t     sha1_to_hex(sha1), type);\n+\twhile (size) {\n+\t\tint len = strlen(buffer) + 1;\n+\t\tunsigned char *sha1 = buffer + len;\n+\t\tunsigned int mode;\n+\t\tint retval;\n+\n+\t\tif (size < len + 20 || sscanf(buffer, \"%o\", &mode) != 1)\n+\t\t\treturn error(\"Invalid tree object\");\n+\n+\t\tbuffer = sha1 + 20;\n+\t\tsize -= len + 20;\n+\n+\t\tretval = fetch(sha1);\n+\t\tif (retval)\n+\t\t\treturn retval;\n+\n+\t\tif (S_ISDIR(mode)) {\n+\t\t\tretval = process_tree(sha1);\n+\t\t\tif (retval)\n+\t\t\t\treturn retval;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int process_commit(unsigned char *sha1)\n+{\n+\tint retval;\n+\tstruct revision *rev = lookup_rev(sha1);\n+\tif (parse_commit_object(rev))\n+\t\treturn error(\"Couldn't parse commit %s\\n\", sha1_to_hex(sha1));\n+\n+\tretval = fetch(rev->tree);\n+\tif (retval)\n+\t\treturn retval;\n+\tretval = process_tree(rev->tree);\n+\treturn retval;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tchar *commit_id = argv[1];\n+\tchar *url = argv[2];\n+\tint retval;\n+\n+\tunsigned char sha1[20];\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+\tretval = fetch(sha1);\n+\tif (retval)\n+\t\treturn 1;\n+\tretval = process_commit(sha1);\n+\tif (retval)\n+\t\treturn 1;\n+\n+\tcurl_global_cleanup();\n+\treturn 0;\n+}\n\n"},{"id":"521","messageId":"20050417190824.GF1461@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171412350.30848-100000@iabervon.org","subject":"Re: [3/5] Add http-pull","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-17T19:08:24Z","receivedAt":"2005-04-17T19:08:24Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, Apr 17, 2005 at 08:49:11PM CEST, I got a letter\nwhere Daniel Barkalow <barkalow@iabervon.org> told me that...\n> On Sun, 17 Apr 2005, Petr Baudis wrote:\n> > > Index: http-pull.c\n> > > ===================================================================\n> > > --- /dev/null  (tree:d662b707e11391f6cfe597fd4d0bf9c41d34d01a)\n> > > +++ 157b46ce1d82b3579e2e1258927b0d9bdbc033ab/http-pull.c  (mode:100644 sha1:106ca31239e6afe6784e7c592234406f5c149e44)\n> > > +\turl = malloc(strlen(base) + 50);\n> > \n> > Off-by-one. What about the trailing NUL?\n> \n> I get length(base) + \"object/\"=8 + 40 SHA1 + 1 for '/' and 1 for NUL = 50.\n\nSorry, counted one '/' more. :-)\n\n> > I think you should have at least two disjunct modes - either you are\n> > downloading everything related to the given commit, or you are\n> > downloading all commit records for commit predecessors.\n> > \n> > Even if you might not want all the intermediate trees, you definitively\n> > want the intermediate commits, to keep the history graph contignuous.\n> > \n> > So in git pull, I'd imagine to do\n> > \n> > \thttp-pull -c $new_head\n> > \thttp-pull -t $(tree-id $new_head)\n> > \n> > So, -c would fetch a given commit and all its predecessors until it hits\n> > what you already have on your side. -t would fetch a given tree with all\n> > files and subtrees and everything. http-pull shouldn't default on\n> > either, since they are mutually exclusive.\n> > \n> > What do you think?\n> \n> I think I'd rather keep the current behavior and add a -c for getting the\n> history of commits, and maybe a -a for getting the history of commits and\n> their tress.\n\nI'm not too kind at this. Either make it totally separate commands, or\nmake a required switch specifying what to do. Otherwise it implies the\nswitches would just modify what it does, but they make it do something\ncompletely different.\n\n-a would be fine too - basically a combination of -c and -t. I'd imagine\nthat is what Linus would want to use, e.g.\n\n> There's some trickiness for the history of commits thing for stopping at\n> the point where you have everything, but also behaving appropriately if\n> you try once, fail partway through, and then try again. It's on my queue\n> of things to think about.\n\nCan't you just stop the recursion when you hit a commit you already\nhave?\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"},{"id":"522","messageId":"Pine.LNX.4.21.0504171458310.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.58.0504171114020.7211@ppc970.osdl.org","subject":"Re: [1/5] Parsing code in revision.h","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T19:09:20Z","receivedAt":"2005-04-17T19:09:20Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sun, 17 Apr 2005, Linus Torvalds wrote:\n\n> On Sun, 17 Apr 2005, Daniel Barkalow wrote:\n> >\n> > --- 45f926575d2c44072bfcf2317dbf3f0fbb513a4e/revision.h  (mode:100644 sha1:28d0de3261a61f68e4e0948a25a416a515cd2e83)\n> > +++ 37a0b01b85c2999243674d48bfc71cdba0e5518e/revision.h  (mode:100644 sha1:523bde6e14e18bb0ecbded8f83ad4df93fc467ab)\n> > @@ -24,6 +24,7 @@\n> >  \tunsigned int flags;\n> >  \tunsigned char sha1[20];\n> >  \tunsigned long date;\n> > +\tunsigned char tree[20];\n> >  \tstruct parent *parent;\n> >  };\n> >  \n> \n> I think this is really wrong.\n> \n> The whole point of \"revision.h\" is that it's a generic framework for \n> keeping track of relationships between different objects. And those \n> objects are in no way just \"commit\" objects.\n>\n> For example, fsck uses this \"struct revision\" to create a full free of \n> _all_ the object dependencies, which means that a \"struct revision\" can be \n> any object at all - it's not in any way limited to commit objects, and \n> there is no \"tree\" object that is associated with these things at all.\n\nI entirely missed this. No wonder my fsck-cache conversion wasn't going\nso well...\n\n> Besides, why do you want the tree? There's really nothing you can do with \n> the tree to a first approximation - you need to _first_ do the \n> reachability analysis entirely on the commit dependencies, and then when \n> you've selected a set of commits, you can just output those.\n\nI actually want the tree for http-pull, not merging stuff. I was trying to\nget a commit parser, not reachability at that point.\n\nI think the right thing is to make a separate struct commit that has the\nstuff I want in it, and probably do a struct tree at the same time.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"525","messageId":"Pine.LNX.4.21.0504171510120.30848-100000@iabervon.org","threadId":"86","inReplyTo":"20050417190824.GF1461@pasky.ji.cz","subject":"Re: [3/5] Add http-pull","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T19:24:27Z","receivedAt":"2005-04-17T19:24:27Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sun, 17 Apr 2005, Petr Baudis wrote:\n\n> Dear diary, on Sun, Apr 17, 2005 at 08:49:11PM CEST, I got a letter\n> where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> \n> I'm not too kind at this. Either make it totally separate commands, or\n> make a required switch specifying what to do. Otherwise it implies the\n> switches would just modify what it does, but they make it do something\n> completely different.\n\nThat's a good point. I'll require a -t for now, and add more later.\n\n> -a would be fine too - basically a combination of -c and -t. I'd imagine\n> that is what Linus would want to use, e.g.\n\nWell, -c -t would give you the current tree and the whole commit log, but\nnot old trees. -a would additionally give you old trees.\n\n> > There's some trickiness for the history of commits thing for stopping at\n> > the point where you have everything, but also behaving appropriately if\n> > you try once, fail partway through, and then try again. It's on my queue\n> > of things to think about.\n> \n> Can't you just stop the recursion when you hit a commit you already\n> have?\n\nThe problem is that, if you've fetched the final commit already, and then\nthe server dies, and you try again later, you already have the last one,\nand so you think you've got everything.\n\nAt this point, I also want to put off doing much further with recursion\nand commits until revision.h and such are sorted out.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"523","messageId":"20050417122517.4b12faea.pj@sgi.com","threadId":"86","inReplyTo":"20050417174736.GA1461@pasky.ji.cz","subject":"Re: [4/5] Add option for hardlinkable cache of extracted blobs","fromName":"Paul Jackson","fromEmail":"pj@sgi.com","sentAt":"2005-04-17T19:25:17Z","receivedAt":"2005-04-17T19:25:17Z","isPatch":false,"sender":{"key":"pj@sgi.com","avatar":null},"body":"Petr wrote:\n> BTW, I'd just use access(F_OK) instead of stat() it I don't care about\n\nThat's a bad habit to get into.\n\naccess(2) checks with the process's real uid and gid, rather than with\nthe effective ids as is done when actually attempting an operation. \nThis is to allow set-UID programs to easily determine the invoking\nuser's authority.\n\nUsing access(2) when it shouldn't be used is a common source of bugs.\n\nI recommend _only_ using it when you require exactly the above real vs.\neffective id behaviour.\n\n-- \n                  I won't rest till it's the best ...\n                  Programmer, Linux Scalability\n                  Paul Jackson <pj@engr.sgi.com> 1.650.933.1373, 1.925.600.0401\n"},{"id":"524","messageId":"Pine.LNX.4.58.0504171221130.7211@ppc970.osdl.org","threadId":"86","inReplyTo":"20050417183002.GE1461@pasky.ji.cz","subject":"Re: [1/5] Parsing code in revision.h","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-04-17T19:25:21Z","receivedAt":"2005-04-17T19:25:21Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 17 Apr 2005, Petr Baudis wrote:\n> \n> Someone started the avalanche by adding date to the structure. Of\n> course, date is smaller, but it leads people (including me) out of the\n> way.\n\nYeah, the naming and the structure comes from \"rev-tree.c\", so there's a \nbit of historical baggage already. \n\nAnyway, I don't think you should need it. I cleaned up things a bit, and \nwrote a really simple \"merge-base\" thing that does base the \"best\" hit on \ndate, which ends up probably doing the right thing in practice.\n\nIt might be interesting to extend that to do the \"five best\" common\nparents according to date (making sure to remove the trivial cases: a\nparent of a common parent is always itself a common parent, but such a\ncommon grandparent is obviously always uninteresting).\n\nThen, for that small set of parents, doing something much more involved\n(generation counting is fairly simple, but possibly not as good a\n\"goodness\" match as tree-diff or something).\n\n\t\tLinus\n"},{"id":"528","messageId":"Pine.LNX.4.21.0504171531180.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.58.0504171221130.7211@ppc970.osdl.org","subject":"Re: [1/5] Parsing code in revision.h","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T19:45:34Z","receivedAt":"2005-04-17T19:45:34Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sun, 17 Apr 2005, Linus Torvalds wrote:\n\n> On Sun, 17 Apr 2005, Petr Baudis wrote:\n> > \n> > Someone started the avalanche by adding date to the structure. Of\n> > course, date is smaller, but it leads people (including me) out of the\n> > way.\n> \n> Yeah, the naming and the structure comes from \"rev-tree.c\", so there's a \n> bit of historical baggage already. \n> \n> Anyway, I don't think you should need it. I cleaned up things a bit, and \n> wrote a really simple \"merge-base\" thing that does base the \"best\" hit on \n> date, which ends up probably doing the right thing in practice.\n\nYours reads the whole commit history; I intentionally wrote mine to\nonly read as far back as turns out to be necessary. I think that looking\nat the whole history is going to be impractical when you're trying to\nmerge in a bunch of patches against the latest release, even if you pull\nthe history out of a cache. When it's one step on one side and a dozen on\nthe other, it matters a whole lot if there's a year of history behind the\ncommon ancestor(s).\n\nSo I still think it's best to have a non-recursive commit parser, and do\nthe recursion only as needed for the operation under consideration.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"531","messageId":"Pine.LNX.4.58.0504171253030.7211@ppc970.osdl.org","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171531180.30848-100000@iabervon.org","subject":"Re: [1/5] Parsing code in revision.h","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-04-17T19:54:22Z","receivedAt":"2005-04-17T19:54:22Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 17 Apr 2005, Daniel Barkalow wrote:\n> \n> Yours reads the whole commit history; I intentionally wrote mine to\n> only read as far back as turns out to be necessary.\n\nYes. I'm not opposed to yours, I was just opposed to some of the things \naround it you did, so I wrote mine as a kind of place-holder. I'll happily \ntake patches to turn it from a rally simple and stupid one into a more \npolished version.\n\n\t\tLinus\n"},{"id":"532","messageId":"20050417195900.GH1461@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171510120.30848-100000@iabervon.org","subject":"Re: [3/5] Add http-pull","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-17T19:59:00Z","receivedAt":"2005-04-17T19:59:00Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, Apr 17, 2005 at 09:24:27PM CEST, I got a letter\nwhere Daniel Barkalow <barkalow@iabervon.org> told me that...\n> On Sun, 17 Apr 2005, Petr Baudis wrote:\n> \n> > Dear diary, on Sun, Apr 17, 2005 at 08:49:11PM CEST, I got a letter\n> > where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > > There's some trickiness for the history of commits thing for stopping at\n> > > the point where you have everything, but also behaving appropriately if\n> > > you try once, fail partway through, and then try again. It's on my queue\n> > > of things to think about.\n> > \n> > Can't you just stop the recursion when you hit a commit you already\n> > have?\n> \n> The problem is that, if you've fetched the final commit already, and then\n> the server dies, and you try again later, you already have the last one,\n> and so you think you've got everything.\n\nHmm, some kind of journaling? ;-)\n\n> At this point, I also want to put off doing much further with recursion\n> and commits until revision.h and such are sorted out.\n\nAgreed.\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"},{"id":"544","messageId":"20050417212116.GK1461@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504171251150.30848-100000@iabervon.org","subject":"Re: [2.1/5] Add merge-base","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-17T21:21:16Z","receivedAt":"2005-04-17T21:21:16Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, Apr 17, 2005 at 06:51:59PM CEST, I got a letter\nwhere Daniel Barkalow <barkalow@iabervon.org> told me that...\n> merge-base finds one of the best common ancestors of a pair of commits. In\n> particular, it finds one of the ones which is fewest commits away from the\n> further of the heads.\n> \n> Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>\n\nNote that during merge with Linus (probably the most complicated I've\ngot so far, but still thankfully not too painful thanks to the rej\ntool) I've decided to revert your merge-base in favour of Linus'\nversion. I did this mainly to make me merging Linus less awful; we\nshould probably clean it up first and decide which solution to go for in\nthe first place before possibly replacing it again, I think.\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"},{"id":"545","messageId":"Pine.LNX.4.21.0504171722110.30848-100000@iabervon.org","threadId":"86","inReplyTo":"20050417212116.GK1461@pasky.ji.cz","subject":"Re: [2.1/5] Add merge-base","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-17T21:25:14Z","receivedAt":"2005-04-17T21:25:14Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sun, 17 Apr 2005, Petr Baudis wrote:\n\n> Dear diary, on Sun, Apr 17, 2005 at 06:51:59PM CEST, I got a letter\n> where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > merge-base finds one of the best common ancestors of a pair of commits. In\n> > particular, it finds one of the ones which is fewest commits away from the\n> > further of the heads.\n> > \n> > Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org>\n> \n> Note that during merge with Linus (probably the most complicated I've\n> got so far, but still thankfully not too painful thanks to the rej\n> tool) I've decided to revert your merge-base in favour of Linus'\n> version. I did this mainly to make me merging Linus less awful; we\n> should probably clean it up first and decide which solution to go for in\n> the first place before possibly replacing it again, I think.\n\nSure. I'm working on the rearrangement now.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"1083","messageId":"Pine.LNX.4.44.0504202026180.2625-100000@bellevue.puremagic.com","threadId":"86","inReplyTo":"20050417195900.GH1461@pasky.ji.cz","subject":"Re: [3/5] Add http-pull","fromName":"Brad Roberts","fromEmail":"braddr@puremagic.com","sentAt":"2005-04-21T03:27:17Z","receivedAt":"2005-04-21T03:27:17Z","isPatch":false,"sender":{"key":"braddr@puremagic.com","avatar":null},"body":"On Sun, 17 Apr 2005, Petr Baudis wrote:\n\n> Date: Sun, 17 Apr 2005 21:59:00 +0200\n> From: Petr Baudis <pasky@ucw.cz>\n> To: Daniel Barkalow <barkalow@iabervon.org>\n> Cc: git@vger.kernel.org\n> Subject: Re: [3/5] Add http-pull\n>\n> Dear diary, on Sun, Apr 17, 2005 at 09:24:27PM CEST, I got a letter\n> where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > On Sun, 17 Apr 2005, Petr Baudis wrote:\n> >\n> > > Dear diary, on Sun, Apr 17, 2005 at 08:49:11PM CEST, I got a letter\n> > > where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > > > There's some trickiness for the history of commits thing for stopping at\n> > > > the point where you have everything, but also behaving appropriately if\n> > > > you try once, fail partway through, and then try again. It's on my queue\n> > > > of things to think about.\n> > >\n> > > Can't you just stop the recursion when you hit a commit you already\n> > > have?\n> >\n> > The problem is that, if you've fetched the final commit already, and then\n> > the server dies, and you try again later, you already have the last one,\n> > and so you think you've got everything.\n>\n> Hmm, some kind of journaling? ;-)\n\nHow about fetching in the inverse order.  Ie, deepest parents up towards\ncurrent.  With that method the repository is always self consistent, even\nif not yet current.\n\nLater,\nBrad\n\n"},{"id":"1090","messageId":"Pine.LNX.4.21.0504210007410.30848-100000@iabervon.org","threadId":"86","inReplyTo":"Pine.LNX.4.44.0504202026180.2625-100000@bellevue.puremagic.com","subject":"Re: [3/5] Add http-pull","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-21T04:28:03Z","receivedAt":"2005-04-21T04:28:03Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Wed, 20 Apr 2005, Brad Roberts wrote:\n\n> How about fetching in the inverse order.  Ie, deepest parents up towards\n> current.  With that method the repository is always self consistent, even\n> if not yet current.\n\nYou don't know the deepest parents to fetch until you've read everything\nmore recent, since the history you'd have to walk is the history you're\ndownloading.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"1204","messageId":"200504212205.j3LM5J005103@unix-os.sc.intel.com","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504210007410.30848-100000@iabervon.org","subject":"Re: [3/5] Add http-pull","fromName":"","fromEmail":"tony.luck@intel.com","sentAt":"2005-04-21T22:05:19Z","receivedAt":"2005-04-21T22:05:19Z","isPatch":false,"sender":{"key":"tony.luck@intel.com","avatar":"https://avatars.githubusercontent.com/u/5446021?v=4"},"body":"On Wed, 20 Apr 2005, Brad Roberts wrote:\n> How about fetching in the inverse order.  Ie, deepest parents up towards\n> current.  With that method the repository is always self consistent, even\n> if not yet current.\n\nDaniel Barkalow replied:\n> You don't know the deepest parents to fetch until you've read everything\n> more recent, since the history you'd have to walk is the history you're\n> downloading.\n\nYou \"just\" need to defer adding tree/commit objects to the repository until\nafter you have inserted all objects on which they depend.  That's what my\n\"wget\" based version does ... it's very crude, in that it loads all tree\n& commit objects into a temporary repository (.gittmp) ... since you can\nonly use \"cat-file\" and \"ls-tree\" on things if they live in objects/xx/xxx..xxx\nThe blobs can go directly into the real repo (but to be really safe you'd\nhave to ensure that the whole blob had been pulled from the network before\ninserting it ... it's probably a good move to validate everything that you\npull from the outside world too).\n\n-Tony\n"},{"id":"1313","messageId":"Pine.LNX.4.21.0504221532120.30848-100000@iabervon.org","threadId":"86","inReplyTo":"200504212205.j3LM5J005103@unix-os.sc.intel.com","subject":"Re: [3/5] Add http-pull","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-22T19:46:35Z","receivedAt":"2005-04-22T19:46:35Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Thu, 21 Apr 2005 tony.luck@intel.com wrote:\n\n> On Wed, 20 Apr 2005, Brad Roberts wrote:\n> > How about fetching in the inverse order.  Ie, deepest parents up towards\n> > current.  With that method the repository is always self consistent, even\n> > if not yet current.\n> \n> Daniel Barkalow replied:\n> > You don't know the deepest parents to fetch until you've read everything\n> > more recent, since the history you'd have to walk is the history you're\n> > downloading.\n> \n> You \"just\" need to defer adding tree/commit objects to the repository until\n> after you have inserted all objects on which they depend.  That's what my\n> \"wget\" based version does ... it's very crude, in that it loads all tree\n> & commit objects into a temporary repository (.gittmp) ... since you can\n> only use \"cat-file\" and \"ls-tree\" on things if they live in objects/xx/xxx..xxx\n> The blobs can go directly into the real repo (but to be really safe you'd\n> have to ensure that the whole blob had been pulled from the network before\n> inserting it ... it's probably a good move to validate everything that you\n> pull from the outside world too).\n\nThe problem with this general scheme is that it means that you have to\nstart over if something goes wrong, rather than resuming from where you\nleft off (and being able to use what you got until then). I think a better\nsolution is to track what things you mean to have and what things you\nexpect you could get from where.\n\nAs for validation, I now have my programs (which I haven't gotten a chance\nto send out recently) checking everything as it is downloaded to make sure\nit is complete (zlib likes it) and has the correct hash.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"1340","messageId":"20050422224008.GD21204@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504221532120.30848-100000@iabervon.org","subject":"Re: [3/5] Add http-pull","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-22T22:40:08Z","receivedAt":"2005-04-22T22:40:08Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Fri, Apr 22, 2005 at 09:46:35PM CEST, I got a letter\nwhere Daniel Barkalow <barkalow@iabervon.org> told me that...\n> On Thu, 21 Apr 2005 tony.luck@intel.com wrote:\n> \n> > On Wed, 20 Apr 2005, Brad Roberts wrote:\n> > > How about fetching in the inverse order.  Ie, deepest parents up towards\n> > > current.  With that method the repository is always self consistent, even\n> > > if not yet current.\n> > \n> > Daniel Barkalow replied:\n> > > You don't know the deepest parents to fetch until you've read everything\n> > > more recent, since the history you'd have to walk is the history you're\n> > > downloading.\n> > \n> > You \"just\" need to defer adding tree/commit objects to the repository until\n> > after you have inserted all objects on which they depend.  That's what my\n> > \"wget\" based version does ... it's very crude, in that it loads all tree\n> > & commit objects into a temporary repository (.gittmp) ... since you can\n> > only use \"cat-file\" and \"ls-tree\" on things if they live in objects/xx/xxx..xxx\n> > The blobs can go directly into the real repo (but to be really safe you'd\n> > have to ensure that the whole blob had been pulled from the network before\n> > inserting it ... it's probably a good move to validate everything that you\n> > pull from the outside world too).\n> \n> The problem with this general scheme is that it means that you have to\n> start over if something goes wrong, rather than resuming from where you\n> left off (and being able to use what you got until then).\n\nHuh. Why? You just go back to history until you find a commit you\nalready have. If you did it the way as Tony described, if you have that\ncommit, you can be sure that you have everything it depends on too.\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"},{"id":"1347","messageId":"Pine.LNX.4.21.0504221844420.30848-100000@iabervon.org","threadId":"86","inReplyTo":"20050422224008.GD21204@pasky.ji.cz","subject":"Re: [3/5] Add http-pull","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-22T23:00:33Z","receivedAt":"2005-04-22T23:00:33Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 23 Apr 2005, Petr Baudis wrote:\n\n> Dear diary, on Fri, Apr 22, 2005 at 09:46:35PM CEST, I got a letter\n> where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> \n> Huh. Why? You just go back to history until you find a commit you\n> already have. If you did it the way as Tony described, if you have that\n> commit, you can be sure that you have everything it depends on too.\n\nBut if you download 1000 files of the 1010 you need, and then your network\ngoes down, you will need to download those 1000 again when it comes back,\nbecause you can't save them unless you have the full history. \n\nThere's also no way to say, give me just the head and the tree associated\nwith it, let me check it out, next download the commit history so I can do\nmy merge most correctly, let me do that, finally download the intermediate\nblobs and trees so that I can track down where something broke.\n\nIdeally, you'd be able to put the latest head and tree into your database,\nand it would know that you just hadn't gotten the ancestor yet, and would\nbe able to determine from your personal metadata (rather than based on\nwhat you had or lacked) that you believe you have all ancestors of the\nprevious time you pulled, you don't want the trees that Linus merged in\nmidway through, but everything else you just don't have yet.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"1350","messageId":"20050422230855.GJ21204@pasky.ji.cz","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504221844420.30848-100000@iabervon.org","subject":"Re: [3/5] Add http-pull","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-04-22T23:08:55Z","receivedAt":"2005-04-22T23:08:55Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sat, Apr 23, 2005 at 01:00:33AM CEST, I got a letter\nwhere Daniel Barkalow <barkalow@iabervon.org> told me that...\n> On Sat, 23 Apr 2005, Petr Baudis wrote:\n> \n> > Dear diary, on Fri, Apr 22, 2005 at 09:46:35PM CEST, I got a letter\n> > where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > \n> > Huh. Why? You just go back to history until you find a commit you\n> > already have. If you did it the way as Tony described, if you have that\n> > commit, you can be sure that you have everything it depends on too.\n> \n> But if you download 1000 files of the 1010 you need, and then your network\n> goes down, you will need to download those 1000 again when it comes back,\n> because you can't save them unless you have the full history. \n\nWhy can't I? I think I can do that perfectly fine. The worst thing that\ncan happen is that fsck-cache will complain a bit.\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"},{"id":"1352","messageId":"Pine.LNX.4.21.0504221911340.30848-100000@iabervon.org","threadId":"86","inReplyTo":"20050422230855.GJ21204@pasky.ji.cz","subject":"Re: [3/5] Add http-pull","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-04-22T23:12:42Z","receivedAt":"2005-04-22T23:12:42Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 23 Apr 2005, Petr Baudis wrote:\n\n> Dear diary, on Sat, Apr 23, 2005 at 01:00:33AM CEST, I got a letter\n> where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > On Sat, 23 Apr 2005, Petr Baudis wrote:\n> > \n> > > Dear diary, on Fri, Apr 22, 2005 at 09:46:35PM CEST, I got a letter\n> > > where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > > \n> > > Huh. Why? You just go back to history until you find a commit you\n> > > already have. If you did it the way as Tony described, if you have that\n> > > commit, you can be sure that you have everything it depends on too.\n> > \n> > But if you download 1000 files of the 1010 you need, and then your network\n> > goes down, you will need to download those 1000 again when it comes back,\n> > because you can't save them unless you have the full history. \n> \n> Why can't I? I think I can do that perfectly fine. The worst thing that\n> can happen is that fsck-cache will complain a bit.\n\nNot if you're using the fact that you don't have them to tell you that you\nstill need the other 10, which is what tony's scheme would do.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"1353","messageId":"1114212282.27940.11.camel@nosferatu.lan","threadId":"86","inReplyTo":"Pine.LNX.4.21.0504221911340.30848-100000@iabervon.org","subject":"Re: [3/5] Add http-pull","fromName":"Martin Schlemmer","fromEmail":"azarah@nosferatu.za.org","sentAt":"2005-04-22T23:24:42Z","receivedAt":"2005-04-22T23:24:42Z","isPatch":false,"sender":{"key":"azarah@nosferatu.za.org","avatar":null},"body":"On Fri, 2005-04-22 at 19:12 -0400, Daniel Barkalow wrote:\n> On Sat, 23 Apr 2005, Petr Baudis wrote:\n> \n> > Dear diary, on Sat, Apr 23, 2005 at 01:00:33AM CEST, I got a letter\n> > where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > > On Sat, 23 Apr 2005, Petr Baudis wrote:\n> > > \n> > > > Dear diary, on Fri, Apr 22, 2005 at 09:46:35PM CEST, I got a letter\n> > > > where Daniel Barkalow <barkalow@iabervon.org> told me that...\n> > > > \n> > > > Huh. Why? You just go back to history until you find a commit you\n> > > > already have. If you did it the way as Tony described, if you have that\n> > > > commit, you can be sure that you have everything it depends on too.\n> > > \n> > > But if you download 1000 files of the 1010 you need, and then your network\n> > > goes down, you will need to download those 1000 again when it comes back,\n> > > because you can't save them unless you have the full history. \n> > \n> > Why can't I? I think I can do that perfectly fine. The worst thing that\n> > can happen is that fsck-cache will complain a bit.\n> \n> Not if you're using the fact that you don't have them to tell you that you\n> still need the other 10, which is what tony's scheme would do.\n> \n\nAny way (like maybe extending one of the web interfaces already around)\nto first get a list of all the sha1's you need, and then starting from\nthe bottom like Tony/Petr wants you to do?\n\n\n-- \nMartin Schlemmer\n\n"}]}