Skip to content

Commit

Permalink
Work around lack of -i in (Open|Net)BSD sed.
Browse files Browse the repository at this point in the history
Fixes #288.
  • Loading branch information
bitprophet committed Mar 20, 2011
1 parent ecc4b16 commit 28500e9
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
3 changes: 3 additions & 0 deletions docs/changes/0.9.5.rst
Expand Up @@ -29,6 +29,9 @@ Bugfixes
* :issue:`287`: Fix bug in password prompt causing occasional tracebacks.
Thanks to Antti Kaihola for the catch and Rick Harding for testing the
proposed solution.
* :issue:`288`: Use temporary files to work around the lack of a ``-i`` flag in
OpenBSD and NetBSD `~fabric.contrib.files.sed`. Thanks to Morgan Lefieux for
catch + patches.
* :issue:`305`: Strip whitespace from hostnames to help prevent user error.
Thanks to Michael Bravo for the report and Rick Harding for the patch.
* :issue:`316`: Use of `~fabric.context_managers.settings` with key names not
Expand Down
23 changes: 20 additions & 3 deletions fabric/contrib/files.py
Expand Up @@ -4,11 +4,12 @@

from __future__ import with_statement

import hashlib
import tempfile
import re
import os

from fabric.api import run, sudo, settings, put, hide, abort
from fabric.api import run, sudo, settings, put, hide, abort, env


def exists(path, use_sudo=False, verbose=False):
Expand Down Expand Up @@ -130,12 +131,28 @@ def sed(filename, before, after, limit='', use_sudo=False, backup='.bak'):
with many nested levels of quotes and backslashes.
"""
func = use_sudo and sudo or run
expr = r"sed -i%s -r -e '%ss/%s/%s/g' %s"
before = before.replace('/', r'\/')
after = after.replace('/', r'\/')
if limit:
limit = r'/%s/ ' % limit
command = expr % (backup, limit, before, after, filename)
# Test the OS because of differences between sed versions
with hide('running', 'stdout'):
platform = run("uname")
if platform in ('NetBSD', 'OpenBSD'):
# Attempt to protect against failures/collisions
hasher = hashlib.sha1()
hasher.update(env.host_string)
hasher.update(filename)
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 '%(limit)ss/%(before)s/%(after)s/g' %(filename)s > %(tmp)s \
&& cp -p %(filename)s %(filename)s%(backup)s \
&& mv %(tmp)s %(filename)s"""
command = expr % locals()
else:
expr = r"sed -i%s -r -e '%ss/%s/%s/g' %s"
command = expr % (backup, limit, before, after, filename)
return func(command, shell=False)


Expand Down

0 comments on commit 28500e9

Please sign in to comment.