refs = tuple(x[:-1] for x in lines_until_sentinel(conn, '\n', Exception))
args = git.rev_list_invocation(refs, count=count, format=fmt)
p = subprocess.Popen(git.rev_list_invocation(refs, count=count, format=fmt),
- preexec_fn=git._gitenv(git.repodir),
+ env=git._gitenv(git.repodir),
stdout=subprocess.PIPE)
while True:
out = p.stdout.read(64 * 1024)
bloom.clear_bloom(packdir)
if verbosity: log('clearing reflog\n')
expirelog_cmd = ['git', 'reflog', 'expire', '--all', '--expire=all']
- expirelog = subprocess.Popen(expirelog_cmd, preexec_fn = git._gitenv())
+ expirelog = subprocess.Popen(expirelog_cmd, env=git._gitenv())
git._git_wait(' '.join(expirelog_cmd), expirelog)
if verbosity: log('removing unreachable data\n')
sweep(live_objects, existing_count, cat_pipe,
from bup.compat import range
from bup.helpers import (Sha1, add_error, chunkyreader, debug1, debug2,
fdatasync,
- hostname, localtime, log, merge_iter,
+ hostname, localtime, log,
+ merge_dict,
+ merge_iter,
mmap_read, mmap_readwrite,
parse_num,
progress, qprogress, shstr, stat_if_exists,
pass
+def _gitenv(repo_dir=None):
+ if not repo_dir:
+ repo_dir = repo()
+ return merge_dict(os.environ, {'GIT_DIR': os.path.abspath(repo_dir)})
+
def _git_wait(cmd, p):
rv = p.wait()
if rv != 0:
raise GitError('%s returned %d' % (shstr(cmd), rv))
def _git_capture(argv):
- p = subprocess.Popen(argv, stdout=subprocess.PIPE, preexec_fn = _gitenv())
+ p = subprocess.Popen(argv, stdout=subprocess.PIPE, env=_gitenv())
r = p.stdout.read()
_git_wait(repr(argv), p)
return r
def git_config_get(option, repo_dir=None):
cmd = ('git', 'config', '--get', option)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- preexec_fn=_gitenv(repo_dir=repo_dir))
+ env=_gitenv(repo_dir=repo_dir))
r = p.stdout.read()
rc = p.wait()
if rc == 0:
idx_f.close()
-def _gitenv(repo_dir = None):
- if not repo_dir:
- repo_dir = repo()
- def env():
- os.environ['GIT_DIR'] = os.path.abspath(repo_dir)
- return env
-
-
def list_refs(patterns=None, repo_dir=None,
limit_to_heads=False, limit_to_tags=False):
"""Yield (refname, hash) tuples for all repository refs unless
argv.append('--')
if patterns:
argv.extend(patterns)
- p = subprocess.Popen(argv,
- preexec_fn = _gitenv(repo_dir),
- stdout = subprocess.PIPE)
+ p = subprocess.Popen(argv, env=_gitenv(repo_dir), stdout=subprocess.PIPE)
out = p.stdout.read().strip()
rv = p.wait() # not fatal
if rv:
assert bool(parse) == bool(format)
p = subprocess.Popen(rev_list_invocation(ref_or_refs, count=count,
format=format),
- preexec_fn = _gitenv(repo_dir),
+ env=_gitenv(repo_dir),
stdout = subprocess.PIPE)
if not format:
for line in p.stdout:
or refname.startswith('refs/tags/'))
p = subprocess.Popen(['git', 'update-ref', refname,
newval.encode('hex'), oldval.encode('hex')],
- preexec_fn = _gitenv(repo_dir))
+ env=_gitenv(repo_dir))
_git_wait('git update-ref', p)
assert(refname.startswith('refs/'))
oldvalue = [] if not oldvalue else [oldvalue]
p = subprocess.Popen(['git', 'update-ref', '-d', refname] + oldvalue,
- preexec_fn = _gitenv())
+ env=_gitenv())
_git_wait('git update-ref', p)
if os.path.exists(d) and not os.path.isdir(os.path.join(d, '.')):
raise GitError('"%s" exists but is not a directory\n' % d)
p = subprocess.Popen(['git', '--bare', 'init'], stdout=sys.stderr,
- preexec_fn = _gitenv())
+ env=_gitenv())
_git_wait('git init', p)
# Force the index version configuration in order to ensure bup works
# regardless of the version of the installed Git binary.
p = subprocess.Popen(['git', 'config', 'pack.indexVersion', '2'],
- stdout=sys.stderr, preexec_fn = _gitenv())
+ stdout=sys.stderr, env=_gitenv())
_git_wait('git config', p)
# Enable the reflog
p = subprocess.Popen(['git', 'config', 'core.logAllRefUpdates', 'true'],
- stdout=sys.stderr, preexec_fn = _gitenv())
+ stdout=sys.stderr, env=_gitenv())
_git_wait('git config', p)
stdout=subprocess.PIPE,
close_fds = True,
bufsize = 4096,
- preexec_fn = _gitenv(self.repo_dir))
+ env=_gitenv(self.repo_dir))
def get(self, ref):
"""Yield (oidx, type, size), followed by the data referred to by ref.
return (leading_matches(), rest())
+def merge_dict(*xs):
+ result = {}
+ for x in xs:
+ result.update(x)
+ return result
+
+
def lines_until_sentinel(f, sentinel, ex_type):
# sentinel must end with \n and must contain only one \n
while True:
Connect to a remote host via SSH and execute a command on the host.
"""
-from __future__ import absolute_import
+from __future__ import absolute_import, print_function
import sys, os, re, subprocess
from bup import helpers, path
argv.extend(('-p', port))
argv.extend((rhost, '--', cmd.strip()))
#helpers.log('argv is: %r\n' % argv)
- def setup():
- # runs in the child process
- if not rhost:
- os.environ['PATH'] = ':'.join([nicedir,
- os.environ.get('PATH', '')])
- os.setsid()
- return subprocess.Popen(argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
- stderr=stderr,
- preexec_fn=setup)
+ if rhost:
+ env = os.environ
+ else:
+ envpath = os.environ.get('PATH')
+ env = os.environ.copy()
+ env['PATH'] = nicedir if not envpath else nicedir + ':' + envpath
+ if sys.version_info[0] < 3:
+ return subprocess.Popen(argv,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=stderr,
+ env=env,
+ preexec_fn=lambda: os.setsid())
+ else:
+ return subprocess.Popen(argv,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=stderr,
+ env=env,
+ start_new_session=True)
fix_stdout = not already_fixed and os.isatty(1)
fix_stderr = not already_fixed and os.isatty(2)
-def force_tty():
- if fix_stdout or fix_stderr:
- amt = (fix_stdout and 1 or 0) + (fix_stderr and 2 or 0)
- os.environ['BUP_FORCE_TTY'] = str(amt)
+if fix_stdout or fix_stderr:
+ tty_env = merge_dict(os.environ,
+ {'BUP_FORCE_TTY': str((fix_stdout and 1 or 0)
+ + (fix_stderr and 2 or 0))})
+else:
+ tty_env = os.environ
sep_rx = re.compile(br'([\r\n])')
p = subprocess.Popen(c,
stdout=PIPE if fix_stdout else sys.stdout,
stderr=PIPE if fix_stderr else sys.stderr,
- preexec_fn=force_tty,
- bufsize=4096,
- close_fds=True)
+ env=tty_env, bufsize=4096, close_fds=True)
# Assume p will receive these signals and quit, which will
# then cause us to quit.
for sig in (signal.SIGINT, signal.SIGTERM, signal.SIGQUIT):
sys.path[:0] = [abspath(script_home + '/../lib'), abspath(script_home + '/..')]
from bup import compat
-from bup.helpers import unlink
+from bup.helpers import merge_dict, unlink
from buptest import ex, exo, test_tempdir
from wvtest import wvcheck, wvfail, wvmsg, wvpass, wvpasseq, wvpassne, wvstart
def validate_tree(src_id, dest_id):
- def set_committer_date():
- environ['GIT_COMMITTER_DATE'] = "2014-01-01 01:01"
-
rmrf('restore-src')
rmrf('restore-dest')
mkdir('restore-src')
mkdir('restore-dest')
+ commit_env = merge_dict(environ, {'GIT_COMMITTER_DATE': '2014-01-01 01:01'})
+
# Create a commit so the archive contents will have matching timestamps.
src_c = exo(('git', '--git-dir', 'get-src',
'commit-tree', '-m', 'foo', src_id),
- preexec_fn=set_committer_date).out.strip()
+ env=commit_env).out.strip()
dest_c = exo(('git', '--git-dir', 'get-dest',
'commit-tree', '-m', 'foo', dest_id),
- preexec_fn=set_committer_date).out.strip()
+ env=commit_env).out.strip()
exr = verify_rcz('git --git-dir get-src archive %s | tar xvf - -C restore-src'
% quote(src_c),
shell=True)