|
@@ -51,9 +51,8 @@ class ToggleAction(argparse.Action):
|
|
|
|
|
|
class Archiver:
|
|
class Archiver:
|
|
|
|
|
|
- def __init__(self, verbose=False, lock_wait=None):
|
|
|
|
|
|
+ def __init__(self, lock_wait=None):
|
|
self.exit_code = EXIT_SUCCESS
|
|
self.exit_code = EXIT_SUCCESS
|
|
- self.verbose = verbose
|
|
|
|
self.lock_wait = lock_wait
|
|
self.lock_wait = lock_wait
|
|
|
|
|
|
def open_repository(self, location, create=False, exclusive=False, lock=True):
|
|
def open_repository(self, location, create=False, exclusive=False, lock=True):
|
|
@@ -74,10 +73,9 @@ class Archiver:
|
|
self.exit_code = EXIT_WARNING # we do not terminate here, so it is a warning
|
|
self.exit_code = EXIT_WARNING # we do not terminate here, so it is a warning
|
|
logger.warning(msg)
|
|
logger.warning(msg)
|
|
|
|
|
|
- def print_verbose(self, msg, *args):
|
|
|
|
- if self.verbose:
|
|
|
|
- msg = args and msg % args or msg
|
|
|
|
- logger.info(msg)
|
|
|
|
|
|
+ def print_file_status(self, status, path):
|
|
|
|
+ if self.output_filter is None or status in self.output_filter:
|
|
|
|
+ logger.info("%1s %s", status, remove_surrogates(path))
|
|
|
|
|
|
def do_serve(self, args):
|
|
def do_serve(self, args):
|
|
"""Start in server mode. This command is usually not used manually.
|
|
"""Start in server mode. This command is usually not used manually.
|
|
@@ -123,6 +121,7 @@ class Archiver:
|
|
|
|
|
|
def do_create(self, args):
|
|
def do_create(self, args):
|
|
"""Create new archive"""
|
|
"""Create new archive"""
|
|
|
|
+ self.output_filter = args.output_filter
|
|
dry_run = args.dry_run
|
|
dry_run = args.dry_run
|
|
t0 = datetime.now()
|
|
t0 = datetime.now()
|
|
if not dry_run:
|
|
if not dry_run:
|
|
@@ -163,7 +162,7 @@ class Archiver:
|
|
self.print_warning('%s: %s', path, e)
|
|
self.print_warning('%s: %s', path, e)
|
|
else:
|
|
else:
|
|
status = '-'
|
|
status = '-'
|
|
- self.print_verbose("%1s %s", status, remove_surrogates(path))
|
|
|
|
|
|
+ self.print_file_status(status, path)
|
|
continue
|
|
continue
|
|
path = os.path.normpath(path)
|
|
path = os.path.normpath(path)
|
|
if args.one_file_system:
|
|
if args.one_file_system:
|
|
@@ -262,9 +261,7 @@ class Archiver:
|
|
status = '?' # need to add a status code somewhere
|
|
status = '?' # need to add a status code somewhere
|
|
else:
|
|
else:
|
|
status = '-' # dry run, item was not backed up
|
|
status = '-' # dry run, item was not backed up
|
|
- # output ALL the stuff - it can be easily filtered using grep.
|
|
|
|
- # even stuff considered unchanged might be interesting.
|
|
|
|
- self.print_verbose("%1s %s", status, remove_surrogates(path))
|
|
|
|
|
|
+ self.print_file_status(status, path)
|
|
|
|
|
|
def do_extract(self, args):
|
|
def do_extract(self, args):
|
|
"""Extract archive contents"""
|
|
"""Extract archive contents"""
|
|
@@ -292,7 +289,7 @@ class Archiver:
|
|
if not args.dry_run:
|
|
if not args.dry_run:
|
|
while dirs and not item[b'path'].startswith(dirs[-1][b'path']):
|
|
while dirs and not item[b'path'].startswith(dirs[-1][b'path']):
|
|
archive.extract_item(dirs.pop(-1), stdout=stdout)
|
|
archive.extract_item(dirs.pop(-1), stdout=stdout)
|
|
- self.print_verbose(remove_surrogates(orig_path))
|
|
|
|
|
|
+ logger.info(remove_surrogates(orig_path))
|
|
try:
|
|
try:
|
|
if dry_run:
|
|
if dry_run:
|
|
archive.extract_item(item, dry_run=True)
|
|
archive.extract_item(item, dry_run=True)
|
|
@@ -378,7 +375,7 @@ class Archiver:
|
|
else:
|
|
else:
|
|
archive = None
|
|
archive = None
|
|
operations = FuseOperations(key, repository, manifest, archive)
|
|
operations = FuseOperations(key, repository, manifest, archive)
|
|
- self.print_verbose("Mounting filesystem")
|
|
|
|
|
|
+ logger.info("Mounting filesystem")
|
|
try:
|
|
try:
|
|
operations.mount(args.mountpoint, args.options, args.foreground)
|
|
operations.mount(args.mountpoint, args.options, args.foreground)
|
|
except RuntimeError:
|
|
except RuntimeError:
|
|
@@ -481,12 +478,12 @@ class Archiver:
|
|
to_delete = [a for a in archives if a not in keep]
|
|
to_delete = [a for a in archives if a not in keep]
|
|
stats = Statistics()
|
|
stats = Statistics()
|
|
for archive in keep:
|
|
for archive in keep:
|
|
- self.print_verbose('Keeping archive: %s' % format_archive(archive))
|
|
|
|
|
|
+ logger.info('Keeping archive: %s' % format_archive(archive))
|
|
for archive in to_delete:
|
|
for archive in to_delete:
|
|
if args.dry_run:
|
|
if args.dry_run:
|
|
- self.print_verbose('Would prune: %s' % format_archive(archive))
|
|
|
|
|
|
+ logger.info('Would prune: %s' % format_archive(archive))
|
|
else:
|
|
else:
|
|
- self.print_verbose('Pruning archive: %s' % format_archive(archive))
|
|
|
|
|
|
+ logger.info('Pruning archive: %s' % format_archive(archive))
|
|
Archive(repository, key, manifest, archive.name, cache).delete(stats)
|
|
Archive(repository, key, manifest, archive.name, cache).delete(stats)
|
|
if to_delete and not args.dry_run:
|
|
if to_delete and not args.dry_run:
|
|
manifest.write()
|
|
manifest.write()
|
|
@@ -663,11 +660,12 @@ class Archiver:
|
|
|
|
|
|
def build_parser(self, args=None, prog=None):
|
|
def build_parser(self, args=None, prog=None):
|
|
common_parser = argparse.ArgumentParser(add_help=False, prog=prog)
|
|
common_parser = argparse.ArgumentParser(add_help=False, prog=prog)
|
|
- common_parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False,
|
|
|
|
- help='verbose output')
|
|
|
|
- common_parser.add_argument('--log-level', dest='log_level', default='info', metavar='LEVEL',
|
|
|
|
- choices=('debug', 'info', 'warning', 'error', 'critical'),
|
|
|
|
- help='set the log level to LEVEL, default: %(default)s)')
|
|
|
|
|
|
+ common_parser.add_argument('-v', '--verbose', '--info', dest='log_level',
|
|
|
|
+ action='store_const', const='info', default='warning',
|
|
|
|
+ help='enable informative (verbose) output, work on log level INFO')
|
|
|
|
+ common_parser.add_argument('--debug', dest='log_level',
|
|
|
|
+ action='store_const', const='debug', default='warning',
|
|
|
|
+ help='enable debug output, work on log level DEBUG')
|
|
common_parser.add_argument('--lock-wait', dest='lock_wait', type=int, metavar='N', default=1,
|
|
common_parser.add_argument('--lock-wait', dest='lock_wait', type=int, metavar='N', default=1,
|
|
help='wait for the lock, but max. N seconds (default: %(default)d).')
|
|
help='wait for the lock, but max. N seconds (default: %(default)d).')
|
|
common_parser.add_argument('--show-rc', dest='show_rc', action='store_true', default=False,
|
|
common_parser.add_argument('--show-rc', dest='show_rc', action='store_true', default=False,
|
|
@@ -802,6 +800,8 @@ class Archiver:
|
|
help="""toggle progress display while creating the archive, showing Original,
|
|
help="""toggle progress display while creating the archive, showing Original,
|
|
Compressed and Deduplicated sizes, followed by the Number of files seen
|
|
Compressed and Deduplicated sizes, followed by the Number of files seen
|
|
and the path being processed, default: %(default)s""")
|
|
and the path being processed, default: %(default)s""")
|
|
|
|
+ subparser.add_argument('--filter', dest='output_filter', metavar='STATUSCHARS',
|
|
|
|
+ help='only display items with the given status characters')
|
|
subparser.add_argument('-e', '--exclude', dest='excludes',
|
|
subparser.add_argument('-e', '--exclude', dest='excludes',
|
|
type=ExcludePattern, action='append',
|
|
type=ExcludePattern, action='append',
|
|
metavar="PATTERN", help='exclude paths matching PATTERN')
|
|
metavar="PATTERN", help='exclude paths matching PATTERN')
|
|
@@ -1177,7 +1177,6 @@ class Archiver:
|
|
|
|
|
|
def run(self, args):
|
|
def run(self, args):
|
|
os.umask(args.umask) # early, before opening files
|
|
os.umask(args.umask) # early, before opening files
|
|
- self.verbose = args.verbose
|
|
|
|
self.lock_wait = args.lock_wait
|
|
self.lock_wait = args.lock_wait
|
|
RemoteRepository.remote_path = args.remote_path
|
|
RemoteRepository.remote_path = args.remote_path
|
|
RemoteRepository.umask = args.umask
|
|
RemoteRepository.umask = args.umask
|