Merge pull request #1874 from Abogical/cache-progress

Add progress display for cache commit
This commit is contained in:
enkore 2016-11-26 00:50:16 +01:00 committed by GitHub
commit 1250b14ce2
2 changed files with 44 additions and 19 deletions

View File

@ -18,6 +18,7 @@ from .helpers import get_cache_dir
from .helpers import decode_dict, int_to_bigint, bigint_to_int, bin_to_hex from .helpers import decode_dict, int_to_bigint, bigint_to_int, bin_to_hex
from .helpers import format_file_size from .helpers import format_file_size
from .helpers import yes from .helpers import yes
from .helpers import ProgressIndicatorMessage
from .item import Item, ArchiveItem from .item import Item, ArchiveItem
from .key import PlaintextKey from .key import PlaintextKey
from .locking import Lock from .locking import Lock
@ -246,7 +247,9 @@ Chunk index: {0.total_unique_chunks:20d} {0.total_chunks:20d}"""
""" """
if not self.txn_active: if not self.txn_active:
return return
pi = ProgressIndicatorMessage()
if self.files is not None: if self.files is not None:
pi.output('Saving files cache')
ttl = int(os.environ.get('BORG_FILES_CACHE_TTL', 20)) ttl = int(os.environ.get('BORG_FILES_CACHE_TTL', 20))
with SaveFile(os.path.join(self.path, 'files'), binary=True) as fd: with SaveFile(os.path.join(self.path, 'files'), binary=True) as fd:
for path_hash, item in self.files.items(): for path_hash, item in self.files.items():
@ -257,17 +260,20 @@ Chunk index: {0.total_unique_chunks:20d} {0.total_chunks:20d}"""
if entry.age == 0 and bigint_to_int(entry.mtime) < self._newest_mtime or \ if entry.age == 0 and bigint_to_int(entry.mtime) < self._newest_mtime or \
entry.age > 0 and entry.age < ttl: entry.age > 0 and entry.age < ttl:
msgpack.pack((path_hash, entry), fd) msgpack.pack((path_hash, entry), fd)
pi.output('Saving cache config')
self.config.set('cache', 'manifest', self.manifest.id_str) self.config.set('cache', 'manifest', self.manifest.id_str)
self.config.set('cache', 'timestamp', self.manifest.timestamp) self.config.set('cache', 'timestamp', self.manifest.timestamp)
self.config.set('cache', 'key_type', str(self.key.TYPE)) self.config.set('cache', 'key_type', str(self.key.TYPE))
self.config.set('cache', 'previous_location', self.repository._location.canonical_path()) self.config.set('cache', 'previous_location', self.repository._location.canonical_path())
with SaveFile(os.path.join(self.path, 'config')) as fd: with SaveFile(os.path.join(self.path, 'config')) as fd:
self.config.write(fd) self.config.write(fd)
pi.output('Saving chunks cache')
self.chunks.write(os.path.join(self.path, 'chunks').encode('utf-8')) self.chunks.write(os.path.join(self.path, 'chunks').encode('utf-8'))
os.rename(os.path.join(self.path, 'txn.active'), os.rename(os.path.join(self.path, 'txn.active'),
os.path.join(self.path, 'txn.tmp')) os.path.join(self.path, 'txn.tmp'))
shutil.rmtree(os.path.join(self.path, 'txn.tmp')) shutil.rmtree(os.path.join(self.path, 'txn.tmp'))
self.txn_active = False self.txn_active = False
pi.finish()
def rollback(self): def rollback(self):
"""Roll back partial and aborted transactions """Roll back partial and aborted transactions

View File

@ -1210,23 +1210,10 @@ def ellipsis_truncate(msg, space):
return msg + ' ' * (space - msg_width) return msg + ' ' * (space - msg_width)
class ProgressIndicatorPercent: class ProgressIndicatorBase:
LOGGER = 'borg.output.progress' LOGGER = 'borg.output.progress'
def __init__(self, total=0, step=5, start=0, msg="%3.0f%%"): def __init__(self):
"""
Percentage-based progress indicator
:param total: total amount of items
:param step: step size in percent
:param start: at which percent value to start
:param msg: output message, must contain one %f placeholder for the percentage
"""
self.counter = 0 # 0 .. (total-1)
self.total = total
self.trigger_at = start # output next percentage value when reaching (at least) this
self.step = step
self.msg = msg
self.handler = None self.handler = None
self.logger = logging.getLogger(self.LOGGER) self.logger = logging.getLogger(self.LOGGER)
@ -1248,6 +1235,41 @@ class ProgressIndicatorPercent:
self.logger.removeHandler(self.handler) self.logger.removeHandler(self.handler)
self.handler.close() self.handler.close()
def justify_to_terminal_size(message):
terminal_space = get_terminal_size(fallback=(-1, -1))[0]
# justify only if we are outputting to a terminal
if terminal_space != -1:
return message.ljust(terminal_space)
return message
class ProgressIndicatorMessage(ProgressIndicatorBase):
def output(self, msg):
self.logger.info(justify_to_terminal_size(msg))
def finish(self):
self.output('')
class ProgressIndicatorPercent(ProgressIndicatorBase):
def __init__(self, total=0, step=5, start=0, msg="%3.0f%%"):
"""
Percentage-based progress indicator
:param total: total amount of items
:param step: step size in percent
:param start: at which percent value to start
:param msg: output message, must contain one %f placeholder for the percentage
"""
self.counter = 0 # 0 .. (total-1)
self.total = total
self.trigger_at = start # output next percentage value when reaching (at least) this
self.step = step
self.msg = msg
super().__init__()
def progress(self, current=None, increase=1): def progress(self, current=None, increase=1):
if current is not None: if current is not None:
self.counter = current self.counter = current
@ -1280,10 +1302,7 @@ class ProgressIndicatorPercent:
def output(self, message, justify=True): def output(self, message, justify=True):
if justify: if justify:
terminal_space = get_terminal_size(fallback=(-1, -1))[0] message = justify_to_terminal_size(message)
# no need to ljust if we're not outputing to a terminal
if terminal_space != -1:
message = message.ljust(terminal_space)
self.logger.info(message) self.logger.info(message)
def finish(self): def finish(self):