Patchwork [1,of,4,V2] pathutil: add dirname and join functions

login
register
mail settings
Submitter Durham Goode
Date May 22, 2015, 8:50 p.m.
Message ID <53d97bfd60a1d5e397b8.1432327815@dev2000.prn2.facebook.com>
Download mbox | patch
Permalink /patch/9242/
State Accepted
Delegated to: Augie Fackler
Headers show

Comments

Durham Goode - May 22, 2015, 8:50 p.m.
# HG changeset patch
# User Durham Goode <durham@fb.com>
# Date 1432324038 25200
#      Fri May 22 12:47:18 2015 -0700
# Node ID 53d97bfd60a1d5e397b808def920fe6a73a1cac6
# Parent  f2b98dacb37ddd6713b11a1a871fcdbbc5fd8bb2
pathutil: add dirname and join functions

This adds dirname and join functions to pathutil which are explicitly for
handling '/' delimited paths. The implementations are basically copy paste from
python's posix os.path.dirname and os.path.join functions.
Augie Fackler - May 26, 2015, 3:01 p.m.
On Fri, May 22, 2015 at 01:50:15PM -0700, Durham Goode wrote:
> # HG changeset patch
> # User Durham Goode <durham@fb.com>
> # Date 1432324038 25200
> #      Fri May 22 12:47:18 2015 -0700
> # Node ID 53d97bfd60a1d5e397b808def920fe6a73a1cac6
> # Parent  f2b98dacb37ddd6713b11a1a871fcdbbc5fd8bb2
> pathutil: add dirname and join functions
>
> This adds dirname and join functions to pathutil which are explicitly for
> handling '/' delimited paths. The implementations are basically copy paste from
> python's posix os.path.dirname and os.path.join functions.

Why not just *use* posixpath.join() et al in these methods, rather
than carrying around a bonus implementation?

>
> diff --git a/mercurial/pathutil.py b/mercurial/pathutil.py
> --- a/mercurial/pathutil.py
> +++ b/mercurial/pathutil.py
> @@ -187,3 +187,68 @@ def normasprefix(path):
>          return path + os.sep
>      else:
>          return path
> +
> +def join(path, *paths):
> +    '''Join two or more pathname components, inserting '/' as needed.
> +
> +    Based on the posix os.path.join() implementation.
> +
> +    >>> join('foo', 'bar')
> +    'foo/bar'
> +    >>> join('/foo', 'bar')
> +    '/foo/bar'
> +    >>> join('foo', '/bar')
> +    '/bar'
> +    >>> join('foo', 'bar/')
> +    'foo/bar/'
> +    >>> join('foo', 'bar', 'gah')
> +    'foo/bar/gah'
> +    >>> join('foo')
> +    'foo'
> +    >>> join('', 'foo')
> +    'foo'
> +    >>> join('foo/', 'bar')
> +    'foo/bar'
> +    >>> join('', '', '')
> +    ''
> +    >>> join ('foo', '', '', 'bar')
> +    'foo/bar'
> +    '''
> +    sep = '/'
> +    if not paths:
> +        path[:0] + sep #23780: Ensure compatible data type even if p is null.
> +    for piece in paths:
> +        if piece.startswith(sep):
> +            path = piece
> +        elif not path or path.endswith(sep):
> +            path += piece
> +        else:
> +            path += sep + piece
> +    return path
> +
> +def dirname(path):
> +    '''returns the directory portion of the given path
> +
> +    Based on the posix os.path.split() implementation.
> +
> +    >>> dirname('foo')
> +    ''
> +    >>> dirname('foo/')
> +    'foo'
> +    >>> dirname('foo/bar')
> +    'foo'
> +    >>> dirname('/foo')
> +    '/'
> +    >>> dirname('/foo/bar')
> +    '/foo'
> +    >>> dirname('/foo//bar/poo')
> +    '/foo//bar'
> +    >>> dirname('/foo//bar')
> +    '/foo'
> +    '''
> +    sep = '/'
> +    i = path.rfind(sep) + 1
> +    dirname = path[:i]
> +    if dirname and dirname != sep * len(dirname):
> +        dirname = dirname.rstrip(sep)
> +    return dirname
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Durham Goode - May 27, 2015, 6:04 p.m.
On 5/26/15 8:01 AM, Augie Fackler wrote:
> On Fri, May 22, 2015 at 01:50:15PM -0700, Durham Goode wrote:
>> # HG changeset patch
>> # User Durham Goode <durham@fb.com>
>> # Date 1432324038 25200
>> #      Fri May 22 12:47:18 2015 -0700
>> # Node ID 53d97bfd60a1d5e397b808def920fe6a73a1cac6
>> # Parent  f2b98dacb37ddd6713b11a1a871fcdbbc5fd8bb2
>> pathutil: add dirname and join functions
>>
>> This adds dirname and join functions to pathutil which are explicitly for
>> handling '/' delimited paths. The implementations are basically copy paste from
>> python's posix os.path.dirname and os.path.join functions.
> Why not just *use* posixpath.join() et al in these methods, rather
> than carrying around a bonus implementation?
I didn't realize it existed.  I'll resend with them.
Augie Fackler - May 27, 2015, 6:04 p.m.
On Wed, May 27, 2015 at 2:04 PM, Durham Goode <durham@fb.com> wrote:
>> Why not just *use* posixpath.join() et al in these methods, rather
>> than carrying around a bonus implementation?
>
> I didn't realize it existed.  I'll resend with them.


These are already pushed with that fixed in a followup. :)

Patch

diff --git a/mercurial/pathutil.py b/mercurial/pathutil.py
--- a/mercurial/pathutil.py
+++ b/mercurial/pathutil.py
@@ -187,3 +187,68 @@  def normasprefix(path):
         return path + os.sep
     else:
         return path
+
+def join(path, *paths):
+    '''Join two or more pathname components, inserting '/' as needed.
+
+    Based on the posix os.path.join() implementation.
+
+    >>> join('foo', 'bar')
+    'foo/bar'
+    >>> join('/foo', 'bar')
+    '/foo/bar'
+    >>> join('foo', '/bar')
+    '/bar'
+    >>> join('foo', 'bar/')
+    'foo/bar/'
+    >>> join('foo', 'bar', 'gah')
+    'foo/bar/gah'
+    >>> join('foo')
+    'foo'
+    >>> join('', 'foo')
+    'foo'
+    >>> join('foo/', 'bar')
+    'foo/bar'
+    >>> join('', '', '')
+    ''
+    >>> join ('foo', '', '', 'bar')
+    'foo/bar'
+    '''
+    sep = '/'
+    if not paths:
+        path[:0] + sep #23780: Ensure compatible data type even if p is null.
+    for piece in paths:
+        if piece.startswith(sep):
+            path = piece
+        elif not path or path.endswith(sep):
+            path += piece
+        else:
+            path += sep + piece
+    return path
+
+def dirname(path):
+    '''returns the directory portion of the given path
+
+    Based on the posix os.path.split() implementation.
+
+    >>> dirname('foo')
+    ''
+    >>> dirname('foo/')
+    'foo'
+    >>> dirname('foo/bar')
+    'foo'
+    >>> dirname('/foo')
+    '/'
+    >>> dirname('/foo/bar')
+    '/foo'
+    >>> dirname('/foo//bar/poo')
+    '/foo//bar'
+    >>> dirname('/foo//bar')
+    '/foo'
+    '''
+    sep = '/'
+    i = path.rfind(sep) + 1
+    dirname = path[:i]
+    if dirname and dirname != sep * len(dirname):
+        dirname = dirname.rstrip(sep)
+    return dirname