0

I am trying to remove a complete git repository clone from my disk using std::filesystem::remove_all()

std::filesystem::remove_all( myRepoName );

This throws an exception

terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
  what():  filesystem error: cannot remove all: Input/output error [windex] 
[windex\.git\objects\pack\pack-6592b2cba8201deb33301b149bcb61af6b4be49b.idx]

This file is read-only. It can be deleted with no problem from windows explorer.

This in windows 10 and mingw g++ v11.2. So this seems to be a bug in the implementation of std::filesystem.

Any workaround available? Maybe std::filesystem::permissions https://en.cppreference.com/w/cpp/filesystem/permissions?

Tried adding

    std::filesystem::permissions(
        "windex/.git/objects/pack/pack-3b1477e94a042244b9aed7021724d8a020be62c9.idx",
        std::filesystem::perms::others_all );

but still get same error and the file remains readonly.

After experimenting, found that owner_write does the job

ravenspoint
  • 19,093
  • 6
  • 57
  • 103
  • 1
    I have to ask the dumb question: do you have any process that might have any file in there opened? An explorer window sitting in that folder? Windows is really picked about that. – joanis Jan 20 '22 at 22:05
  • Can you catch the exception and print out the value returned by `GetLastError`? That might tell you what the underlying problem is. – Paul Sanders Jan 20 '22 at 22:41
  • 1
    Anti virus or a git client locking the file would be my guess. Might be able to see what's got it open using process explorer? – Alan Birtles Jan 20 '22 at 22:49
  • Also This Computer -> right click -> Manage -> Shared Folders -> Open Files might tell you something. – Paul Sanders Jan 20 '22 at 23:22
  • no git clients running and no open files – ravenspoint Jan 21 '22 at 17:11
  • Antivirus is the most likely remaining suspect. In general when doing lots of operations on a folder on Windows it's a good idea to stick a few retries in to avoid these sort of issues – Alan Birtles Jan 21 '22 at 22:54
  • @AlanBirtles tried retrying. No go. See edit – ravenspoint Jan 22 '22 at 15:37
  • well something is locking that file, have you tried using [process explorer](https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer) to see what has got it open? You'd normally put some sleeps between retires – Alan Birtles Jan 22 '22 at 16:10
  • @AlanBirtles added a sleep, and process explorer cannot find a lock – ravenspoint Jan 23 '22 at 01:32
  • 1
    Perhaps the file has read-only attribute set? At lleast on my system, all files in such `".git/object/pack"` subfolders are read-only. You can check via command line: `ATTRIB "windex\.git\objects\pack\pack-6592b2cba8201deb33301b149bcb61af6b4be49b.idx"` and see if `R` attribute is present. Microsoft C++ standard library had a [bug #1511](https://github.com/microsoft/STL/issues/1511), which was supposedly fixed only since VS 2022 17.0 Preview 3. – heap underrun Jan 23 '22 at 04:15
  • @heapunderrun Yes. I did not think to check that because I can delete the repo using windows explorer. I am using mingw, so this is a bug in the mingw implementation of std::filesystem? – ravenspoint Jan 23 '22 at 13:59
  • Just looked it up, libstdc++'s [current implementation](https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/src/filesystem/ops.cc;h=c0e25c50a8544335509ff9d401bc07b6a42068f8;hb=HEAD#l1051) of `std::filesystem::remove` seems rather primitive on Windows: it just calls the Windows API function [`::DeleteFileW`](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilew) and that's it (no special handling of read-only files whatsoever). You could try it out: create a folder with a read-only file in it, call `std::filesystem::remove_all` on it and see what happens. – heap underrun Jan 23 '22 at 14:44
  • I see there's a similar [bug (#216)](https://github.com/boostorg/filesystem/issues/216) filed for the `boost::filesystem::remove` implementation on Windows, so this problem seems to be quite common. – heap underrun Jan 23 '22 at 14:44

1 Answers1

0

This code solves the problem by changing the readonly permission of any file that fails to delete.

int count = 0;
while (count < 5)   //give up after 5, there should be just 2 in a git repo
{       
    try
    {
        std::filesystem::remove_all(myRepoName);
        break;     // all done
    }
    catch (std::filesystem::filesystem_error &e)
    {
        std::this_thread::sleep_for (std::chrono::milliseconds(250));
        std::string f ( e.what() );
        int p = f.find("[");
        p = f.find("[",p+1);
        f = f.substr(p+1);
        f = f.substr(0,f.length()-1);
        std::filesystem::permissions(
            f, std::filesystem::perms::owner_write );
        count++;
    }
}
ravenspoint
  • 19,093
  • 6
  • 57
  • 103
  • 1
    Good to know you've found a quick workaround. But why are you catching some strange `std::filesystem::__cxx11::filesystem_error` instead of the standard [`std::filesystem::filesystem_error`](https://en.cppreference.com/w/cpp/filesystem/filesystem_error) exception? Are you using an experimental version of the filesystem library? Or perhaps this `__cxx11` part is just an internal implementation detail? What happens if you catch `std::filesystem::filesystem_error` instead? – heap underrun Jan 23 '22 at 14:53
  • Also, what happens if there are more than 5 read-only files in a folder? ;-P – heap underrun Jan 23 '22 at 14:56
  • @heapunderrun I am catching __cxx11::filesystem_error because that is the exception that is being thrown. See 4th para of my question. – ravenspoint Jan 23 '22 at 14:57
  • There are 2 readonly files in a git repo – ravenspoint Jan 23 '22 at 14:57
  • Yes, but I think you should try catching the standard `std::filesystem::filesystem_error` still and see if it works. Because I suspect the strange exception class you mention is actually derived from the standard one. But I'm not sure. – heap underrun Jan 23 '22 at 14:59
  • 1
    std::filesystem::filesystem_error works – ravenspoint Jan 23 '22 at 15:01
  • Only 2 read-only files? This depends on the actual repo or how fresh it is. For example, mine has thousands read-only files in such "`.git\object`" folder and its subfolders… But I guess, whatever floats your boat, as they say. – heap underrun Jan 23 '22 at 15:04
  • For this use case, part of a source code package manager, the repo only exists for a moment while required files are extracted, then the repo is immediately deleted. – ravenspoint Jan 23 '22 at 15:08