* [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack
[not found] <CABPQNSbo5yEosEid_SKoiCS4c8eYAaOHy4skSOBJsef+E6H6Sw@mail.gmail.com>
@ 2012-03-06 9:18 ` karsten.blees
2012-03-06 18:32 ` [msysGit] " Johannes Sixt
0 siblings, 1 reply; 9+ messages in thread
From: karsten.blees @ 2012-03-06 9:18 UTC (permalink / raw)
To: kusmabite, git; +Cc: Johannes Schindelin, msysGit, Pat Thoyts, Stefan Naewe
On some systems (e.g. Windows XP), directories cannot be deleted while
they're open. Both git-prune and git-repack (and thus, git-gc) try to
rmdir while holding a DIR* handle on the directory, leaving dangling
empty directories in the .git/objects store.
Fix it by swapping the rmdir / closedir calls.
Reported-by: John Chen <john0312@gmail.com>
Reported-by: Stefan Naewe <stefan.naewe@gmail.com>
Signed-off-by: Karsten Blees <blees@dcon.de>
---
Erik Faye-Lund <kusmabite@gmail.com> wrote on 05.03.2012 11:26:08:
> On Mon, Mar 5, 2012 at 10:57 AM, <karsten.blees@dcon.de> wrote:
[...]
> > I thought the delete / rename problems were a Windows illness (at
> > least the retry-ask-user-yes-no logic is exclusive to mingw.c)?
>
> POSIX allows for this behavior:
>
> http://pubs.opengroup.org/onlinepubs/009695399/functions/rmdir.html
>
> (EBUSY: "The directory to be removed is currently in use by the system
> or some process and the implementation considers this to be an
> error.")
>
> I've found traces of similar issues on exotic unices, so I don't think
> it's completely hypothetical either...
>
> > And as all mingw stuff
> > is eventually sent upstream (I hope :-)), I don't see a particular
> > reason to rush this one.
> >
>
> There's no automatic system for this. I tend to send all my patches
> that cleanly fix problems present in git.git directly upstream, so
> people on Windows who doesn't use our branch can benefit from them as
> well.
So what about this one? It applies cleanly to git master, and when
merged / cherry-picked to msysgit devel, the prune-packed.c fix we
already have in b4cb824d is silently ignored.
Note: the is_dir_empty() function in mingw.c is broken in upstream git
as well, but I'm reluctant to backport this as it will clash with the
Unicode patches.
The upstream patch can be pulled from here:
https://github.com/kblees/git/commit/56e1bc62
And cherry-picked to msysgit devel from here:
https://github.com/kblees/git/commit/b07bfd51
Regards,
Karsten
builtin/prune-packed.c | 2 +-
builtin/prune.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index f9463de..a834417 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -36,7 +36,6 @@ static void prune_dir(int i, DIR *dir, char *pathname,
int len, int opts)
display_progress(progress, i + 1);
}
pathname[len] = 0;
- rmdir(pathname);
}
void prune_packed_objects(int opts)
@@ -65,6 +64,7 @@ void prune_packed_objects(int opts)
continue;
prune_dir(i, d, pathname, len + 3, opts);
closedir(d);
+ rmdir(pathname);
}
stop_progress(&progress);
}
diff --git a/builtin/prune.c b/builtin/prune.c
index 58d7cb8..b99b635 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -85,9 +85,9 @@ static int prune_dir(int i, char *path)
}
fprintf(stderr, "bad sha1 file: %s/%s\n", path,
de->d_name);
}
+ closedir(dir);
if (!show_only)
rmdir(path);
- closedir(dir);
return 0;
}
--
1.7.9.msysgit.1.364.g3e2096
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [msysGit] [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack
2012-03-06 9:18 ` [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack karsten.blees
@ 2012-03-06 18:32 ` Johannes Sixt
2012-03-06 20:19 ` Junio C Hamano
2012-03-06 21:47 ` karsten.blees
0 siblings, 2 replies; 9+ messages in thread
From: Johannes Sixt @ 2012-03-06 18:32 UTC (permalink / raw)
To: karsten.blees
Cc: kusmabite, git, Johannes Schindelin, msysGit, Pat Thoyts,
Stefan Naewe
Am 06.03.2012 10:18, schrieb karsten.blees@dcon.de:
> On some systems (e.g. Windows XP), directories cannot be deleted while
> they're open. Both git-prune and git-repack (and thus, git-gc) try to
> rmdir while holding a DIR* handle on the directory, leaving dangling
> empty directories in the .git/objects store.
>
> Fix it by swapping the rmdir / closedir calls.
The reasoning makes a lot of sense. I wonder why object directories are
pruned nevertheless when I run git gc --prune (I run git master plus a
few topics from pu).
> diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
> index f9463de..a834417 100644
> --- a/builtin/prune-packed.c
> +++ b/builtin/prune-packed.c
> @@ -36,7 +36,6 @@ static void prune_dir(int i, DIR *dir, char *pathname,
> int len, int opts)
> display_progress(progress, i + 1);
> }
> pathname[len] = 0;
> - rmdir(pathname);
After moving the rmdir() away from prune_dir(), the truncation of the
pathname does not logically belong here anymore. It should be moved with
the rmdir(). Looks good otherwise.
> }
>
> void prune_packed_objects(int opts)
> @@ -65,6 +64,7 @@ void prune_packed_objects(int opts)
> continue;
> prune_dir(i, d, pathname, len + 3, opts);
> closedir(d);
> + rmdir(pathname);
> }
> stop_progress(&progress);
> }
> diff --git a/builtin/prune.c b/builtin/prune.c
> index 58d7cb8..b99b635 100644
> --- a/builtin/prune.c
> +++ b/builtin/prune.c
> @@ -85,9 +85,9 @@ static int prune_dir(int i, char *path)
> }
> fprintf(stderr, "bad sha1 file: %s/%s\n", path,
> de->d_name);
> }
> + closedir(dir);
> if (!show_only)
> rmdir(path);
> - closedir(dir);
> return 0;
> }
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [msysGit] [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack
2012-03-06 18:32 ` [msysGit] " Johannes Sixt
@ 2012-03-06 20:19 ` Junio C Hamano
2012-03-06 21:19 ` Johannes Sixt
2012-03-06 21:30 ` karsten.blees
2012-03-06 21:47 ` karsten.blees
1 sibling, 2 replies; 9+ messages in thread
From: Junio C Hamano @ 2012-03-06 20:19 UTC (permalink / raw)
To: Johannes Sixt
Cc: karsten.blees, kusmabite, git, Johannes Schindelin, msysGit,
Pat Thoyts, Stefan Naewe
Johannes Sixt <j6t@kdbg.org> writes:
>> diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
>> index f9463de..a834417 100644
>> --- a/builtin/prune-packed.c
>> +++ b/builtin/prune-packed.c
>> @@ -36,7 +36,6 @@ static void prune_dir(int i, DIR *dir, char *pathname,
>> int len, int opts)
>> display_progress(progress, i + 1);
>> }
>> pathname[len] = 0;
>> - rmdir(pathname);
>
> After moving the rmdir() away from prune_dir(), the truncation of the
> pathname does not logically belong here anymore. It should be moved with
> the rmdir(). Looks good otherwise.
I agree that it is better to have the NUL termination close to where
it actually matters.
Do you want me to take it after locally fixing it up, or do you
prefer to feed this as part of msysgit related updates to me later?
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [msysGit] [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack
2012-03-06 20:19 ` Junio C Hamano
@ 2012-03-06 21:19 ` Johannes Sixt
2012-03-06 21:30 ` karsten.blees
1 sibling, 0 replies; 9+ messages in thread
From: Johannes Sixt @ 2012-03-06 21:19 UTC (permalink / raw)
To: Junio C Hamano
Cc: karsten.blees, kusmabite, git, Johannes Schindelin, msysGit,
Pat Thoyts, Stefan Naewe
Am 06.03.2012 21:19, schrieb Junio C Hamano:
> Johannes Sixt <j6t@kdbg.org> writes:
>
>>> diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
>>> index f9463de..a834417 100644
>>> --- a/builtin/prune-packed.c
>>> +++ b/builtin/prune-packed.c
>>> @@ -36,7 +36,6 @@ static void prune_dir(int i, DIR *dir, char *pathname,
>>> int len, int opts)
>>> display_progress(progress, i + 1);
>>> }
>>> pathname[len] = 0;
>>> - rmdir(pathname);
>>
>> After moving the rmdir() away from prune_dir(), the truncation of the
>> pathname does not logically belong here anymore. It should be moved with
>> the rmdir(). Looks good otherwise.
>
> I agree that it is better to have the NUL termination close to where
> it actually matters.
>
> Do you want me to take it after locally fixing it up, or do you
> prefer to feed this as part of msysgit related updates to me later?
This patch is fairly independent from other topics that are queued in
msysgit, IIRC. Please take it with the mentioned fixup.
Thanks,
-- Hannes
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [msysGit] [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack
2012-03-06 20:19 ` Junio C Hamano
2012-03-06 21:19 ` Johannes Sixt
@ 2012-03-06 21:30 ` karsten.blees
2012-03-06 21:49 ` Junio C Hamano
2012-03-06 21:57 ` Junio C Hamano
1 sibling, 2 replies; 9+ messages in thread
From: karsten.blees @ 2012-03-06 21:30 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Sixt, Johannes Schindelin, kusmabite, msysGit,
Pat Thoyts, Stefan Naewe
Junio C Hamano <gitster@pobox.com> wrote on 06.03.2012 21:19:06:
> Johannes Sixt <j6t@kdbg.org> writes:
>
> >> diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
> >> index f9463de..a834417 100644
> >> --- a/builtin/prune-packed.c
> >> +++ b/builtin/prune-packed.c
> >> @@ -36,7 +36,6 @@ static void prune_dir(int i, DIR *dir, char
*pathname,
> >> int len, int opts)
> >> display_progress(progress, i + 1);
> >> }
> >> pathname[len] = 0;
> >> - rmdir(pathname);
> >
> > After moving the rmdir() away from prune_dir(), the truncation of the
> > pathname does not logically belong here anymore. It should be moved
with
> > the rmdir(). Looks good otherwise.
>
> I agree that it is better to have the NUL termination close to where
> it actually matters.
>
The pathname is extended in prune_dir, so I think it should be reset there
as well; moving it to prune_packed_objects would be quite obscure:
d = opendir(pathname);
prune_dir(d, pathname);
pathname[len] = 0;
rmdir(pathname);
OT: While looking at the code I just stumbled across this immediately
above the patch (prune-packed.c line 32ff):
memcpy(pathname + len, de->d_name, 38);
if (opts & DRY_RUN)
printf("rm -f %s\n", pathname);
else
unlink_or_warn(pathname);
Shouldn't this be memcpy(..., 39) (i.e. including '\0')?
> Do you want me to take it after locally fixing it up, or do you
> prefer to feed this as part of msysgit related updates to me later?
The msysgit queue is quite long, and I think it makes sense to fast-track
this one.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack
2012-03-06 18:32 ` [msysGit] " Johannes Sixt
2012-03-06 20:19 ` Junio C Hamano
@ 2012-03-06 21:47 ` karsten.blees
1 sibling, 0 replies; 9+ messages in thread
From: karsten.blees @ 2012-03-06 21:47 UTC (permalink / raw)
To: Johannes Sixt
Cc: git, Johannes Schindelin, kusmabite, msysGit, Pat Thoyts,
Stefan Naewe
Johannes Sixt <j6t@kdbg.org> wrote on 06.03.2012 19:32:41:
> Am 06.03.2012 10:18, schrieb karsten.blees@dcon.de:
> > On some systems (e.g. Windows XP), directories cannot be deleted while
> > they're open. Both git-prune and git-repack (and thus, git-gc) try to
> > rmdir while holding a DIR* handle on the directory, leaving dangling
> > empty directories in the .git/objects store.
> >
> > Fix it by swapping the rmdir / closedir calls.
>
> The reasoning makes a lot of sense. I wonder why object directories are
> pruned nevertheless when I run git gc --prune (I run git master plus a
> few topics from pu).
>
You're right...in upstream git, closedir() is essentially a NOOP. The OS
handle is closed in readdir() on reading the last entry. The dirent.c
'improvements' that move FindFirstFile() to opendir() and FindClose() to
closedir() are in the msysgit fork only [1] (and entirely my fault, I
guess :-)).
So this patch actually isn't currently required for Windows XP (probably
other platforms, I don't know).
[1] https://github.com/msysgit/git/commit/e2b3f70b
--
*** Please reply-to-all at all times ***
*** (do not pretend to know who is subscribed and who is not) ***
*** Please avoid top-posting. ***
You received this message because you are subscribed to the Google
Groups "msysGit" group.
To post to this group, send email to msysgit@googlegroups.com
To unsubscribe from this group, send email to
msysgit+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/msysgit?hl=en_US?hl=en
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [msysGit] [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack
2012-03-06 21:30 ` karsten.blees
@ 2012-03-06 21:49 ` Junio C Hamano
2012-03-07 10:50 ` karsten.blees
2012-03-06 21:57 ` Junio C Hamano
1 sibling, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2012-03-06 21:49 UTC (permalink / raw)
To: karsten.blees
Cc: Junio C Hamano, git, Johannes Sixt, Johannes Schindelin,
kusmabite, msysGit, Pat Thoyts, Stefan Naewe
karsten.blees@dcon.de writes:
> Junio C Hamano <gitster@pobox.com> wrote on 06.03.2012 21:19:06:
>> Johannes Sixt <j6t@kdbg.org> writes:
>>
>> >> diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
>> >> index f9463de..a834417 100644
>> >> --- a/builtin/prune-packed.c
>> >> +++ b/builtin/prune-packed.c
>> >> @@ -36,7 +36,6 @@ static void prune_dir(int i, DIR *dir, char
> *pathname,
>> >> int len, int opts)
>> >> display_progress(progress, i + 1);
>> >> }
>> >> pathname[len] = 0;
>> >> - rmdir(pathname);
>> >
>> > After moving the rmdir() away from prune_dir(), the truncation of the
>> > pathname does not logically belong here anymore. It should be moved
> with
>> > the rmdir(). Looks good otherwise.
>>
>> I agree that it is better to have the NUL termination close to where
>> it actually matters.
>>
>
> The pathname is extended in prune_dir, so I think it should be reset there
> as well; moving it to prune_packed_objects would be quite obscure:
This depends entirely on how you look at it.
You can certainly stare at the original code and declare that the
contract between the caller and the callee was that the caller gives
pathname[] and len (len+3 for the caller) to the callee, and allows
the callee to play with the rest of the pathname[] array but expects
that pathname[] to be properly NUL-terminated when the callee comes
back. From that point of view, "pathname[len] = 0" can belong to
the callee.
But while you are staring the original code, notice that "expects
that pathname[] to be NUL-terminated when the callee comes back" is
not something the caller even depends on. That expectation starts
to matter _only_ if you move rmdir(pathname) to the caller.
That is why I said "where it actually matters."
In other words, "The caller allows the callee to play with the rest
of the pathname[]; as long as the callee does not touch earlier
parts of the array, it can do anything before it returns", without
requiring the callee to NUL-terminate the pathname[] to restore to
its original state, is equally a valid contract between the caller
and the callee in the original code.
And that also holds true for the updated code that has rmdir() in
the caller.
> OT: While looking at the code I just stumbled across this immediately
> above the patch (prune-packed.c line 32ff):
>
> memcpy(pathname + len, de->d_name, 38);
> if (opts & DRY_RUN)
> printf("rm -f %s\n", pathname);
> else
> unlink_or_warn(pathname);
>
> Shouldn't this be memcpy(..., 39) (i.e. including '\0')?
That is not necessary, I think, as get_sha1_hex() does not look at
that NUL in the first place.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [msysGit] [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack
2012-03-06 21:30 ` karsten.blees
2012-03-06 21:49 ` Junio C Hamano
@ 2012-03-06 21:57 ` Junio C Hamano
1 sibling, 0 replies; 9+ messages in thread
From: Junio C Hamano @ 2012-03-06 21:57 UTC (permalink / raw)
To: karsten.blees
Cc: git, Johannes Sixt, Johannes Schindelin, kusmabite, msysGit,
Pat Thoyts, Stefan Naewe
karsten.blees@dcon.de writes:
> OT: While looking at the code I just stumbled across this immediately
> above the patch (prune-packed.c line 32ff):
>
> memcpy(pathname + len, de->d_name, 38);
> if (opts & DRY_RUN)
> printf("rm -f %s\n", pathname);
> else
> unlink_or_warn(pathname);
>
> Shouldn't this be memcpy(..., 39) (i.e. including '\0')?
I think the only thing that is guaranteeing that pathname[len+38] is
NUL is that we do not hop around repositories, so once we fill the
static char pathname[PATH_MAX] in prune_packed_objects(), nobody
writes to that location, because the length of the leading part
(i.e. "len" given to prune_dir()) will stay constant during the
lifetime of the process.
So it is not currently a problem, but it would be better to clear
that byte here.
Good eyes.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [msysGit] [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack
2012-03-06 21:49 ` Junio C Hamano
@ 2012-03-07 10:50 ` karsten.blees
0 siblings, 0 replies; 9+ messages in thread
From: karsten.blees @ 2012-03-07 10:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Junio C Hamano, Johannes Sixt, Johannes Schindelin,
kusmabite, msysGit, Pat Thoyts, Stefan Naewe
Junio C Hamano <gitster@pobox.com> wrote on 06.03.2012 22:49:57:
> karsten.blees@dcon.de writes:
>
> > Junio C Hamano <gitster@pobox.com> wrote on 06.03.2012 21:19:06:
> >> Johannes Sixt <j6t@kdbg.org> writes:
> >>
> >> >> diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
> >> >> index f9463de..a834417 100644
> >> >> --- a/builtin/prune-packed.c
> >> >> +++ b/builtin/prune-packed.c
> >> >> @@ -36,7 +36,6 @@ static void prune_dir(int i, DIR *dir, char
> > *pathname,
> >> >> int len, int opts)
> >> >> display_progress(progress, i + 1);
> >> >> }
> >> >> pathname[len] = 0;
> >> >> - rmdir(pathname);
> >> >
> >> > After moving the rmdir() away from prune_dir(), the truncation of
the
> >> > pathname does not logically belong here anymore. It should be moved
> > with
> >> > the rmdir(). Looks good otherwise.
> >>
> >> I agree that it is better to have the NUL termination close to where
> >> it actually matters.
> >>
> >
> > The pathname is extended in prune_dir, so I think it should be reset
there
> > as well; moving it to prune_packed_objects would be quite obscure:
>
> This depends entirely on how you look at it.
>
> You can certainly stare at the original code and declare that the
> contract between the caller and the callee was that the caller gives
> pathname[] and len (len+3 for the caller) to the callee, and allows
> the callee to play with the rest of the pathname[] array but expects
> that pathname[] to be properly NUL-terminated when the callee comes
> back. From that point of view, "pathname[len] = 0" can belong to
> the callee.
>
> But while you are staring the original code, notice that "expects
> that pathname[] to be NUL-terminated when the callee comes back" is
> not something the caller even depends on. That expectation starts
> to matter _only_ if you move rmdir(pathname) to the caller.
>
> That is why I said "where it actually matters."
>
Well, I just don't like that a function designed to prune a directory
modifies its input parameters as a side effect (it is bad enough that
prune_dir uses the caller's buffer at all). You know, trying to limit
side effects as a general programming principle.
In my opinion, it doesn't matter at all if the caller actually depends on
unmodified parameters or not, it just makes robust APIs that encourage
reuse.
Just my 2 cents, though, prune_packed_objects and prune_dir are so tightly
coupled that it probably doesn't make any difference...(on the other hand,
we have near identical code in prune.c, so thinking about reuse is not so
far fetched)
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-03-07 10:50 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CABPQNSbo5yEosEid_SKoiCS4c8eYAaOHy4skSOBJsef+E6H6Sw@mail.gmail.com>
2012-03-06 9:18 ` [PATCH] fix deletion of .git/objects sub-directories in git-prune/repack karsten.blees
2012-03-06 18:32 ` [msysGit] " Johannes Sixt
2012-03-06 20:19 ` Junio C Hamano
2012-03-06 21:19 ` Johannes Sixt
2012-03-06 21:30 ` karsten.blees
2012-03-06 21:49 ` Junio C Hamano
2012-03-07 10:50 ` karsten.blees
2012-03-06 21:57 ` Junio C Hamano
2012-03-06 21:47 ` karsten.blees
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).