Repository: iterative/dvc

Issue:
updater: make update message more noticeable 
I.e. like in npm:

<img width="623" alt="screen shot 2018-08-21 at 6 26 38 pm" src="https://user-images.githubusercontent.com/5367102/44437841-ea6d3a00-a5c4-11e8-8e1a-975bc4e19e58.png">

Kudos @shcheklein 


Discussion:
Even though we are checking for updates every day now, users still don't notice that and continue working on old versions. Need to make the message more visibly noticeable as well as need to show it every time `dvc` runs, same way `pip` does(currently we only show the message once when we check for updates). 

Resolving patch:
diff --git a/dvc/logger.py b/dvc/logger.py
--- a/dvc/logger.py
+++ b/dvc/logger.py
@@ -2,11 +2,28 @@
 import logging
 import colorama
 import traceback
+import re
 
 
 colorama.init()
 
 
+def visual_width(line):
+    """ Get the the number of columns required to display a string """
+
+    return len(re.sub(colorama.ansitowin32.AnsiToWin32.ANSI_CSI_RE, '', line))
+
+
+def visual_center(line, width):
+    """ Center align string according to it's visual width """
+
+    spaces = max(width - visual_width(line), 0)
+    left_padding = int(spaces / 2)
+    right_padding = (spaces - left_padding)
+
+    return (left_padding * ' ') + line + (right_padding * ' ')
+
+
 class Logger(object):
     FMT = '%(message)s'
     DEFAULT_LEVEL = logging.INFO
@@ -155,3 +172,46 @@ def debug(cls, msg, exc=None):
     @staticmethod
     def info(msg):
         Logger._with_progress(Logger.logger().info, msg)
+
+    @classmethod
+    def box(cls, msg, border_color=''):
+        lines = msg.split('\n')
+        max_width = max(visual_width(line) for line in lines)
+
+        padding_horizontal = 5
+        padding_vertical = 1
+
+        box_size_horizontal = (max_width + (padding_horizontal * 2))
+
+        chars = {
+            'corner':     '+',
+            'horizontal': '-',
+            'vertical':   '|',
+            'empty':      ' ',
+        }
+
+        margin = "{corner}{line}{corner}\n".format(
+            corner=chars['corner'],
+            line=chars['horizontal'] * box_size_horizontal,
+        )
+
+        padding_lines = [
+            "{border}{space}{border}\n".format(
+                border=cls.colorize(chars['vertical'], border_color),
+                space=chars['empty'] * box_size_horizontal,
+            ) * padding_vertical
+        ]
+
+        content_lines = [
+            "{border}{space}{content}{space}{border}\n".format(
+                border=cls.colorize(chars['vertical'], border_color),
+                space=chars['empty'] * padding_horizontal,
+                content=visual_center(line, max_width),
+            ) for line in lines
+        ]
+
+        return "{margin}{padding}{content}{padding}{margin}".format(
+            margin=cls.colorize(margin, border_color),
+            padding=''.join(padding_lines),
+            content=''.join(content_lines),
+        )
diff --git a/dvc/updater.py b/dvc/updater.py
--- a/dvc/updater.py
+++ b/dvc/updater.py
@@ -1,6 +1,7 @@
 import os
 import time
 import requests
+import colorama
 
 from dvc import VERSION_BASE
 from dvc.logger import Logger
@@ -56,6 +57,19 @@ def check(self):
            l_patch <= c_patch:
             return
 
-        msg = 'You are using dvc version {}, however version {} is ' \
-              'available. Consider upgrading.'
-        Logger.warn(msg.format(current, latest))
+        msg = (
+            'Update available {red}{current}{reset} -> {green}{latest}{reset}'
+            '\n'
+            'Run {yellow}pip{reset} install dvc {blue}--upgrade{reset}'
+            .format(
+                red=colorama.Fore.RED,
+                reset=colorama.Fore.RESET,
+                green=colorama.Fore.GREEN,
+                yellow=colorama.Fore.YELLOW,
+                blue=colorama.Fore.BLUE,
+                current=current,
+                latest=latest,
+            )
+        )
+
+        Logger.box(msg, border_color='yellow')


Test patch: