{"thread":{"id":"19102","subject":"error: Unable to append to .git/logs/refs/remotes/origin/master: Permission denied","startedAt":"2009-04-28T07:31:38Z","lastAt":"2009-05-25T22:23:54Z","messageCount":8,"participants":["Ingo Molnar","Jeff King","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"112497","messageId":"20090428073138.GA9094@elte.hu","threadId":"19102","inReplyTo":null,"subject":"error: Unable to append to .git/logs/refs/remotes/origin/master: Permission denied","fromName":"Ingo Molnar","fromEmail":"mingo@elte.hu","sentAt":"2009-04-28T07:31:38Z","receivedAt":"2009-04-28T07:31:38Z","isPatch":false,"sender":{"key":"mingo@elte.hu","avatar":null},"body":"\nI had a portion of a repo owned by root accidentally, and the next \ntime i pulled as user mingo Git gave me this warning and suggestion:\n\n aldebaran:~/git> git pull\n error: Unable to append to .git/logs/refs/remotes/origin/master: Permission denied\n From e2:git\n  ! 66996ec..95110d7  master     -> origin/master  (unable to update local ref)\n  * [new tag]         v1.6.3-rc2 -> v1.6.3-rc2\n error: some local refs could not be updated; try running\n  'git remote prune origin' to remove any old, conflicting branches\n\nObviousy Git cannot update the ref there so the failure is OK, but \nthe git-remote advice it gives is confusing IMHO: the 'git remote \nprune origin' cannot fix anything. (and it is clear from the fetch \npermission failure that there's no chance to fix anything here.)\n\nI suspect there are other, more typical failure modes where that \nadvice is useful - just wanted to point out that it's confusing \nhere.\n\n\tIngo\n"},{"id":"112588","messageId":"20090429032943.GB8826@coredump.intra.peff.net","threadId":"19102","inReplyTo":"20090428073138.GA9094@elte.hu","subject":"Re: error: Unable to append to .git/logs/refs/remotes/origin/master: Permission denied","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-04-29T03:29:43Z","receivedAt":"2009-04-29T03:29:43Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Apr 28, 2009 at 09:31:38AM +0200, Ingo Molnar wrote:\n\n>  aldebaran:~/git> git pull\n>  error: Unable to append to .git/logs/refs/remotes/origin/master: Permission denied\n>  From e2:git\n>   ! 66996ec..95110d7  master     -> origin/master  (unable to update local ref)\n>   * [new tag]         v1.6.3-rc2 -> v1.6.3-rc2\n>  error: some local refs could not be updated; try running\n>   'git remote prune origin' to remove any old, conflicting branches\n> \n> Obviousy Git cannot update the ref there so the failure is OK, but \n> the git-remote advice it gives is confusing IMHO: the 'git remote \n> prune origin' cannot fix anything. (and it is clear from the fetch \n> permission failure that there's no chance to fix anything here.)\n> \n> I suspect there are other, more typical failure modes where that \n> advice is useful - just wanted to point out that it's confusing \n> here.\n\nYeah, I knew that when I wrote it:\n\n  $ git log -1 --format=%s%n%b f3cb169\n  fetch: give a hint to the user when local refs fail to update\n  There are basically two categories of update failures for\n  local refs:\n\n    1. problems outside of git, like disk full, bad\n       permissions, etc.\n\n    2. D/F conflicts on tracking branch ref names\n\n  In either case, there should already have been an error\n  message. In case '1', hopefully enough information has\n  already been given that the user can fix it. In the case of\n  '2', we can hint that the user can clean up their tracking\n  branch area by using 'git remote prune'.\n\n  Note that we don't actually know _which_ case we have, so\n  the user will receive the hint in case 1, as well. In this\n  case the suggestion won't do any good, but hopefully the\n  user is smart enough to figure out that it's just a hint.\n\nNote the repeated use of \"hopefully\". :) Maybe the earlier message is\ntoo hidden to rely on. We might be able to get by with checking \"errno\"\nfor ENOTDIR after trying to lock the ref and using a different message,\nbut I don't know how portable that will be.\n\n-Peff\n"},{"id":"112589","messageId":"20090429040719.GA14912@coredump.intra.peff.net","threadId":"19102","inReplyTo":"20090429032943.GB8826@coredump.intra.peff.net","subject":"Re: error: Unable to append to .git/logs/refs/remotes/origin/master: Permission denied","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-04-29T04:07:20Z","receivedAt":"2009-04-29T04:07:20Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Apr 28, 2009 at 11:29:43PM -0400, Jeff King wrote:\n\n> Note the repeated use of \"hopefully\". :) Maybe the earlier message is\n> too hidden to rely on. We might be able to get by with checking \"errno\"\n> for ENOTDIR after trying to lock the ref and using a different message,\n> but I don't know how portable that will be.\n\nHmm, that actually doesn't work. errno is properly EACCESS in your\nexample, but the D/F problem doesn't actually set errno, since it is git\nitself, and not a failed syscall, that determines that \"foo/bar\" is not\navailable because \"foo\" exists (and git must do it, because \"foo\" may be\na packed ref).\n\nSo I think we would need to simulate the errno setting, like the patch\nbelow. That should generate the hint only when it would actually be\nuseful.\n\n---\ndiff --git a/builtin-fetch.c b/builtin-fetch.c\nindex 0bb290b..ad00bd2 100644\n--- a/builtin-fetch.c\n+++ b/builtin-fetch.c\n@@ -181,9 +181,9 @@ static int s_update_ref(const char *action,\n \tlock = lock_any_ref_for_update(ref->name,\n \t\t\t\t       check_old ? ref->old_sha1 : NULL, 0);\n \tif (!lock)\n-\t\treturn 2;\n+\t\treturn errno == ENOTDIR ? 2 : 1;\n \tif (write_ref_sha1(lock, ref->new_sha1, msg) < 0)\n-\t\treturn 2;\n+\t\treturn errno == ENOTDIR ? 2 : 1;\n \treturn 0;\n }\n \ndiff --git a/refs.c b/refs.c\nindex e65a3b4..79795d0 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -893,8 +893,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char\n \t * name is a proper prefix of our refname.\n \t */\n \tif (missing &&\n-            !is_refname_available(ref, NULL, get_packed_refs(), 0))\n+            !is_refname_available(ref, NULL, get_packed_refs(), 0)) {\n+\t\tlast_errno = ENOTDIR;\n \t\tgoto error_return;\n+\t}\n \n \tlock->lk = xcalloc(1, sizeof(struct lock_file));\n \n"},{"id":"112606","messageId":"20090429073256.GB22129@elte.hu","threadId":"19102","inReplyTo":"20090429040719.GA14912@coredump.intra.peff.net","subject":"Re: error: Unable to append to .git/logs/refs/remotes/origin/master: Permission denied","fromName":"Ingo Molnar","fromEmail":"mingo@elte.hu","sentAt":"2009-04-29T07:32:56Z","receivedAt":"2009-04-29T07:32:56Z","isPatch":false,"sender":{"key":"mingo@elte.hu","avatar":null},"body":"\n* Jeff King <peff@peff.net> wrote:\n\n> On Tue, Apr 28, 2009 at 11:29:43PM -0400, Jeff King wrote:\n> \n> > Note the repeated use of \"hopefully\". :) Maybe the earlier \n> > message is too hidden to rely on. We might be able to get by \n> > with checking \"errno\" for ENOTDIR after trying to lock the ref \n> > and using a different message, but I don't know how portable \n> > that will be.\n> \n> Hmm, that actually doesn't work. errno is properly EACCESS in your \n> example, but the D/F problem doesn't actually set errno, since it \n> is git itself, and not a failed syscall, that determines that \n> \"foo/bar\" is not available because \"foo\" exists (and git must do \n> it, because \"foo\" may be a packed ref).\n> \n> So I think we would need to simulate the errno setting, like the \n> patch below. That should generate the hint only when it would \n> actually be useful.\n\nit wasnt hard to figure out what's going on. So this was more of a \nFYI, not really a bug report. Maybe if someone tries to pull into a \nread-only repo the same could happen? My particular breakage (of a \nsingle ref being root-owned - the rest was mingo owned) is atypical \nenough to be ignored.\n\nIf there's no easy/clean solution then please ignore my report.\n\n\tIngo\n"},{"id":"112610","messageId":"20090429080650.GA25227@coredump.intra.peff.net","threadId":"19102","inReplyTo":"20090429073256.GB22129@elte.hu","subject":"Re: error: Unable to append to .git/logs/refs/remotes/origin/master: Permission denied","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-04-29T08:06:50Z","receivedAt":"2009-04-29T08:06:50Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Apr 29, 2009 at 09:32:56AM +0200, Ingo Molnar wrote:\n\n> > So I think we would need to simulate the errno setting, like the \n> > patch below. That should generate the hint only when it would \n> > actually be useful.\n> \n> it wasnt hard to figure out what's going on. So this was more of a \n> FYI, not really a bug report. Maybe if someone tries to pull into a \n> read-only repo the same could happen? My particular breakage (of a \n> single ref being root-owned - the rest was mingo owned) is atypical \n> enough to be ignored.\n\nActually, it is a little bit tough to get your breakage. A pure\nread-only repo would error out much earlier (permission denied on\nFETCH_HEAD or writing to object db). But if yours was just \"accidentally\nfetched once as root\", then that doesn't seem too uncommon.\n\n> If there's no easy/clean solution then please ignore my report.\n\nI think the patch I posted isn't too bad. We'll see what others say.\n\n-Peff\n"},{"id":"114652","messageId":"20090525103715.GA26574@coredump.intra.peff.net","threadId":"19102","inReplyTo":"20090429080650.GA25227@coredump.intra.peff.net","subject":"[PATCH 1/2] lock_ref: inform callers of unavailable ref","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-05-25T10:37:15Z","receivedAt":"2009-05-25T10:37:15Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"One of the ways that locking might fail is that there is a\nDF conflict between two refs (e.g., you want to lock\n\"foo/bar\" but \"foo\" already exists). In this case, we return\nan error, but there is no way for the caller to know the\nspecific problem.\n\nThis patch sets errno to ENOTDIR, which is the most sensible\ncode. It's what we would see if the refs were stored purely\nin the filesystem (but these days we must check the\nnamespace manually due to packed refs).\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nWe introduce a caller who cares in the next patch.\n\n refs.c |    4 +++-\n 1 files changed, 3 insertions(+), 1 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 45ad556..24438c6 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -893,8 +893,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char\n \t * name is a proper prefix of our refname.\n \t */\n \tif (missing &&\n-            !is_refname_available(ref, NULL, get_packed_refs(), 0))\n+\t     !is_refname_available(ref, NULL, get_packed_refs(), 0)) {\n+\t\tlast_errno = ENOTDIR;\n \t\tgoto error_return;\n+\t}\n \n \tlock->lk = xcalloc(1, sizeof(struct lock_file));\n \n-- \n1.6.3.1.250.g01b8b.dirty\n"},{"id":"114653","messageId":"20090525104054.GA26682@coredump.intra.peff.net","threadId":"19102","inReplyTo":"20090429080650.GA25227@coredump.intra.peff.net","subject":"[PATCH 2/2] fetch: report ref storage DF errors more accurately","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-05-25T10:40:54Z","receivedAt":"2009-05-25T10:40:54Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"When we fail to store a fetched ref, we recommend that the\nuser try running \"git prune\" to remove up any old refs that\nhave been deleted by the remote, which would clear up any DF\nconflicts. However, ref storage might fail for other\nreasons (e.g., permissions problems) in which case the\nadvice is useless and misleading.\n\nThis patch detects when there is an actual DF situation and\nonly issues the advice when one is found.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis is a followup to Ingo's bug report here:\n\n  http://thread.gmane.org/gmane.comp.version-control.git/117751\n\n builtin-fetch.c |   11 ++++++++---\n 1 files changed, 8 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin-fetch.c b/builtin-fetch.c\nindex 77acabf..1eec64e 100644\n--- a/builtin-fetch.c\n+++ b/builtin-fetch.c\n@@ -167,6 +167,9 @@ static struct ref *get_ref_map(struct transport *transport,\n \treturn ref_map;\n }\n \n+#define STORE_REF_ERROR_OTHER 1\n+#define STORE_REF_ERROR_DF_CONFLICT 2\n+\n static int s_update_ref(const char *action,\n \t\t\tstruct ref *ref,\n \t\t\tint check_old)\n@@ -181,9 +184,11 @@ static int s_update_ref(const char *action,\n \tlock = lock_any_ref_for_update(ref->name,\n \t\t\t\t       check_old ? ref->old_sha1 : NULL, 0);\n \tif (!lock)\n-\t\treturn 2;\n+\t\treturn errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :\n+\t\t\t\t\t  STORE_REF_ERROR_OTHER;\n \tif (write_ref_sha1(lock, ref->new_sha1, msg) < 0)\n-\t\treturn 2;\n+\t\treturn errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :\n+\t\t\t\t\t  STORE_REF_ERROR_OTHER;\n \treturn 0;\n }\n \n@@ -386,7 +391,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,\n \t}\n \tfree(url);\n \tfclose(fp);\n-\tif (rc & 2)\n+\tif (rc & STORE_REF_ERROR_DF_CONFLICT)\n \t\terror(\"some local refs could not be updated; try running\\n\"\n \t\t      \" 'git remote prune %s' to remove any old, conflicting \"\n \t\t      \"branches\", remote_name);\n-- \n1.6.3.1.250.g01b8b.dirty\n"},{"id":"114710","messageId":"7vprdwu8hx.fsf@alter.siamese.dyndns.org","threadId":"19102","inReplyTo":"20090525104054.GA26682@coredump.intra.peff.net","subject":"Re: [PATCH 2/2] fetch: report ref storage DF errors more accurately","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-05-25T22:23:54Z","receivedAt":"2009-05-25T22:23:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thanks.\n"}]}