{"thread":{"id":"14114","subject":"[PATCH/RFC] Created git-basis and modified git-bundle to accept --stdin.","startedAt":"2008-06-24T02:21:44Z","lastAt":"2008-06-25T01:14:41Z","messageCount":6,"participants":["Adam Brewster","Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"80822","messageId":"c376da900806231921y2d822been9cd573d509fbf78a@mail.gmail.com","threadId":"14114","inReplyTo":"1214273297-8257-2-git-send-email-adambrewster@gmail.com","subject":"[PATCH/RFC] Created git-basis and modified git-bundle to accept --stdin.","fromName":"Adam Brewster","fromEmail":"adam@adambrewster.com","sentAt":"2008-06-24T02:21:44Z","receivedAt":"2008-06-24T02:21:44Z","isPatch":true,"sender":{"key":"adam@adambrewster.com","avatar":null},"body":"Git-basis is a perl script that remembers bases for use by git-bundle.\nCode from rev-parse was borrowed to allow git-bundle to handle --stdin.\n\nSigned-off-by: Adam Brewster <adambrewster@gmail.com>\n---\nGit-bundle is a great tool to move repositories between computers on\ndifferent networks, but in order to create thin packs, it needs to be\ngiven a list of objects that are available on the remote end.  I don't\nlike any of the options listed in the git-bundle documentation, so I did\nthis.\n\nGit-basis is a script that maintains lists of objects that exist in\nvarious places.\n\nWith this patch, the command:\n\ngit-basis my-basis | git-bundle create my-bundle --all --stdin\n\nwill prepare a bundle containing everything except that which is a part\nof my-basis.\n\nThen you can add the objects in the bundle to the basis, so they won't\nget included in the next pack like this:\n\ngit-basis --update my-basis < my-bundle\n\nI'm sure that my implementation is crap, but I think this is a useful\nidea.  Anybody agree?  Disagree?\n\n bundle.c  |   22 +++++++++++++++++-\n git-basis |   71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 91 insertions(+), 2 deletions(-)\n create mode 100755 git-basis\n\ndiff --git a/bundle.c b/bundle.c\nindex 0ba5df1..0af12d7 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -227,8 +227,26 @@ int create_bundle(struct bundle_header *header,\nconst char *path,\n\n       /* write references */\n       argc = setup_revisions(argc, argv, &revs, NULL);\n-       if (argc > 1)\n-               return error(\"unrecognized argument: %s'\", argv[1]);\n+\n+       for (i = 1; i < argc; i++) {\n+               if ( !strcmp(argv[i], \"--stdin\") ) {\n+                       char line[1000];\n+                               while (fgets(line, sizeof(line),\nstdin) != NULL) {\n+                               int len = strlen(line);\n+                               if (len && line[len - 1] == '\\n')\n+                                       line[--len] = 0;\n+                               if (!len)\n+                                       break;\n+                               if (line[0] == '-')\n+                                       die(\"options not supported in\n--stdin mode\");\n+                               if (handle_revision_arg(line, &revs, 0, 1))\n+                                       die(\"bad revision '%s'\", line);\n+                       }\n+                       continue;\n+               }\n+\n+               return error(\"unrecognized argument: %s'\", argv[i]);\n+       }\n\n       for (i = 0; i < revs.pending.nr; i++) {\n               struct object_array_entry *e = revs.pending.objects + i;\ndiff --git a/git-basis b/git-basis\nnew file mode 100755\nindex 0000000..891635c\n--- /dev/null\n+++ b/git-basis\n@@ -0,0 +1,71 @@\n+#!/usr/bin/perl\n+\n+use strict;\n+\n+use Git;\n+\n+my $r = Git->repository();\n+my $d = $r->repo_path();\n+\n+if ( ! -d \"$d/bases\" ) {\n+    system( \"mkdir '$d/bases'\" );\n+}\n+\n+if ( $#ARGV == -1 ) {\n+    print \"usage: git-basis [--update] basis1...\\n\";\n+    exit;\n+} elsif ( $ARGV[0] eq '--update' ) {\n+    shift @ARGV;\n+\n+    my %new = ();\n+    while (<STDIN>) {\n+       if (!/^^?([a-z0-9]{40})/) {next;}\n+       $new{$1} = 1;\n+    }\n+\n+    foreach my $f (@ARGV) {\n+       my %these = ();\n+       open F, \"<$d/bases/$f\" || die \"Can't open bases/$f: $!\";\n+       while (<F>) {\n+           if (!/^([a-z0-9]{40})/) {next;}\n+           $these{$1} = 1;\n+       }\n+       close F;\n+       open F, \">>$d/bases/$f\" || die \"Can't open bases/$f: $!\";\n+       print F \"\\#\" . `date`;\n+       foreach my $b (keys %new) {\n+           if (exists($these{$b})) {next;}\n+           print F \"$b\\n\";\n+       }\n+       close F;\n+    }\n+} else {\n+    my $n = 0;\n+    my %basis = ();\n+\n+    my $f = shift @ARGV;\n+    open F, \"<$d/bases/$f\" || die \"Can't open bases/$f: $!\";\n+    while (<F>) {\n+       if (!/^([a-z0-9]{40})/) {next;}\n+       $basis{$1} = $n;\n+    }\n+    close F;\n+\n+    foreach $f (@ARGV) {\n+       open F, \"<$d/bases/$f\" || die \"Can't open bases/$f: $!\";\n+       while (<F>) {\n+           if (!/^([a-z0-9]{40})/) {next;}\n+           if (!exists($basis{$1})) {next;}\n+\n+           if ($basis{$1} == $n) {$basis{$1}++;}\n+           else {delete $basis{$1};}\n+       }\n+       close F;\n+       $n++;\n+    }\n+\n+    foreach my $b (keys %basis) {\n+       if ( $basis{$b} != $n ) {next;}\n+       print \"^$b\\n\";\n+    }\n+}\n--\n1.5.5.1.211.g65ea3.dirty\n"},{"id":"80848","messageId":"m3iqvzl091.fsf@localhost.localdomain","threadId":"14114","inReplyTo":"c376da900806231921y2d822been9cd573d509fbf78a@mail.gmail.com","subject":"Re: [PATCH/RFC] Created git-basis and modified git-bundle to accept --stdin.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-06-24T08:09:10Z","receivedAt":"2008-06-24T08:09:10Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"\"Adam Brewster\" <adam@adambrewster.com> writes:\n\n> Git-basis is a perl script that remembers bases for use by git-bundle.\n> Code from rev-parse was borrowed to allow git-bundle to handle --stdin.\n\nI'd rather you follow git-pack-objects, and use `--revs` for the name\nof this option (or even '--not --revs').  The name `--stdin` might\nimply that you are providing objects names on stdin of git-bundle.\n\nBut perhaps I am worrying over nothing.\n \n[...]\n> Then you can add the objects in the bundle to the basis, so they won't\n> get included in the next pack like this:\n> \n>  $ git-basis --update my-basis < my-bundle\n\nWhy not use \"$(git ls-remote my-bundle)\" somewhere in the invocation\ncreating new bundle instead?\n \n> I'm sure that my implementation is crap, but I think this is a useful\n> idea.  Anybody agree?  Disagree?\n\nDocumentation, please?  Especially that it looks like '--stdin' option\nis a bit tricky...\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"80912","messageId":"c376da900806240830p2a48aff0uaf6f22372fead5ef@mail.gmail.com","threadId":"14114","inReplyTo":"m3iqvzl091.fsf@localhost.localdomain","subject":"Re: [PATCH/RFC] Created git-basis and modified git-bundle to accept --stdin.","fromName":"Adam Brewster","fromEmail":"adam@adambrewster.com","sentAt":"2008-06-24T15:30:38Z","receivedAt":"2008-06-24T15:30:38Z","isPatch":true,"sender":{"key":"adam@adambrewster.com","avatar":null},"body":">> Git-basis is a perl script that remembers bases for use by git-bundle.\n>> Code from rev-parse was borrowed to allow git-bundle to handle --stdin.\n>\n> I'd rather you follow git-pack-objects, and use `--revs` for the name\n> of this option (or even '--not --revs').  The name `--stdin` might\n> imply that you are providing objects names on stdin of git-bundle.\n>\n> But perhaps I am worrying over nothing.\n>\n\nThis seems like a fine idea.\n\n> [...]\n>> Then you can add the objects in the bundle to the basis, so they won't\n>> get included in the next pack like this:\n>>\n>>  $ git-basis --update my-basis < my-bundle\n>\n> Why not use \"$(git ls-remote my-bundle)\" somewhere in the invocation\n> creating new bundle instead?\n>\n\nYou could use \"git ls-remote my-bundle | git-basis --update my-basis\"\nto do the same thing as the command I gave above.\n\n>> I'm sure that my implementation is crap, but I think this is a useful\n>> idea.  Anybody agree?  Disagree?\n>\n> Documentation, please?  Especially that it looks like '--stdin' option\n> is a bit tricky...\n>\n\nI wanted to test the waters and make sure that someone was at least\nvaguely interested in this (no need to document code that is never\ngoing to leave my machine).\n\nI'll prepare another patch with documentation and changing --stdin to\n--revs when I get a chance.\n\nThank you,\nAdam Brewster\n"},{"id":"80944","messageId":"200806242055.53776.jnareb@gmail.com","threadId":"14114","inReplyTo":"c376da900806240830p2a48aff0uaf6f22372fead5ef@mail.gmail.com","subject":"Re: [PATCH/RFC] Created git-basis and modified git-bundle to accept --stdin.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-06-24T18:55:52Z","receivedAt":"2008-06-24T18:55:52Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Adam Brewster wrote:\n\n>> [...]\n>>> Then you can add the objects in the bundle to the basis, so they won't\n>>> get included in the next pack like this:\n>>>\n>>>  $ git-basis --update my-basis < my-bundle\n>>\n>> Why not use \"$(git ls-remote my-bundle)\" somewhere in the invocation\n>> creating new bundle instead?\n>>\n> \n> You could use \"git ls-remote my-bundle | git-basis --update my-basis\"\n> to do the same thing as the command I gave above.\n\nI was thinking about\n\n  $ git bundle create my-bundle --all --not $(git ls-remote my-bundle | cut -f1)\n\n(or `--branches' instead of `--all').  Or, if you don't want to keep\nbundle, but only save basis, just use\n\n  $ git bundle create my-bundle --all --not $(git basis --show my-basis)\n\nNo need for `--stdin' / `--revs' / `--basis' option to git-bundle,\nat the cost of little shell trickery.\n\nOr even\n\n  $ git ls-remote my-bundle | cut -f1 > my-bases\n  [...]\n  $ git bundle create my-bundle --all --not $(cat my-bases)\n\n>>> I'm sure that my implementation is crap, but I think this is a useful\n>>> idea.  Anybody agree?  Disagree?\n>>\n>> Documentation, please?  Especially that it looks like '--stdin' option\n>> is a bit tricky...\n> \n> I wanted to test the waters and make sure that someone was at least\n> vaguely interested in this (no need to document code that is never\n> going to leave my machine).\n\nSee above example, to check if this would be enough...\n\n> I'll prepare another patch with documentation and changing --stdin to\n> --revs when I get a chance.\n\nI'm not sure if another name, like --bases=<filename / basename> wouldn't\nbe better.  Perhaps --stdin is a good name...\n\n-- \nJakub Narebski\nPoland\n"},{"id":"81031","messageId":"8fe92b430806241721j43f9443eu80e16dcd64b8d143@mail.gmail.com","threadId":"14114","inReplyTo":"c376da900806241655q85fc1d9r5bf67096a7930f94@mail.gmail.com","subject":"Re: [PATCH/RFC] Created git-basis and modified git-bundle to accept --stdin.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-06-25T00:21:44Z","receivedAt":"2008-06-25T00:21:44Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On 6/25/08, Adam Brewster <adam@adambrewster.com> wrote:\n>>\n>> I was thinking about\n>>\n>>  $ git bundle create my-bundle --all --not $(git ls-remote my-bundle | cut -f1)\n>\n> Not a bad idea, but it seems like I might be close to the maximum\n>  length for a command line (about 3200 objects) in a couple of cases\n>  (git-svn creates lots of branches).\n\nAh, sorry, I have forgot about that. This is definitely, both in the\ncase of revisions\npacked in bundle, and basis (cutoff) of bundle, case for some kind of --stdin.\n\n>  This also means that I have to remember where I save the old bundles.\n\nThat's what second solution was to save only bases in some file.\n\n>> Or even\n>>\n>>  $ git ls-remote my-bundle | cut -f1 > my-bases\n>>  [...]\n>>  $ git bundle create my-bundle --all --not $(cat my-bases)\n>>\n>\n>\n> That's basically all the perl script does, except it will also create\n>  an intersection of several bases (I don't want to remember the options\n>  to comm).\n\nDoes it prefix bases with ^, i.e. ^basis (negative revision)?\nI think it should, then there would be no need for strange --stdin\nsemantic, or implementing --stdin in such way that --not--stdin\nworks as expected.\n\n>  Now that you mention it, a --basis option in setup_revisions would be\n>  handy, but if I can't sell this, then I probably can't sell that\n>  either.\n\nI think that --stdin would be better idea, as it can be used to enumerate\nall refs to send, even if they are too many or they have too long names  to\nuse arguments.\n\n[...]\n>>> I'll prepare another patch with documentation and changing --stdin to\n>>> --revs when I get a chance.\n>>\n>> I'm not sure if another name, like --bases=<filename / basename> wouldn't\n>> be better.  Perhaps --stdin is a good name...\n>\n> On second thought I'm going to defend my choice of --stdin now that I\n>  remember why I chose it.\n>\n>  The docs for git-bundle specify the syntax is \"git-bundle create\n>  <file> <git-rev-list args>\", where <git-rev-list args> is defined as\n>  \"A list of arguments, acceptable to git-rev-parse and git-rev-list,\n>  that specify the specific objects and references to transport. ...\"\n>  Git-rev-list takes --stdin, so it seems reasonable to expect that\n>  git-bundle will as well.\n\nAhh... git-rev-list... well, I though about git-pack-objects and its different\n--stin semantic (which might make no sense for git-bundle).\n\n[Sorry for bad wrapping, I'm sending it from GMail Web interface]\n-- \nJakub Narebski\n"},{"id":"81033","messageId":"c376da900806241814v22782818w57f53bce5d299ad5@mail.gmail.com","threadId":"14114","inReplyTo":"8fe92b430806241721j43f9443eu80e16dcd64b8d143@mail.gmail.com","subject":"Re: [PATCH/RFC] Created git-basis and modified git-bundle to accept --stdin.","fromName":"Adam Brewster","fromEmail":"adam@adambrewster.com","sentAt":"2008-06-25T01:14:41Z","receivedAt":"2008-06-25T01:14:41Z","isPatch":true,"sender":{"key":"adam@adambrewster.com","avatar":null},"body":">\n> Does it prefix bases with ^, i.e. ^basis (negative revision)?\n> I think it should, then there would be no need for strange --stdin\n> semantic, or implementing --stdin in such way that --not--stdin\n> works as expected.\n>\n\nYes.\n\nI figure that patching to make --not --stdin work how I'd like would\nbreak something else, and implementing --not-stdin seems hackish.\n\nAdam Brewster\n"}]}