diff --git a/infinitepush/__init__.py b/infinitepush/__init__.py --- a/infinitepush/__init__.py +++ b/infinitepush/__init__.py @@ -139,6 +139,7 @@ confignonforwardmove = 'non-forward-move' cmdtable = infinitepushcommands.cmdtable +templatekeyword = backupcommands.templatekeyword _scratchbranchmatcher = lambda x: False _maybehash = re.compile(r'^[a-f0-9]+$').search @@ -316,6 +317,19 @@ partorder.insert( index, partorder.pop(partorder.index(scratchbranchparttype))) + def wrapsmartlog(loaded): + if not loaded: + return + smartlogmod = extensions.find('smartlog') + wrapcommand(smartlogmod.cmdtable, 'smartlog', _smartlog) + extensions.afterloaded('smartlog', wrapsmartlog) + +def _smartlog(orig, ui, repo, **opts): + res = orig(ui, repo, **opts) + if not ui.configbool('infinitepushbackup', 'suppress_smartlog_summary'): + backupcommands.smartlog_summary(ui, repo) + return res + def _showbookmarks(ui, bookmarks, **opts): # Copy-paste from commands.py fm = ui.formatter('bookmarks', opts) diff --git a/infinitepush/backupcommands.py b/infinitepush/backupcommands.py --- a/infinitepush/backupcommands.py +++ b/infinitepush/backupcommands.py @@ -28,9 +28,22 @@ # Hostname value to use. If not specified then socket.gethostname() will # be used hostname = '' + + # Enable reporting of infinitepush backup status in template keywords and + # as a summary at the end of smartlog. + enablestatus = False + + # Suppress the infinitepush backup summary from being appended to smartlog + # output. + suppress_smartlog_summary = False + + # Education message to be displayed to users at the end of smartlog when + # some commits have not been backed up for more than 10 minutes. + smartlog_education = '' """ from __future__ import absolute_import +import datetime import errno import json import os @@ -69,6 +82,7 @@ cmdtable = {} command = registrar.command(cmdtable) +templatekeyword = registrar.templatekeyword() backupbookmarktuple = namedtuple('backupbookmarktuple', ['hostname', 'reporoot', 'localbookmark']) @@ -306,6 +320,45 @@ ui.write(_('backed up' if r in backeduprevs else 'not backed up')) ui.write(_('\n')) +@templatekeyword('backupstatus') +def backupstatus(repo, ctx, templ, **args): + """String. Return the backup status of a revision.""" + if not repo.ui.configbool('infinitepushbackup', 'enablestatus'): + return '' + if ctx.phase() == phases.public: + return 'Public' + bkpstate = _readlocalbackupstate(repo.ui, repo) + unfi = repo.unfiltered() + backeduprevs = unfi.revs('draft() and ::%ls', bkpstate.heads) + if ctx.rev() in backeduprevs: + return 'Backed up' + backup_time = datetime.datetime.now() - datetime.timedelta(minutes=10) + backup_time_hg = util.parsedate(backup_time.strftime('%Y-%m-%d %H:%M:%S')) + if ctx.date()[0] > backup_time_hg[0]: + return 'Backup pending' + return 'Not backed up' + +def smartlog_summary(ui, repo): + if not ui.configbool('infinitepushbackup', 'enablestatus'): + return + bkpstate = _readlocalbackupstate(ui, repo) + unfi = repo.unfiltered() + unbackeduprevs = unfi.revs('draft() and not ::%ls', bkpstate.heads) + backup_time = datetime.datetime.now() - datetime.timedelta(minutes=10) + backup_time_hg = util.parsedate(backup_time.strftime('%Y-%m-%d %H:%M:%S')) + count = 0 + for rev in unbackeduprevs: + if unfi[rev].date()[0] <= backup_time_hg[0]: + count += 1 + if count > 0: + if count > 1: + ui.warn(_('note: %d commits are not backed up.\n') % count) + else: + ui.warn(_('note: a commit is not backed up.\n')) + education = ui.config('infinitepushbackup', 'smartlog_education') + if education: + ui.warn(education + '\n') + def _dobackup(ui, repo, dest, **opts): ui.status(_('starting backup %s\n') % time.strftime('%H:%M:%S %d %b %Y %Z')) start = time.time() diff --git a/tests/test-infinitepush-backup-status.t b/tests/test-infinitepush-backup-status.t new file mode 100644 --- /dev/null +++ b/tests/test-infinitepush-backup-status.t @@ -0,0 +1,98 @@ + + $ setup() { + > cat << EOF >> .hg/hgrc + > [extensions] + > fbamend=$TESTDIR/../hgext3rd/fbamend + > smartlog=$TESTDIR/../hgext3rd/smartlog.py + > [infinitepushbackup] + > enablestatus = True + > smartlog_education = Education Message + > [experimental] + > evolution=createmarkers + > EOF + > } + $ . "$TESTDIR/library.sh" + $ . "$TESTDIR/library-infinitepush.sh" + $ setupcommon + +Setup server + $ hg init repo + $ cd repo + $ setupserver + $ cd .. + +Setup client + $ hg clone ssh://user@dummy/repo client -q + $ cd client + $ setup + $ now=`date +%s` + $ touch file1 + $ hg add file1 + $ commit_time=`expr $now - 15 \* 60` + $ hg commit -d "$commit_time 0" -m "Public commit" + $ hg push + pushing to ssh://user@dummy/repo + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + $ echo a > file1 + $ commit_time=`expr $now - 13 \* 60` + $ hg commit -d "$commit_time 0" -m "Backed up commit" + $ hg pushbackup + starting backup .* (re) + searching for changes + remote: pushing 1 commit: + remote: * Backed up commit (glob) + finished in \d+\.(\d+)? seconds (re) + $ echo b > file1 + $ commit_time=`expr $now - 11 \* 60` + $ hg commit -d "$commit_time 0" -m "Not backed up commit" + $ echo c > file1 + $ commit_time=`expr $now - 9 \* 60` + $ hg commit -d "$commit_time 0" -m "Backup pending commit" + +Check backup status of commits + $ hg log -T '{rev} ({backupstatus}) {desc}\n' + 3 (Backup pending) Backup pending commit + 2 (Not backed up) Not backed up commit + 1 (Backed up) Backed up commit + 0 (Public) Public commit + +Check smartlog output + $ hg smartlog + @ changeset: 3:* (glob) + | tag: tip + | user: test + | date: * (glob) + | summary: Backup pending commit + | + o changeset: 2:* (glob) + | user: test + | date: * (glob) + | summary: Not backed up commit + | + o changeset: 1:* (glob) + | user: test + | date: * (glob) + | summary: Backed up commit + | + o changeset: 0:* (glob) + user: test + date: * (glob) + summary: Public commit + + note: a commit is not backed up. + Education Message + +Check smartlog summary can be suppressed + $ hg smartlog -T '{rev}: {backupstatus}\n' --config infinitepushbackup.suppress_smartlog_summary=yes + @ 3: Backup pending + | + o 2: Not backed up + | + o 1: Backed up + | + o 0: Public +