Changeset - baea97957cae
[Not reviewed]
0 2 0
Lance Edgar - 5 years ago 2019-09-26 22:01:23
lance@edbob.org
Add `sed()` convenience function

copied from fabric1 src
2 files changed with 77 insertions and 1 deletions:
0 comments (0 inline, 0 general) First comment
rattail_fabric2/__init__.py
Show inline comments
 
@@ -37,4 +37,4 @@ from .core import (
 
    set_timezone,
 
    UNSPECIFIED,
 
)
 
from .util import exists, contains, append
 
from .util import exists, contains, append, sed
rattail_fabric2/util.py
Show inline comments
 
@@ -24,6 +24,8 @@
 
Misc. Utilities
 
"""
 

	
 
import hashlib
 

	
 

	
 
def exists(c, path, use_sudo=False):
 
    """
 
@@ -192,3 +194,77 @@ def get_home_path(c, user=None):
 
    home = c.run('getent passwd {} | cut -d: -f6'.format(user)).stdout.strip()
 
    home = home.rstrip('/')
 
    return home
 

	
 

	
 
def sed(c, filename, before, after, limit='', use_sudo=False, backup='.bak',
 
        flags='',
 
        # shell=False,
 
):
 
    """
 
    NOTE: This was copied from the upstream ``fabric.contrib.files`` (v1) module.
 

	
 
    Run a search-and-replace on ``filename`` with given regex patterns.
 

	
 
    Equivalent to ``sed -i<backup> -r -e "/<limit>/ s/<before>/<after>/<flags>g"
 
    <filename>``. Setting ``backup`` to an empty string will, disable backup
 
    file creation.
 

	
 
    For convenience, ``before`` and ``after`` will automatically escape forward
 
    slashes, single quotes and parentheses for you, so you don't need to
 
    specify e.g.  ``http:\/\/foo\.com``, instead just using ``http://foo\.com``
 
    is fine.
 

	
 
    If ``use_sudo`` is True, will use `sudo` instead of `run`.
 

	
 
    ..
 
       The ``shell`` argument will be eventually passed to `run`/`sudo`. It
 
       defaults to False in order to avoid problems with many nested levels of
 
       quotes and backslashes. However, setting it to True may help when using
 
       ``~fabric.operations.cd`` to wrap explicit or implicit ``sudo`` calls.
 
       (``cd`` by it's nature is a shell built-in, not a standalone command, so it
 
       should be called within a shell.)
 

	
 
    Other options may be specified with sed-compatible regex flags -- for
 
    example, to make the search and replace case insensitive, specify
 
    ``flags="i"``. The ``g`` flag is always specified regardless, so you do not
 
    need to remember to include it when overriding this parameter.
 
    """
 
    func = use_sudo and c.sudo or c.run
 
    # Characters to be escaped in both
 
    for char in "/'":
 
        before = before.replace(char, r'\%s' % char)
 
        after = after.replace(char, r'\%s' % char)
 
    # Characters to be escaped in replacement only (they're useful in regexen
 
    # in the 'before' part)
 
    for char in "()":
 
        after = after.replace(char, r'\%s' % char)
 
    if limit:
 
        limit = r'/%s/ ' % limit
 
    context = {
 
        'script': r"'%ss/%s/%s/%sg'" % (limit, before, after, flags),
 
        'filename': _expand_path(c, filename),
 
        'backup': backup
 
    }
 
    # Test the OS because of differences between sed versions
 

	
 
    # with hide('running', 'stdout'):
 
    #     platform = run("uname", shell=False, pty=False)
 
    platform = c.run("uname", pty=False, echo=False, hide=True)
 
    if platform in ('NetBSD', 'OpenBSD', 'QNX'):
 
        # Attempt to protect against failures/collisions
 
        hasher = hashlib.sha1()
 
        hasher.update(c.host_string) # TODO: what did env.host_string become?
 
        hasher.update(filename)
 
        context['tmp'] = "/tmp/%s" % hasher.hexdigest()
 
        # Use temp file to work around lack of -i
 
        expr = r"""cp -p %(filename)s %(tmp)s \
 
&& sed -r -e %(script)s %(filename)s > %(tmp)s \
 
&& cp -p %(filename)s %(filename)s%(backup)s \
 
&& mv %(tmp)s %(filename)s"""
 
    else:
 
        context['extended_regex'] = '-E' if platform == 'Darwin' else '-r'
 
        expr = r"sed -i%(backup)s %(extended_regex)s -e %(script)s %(filename)s"
 
    command = expr % context
 
    return func(command,
 
                # shell=shell
 
    )
0 comments (0 inline, 0 general) First comment
You need to be logged in to comment. Login now