Re: Git changes permissions on directories when deleting files.
- From
Chad Joan <chadjoan@gmail.com>
- Date
- Mar 11, 2011, 06:09 UTC
- Message-ID
- <AANLkTin1sePpEbzPq5PFnk21BSRSmJf6wi0UhzSsZe7+@mail.gmail.com>
- In-Reply-To
- <20110303151608.GD1074@sigill.intra.peff.net>
On Thu, Mar 3, 2011 at 10:16 AM, Jeff King <peff@peff.net> wrote:
Show 9 quoted lines
> > ... > > > diff -crB git-1.7.3.4/dir.c git-1.7.3.4-new/dir.c > > Context diff? Eww. There is this awesome tool called "git" that can help > you with managing versions of software. :) > > -Peff
Yes... though I'm just letting Gentoo compile it for me and I'm not doing anything serious enough to justify downloading/installing GIT by hand and next to the one that's already there. So I just worked from the tarball that Gentoo uses and added stuff. Any other day and I'd be all over that git usage ;)
I did run into more permissions being messed up, so I grepped for rmdir and replaced /all/ instances of it in git's C code. I haven't had anymore trouble so far. Here's the newer patch:
diff -crB git-1.7.3.4/dir.c git-1.7.3.4-new/dir.c *** git-1.7.3.4/dir.c Wed Mar 2 13:00:54 2011 --- git-1.7.3.4-new/dir.c Thu Mar 10 11:09:32 2011 *************** *** 994,999 **** --- 994,1022 ---- return ret; }
+ int rmdir_on_broken_cifs(const char *path)
+ {
+ struct stat sb;
+ if (stat(path, &sb) < 0) {
+ /* Oh well, hopefully if we can't stat it
+ * it is already gone or we don't have
+ * permissions to screw it up anyway. */
+ return rmdir(path);
+ }
+ if (rmdir(path) == 0) {
+ /* it worked, nothing to restore */
+ return 0;
+ }
+ /* maybe remove this conditional if you can trigger
+ * the problem with other types of errors */
+ if (errno != ENOTEMPTY)
+ return -1;
+ if (chmod(path, sb.st_mode) < 0)
+ warning("we probably just screwed up the permissions of %s",
+ path);
+ return -1;
+ }
+
int remove_dir_recursively(struct strbuf *path, int flag)
{
DIR *dir;
***************
*** 1037,1043 ****strbuf_setlen(path, original_len); if (!ret) ! ret = rmdir(path->buf); return ret; }
--- 1060,1066 ----
strbuf_setlen(path, original_len); if (!ret) ! ret = rmdir_on_broken_cifs(path->buf); return ret; }
***************
*** 1066,1072 ****
slash = dirs + (slash - name);
do {
*slash = '\0';
! } while (rmdir(dirs) == 0 && (slash = strrchr(dirs, '/')));
free(dirs);
}
return 0;
--- 1090,1096 ----
slash = dirs + (slash - name);
do {
*slash = '\0';
! } while (rmdir_on_broken_cifs(dirs) == 0 && (slash = strrchr(dirs, '/')));
free(dirs);
}
return 0;
Only in git-1.7.3.4: dir.c~
diff -crB git-1.7.3.4/dir.h git-1.7.3.4-new/dir.h
*** git-1.7.3.4/dir.h Wed Dec 15 21:52:11 2010
--- git-1.7.3.4-new/dir.h Thu Mar 10 11:09:13 2011
***************
*** 101,104 ****
--- 101,106 ----
/* tries to remove the path with empty directories along it, ignores ENOENT */
extern int remove_path(const char *path);+ extern int rmdir_on_broken_cifs(const char *path);
+
#endif
diff -crB git-1.7.3.4/entry.c git-1.7.3.4-new/entry.c
*** git-1.7.3.4/entry.c Wed Dec 15 21:52:11 2010
--- git-1.7.3.4-new/entry.c Thu Mar 10 11:12:25 2011
***************
*** 68,74 ****
die_errno("cannot unlink '%s'", pathbuf);
}
closedir(dir);
! if (rmdir(path))
die_errno("cannot rmdir '%s'", path);
}--- 68,74 ----
die_errno("cannot unlink '%s'", pathbuf);
}
closedir(dir);
! if (rmdir_on_broken_cifs(path))
die_errno("cannot rmdir '%s'", path);
}diff -crB git-1.7.3.4/pack-refs.c git-1.7.3.4-new/pack-refs.c *** git-1.7.3.4/pack-refs.c Wed Dec 15 21:52:11 2010 --- git-1.7.3.4-new/pack-refs.c Thu Mar 10 12:34:53 2011 *************** *** 2,7 **** --- 2,8 ---- #include "refs.h" #include "tag.h" #include "pack-refs.h" + #include "dir.h"
struct ref_to_prune {
struct ref_to_prune *next;
***************
*** 86,92 ****
if (q == p)
break;
*q = '\0';
! if (rmdir(git_path("%s", name)))
break;
}
}
--- 87,93 ----
if (q == p)
break;
*q = '\0';
! if (rmdir_on_broken_cifs(git_path("%s", name)))
break;
}
}
diff -crB git-1.7.3.4/symlinks.c git-1.7.3.4-new/symlinks.c
*** git-1.7.3.4/symlinks.c Wed Dec 15 21:52:11 2010
--- git-1.7.3.4-new/symlinks.c Thu Mar 10 11:24:08 2011
***************
*** 1,4 ****
--- 1,5 ----
#include "cache.h"
+ #include "dir.h" /*
* Returns the length (on a path component basis) of the longest
***************
*** 255,261 ****
{
while (removal.len > new_len) {
removal.path[removal.len] = '\0';
! if (rmdir(removal.path))
break;
do {
removal.len--;
--- 256,262 ----
{
while (removal.len > new_len) {
removal.path[removal.len] = '\0';
! if (rmdir_on_broken_cifs(removal.path))
break;
do {
removal.len--;
diff -crB git-1.7.3.4/wrapper.c git-1.7.3.4-new/wrapper.c
*** git-1.7.3.4/wrapper.c Wed Dec 15 21:52:11 2010
--- git-1.7.3.4-new/wrapper.c Thu Mar 10 11:12:36 2011
***************
*** 2,7 ****
--- 2,8 ----
* Various trivial helper wrappers around standard functions
*/
#include "cache.h"
+ #include "dir.h" static void try_to_free_builtin(size_t size)
{
***************
*** 346,352 **** int rmdir_or_warn(const char *file)
{
! return warn_if_unremovable("rmdir", file, rmdir(file));
}int remove_or_warn(unsigned int mode, const char *file) --- 347,353 ----
int rmdir_or_warn(const char *file)
{
! return warn_if_unremovable("rmdir", file, rmdir_on_broken_cifs(file));
}int remove_or_warn(unsigned int mode, const char *file)