{"thread":{"id":"4196","subject":"Feature wish: Cloning without history","startedAt":"2006-05-18T19:21:44Z","lastAt":"2006-05-19T22:56:16Z","messageCount":7,"participants":["Sven Ekman","Jakub Narebski","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"20242","messageId":"20060518192144.15912.qmail@web25913.mail.ukl.yahoo.com","threadId":"4196","inReplyTo":null,"subject":"Feature wish: Cloning without history","fromName":"Sven Ekman","fromEmail":"svekman@yahoo.se","sentAt":"2006-05-18T19:21:44Z","receivedAt":"2006-05-18T19:21:44Z","isPatch":false,"sender":{"key":"svekman@yahoo.se","avatar":null},"body":"Hello,\n\nWould it be possible to add an option to git-clone to\nskip the complete history? The result should be a\nrepository which contains the current head only (or\nmaybe a specified tag) and has that commit id added to\n.git/info/grafts. For the fetch process, this would\ncertainly have to imply the --no-tags flag.\n\n>From a user's point of view I'd imagine something like\nthis:\n\ngit-clone --no-history=v2.6.16 \\\n    git://git.kernel.org/.../linux-2.6.git\n\nThe background: I'm regularly building kernels for a\nhandful of machines, and while I am happy to use the\nblessings of git to get updates from the -stable\nreleases, I see no point in wasting space for a copy\nof the complete kernel history on every single\nmachine. In practice this works pretty good, once I\nhave manually created such a castrated repository.\n\nSven\n"},{"id":"20243","messageId":"e4ii8u$p7j$1@sea.gmane.org","threadId":"4196","inReplyTo":"20060518192144.15912.qmail@web25913.mail.ukl.yahoo.com","subject":"Re: Feature wish: Cloning without history","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-05-18T19:35:05Z","receivedAt":"2006-05-18T19:35:05Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Sven Ekman wrote:\n\n> Would it be possible to add an option to git-clone to\n> skip the complete history? The result should be a\n> repository which contains the current head only (or\n> maybe a specified tag) and has that commit id added to\n> .git/info/grafts. For the fetch process, this would\n> certainly have to imply the --no-tags flag.\n\nIt is certainly reccuring request.\n\nCheck for \"shallow clone\" in git mailing list archives.\n\n-- \nJakub Narebski\nWarsaw, Poland\n"},{"id":"20261","messageId":"7vodxulnqx.fsf_-_@assigned-by-dhcp.cox.net","threadId":"4196","inReplyTo":"20060518192144.15912.qmail@web25913.mail.ukl.yahoo.com","subject":"[PATCH] built-in tar-tree and remote tar-tree","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-05-19T03:03:34Z","receivedAt":"2006-05-19T03:03:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This makes tar-tree a built-in.  As an added bonus, you can now\nsay:\n\n\tgit tar-tree --remote=remote-repository <ent> [<base>]\n\nThis does not work with git-daemon yet, but should work with\nlocalhost and git over ssh transports.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n * It comes up every once in a while that somebody says he wants\n   a shallow clone, but when asked \"what for?\" it turns out that\n   what is wanted is the ability to download a tarball for a\n   specific revision for building that version, so here is one.\n\n   If people think this is a useful thing, we would need to\n   teach git-daemon about git-upload-tar, and perhaps we would\n   also want to compress the tar image while it goes over the\n   wire, which would be more work.\n\n Makefile                         |    8 +++--\n tar-tree.c => builtin-tar-tree.c |   62 +++++++++++++++++++++++++++++++++++-\n builtin-upload-tar.c             |   66 ++++++++++++++++++++++++++++++++++++++\n builtin.h                        |    2 +\n git.c                            |    2 +\n 5 files changed, 135 insertions(+), 5 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 2149fb8..caf1e70 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -161,7 +161,7 @@ PROGRAMS = \\\n \tgit-receive-pack$X git-rev-parse$X \\\n \tgit-send-pack$X git-show-branch$X git-shell$X \\\n \tgit-show-index$X git-ssh-fetch$X \\\n-\tgit-ssh-upload$X git-tar-tree$X git-unpack-file$X \\\n+\tgit-ssh-upload$X git-unpack-file$X \\\n \tgit-unpack-objects$X git-update-index$X git-update-server-info$X \\\n \tgit-upload-pack$X git-verify-pack$X git-write-tree$X \\\n \tgit-update-ref$X git-symbolic-ref$X \\\n@@ -170,7 +170,8 @@ PROGRAMS = \\\n \n BUILT_INS = git-log$X git-whatchanged$X git-show$X \\\n \tgit-count-objects$X git-diff$X git-push$X \\\n-\tgit-grep$X git-rev-list$X git-check-ref-format$X\n+\tgit-grep$X git-rev-list$X git-check-ref-format$X \\\n+\tgit-tar-tree$X git-upload-tar$X\n \n # what 'all' will build and 'install' will install, in gitexecdir\n ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)\n@@ -218,7 +219,8 @@ LIB_OBJS = \\\n \n BUILTIN_OBJS = \\\n \tbuiltin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \\\n-\tbuiltin-grep.o builtin-rev-list.o builtin-check-ref-format.o\n+\tbuiltin-grep.o builtin-rev-list.o builtin-check-ref-format.o \\\n+\tbuiltin-tar-tree.o builtin-upload-tar.o\n \n GITLIBS = $(LIB_FILE) $(XDIFF_LIB)\n LIBS = $(GITLIBS) -lz\ndiff --git a/tar-tree.c b/builtin-tar-tree.c\nsimilarity index 86%\nrename from tar-tree.c\nrename to builtin-tar-tree.c\nindex 3308736..e97e0af 100644\n--- a/tar-tree.c\n+++ b/builtin-tar-tree.c\n@@ -7,11 +7,14 @@ #include \"tree-walk.h\"\n #include \"commit.h\"\n #include \"strbuf.h\"\n #include \"tar.h\"\n+#include \"builtin.h\"\n+#include \"pkt-line.h\"\n \n #define RECORDSIZE\t(512)\n #define BLOCKSIZE\t(RECORDSIZE * 20)\n \n-static const char tar_tree_usage[] = \"git-tar-tree <key> [basedir]\";\n+static const char tar_tree_usage[] =\n+\"git-tar-tree [--remote=<repo>] <ent> [basedir]\";\n \n static char block[BLOCKSIZE];\n static unsigned long offset;\n@@ -301,7 +304,7 @@ static void traverse_tree(struct tree_de\n \t}\n }\n \n-int main(int argc, char **argv)\n+int generate_tar(int argc, const char **argv)\n {\n \tunsigned char sha1[20], tree_sha1[20];\n \tstruct commit *commit;\n@@ -348,3 +351,58 @@ int main(int argc, char **argv)\n \tfree(current_path.buf);\n \treturn 0;\n }\n+\n+static const char *exec = \"git-upload-tar\";\n+\n+static int remote_tar(int argc, const char **argv)\n+{\n+\tint fd[2], ret, len;\n+\tpid_t pid;\n+\tchar buf[1024];\n+\tchar *url;\n+\n+\tif (argc < 3 || 4 < argc)\n+\t\tusage(tar_tree_usage);\n+\n+\t/* --remote=<repo> */\n+\turl = strdup(argv[1]+9);\n+\tpid = git_connect(fd, url, exec);\n+\tif (pid < 0)\n+\t\treturn 1;\n+\n+\tpacket_write(fd[1], \"want %s\\n\", argv[2]);\n+\tif (argv[3])\n+\t\tpacket_write(fd[1], \"base %s\\n\", argv[3]);\n+\tpacket_flush(fd[1]);\n+\n+\tlen = packet_read_line(fd[0], buf, sizeof(buf));\n+\tif (!len)\n+\t\tdie(\"git-tar-tree: expected ACK/NAK, got EOF\");\n+\tif (buf[len-1] == '\\n')\n+\t\tbuf[--len] = 0;\n+\tif (strcmp(buf, \"ACK\")) {\n+\t\tif (5 < len && !strncmp(buf, \"NACK \", 5))\n+\t\t\tdie(\"git-tar-tree: NACK %s\", buf + 5);\n+\t\tdie(\"git-tar-tree: protocol error\");\n+\t}\n+\t/* expect a flush */\n+\tlen = packet_read_line(fd[0], buf, sizeof(buf));\n+\tif (len)\n+\t\tdie(\"git-tar-tree: expected a flush\");\n+\n+\t/* Now, start reading from fd[0] and spit it out to stdout */\n+\tret = copy_fd(fd[0], 1);\n+\tclose(fd[0]);\n+\n+\tret |= finish_connect(pid);\n+\treturn !!ret;\n+}\n+\n+int cmd_tar_tree(int argc, const char **argv, char **envp)\n+{\n+\tif (argc < 2)\n+\t\tusage(tar_tree_usage);\n+\tif (!strncmp(\"--remote=\", argv[1], 9))\n+\t\treturn remote_tar(argc, argv);\n+\treturn generate_tar(argc, argv);\n+}\ndiff --git a/builtin-upload-tar.c b/builtin-upload-tar.c\nnew file mode 100644\nindex 0000000..883b5aa\n--- /dev/null\n+++ b/builtin-upload-tar.c\n@@ -0,0 +1,66 @@\n+/*\n+ * Copyright (c) 2006 Junio C Hamano\n+ */\n+#include \"cache.h\"\n+#include \"pkt-line.h\"\n+#include \"exec_cmd.h\"\n+#include \"builtin.h\"\n+\n+static const char upload_tar_usage[] = \"git-upload-tar <repo>\";\n+\n+static int nack(const char *reason)\n+{\n+\tpacket_write(1, \"NACK %s\\n\", reason);\n+\tpacket_flush(1);\n+\treturn 1;\n+}\n+\n+int cmd_upload_tar(int argc, const char **argv, char **envp)\n+{\n+\tint len;\n+\tchar *dir = argv[1];\n+\tchar buf[8129];\n+\tunsigned char sha1[20];\n+\tchar *base = NULL;\n+\tchar hex[41];\n+\tint ac;\n+\tconst char *av[4];\n+\n+\tif (argc != 2)\n+\t\tusage(upload_tar_usage);\n+\tif (!enter_repo(dir, 0))\n+\t\treturn nak(\"not a git archive\", dir);\n+\tlen = packet_read_line(0, buf, sizeof(buf));\n+\tif (len < 5 || strncmp(\"want \", buf, 5))\n+\t\treturn nak(\"expected want\");\n+\tif (buf[len-1] == '\\n')\n+\t\tbuf[--len] = 0;\n+\tif (get_sha1(buf + 5, sha1))\n+\t\treturn nak(\"expected sha1\");\n+        strcpy(hex, sha1_to_hex(sha1));\n+\n+\tlen = packet_read_line(0, buf, sizeof(buf));\n+\tif (len) {\n+\t\tif (len < 5 || strncmp(\"base \", buf, 5))\n+\t\t\treturn nak(\"expected (optional) base\");\n+\t\tif (buf[len-1] == '\\n')\n+\t\t\tbuf[--len] = 0;\n+\t\tbase = strdup(buf + 5);\n+\t\tlen = packet_read_line(0, buf, sizeof(buf));\n+\t}\n+\tif (len)\n+\t\treturn nak(\"expected flush\");\n+\n+\tpacket_write(1, \"ACK\\n\");\n+\tpacket_flush(1);\n+\n+\tac = 0;\n+\tav[ac++] = \"tar-tree\";\n+\tav[ac++] = hex;\n+\tif (base)\n+\t\tav[ac++] = base;\n+\tav[ac++] = NULL;\n+\texecv_git_cmd(av);\n+\t/* should it return that is an error */\n+\treturn 1;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex ff559de..3ed5d65 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -26,5 +26,7 @@ extern int cmd_push(int argc, const char\n extern int cmd_grep(int argc, const char **argv, char **envp);\n extern int cmd_rev_list(int argc, const char **argv, char **envp);\n extern int cmd_check_ref_format(int argc, const char **argv, char **envp);\n+extern int cmd_tar_tree(int argc, const char **argv, char **envp);\n+extern int cmd_upload_tar(int argc, const char **argv, char **envp);\n \n #endif\ndiff --git a/git.c b/git.c\nindex d0650bb..79d81b1 100644\n--- a/git.c\n+++ b/git.c\n@@ -50,6 +50,8 @@ static void handle_internal_command(int \n \t\t{ \"count-objects\", cmd_count_objects },\n \t\t{ \"diff\", cmd_diff },\n \t\t{ \"grep\", cmd_grep },\n+\t\t{ \"tar-tree\", cmd_tar_tree },\n+\t\t{ \"upload-tar\", cmd_upload_tar },\n \t\t{ \"rev-list\", cmd_rev_list },\n \t\t{ \"check-ref-format\", cmd_check_ref_format }\n \t};\n-- \n1.3.3.gfad60\n"},{"id":"20267","messageId":"7v7j4ik1fr.fsf@assigned-by-dhcp.cox.net","threadId":"4196","inReplyTo":"7vodxulnqx.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] built-in tar-tree and remote tar-tree","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-05-19T05:50:48Z","receivedAt":"2006-05-19T05:50:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sorry for sending a crapoid that does not even compile.  I ran\nformat-patch while on a wrong branch.\n\nTonight's \"pu\" will have a fixed up one for people who are\ninterested to play with.\n"},{"id":"20300","messageId":"20060519214318.38240.qmail@web25910.mail.ukl.yahoo.com","threadId":"4196","inReplyTo":"7v7j4ik1fr.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] built-in tar-tree and remote tar-tree","fromName":"Sven Ekman","fromEmail":"svekman@yahoo.se","sentAt":"2006-05-19T21:43:18Z","receivedAt":"2006-05-19T21:43:18Z","isPatch":true,"sender":{"key":"svekman@yahoo.se","avatar":null},"body":"Junio C Hamano <junkio@cox.net> skrev:\n\n> Sorry for sending a crapoid that does not even\n> compile.  I ran format-patch while on a wrong \n> branch.\n> \n> Tonight's \"pu\" will have a fixed up one for \n> people who are interested to play with.\n\nHi Junio,\n\nThanks for your answer. I'm looking forward to try the\nremote tar-tree at the weekend.  While this will\ndefinitely make it much more easy to grab single\nrevisions out of a git tree, it only solves a part of\nthe issue I was trying to address. If one wanted a\nsimple snapshot of the source, it's usually easier to\ndownload a tarball. \n\nThe great thing about having the kernel source in a\ngit repository is that it lets me upgrade the kernel\nsource tree in place with a single simple command. No\nfiring up a browser, downloading and applying a patch.\nIt is also braindead easy to maintain a set of local\npatches across different kernel versions. Git makes\nall this quick and easy.\n\nIs there a simple way to retrieve a single object or a\nlist of objects _without_ any of their parents? If so\none could retrieve the wanted commit and the\ncorresponding tree and parse it on the client side to\nretrieve its descendents and commits.  If so, the\nnumber of roundtrips would be roughly proportional to\nthe depth of the trees, which would probably still be\nacceptable.\n\nGreetings, Sven\n"},{"id":"20301","messageId":"e4let3$17u$1@sea.gmane.org","threadId":"4196","inReplyTo":"20060519214318.38240.qmail@web25910.mail.ukl.yahoo.com","subject":"Re: [PATCH] built-in tar-tree and remote tar-tree","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-05-19T21:56:03Z","receivedAt":"2006-05-19T21:56:03Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Sven Ekman wrote:\n\n> Is there a simple way to retrieve a single object or a\n> list of objects _without_ any of their parents? If so\n> one could retrieve the wanted commit and the\n> corresponding tree and parse it on the client side to\n> retrieve its descendents and commits.  If so, the\n> number of roundtrips would be roughly proportional to\n> the depth of the trees, which would probably still be\n> acceptable.\n\nPerhaps alternates file which points to _remote_ git repository, \nleaving all unused objects at remote directory, and needing constant\nnet access to said remote repository for almost all operations?\n\n-- \nJakub Narebski\nWarsaw, Poland\n"},{"id":"20306","messageId":"7vbqtthbe7.fsf@assigned-by-dhcp.cox.net","threadId":"4196","inReplyTo":"20060519214318.38240.qmail@web25910.mail.ukl.yahoo.com","subject":"Re: [PATCH] built-in tar-tree and remote tar-tree","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-05-19T22:56:16Z","receivedAt":"2006-05-19T22:56:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sven Ekman <svekman@yahoo.se> writes:\n\n> Thanks for your answer. I'm looking forward to try the\n> remote tar-tree at the weekend.\n\nA word of caution.  This obviously needs the updated stuff on\nboth ends.  The downloader needs to have updated tar-tree, and\nthe other end needs the new command upload-tar.\n\n> Is there a simple way to retrieve a single object or a\n> list of objects _without_ any of their parents?\n\nThe thing is, I do not think that is what you really want.\n\nIf you do not have the necessary parents, many of the benefit\nyou list as \"why do I want kernel from git repo\" would not work.\nThe next fetch will try to see where the common ancestry commit\nis, in order to download only from that one, for example. For\nthat you would need a well formed repositories on both ends.\n\nObviously bisect and anything that deal with the traversal of\nancestry chain would break, and while you would say \"I accept\nthat some things may not work\", their failure mode do not even\nconsider that the user might start from such an incomplete\nrepositories to begin with, so one thing is that the user would\nbe very confused, and another thing is that I would not be\nsurprised if some operations further \"corrupt\" such an already\nincomplete repository (fsck, prune and probably bisect when it\ntries to rewind the bisection branch -- your branch head may\npoint at nowhere and the user might need to do manual update-ref\ninstead of \"git checkout master\" to recover from it), causing\nfurther grief.\n\nIn other words, to support such partial/incomplete repositories\nproperly, you are talking about a major major surgery.  I just\ndo not want to think about it right now.\n\nOn the other hand, the primary point of my patch is that the\nresult does _not_ pretend it is a proper git repository, so we\ndo not have to worry about all the above issues.\n"}]}