Issue #842 resolved

Icon overlays cannot be disabled in remote shares

created an issue


I use the latest TortoiseHG 2.05 x64 on Windows 7. I use network mounts to access shared drives on remote machines, of two different types: Samba and SSHFS (this one using the implementation of Dokan SSHFS). In both cases, the shares are mounted using a local unit drive. I have selected the "local disk only" option for TortoiseHG's icon overlays; however, no matter the value of this field, the overlays are always applied on these network units. This has a significant negative impact on the speed of navigation through the different folders of the remote shares.

I don't know if this might be a problem of mounting the shares with a local drive letter; however, it would be nice if this case was detected as a non-local drive and the overlays avoided, because of their appreciable navigation speed slowdown. Alternatively, it would be nice if a per-folder (or per-drive) icon overaly disabling option could be applied, similarly to what is implemented in TortoiseSVN.

Thanks in advance!

Comments (27)

  1. Adrian Buehlmann
    • changed status to open

    Yeah, I think drive letter mounts are considered local, no matter what they hide behind them (but it's been a while since I looked at that code).

    I think, if anything, a list of drive letters with to-be-ignored volumes shouldn't be that hard to implement in the overlay handler without unduly impacting it's speed. About the hardest part would be the configuration and the UI for it.

    That said, using network shares for sharing Mercurial repositories is not recommended best practice. I wonder what surprises that Dokan SSHFS (which I've never heard of) entails. Windows shares alone can make your life pretty interesting already.

  2. enriquevagu reporter

    Thanks for your answer.

    Regarding the network shares, neither of them (SSH or SMB) are intended to share a mercurial repository (OK, I admit I access some code, but it is not its main function).

    However, regardless there is a repository in them or not, the fact that TortoiseHG's Icon Overlay scans the folders for the .hg subfolder makes the navigation significantly slower. That was the point of my issue suggestion, there is currently no way to disable the scanning of these folders.

    Thanks for the info on the hard links! :)

  3. Adrian Buehlmann

    Ah, you are right. So this is a perfectly reasonable proposal!

    (I probably have spent way too much time looking at repositories-on-windows-shares-problems that I started to neglect that people may actually use shares for other things as well. Sorry! :-)

    Developer note: Maybe I'll look into implementing this after July 1st (release of thg 2.1). But if anyone else would like to take a stab at this, feel free to do so.

  4. Adrian Buehlmann

    It just occurred to me that it might make sense to have a positive list of drive letters (instead of a negative list).

    Tentative spec:

    Create a new shell extension config option which is empty or missing by default. If it is empty or missing, the overlay handler scans all drive letters for Mercurial repositories. If it is non-empty, the overlay handler parses it as a list of comma separated drive letters and scans only these drives for mercurial repositories, ignoring all drive letters not listed.

  5. Eduard-Cristian Stefan

    Is it acceptable to keep just a list of paths that should be scanned? I have a tendency to group repos under a folder in the root of the drive, and maybe I'm not the only one. Also, it might be possible to restrict TortoiseSVN to a folder and TortoiseHg to another folder in the same drive, and they won't conflict in any way.

  6. Adrian Buehlmann

    No, I can see that your proposal makes sense.

    It's just that I'm not that keen on hacking on the overlay handler any more these days. I've wasted a lot of time there in the past.

  7. Eduard-Cristian Stefan

    Maybe this can be easily adapted:

    # detect remote drives like:
    # * Z: = \\server1\folder1 (net use)
    # * Y: = Z:\folder2 (subst a folder from a network mapped drive)
    # * X: = \\server2\folder3 (subst a folder from a network path,
    #                           shown in subst output like UNC\server2\folder3)
    import win32api
    import win32file
    drivetype = {win32file.DRIVE_CDROM: "DRIVE_CDROM",
                 win32file.DRIVE_FIXED: "DRIVE_FIXED",
                 win32file.DRIVE_REMOTE: "DRIVE_REMOTE"}
    for d in win32api.GetLogicalDriveStrings().split("\x00"):
        if d:
            print "drive", d[:2], drivetype[win32file.GetDriveType(d[:2])]
  8. Adrian Buehlmann

    I might be retarded, but how is GetLogicalDriveStrings supposed to help here?

    "Fills a buffer with strings that specify valid drives in the system."

    So you get a list of strings with the drives. Now what?

    If I run

    import win32api
    import win32file
    for d in win32api.GetLogicalDriveStrings().split("\x00"):
        print d

    on my Windows 7 x64 here I get


    I have K:\ mapped to a share served by samba which is running on a FreeBSD box.

  9. Eduard-Cristian Stefan

    True, and GetDriveType tells you which are the remote drives. Or you can get the other way around and get the list of the non-remote drives and enable the overlays only for them. You can even put a checkbox for optical drives and/or removable drives.

  10. Adrian Buehlmann

    Ok. I am retarded (but I know C++ ;-). Overlooked the GetDriveType call


    import win32api
    import win32file
    for d in win32api.GetLogicalDriveStrings().split("\x00"):
        print d, win32file.GetDriveType(d[:2])

    I get

    $ python
    A:\ 2
    C:\ 3
    D:\ 5
    E:\ 5
    K:\ 4

    here with the numbers being

    The drive type cannot be determined.
    The root path is invalid; for example, there is no volume mounted at the specified path.
    The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.
    The drive has fixed media; for example, a hard drive or flash drive.
    The drive is a remote (network) drive.
    The drive is a CD-ROM drive.
    The drive is a RAM disk.

    Lo and behold I still have a floppy drive A:

  11. Adrian Buehlmann

    So if we see a drive letter in a path, we can call GetDriveType on it. If the return value is 4, it's a not a local disk and thus we should not show overlays for such paths if "Local disks only" is ticked in the "Icons" tab of the "TortoiseHg Shell Configuration".

    Guess what: I'll look into implementing that (I hope calling GetDriveType is not too slow).

    Thanks for the tip.

  12. Eduard-Cristian Stefan

    I just hope that instead of extracting only the drive letter from the path being evaluated and check it against the positive list of drive letters (the default being the list of fixed drives) it might be fast enough to check if the path being evaluated starts with one of the members of the positive list of paths (the default for this list being the same list of fixed drives).

    Update: I can try to start from your code and add checks for optical and removable drives, and maybe give a shot to path list instead of drive letter list.

  13. Adrian Buehlmann

    Not sure I understand what you mean, but I think we don't need any new config option and thus we don't need that new "positive list" config option I was airing two days ago.

    If the path starts with a drive letter and "Local disks only" is set, we just additionally call GetDriveType() for that drive and skip that path if the return value is 4.

  14. Eduard-Cristian Stefan

    Given a path like d:\repos\hg_svn\flatpress there are two choices:

    1. extract the drive letter and call GetDriveType() (or compare the drive letter with a white list)
    2. check if one of the paths from a white list matches the beginning of the given path, where the white list for my home PC would be:
    • d:\repos
    • h:\
    • k:\py
    • k:\pr
    • k:\thg

    so for the given path the overlay icons should be shown.

    When I specify the white list of paths I also expect that all other paths would be ignored by the shell extension, so the calls to GetDriveType() can be entirely avoided.

  15. Adrian Buehlmann

    Probably something like

    diff --git a/win32/shellext/CShellExtOverlay.cpp b/win32/shellext/CShellExtOverlay.cpp
    --- a/win32/shellext/CShellExtOverlay.cpp
    +++ b/win32/shellext/CShellExtOverlay.cpp
    @@ -45,9 +45,19 @@
         std::string path = WideToMultibyte(lowerpath.c_str());
    -    if (GetRegistryConfig("LocalDisksOnly", cval) != 0 && cval != "0"
    -            && PathIsNetworkPath(path.c_str()))
    -        return S_FALSE;
    +    if (GetRegistryConfig("LocalDisksOnly", cval) != 0 && cval != "0")
    +    {
    +        if (::PathIsNetworkPath(path.c_str()))
    +            return S_FALSE;
    +        if (path.size() > 2 && path[1] == ':')
    +        {
    +            std::string t = "C:\\";
    +            t[0] = path[0];
    +            if (::GetDriveType(t.c_str()) == 4)
    +                return S_FALSE;
    +        }
    +    }
         char filterStatus = 0;
         if (myTortoiseClass == 'A')
  16. Log in to comment