Patchwork [stable] fsmonitor: match watchman and local encoding

login
register
mail settings
Submitter Olivier Trempe
Date March 6, 2017, 2:54 p.m.
Message ID <06a427b6b4a4efe3c190.1488812095@ronce.innov.local>
Download mbox | patch
Permalink /patch/18943/
State Superseded
Headers show

Comments

Olivier Trempe - March 6, 2017, 2:54 p.m.
# HG changeset patch
# User Olivier Trempe <oliviertrempe@gmail.com>
# Date 1488810111 18000
#      Mon Mar 06 09:21:51 2017 -0500
# Branch stable
# Node ID 06a427b6b4a4efe3c19029951c654a2c8d835fb3
# Parent  6b00c3ecd15b26587de8cca6fab811069cba3b2f
fsmonitor: match watchman and local encoding

watchman's paths encoding is os dependant. For example, on Windows, it's
always utf-8. This causes paths comparison mismatch when paths contain non ascii
characters.
Olivier Trempe - March 6, 2017, 5:43 p.m.
I'll send a more robust implementation of _watchmanencodingtolocal

On Mon, Mar 6, 2017 at 9:54 AM, Olivier Trempe <oliviertrempe@gmail.com>
wrote:

> # HG changeset patch
> # User Olivier Trempe <oliviertrempe@gmail.com>
> # Date 1488810111 18000
> #      Mon Mar 06 09:21:51 2017 -0500
> # Branch stable
> # Node ID 06a427b6b4a4efe3c19029951c654a2c8d835fb3
> # Parent  6b00c3ecd15b26587de8cca6fab811069cba3b2f
> fsmonitor: match watchman and local encoding
>
> watchman's paths encoding is os dependant. For example, on Windows, it's
> always utf-8. This causes paths comparison mismatch when paths contain non
> ascii
> characters.
>
> diff -r 6b00c3ecd15b -r 06a427b6b4a4 hgext/fsmonitor/__init__.py
> --- a/hgext/fsmonitor/__init__.py       Thu Mar 02 20:19:45 2017 -0500
> +++ b/hgext/fsmonitor/__init__.py       Mon Mar 06 09:21:51 2017 -0500
> @@ -110,6 +110,7 @@
>  from mercurial import match as matchmod
>
>  from . import (
> +    pywatchman,
>      state,
>      watchmanclient,
>  )
> @@ -159,6 +160,16 @@
>      sha1.update('\0')
>      return sha1.hexdigest()
>
> +def _watchmanencodingtolocal(path):
> +    """Fix path to match watchman and local encoding
> +
> +    watchman's paths encoding is os dependant. For example, on Windows,
> it's
> +    always utf-8. This converts watchman encoded paths to local encoding
> to
> +    avoid paths comparison mismatch.
> +    """
> +    watchmandecode = pywatchman.encoding.decode_local
> +    return watchmandecode(path).encode(encoding.encoding)
> +
>  def overridewalk(orig, self, match, subrepos, unknown, ignored,
> full=True):
>      '''Replacement for dirstate.walk, hooking into Watchman.
>
> @@ -302,7 +313,7 @@
>      # Watchman tracks files.  We use this property to reconcile deletes
>      # for name case changes.
>      for entry in result['files']:
> -        fname = entry['name']
> +        fname = _watchmanencodingtolocal(entry['name'])
>          if switch_slashes:
>              fname = fname.replace('\\', '/')
>          if normalize:
>

Patch

diff -r 6b00c3ecd15b -r 06a427b6b4a4 hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py	Thu Mar 02 20:19:45 2017 -0500
+++ b/hgext/fsmonitor/__init__.py	Mon Mar 06 09:21:51 2017 -0500
@@ -110,6 +110,7 @@ 
 from mercurial import match as matchmod
 
 from . import (
+    pywatchman,
     state,
     watchmanclient,
 )
@@ -159,6 +160,16 @@ 
     sha1.update('\0')
     return sha1.hexdigest()
 
+def _watchmanencodingtolocal(path):
+    """Fix path to match watchman and local encoding
+
+    watchman's paths encoding is os dependant. For example, on Windows, it's
+    always utf-8. This converts watchman encoded paths to local encoding to
+    avoid paths comparison mismatch.
+    """
+    watchmandecode = pywatchman.encoding.decode_local
+    return watchmandecode(path).encode(encoding.encoding)
+
 def overridewalk(orig, self, match, subrepos, unknown, ignored, full=True):
     '''Replacement for dirstate.walk, hooking into Watchman.
 
@@ -302,7 +313,7 @@ 
     # Watchman tracks files.  We use this property to reconcile deletes
     # for name case changes.
     for entry in result['files']:
-        fname = entry['name']
+        fname = _watchmanencodingtolocal(entry['name'])
         if switch_slashes:
             fname = fname.replace('\\', '/')
         if normalize: