"""
# end of bup preamble
-from __future__ import print_function
+from __future__ import absolute_import, print_function
from collections import defaultdict
from difflib import unified_diff
from itertools import chain, dropwhile, groupby, takewhile
from os import environ, chdir
from os.path import abspath, dirname
-from pipes import quote
from random import choice, randint
from shutil import copytree, rmtree
-from subprocess import PIPE, Popen, check_call
+from subprocess import PIPE
from sys import stderr
from time import localtime, strftime, time
import os, random, sys
top = os.getcwd()
bup_cmd = top + '/bup'
-from buptest import test_tempdir
+from buptest import ex, exo, test_tempdir
from wvtest import wvfail, wvpass, wvpasseq, wvpassne, wvstart
+from bup import compat
from bup.helpers import partition, period_as_secs, readpipe
-def logcmd(cmd):
- if isinstance(cmd, basestring):
- print(cmd, file=stderr)
- else:
- print(' '.join(map(quote, cmd)), file=stderr)
-
-def exc(cmd, shell=False):
- logcmd(cmd)
- check_call(cmd, shell=shell)
-
-def exo(cmd, stdin=None, stdout=True, stderr=False, shell=False, check=True):
- logcmd(cmd)
- p = Popen(cmd,
- stdin=None,
- stdout=(PIPE if stdout else None),
- stderr=PIPE,
- shell=shell)
- out, err = p.communicate()
- if check and p.returncode != 0:
- raise Exception('subprocess %r failed with status %d, stderr: %r'
- % (' '.join(argv), p.returncode, err))
- return out, err, p
-
-def bup(*args):
- return exo((bup_cmd,) + args)[0]
-
-def bupc(*args):
- return exc((bup_cmd,) + args)
-
def create_older_random_saves(n, start_utc, end_utc):
with open('foo', 'w') as f:
pass
- exc(['git', 'add', 'foo'])
+ ex(['git', 'add', 'foo'])
utcs = set()
while len(utcs) != n:
utcs.add(randint(start_utc, end_utc))
for utc in utcs:
with open('foo', 'w') as f:
f.write(str(utc) + '\n')
- exc(['git', 'commit', '--date', str(utc), '-qam', str(utc)])
- exc(['git', 'gc', '--aggressive'])
+ ex(['git', 'commit', '--date', str(utc), '-qam', str(utc)])
+ ex(['git', 'gc', '--aggressive'])
return utcs
# There is corresponding code in bup for some of this, but the
return utcs
utcs = sorted(utcs, reverse=True)
period_start = dict(spec)
- for kind, duration in period_start.iteritems():
+ for kind, duration in compat.items(period_start):
period_start[kind] = utc_start - period_as_secs(duration)
period_start = defaultdict(lambda: float('inf'), period_start)
utcs = list(dropwhile(lambda x: x >= period_start['all'], utcs))
matches = takewhile(lambda x: x >= period_start['dailies'], utcs)
- dailies = [min(day_utcs) for yday, day_utcs
+ dailies = [max(day_utcs) for yday, day_utcs
in groupby(matches, lambda x: localtime(x).tm_yday)]
utcs = list(dropwhile(lambda x: x >= period_start['dailies'], utcs))
matches = takewhile(lambda x: x >= period_start['monthlies'], utcs)
- monthlies = [min(month_utcs) for month, month_utcs
+ monthlies = [max(month_utcs) for month, month_utcs
in groupby(matches, lambda x: localtime(x).tm_mon)]
utcs = dropwhile(lambda x: x >= period_start['monthlies'], utcs)
matches = takewhile(lambda x: x >= period_start['yearlies'], utcs)
- yearlies = [min(year_utcs) for year, year_utcs
+ yearlies = [max(year_utcs) for year, year_utcs
in groupby(matches, lambda x: localtime(x).tm_year)]
return chain(all, dailies, monthlies, yearlies)
def check_prune_result(expected):
actual = sorted([int(x)
for x in exo(['git', 'log',
- '--pretty=format:%at'])[0].splitlines()])
+ '--pretty=format:%at']).out.splitlines()])
if expected != actual:
for x in expected:
print('ex:', x, strftime('%Y-%m-%d-%H%M%S', localtime(x)),
now = int(time())
three_years_ago = now - (60 * 60 * 24 * 366 * 3)
chdir(tmpdir)
- exc(['git', 'init', 'work'])
+ ex(['git', 'init', 'work'])
wvstart('generating ' + str(save_population) + ' random saves')
chdir(tmpdir + '/work')
save_utcs = create_older_random_saves(save_population, three_years_ago, now)
chdir(tmpdir)
- test_set_hash = exo(['git', 'show-ref', '-s', 'master'])[0].rstrip()
- ls_saves = bup('ls', 'master').splitlines()
+ test_set_hash = exo(['git', 'show-ref', '-s', 'master']).out.rstrip()
+ ls_saves = exo((bup_cmd, 'ls', 'master')).out.splitlines()
wvpasseq(save_population + 1, len(ls_saves))
wvstart('ensure everything kept, if no keep arguments')
- exc(['git', 'reset', '--hard', test_set_hash])
- _, errmsg, proc = exo((bup_cmd,
- 'prune-older', '-v', '--unsafe', '--no-gc',
- '--wrt', str(now)) \
- + ('master',),
- stdout=False, stderr=True, check=False)
- wvpassne(proc.returncode, 0)
- wvpass('at least one keep argument is required' in errmsg)
+ ex(['git', 'reset', '--hard', test_set_hash])
+ proc = ex((bup_cmd,
+ 'prune-older', '-v', '--unsafe', '--no-gc',
+ '--wrt', str(now)) \
+ + ('master',),
+ stdout=None, stderr=PIPE, check=False)
+ wvpassne(proc.rc, 0)
+ wvpass('at least one keep argument is required' in proc.err)
check_prune_result(save_utcs)
# some outside the save range.
three_years_ago - period_scale['m'],
now):
- exc(['git', 'reset', '--hard', test_set_hash])
+ ex(['git', 'reset', '--hard', test_set_hash])
expected = sorted(expected_retentions(save_utcs, now, spec))
- exc((bup_cmd,
- 'prune-older', '-v', '--unsafe', '--no-gc', '--wrt', str(now)) \
- + period_spec_to_period_args(spec) \
- + ('master',))
+ ex((bup_cmd,
+ 'prune-older', '-v', '--unsafe', '--no-gc', '--wrt', str(now)) \
+ + period_spec_to_period_args(spec) \
+ + ('master',))
check_prune_result(expected)
# More expensive because we have to recreate the repo each time
wvstart('running %d generative gc tests on %d saves' % (prune_gc_cycles,
save_population))
- exc(['git', 'reset', '--hard', test_set_hash])
+ ex(['git', 'reset', '--hard', test_set_hash])
copytree('work/.git', 'clean-test-repo', symlinks=True)
for spec in unique_period_specs(prune_gc_cycles,
# Make it more likely we'll have
rmtree('work/.git')
copytree('clean-test-repo', 'work/.git')
expected = sorted(expected_retentions(save_utcs, now, spec))
- exc((bup_cmd,
- 'prune-older', '-v', '--unsafe', '--wrt', str(now)) \
- + period_spec_to_period_args(spec) \
- + ('master',))
+ ex((bup_cmd,
+ 'prune-older', '-v', '--unsafe', '--wrt', str(now)) \
+ + period_spec_to_period_args(spec) \
+ + ('master',))
check_prune_result(expected)