|
@@ -20,6 +20,8 @@ from .helpers import Error, location_validator, format_time, format_file_size, \
|
|
|
get_cache_dir, get_keys_dir, format_timedelta, prune_within, prune_split, \
|
|
|
Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \
|
|
|
is_cachedir, bigint_to_int, ChunkerParams, CompressionSpec, have_cython
|
|
|
+from .logger import create_logger, setup_logging
|
|
|
+logger = create_logger()
|
|
|
if have_cython():
|
|
|
from .compress import Compressor, COMPR_BUFFER
|
|
|
from .upgrader import AtticRepositoryUpgrader
|
|
@@ -48,15 +50,11 @@ class Archiver:
|
|
|
def print_error(self, msg, *args):
|
|
|
msg = args and msg % args or msg
|
|
|
self.exit_code = 1
|
|
|
- print('borg: ' + msg, file=sys.stderr)
|
|
|
+ logger.error('borg: ' + msg)
|
|
|
|
|
|
def print_verbose(self, msg, *args, **kw):
|
|
|
- if self.verbose:
|
|
|
- msg = args and msg % args or msg
|
|
|
- if kw.get('newline', True):
|
|
|
- print(msg)
|
|
|
- else:
|
|
|
- print(msg, end=' ')
|
|
|
+ msg = args and msg % args or msg
|
|
|
+ logger.info(msg)
|
|
|
|
|
|
def do_serve(self, args):
|
|
|
"""Start in server mode. This command is usually not used manually.
|
|
@@ -65,7 +63,7 @@ class Archiver:
|
|
|
|
|
|
def do_init(self, args):
|
|
|
"""Initialize an empty repository"""
|
|
|
- print('Initializing repository at "%s"' % args.repository.orig)
|
|
|
+ logger.info('Initializing repository at "%s"' % args.repository.orig)
|
|
|
repository = self.open_repository(args.repository, create=True, exclusive=True)
|
|
|
key = key_creator(repository, args)
|
|
|
manifest = Manifest(key, repository)
|
|
@@ -87,9 +85,9 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|
|
if input('Do you want to continue? ') == 'Yes I am sure':
|
|
|
break
|
|
|
if not args.archives_only:
|
|
|
- print('Starting repository check...')
|
|
|
+ logger.warning('Starting repository check...')
|
|
|
if repository.check(repair=args.repair):
|
|
|
- print('Repository check complete, no problems found.')
|
|
|
+ logger.info('Repository check complete, no problems found.')
|
|
|
else:
|
|
|
return 1
|
|
|
if not args.repo_only and not ArchiveChecker().check(
|
|
@@ -118,7 +116,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|
|
archive = Archive(repository, key, manifest, args.archive.archive, cache=cache,
|
|
|
create=True, checkpoint_interval=args.checkpoint_interval,
|
|
|
numeric_owner=args.numeric_owner, progress=args.progress,
|
|
|
- chunker_params=args.chunker_params)
|
|
|
+ chunker_params=args.chunker_params, start=t0)
|
|
|
else:
|
|
|
archive = cache = None
|
|
|
# Add cache dir to inode_skip list
|
|
@@ -163,16 +161,10 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|
|
if args.progress:
|
|
|
archive.stats.show_progress(final=True)
|
|
|
if args.stats:
|
|
|
- t = datetime.now()
|
|
|
- diff = t - t0
|
|
|
+ archive.end = datetime.now()
|
|
|
print('-' * 78)
|
|
|
- print('Archive name: %s' % args.archive.archive)
|
|
|
- print('Archive fingerprint: %s' % hexlify(archive.id).decode('ascii'))
|
|
|
- print('Start time: %s' % t0.strftime('%c'))
|
|
|
- print('End time: %s' % t.strftime('%c'))
|
|
|
- print('Duration: %s' % format_timedelta(diff))
|
|
|
- print('Number of files: %d' % archive.stats.nfiles)
|
|
|
- archive.stats.print_('This archive:', cache)
|
|
|
+ print(str(archive))
|
|
|
+ print(archive.stats.print_('This archive:', cache))
|
|
|
print('-' * 78)
|
|
|
return self.exit_code
|
|
|
|
|
@@ -252,7 +244,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|
|
"""Extract archive contents"""
|
|
|
# be restrictive when restoring files, restore permissions later
|
|
|
if sys.getfilesystemencoding() == 'ascii':
|
|
|
- print('Warning: File system encoding is "ascii", extracting non-ascii filenames will not be supported.')
|
|
|
+ logger.warning('Warning: File system encoding is "ascii", extracting non-ascii filenames will not be supported.')
|
|
|
repository = self.open_repository(args.archive)
|
|
|
manifest, key = Manifest.load(repository)
|
|
|
archive = Archive(repository, key, manifest, args.archive.archive,
|
|
@@ -318,21 +310,22 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|
|
repository.commit()
|
|
|
cache.commit()
|
|
|
if args.stats:
|
|
|
- stats.print_('Deleted data:', cache)
|
|
|
+ logger.info(stats.print_('Deleted data:', cache))
|
|
|
else:
|
|
|
if not args.cache_only:
|
|
|
- print("You requested to completely DELETE the repository *including* all archives it contains:")
|
|
|
+ print("You requested to completely DELETE the repository *including* all archives it contains:", file=sys.stderr)
|
|
|
for archive_info in manifest.list_archive_infos(sort_by='ts'):
|
|
|
- print(format_archive(archive_info))
|
|
|
+ print(format_archive(archive_info), file=sys.stderr)
|
|
|
if not os.environ.get('BORG_CHECK_I_KNOW_WHAT_I_AM_DOING'):
|
|
|
- print("""Type "YES" if you understand this and want to continue.\n""")
|
|
|
+ print("""Type "YES" if you understand this and want to continue.\n""", file=sys.stderr)
|
|
|
+ # XXX: prompt may end up on stdout, but we'll assume that input() does the right thing
|
|
|
if input('Do you want to continue? ') != 'YES':
|
|
|
self.exit_code = 1
|
|
|
return self.exit_code
|
|
|
repository.destroy()
|
|
|
- print("Repository deleted.")
|
|
|
+ logger.info("Repository deleted.")
|
|
|
cache.destroy()
|
|
|
- print("Cache deleted.")
|
|
|
+ logger.info("Cache deleted.")
|
|
|
return self.exit_code
|
|
|
|
|
|
def do_mount(self, args):
|
|
@@ -418,7 +411,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|
|
print('Time: %s' % to_localtime(archive.ts).strftime('%c'))
|
|
|
print('Command line:', remove_surrogates(' '.join(archive.metadata[b'cmdline'])))
|
|
|
print('Number of files: %d' % stats.nfiles)
|
|
|
- stats.print_('This archive:', cache)
|
|
|
+ print(stats.print_('This archive:', cache))
|
|
|
return self.exit_code
|
|
|
|
|
|
def do_prune(self, args):
|
|
@@ -463,7 +456,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|
|
repository.commit()
|
|
|
cache.commit()
|
|
|
if args.stats:
|
|
|
- stats.print_('Deleted data:', cache)
|
|
|
+ logger.info(stats.print_('Deleted data:', cache))
|
|
|
return self.exit_code
|
|
|
|
|
|
def do_upgrade(self, args):
|
|
@@ -551,9 +544,8 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|
|
|
|
|
def build_parser(self, args=None, prog=None):
|
|
|
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('-v', '--verbose', dest='verbose', action='count',
|
|
|
+ help='verbose output, defaults to warnings only')
|
|
|
common_parser.add_argument('--no-files-cache', dest='cache_files', action='store_false',
|
|
|
help='do not load/update the file metadata cache used to detect unchanged files')
|
|
|
common_parser.add_argument('--umask', dest='umask', type=lambda s: int(s, 8), default=RemoteRepository.umask, metavar='M',
|
|
@@ -983,7 +975,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|
|
parser = self.build_parser(args)
|
|
|
|
|
|
args = parser.parse_args(args or ['-h'])
|
|
|
- self.verbose = args.verbose
|
|
|
+ setup_logging(args)
|
|
|
os.umask(args.umask)
|
|
|
RemoteRepository.remote_path = args.remote_path
|
|
|
RemoteRepository.umask = args.umask
|
|
@@ -1002,7 +994,7 @@ def sig_info_handler(signum, stack): # pragma: no cover
|
|
|
total = loc['st'].st_size
|
|
|
except Exception:
|
|
|
pos, total = 0, 0
|
|
|
- print("{0} {1}/{2}".format(path, format_file_size(pos), format_file_size(total)))
|
|
|
+ logger.warning("{0} {1}/{2}".format(path, format_file_size(pos), format_file_size(total)))
|
|
|
break
|
|
|
if func in ('extract_item', ): # extract op
|
|
|
path = loc['item'][b'path']
|
|
@@ -1010,7 +1002,7 @@ def sig_info_handler(signum, stack): # pragma: no cover
|
|
|
pos = loc['fd'].tell()
|
|
|
except Exception:
|
|
|
pos = 0
|
|
|
- print("{0} {1}/???".format(path, format_file_size(pos)))
|
|
|
+ logger.warning("{0} {1}/???".format(path, format_file_size(pos)))
|
|
|
break
|
|
|
|
|
|
|