Subject: Error writing loose object on Cygwin

From: Shawn Pearce <[email-masked]>
Date: Tue, 11 Jul 2006 23:57:46 -0400

I've got a weird bug that a coworker just found today on Cygwin
running on XP.  He was trying to do `git add foo` in a brand new
repository which was stored on a Solaris server[*1*] and mounted
on his XP desktop by way of samba[*2*].

My coworker received the "unable to write sha1 filename %s:%s"
error in move_temp_to_file during git-add.  After sprinkling some
printfs all over that area of sha1_file.c I concluded that GIT was
receiving back EACCES as the error from the first link attempt in
link_temp_to_file (rather than ENOENT) when the parent directory
didn't exist.

Reproducing it on XP systems was easy, as was working around the
problem:

	mkdir foo
	cd foo
	git init-db
	echo foo>foo
	git add foo # dies with "unable to write sha1 filename"
	mkdir .git/objects/25
	git add foo # now succeeds without error

What's more interesting is Windows 2000 systems accessing the same
Solaris server and the same samba server with the same version of
Cygwin didn't have any problems (the first git add succeeded).

This was Cygwin 1.5.19-4 and 1.4.1.  The tiny patch below fixes
the issue for us, but certainly seems like not the best way to go
about this...  But right now I've got my coworkers running GIT 1.4.1
plus the patch below.

Has anyone else seen this type of behavior before?  Any suggestions
on debugging this issue?

Footnotes:
[*1*] Yes, this Solaris server is the same one that has the old
      compiler and almost no GNU tools, which means GIT, StGIT,
	  cogito and pg's higher level functions are all broken...

[*2*] Yes, Solaris is a real UNIX and the coworker should just use
      GIT there.  The problem is we have some GIT based scripts which
      mirror a version control tool that is only available through
	  a Java applet running in Internet Explorer on a Windows
	  system.  Which means although we can use GIT on Solaris
	  there are some operations that we need to execute on
	  Windows...

-->8--
Assume EACCES means ENOENT when creating sha1 objects.
---
 sha1_file.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index 8179630..c04d6a5 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1344,7 +1344,7 @@ static int link_temp_to_file(const char 
         * else succeeded.
         */
        ret = errno;
-       if (ret == ENOENT) {
+       if (ret == ENOENT || ret == EACCES) {
                char *dir = strrchr(filename, '/');
                if (dir) {
                        *dir = 0;
-- 
1.4.1