{"thread":{"id":"15391","subject":"Is \"show-ref -h\" a good test for an empty repository?","startedAt":"2008-09-06T00:45:34Z","lastAt":"2008-09-08T14:42:00Z","messageCount":8,"participants":["Eric Gerlach","Jeff King","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"89885","messageId":"48C1D2AE.3010001@feds.uwaterloo.ca","threadId":"15391","inReplyTo":null,"subject":"Is \"show-ref -h\" a good test for an empty repository?","fromName":"Eric Gerlach","fromEmail":"egerlach@feds.uwaterloo.ca","sentAt":"2008-09-06T00:45:34Z","receivedAt":"2008-09-06T00:45:34Z","isPatch":false,"sender":{"key":"egerlach@feds.uwaterloo.ca","avatar":null},"body":"Hi,\n\nI'm trying to test to see if \"git diff --cached\" will fail because there \nare no existing commits.  I've come up with running \"git show-ref -h -q\" \nand testing its return value.  My hypothesis is: If and only if \ngit-show-ref succeeds then git-diff will succeed.\n\nAre my logic and assumptions sound?  I'm a bit out of my git comfort \nzone here, so I'd like to get some validation from some people who know \nbetter.\n\nThanks in advance for the help!\n\nCheers,\n\n-- \nEric Gerlach, Network Administrator\nFederation of Students\nUniversity of Waterloo\np: (519) 888-4567 x36329\ne: egerlach@feds.uwaterloo.ca\n"},{"id":"89886","messageId":"20080906012941.GA2009@coredump.intra.peff.net","threadId":"15391","inReplyTo":"48C1D2AE.3010001@feds.uwaterloo.ca","subject":"Re: Is \"show-ref -h\" a good test for an empty repository?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-09-06T01:29:41Z","receivedAt":"2008-09-06T01:29:41Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Sep 05, 2008 at 08:45:34PM -0400, Eric Gerlach wrote:\n\n> I'm trying to test to see if \"git diff --cached\" will fail because there  \n> are no existing commits.  I've come up with running \"git show-ref -h -q\"  \n> and testing its return value.  My hypothesis is: If and only if  \n> git-show-ref succeeds then git-diff will succeed.\n>\n> Are my logic and assumptions sound?  I'm a bit out of my git comfort zone \n> here, so I'd like to get some validation from some people who know  \n> better.\n\nMaybe \"git rev-parse --verify HEAD\"?\n\n-Peff\n"},{"id":"89975","messageId":"48C3E35C.2050903@feds.uwaterloo.ca","threadId":"15391","inReplyTo":"20080906012941.GA2009@coredump.intra.peff.net","subject":"Re: Is \"show-ref -h\" a good test for an empty repository?","fromName":"Eric Gerlach","fromEmail":"egerlach@feds.uwaterloo.ca","sentAt":"2008-09-07T14:21:16Z","receivedAt":"2008-09-07T14:21:16Z","isPatch":false,"sender":{"key":"egerlach@feds.uwaterloo.ca","avatar":null},"body":"Jeff King wrote:\n> On Fri, Sep 05, 2008 at 08:45:34PM -0400, Eric Gerlach wrote:\n> \n>> I'm trying to test to see if \"git diff --cached\" will fail because there  \n>> are no existing commits.  I've come up with running \"git show-ref -h -q\"  \n>> and testing its return value.  My hypothesis is: If and only if  \n>> git-show-ref succeeds then git-diff will succeed.\n>>\n>> Are my logic and assumptions sound?  I'm a bit out of my git comfort zone \n>> here, so I'd like to get some validation from some people who know  \n>> better.\n> \n> Maybe \"git rev-parse --verify HEAD\"?\n\nThat seems like it would work too... any reason one would be better than \nthe other?\n\nCheers,\n\nEric Gerlach\n"},{"id":"89976","messageId":"20080907155033.GA25031@coredump.intra.peff.net","threadId":"15391","inReplyTo":"48C3E35C.2050903@feds.uwaterloo.ca","subject":"Re: Is \"show-ref -h\" a good test for an empty repository?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-09-07T15:50:33Z","receivedAt":"2008-09-07T15:50:33Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Sep 07, 2008 at 10:21:16AM -0400, Eric Gerlach wrote:\n\n>>> I'm trying to test to see if \"git diff --cached\" will fail because \n>>> there  are no existing commits.  I've come up with running \"git \n>>> show-ref -h -q\"  and testing its return value.  My hypothesis is: If \n>>\n>> Maybe \"git rev-parse --verify HEAD\"?\n>\n> That seems like it would work too... any reason one would be better than  \n> the other?\n\nMy thinking was:\n\n  1. It's a plumbing command, and so less likely to change its behavior\n     versus \"git diff\".\n\n  2. The seems more obvious to me. rev-parse --verify is meant to ask\n     \"is this a valid object name?\"\n\nIt is slightly different from your show-ref. Yours asks \"is there\nanything in refs/heads in this repository?\" Mine asks \"does the current\nHEAD exist?\" In practice, they are both reasonable tests, since once you\nhave a branch, it is very difficult to get HEAD to point to something\ninvalid short of editing manually to some bogus value. But you might\nprefer one over the other depending on what you are trying to say.\n\n-Peff\n"},{"id":"89986","messageId":"7vprnfn9pz.fsf@gitster.siamese.dyndns.org","threadId":"15391","inReplyTo":"20080907155033.GA25031@coredump.intra.peff.net","subject":"Re: Is \"show-ref -h\" a good test for an empty repository?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-09-07T17:31:52Z","receivedAt":"2008-09-07T17:31:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Sun, Sep 07, 2008 at 10:21:16AM -0400, Eric Gerlach wrote:\n>\n>>>> I'm trying to test to see if \"git diff --cached\" will fail because \n>>>> there  are no existing commits.  I've come up with running \"git \n>>>> show-ref -h -q\"  and testing its return value.  My hypothesis is: If \n>>>\n>>> Maybe \"git rev-parse --verify HEAD\"?\n>>\n>> That seems like it would work too... any reason one would be better than  \n>> the other?\n>\n> My thinking was:\n>\n>   1. It's a plumbing command, and so less likely to change its behavior\n>      versus \"git diff\".\n>\n>   2. The seems more obvious to me. rev-parse --verify is meant to ask\n>      \"is this a valid object name?\"\n>\n> It is slightly different from your show-ref. Yours asks \"is there\n> anything in refs/heads in this repository?\" Mine asks \"does the current\n> HEAD exist?\" In practice, they are both reasonable tests, since once you\n> have a branch, it is very difficult to get HEAD to point to something\n> invalid short of editing manually to some bogus value. But you might\n> prefer one over the other depending on what you are trying to say.\n\nAll depends on how \"an empty repository\" is defined.  My definition of an\nempty repository would have been:\n\n - No objects in it;\n - No index;\n - No refs except symrefs.\n"},{"id":"89987","messageId":"20080907173434.GA26182@coredump.intra.peff.net","threadId":"15391","inReplyTo":"7vprnfn9pz.fsf@gitster.siamese.dyndns.org","subject":"Re: Is \"show-ref -h\" a good test for an empty repository?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-09-07T17:34:34Z","receivedAt":"2008-09-07T17:34:34Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Sep 07, 2008 at 10:31:52AM -0700, Junio C Hamano wrote:\n\n> All depends on how \"an empty repository\" is defined.  My definition of an\n> empty repository would have been:\n> \n>  - No objects in it;\n>  - No index;\n>  - No refs except symrefs.\n\nAgreed. In the original message, he used the phrase \"no existing\ncommits\" which I latched onto (to mean \"no existing commits on this\nbranch\"). But the subject does say \"empty repository\". :)\n\nEric, maybe you can tell us more about what you're trying to accomplish?\n\n-Peff\n"},{"id":"90078","messageId":"48C52797.3030500@feds.uwaterloo.ca","threadId":"15391","inReplyTo":"20080907173434.GA26182@coredump.intra.peff.net","subject":"Re: Is \"show-ref -h\" a good test for an empty repository?","fromName":"Eric Gerlach","fromEmail":"egerlach@feds.uwaterloo.ca","sentAt":"2008-09-08T13:24:39Z","receivedAt":"2008-09-08T13:24:39Z","isPatch":false,"sender":{"key":"egerlach@feds.uwaterloo.ca","avatar":null},"body":"Jeff King wrote:\n> On Sun, Sep 07, 2008 at 10:31:52AM -0700, Junio C Hamano wrote:\n> \n>> All depends on how \"an empty repository\" is defined.  My definition of an\n>> empty repository would have been:\n>>\n>>  - No objects in it;\n>>  - No index;\n>>  - No refs except symrefs.\n> \n> Agreed. In the original message, he used the phrase \"no existing\n> commits\" which I latched onto (to mean \"no existing commits on this\n> branch\"). But the subject does say \"empty repository\". :)\n> \n> Eric, maybe you can tell us more about what you're trying to accomplish?\n\nSure, I'm writing a patch for the debcommit script for the Debian \nproject.  It's a script which parses the Debian changelog for a package, \ngenerates a commit message, and commits to an SCM system.\n\nThe case I'm looking to protect against is the following:\n\n$ mkdir -p new-repo/debian\n$ cd new-repo\n$ git init\n$ vi debian/changelog (add a few lines)\n$ git add debian/changelog\n$ debcommit\n\n(which runs\n$ git diff --cached debian/changelog)\n\nIf I can test before the git-diff, then I can run \"diff debian/changelog \n/dev/null\" instead of the git-diff and all is well.\n\nI don't want to test failure of the git-diff itself, because I want \ndebcommit to fail if there's something wrong *other* than a new repo. \nAlso, I want to use a git command to do it, because I don't have any \nguarantees about how things are setup, other than \"we're using git.\"\n\nI'm okay with debcommit proceeding if the repo has a commit but is \nborked from manually editing the HEAD ref, but I'm not sure how the \nmaintainers of the script feel about that.  So if it's possible to \ndifferentiate between the two cases, bonus, but not necessary.\n\nSo that's where I'm sitting.  Jeff and Junio, thanks for the help and \ndiscussion.  This is great :-)\n\n(BTW, I'm leaning to the rev-parse right now; looking at the source it \nseems to be more precise, i.e. has fewer ways to fail)\n\nCheers,\n\nEric\n"},{"id":"90085","messageId":"20080908144159.GA10331@coredump.intra.peff.net","threadId":"15391","inReplyTo":"48C52797.3030500@feds.uwaterloo.ca","subject":"Re: Is \"show-ref -h\" a good test for an empty repository?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-09-08T14:42:00Z","receivedAt":"2008-09-08T14:42:00Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Sep 08, 2008 at 09:24:39AM -0400, Eric Gerlach wrote:\n\n> The case I'm looking to protect against is the following:\n>\n> $ mkdir -p new-repo/debian\n> $ cd new-repo\n> $ git init\n> $ vi debian/changelog (add a few lines)\n> $ git add debian/changelog\n> $ debcommit\n>\n> (which runs\n> $ git diff --cached debian/changelog)\n>\n> If I can test before the git-diff, then I can run \"diff debian/changelog  \n> /dev/null\" instead of the git-diff and all is well.\n\nIn that case, I would use the \"rev-parse --verify HEAD\" I mentioned,\nsince it exactly covers the situation you are trying to avoid.  What you\nare saying is something like:\n\n  if there is a previous commit on the current branch\n    diff against previous commit on the current branch\n  else\n    diff against /dev/null\n\nSo your \"show-ref\" attempt could actually say \"yes, the repo is\nnon-empty\" but your diff would still fail (because the commits just\nweren't on the current branch).\n\n\nAs an aside, it's too bad \"--root\" isn't more widely supported. Then\n\n  git diff --root --cached\n\nwould do what you want without the need for any conditionals. But it\nseems that --root only works between trees. Something like the patch\nbelow would help, but I'm sure this is covering only one of many cases.\n\n---\n\ndiff --git a/builtin-diff.c b/builtin-diff.c\nindex 52470c7..43db970 100644\n--- a/builtin-diff.c\n+++ b/builtin-diff.c\n@@ -317,8 +317,11 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \t\t\t\tbreak;\n \t\t\telse if (!strcmp(arg, \"--cached\")) {\n \t\t\t\tadd_head_to_pending(&rev);\n-\t\t\t\tif (!rev.pending.nr)\n-\t\t\t\t\tdie(\"No HEAD commit to compare with (yet)\");\n+\t\t\t\tif (!rev.pending.nr) {\n+\t\t\t\t\tif (!rev.show_root_diff)\n+\t\t\t\t\t\tdie(\"No HEAD commit to compare with (yet)\");\n+\t\t\t\t\tadd_empty_to_pending(&rev);\n+\t\t\t\t}\n \t\t\t\tbreak;\n \t\t\t}\n \t\t}\ndiff --git a/revision.c b/revision.c\nindex 2f646de..7ec3990 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -145,16 +145,27 @@ void add_pending_object(struct rev_info *revs, struct object *obj, const char *n\n \tadd_pending_object_with_mode(revs, obj, name, S_IFINVALID);\n }\n \n-void add_head_to_pending(struct rev_info *revs)\n+static void add_to_pending_by_name(struct rev_info *revs, const char *name)\n {\n \tunsigned char sha1[20];\n \tstruct object *obj;\n-\tif (get_sha1(\"HEAD\", sha1))\n+\tif (get_sha1(name, sha1))\n \t\treturn;\n \tobj = parse_object(sha1);\n \tif (!obj)\n \t\treturn;\n-\tadd_pending_object(revs, obj, \"HEAD\");\n+\tadd_pending_object(revs, obj, name);\n+}\n+\n+void add_head_to_pending(struct rev_info *revs)\n+{\n+\tadd_to_pending_by_name(revs, \"HEAD\");\n+}\n+\n+void add_empty_to_pending(struct rev_info *revs)\n+{\n+\tadd_to_pending_by_name(revs,\n+\t\t\t\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\");\n }\n \n static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)\ndiff --git a/revision.h b/revision.h\nindex 2fdb2dd..8c990d5 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -152,6 +152,7 @@ extern void add_object(struct object *obj,\n extern void add_pending_object(struct rev_info *revs, struct object *obj, const char *name);\n \n extern void add_head_to_pending(struct rev_info *);\n+extern void add_empty_to_pending(struct rev_info *);\n \n enum commit_action {\n \tcommit_ignore,\n"}]}