[PATCH STABLE V2] windows: implement nlinks() using Python's ctypes (issue1922)

Adrian Buehlmann adrian at cadifra.com
Wed Jan 26 10:56:50 CST 2011


On 2011-01-25 23:45, Matt Mackall wrote:
> On Sun, 2011-01-23 at 16:12 +0100, Adrian Buehlmann wrote:
>> On 2011-01-23 15:17, Adrian Buehlmann wrote:
>>> # HG changeset patch
>>> # User Adrian Buehlmann <adrian at cadifra.com>
>>> # Date 1295790385 -3600
>>> # Branch stable
>>> # Node ID 99f2b980756d1c22775cf6ec6e93c646bc910a55
>>> # Parent  d0e0d3d43e1439d63564ab4dddfe0daa69ae2d86
>>> windows: implement nlinks() using Python's ctypes (issue1922)
>>>
>>> If the pywin32 package was not installed, the import of win32 in
>>> windows.py silently failed and (before this patch) util.nlinks was then
>>> used as a fallback when running on Windows.
>>>
>>> util.nlinks() returned 0 for all files when called on Windows, because
>>> Python's
>>>
>>>     os.lstat(name).st_nlink
>>>
>>> is 0 on Windows for all files.
>>>
>>> If nlinks() returns 0, util.opener failed to break up hardlinks, which
>>> could lead to repository corruption when committing or pushing to a
>>> hardlinked clone (hg verify detects it).
>>>
>>> We now provide our own nlinks() in windows.py by using Python's ctypes
>>> library, so we don't depend on the pywin32 package being installed for
>>> nlinks().
>>>
>>>   ** Since Python's ctypes were introduced in Python 2.5, we now
>>>   ** require Python 2.5 or later for Mercurial on Windows
>>>
>>> Using ctypes also has the benefit that nlinks() also works correctly
>>> for the pure Python Mercurial.
>>>
>>> And we force breaking up hardlinks on every append file access in the
>>> opener if nlinks() returns < 1, thus making sure that we can't cause
>>> any hardlink repository corruption.
>>>
>>> It would have been possible to simply require the pywin32 package on
>>> Windows and abort with an import error if it's not installed, but such
>>> a policy change should be avoided on the stable branch. Previous packages
>>> like for example
>>>
>>>     mercurial-1.7.3-1.win32-py2.6.exe
>>>
>>> didn't make it obvious that pywin32 was needed as a dependency. It just
>>> silently caused repository corruption in hardlinked clones if pywin32
>>> was not installed.
> 
> Alright, now I've lost the plot. Let me see if I can recover it:
> 
> require pywin32
>  - adds a new dependency
>  - solves problem for native
>  - pure may or may not be able to use it (ie jython)
> extend osutils
>  - no new dependency
>  - solves problem for native
>  - pure still broken
> use ctypes
>  - requires py2.5 or separate ctypes
>  - solves problem for native
>  - pure may or may not be able to use it
> 
> It's worth noting that pure has pretty substantial problems on Windows
> due to the use of "native" open() and the like.
> 
> So in this analysis, osutils looks like the winner. Is your osutils
> patch good for 1.7.4?

Looking at your statements in this mail, I'm tempted to say no.

I think my osutil.c patch is quite risky for 1.7.4, it lacks a nlinks()
implementation for pure and it is going in a wrong direction.

IMHO, the right direction for the future is using Python's ctypes.

I'd rather like to see

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -913,6 +909,8 @@ class opener(object):
                     # shares if the file is open.
                     fd = open(f)
                     nlink = nlinks(f)
+                    if nlink < 1:
+                        nlink = 2 # force mktempcopy (issue1922)
                     fd.close()
             except (OSError, IOError):
                 nlink = 0

alone in 1.7.4.

This simply forces a file copy on 'a'ppend if pywin32 is not installed.

I'll send a patch for this.

> Another way to look at it is "what else breaks without pywin32"?
> The answer looks like:
> 
> - finding stale locks
> - finding rc paths
> - finding usernames
> - signal handling
> - terminal width
> - window hiding??
> 
> Looks like pretty minor stuff. 
> 
> A related question is "can we replace pywin32 with ctypes"? If the
> answer is yes, it might make sense to do that so we'll have no
> dependencies when we move to Py2.5 a few years from now. Switching to
> ctypes might make sense for 1.8 or 1.9.
> 

I think we can get rid of the pywin32 dependency and we should.

I hope we can switch to ctypes for 1.8.

Can we require Python >=2.5 (at least for Windows) for 1.8?



More information about the Mercurial-devel mailing list