summaryrefslogtreecommitdiffstats
path: root/gita/info.py
diff options
context:
space:
mode:
Diffstat (limited to 'gita/info.py')
-rw-r--r--gita/info.py108
1 files changed, 79 insertions, 29 deletions
diff --git a/gita/info.py b/gita/info.py
index 18d20fd..473127a 100644
--- a/gita/info.py
+++ b/gita/info.py
@@ -2,14 +2,19 @@ import os
import sys
import yaml
import subprocess
+from enum import Enum
+from pathlib import Path
+from functools import lru_cache
from typing import Tuple, List, Callable, Dict
+
from . import common
-class Color:
+class Color(str, Enum):
"""
Terminal color
"""
+ black = '\x1b[30m'
red = '\x1b[31m' # local diverges from remote
green = '\x1b[32m' # local == remote
yellow = '\x1b[33m' # local is behind
@@ -18,6 +23,43 @@ class Color:
cyan = '\x1b[36m'
white = '\x1b[37m' # no remote branch
end = '\x1b[0m'
+ b_black = '\x1b[30;1m'
+ b_red = '\x1b[31;1m'
+ b_green = '\x1b[32;1m'
+ b_yellow = '\x1b[33;1m'
+ b_blue = '\x1b[34;1m'
+ b_purple = '\x1b[35;1m'
+ b_cyan = '\x1b[36;1m'
+ b_white = '\x1b[37;1m'
+
+
+def show_colors(): # pragma: no cover
+ """
+
+ """
+ for i, c in enumerate(Color, start=1):
+ if c != Color.end:
+ print(f'{c.value}{c.name:<8} ', end='')
+ if i % 9 == 0:
+ print()
+ print(f'{Color.end}')
+ for situation, c in get_color_encoding().items():
+ print(f'{situation:<12}: {c.value}{c.name:<8}{Color.end} ')
+
+
+@lru_cache()
+def get_color_encoding():
+ """
+
+ """
+ # TODO: add config file
+ return {
+ 'no-remote': Color.white,
+ 'in-sync': Color.green,
+ 'diverged': Color.red,
+ 'local-ahead': Color.purple,
+ 'remote-ahead': Color.yellow,
+ }
def get_info_funcs() -> List[Callable[[str], str]]:
@@ -26,35 +68,30 @@ def get_info_funcs() -> List[Callable[[str], str]]:
take the repo path as input and return the corresponding information as str.
See `get_path`, `get_repo_status`, `get_common_commit` for examples.
"""
- info_items, to_display = get_info_items()
- return [info_items[k] for k in to_display]
+ to_display = get_info_items()
+ # This re-definition is to make unit test mocking to work
+ all_info_items = {
+ 'branch': get_repo_status,
+ 'commit_msg': get_commit_msg,
+ 'path': get_path,
+ }
+ return [all_info_items[k] for k in to_display]
-def get_info_items() -> Tuple[Dict[str, Callable[[str], str]], List[str]]:
+def get_info_items() -> List[str]:
"""
- Return the available information items for display in the `gita ll`
- sub-command, and the ones to be displayed.
- It loads custom information functions and configuration if they exist.
+ Return the information items to be displayed in the `gita ll` command.
"""
# default settings
- info_items = {'branch': get_repo_status,
- 'commit_msg': get_commit_msg,
- 'path': get_path, }
display_items = ['branch', 'commit_msg']
# custom settings
- root = common.get_config_dir()
- src_fname = os.path.join(root, 'extra_repo_info.py')
- yml_fname = os.path.join(root, 'info.yml')
- if os.path.isfile(src_fname):
- sys.path.append(root)
- from extra_repo_info import extra_info_items
- info_items.update(extra_info_items)
- if os.path.isfile(yml_fname):
- with open(yml_fname, 'r') as stream:
+ yml_config = Path(common.get_config_fname('info.yml'))
+ if yml_config.is_file():
+ with open(yml_config, 'r') as stream:
display_items = yaml.load(stream, Loader=yaml.FullLoader)
- display_items = [x for x in display_items if x in info_items]
- return info_items, display_items
+ display_items = [x for x in display_items if x in ALL_INFO_ITEMS]
+ return display_items
def get_path(path):
@@ -113,13 +150,15 @@ def get_commit_msg(path: str) -> str:
return result.stdout.strip()
-def get_repo_status(path: str) -> str:
+def get_repo_status(path: str, no_colors=False) -> str:
head = get_head(path)
- dirty, staged, untracked, color = _get_repo_status(path)
- return f'{color}{head+" "+dirty+staged+untracked:<10}{Color.end}'
+ dirty, staged, untracked, color = _get_repo_status(path, no_colors)
+ if color:
+ return f'{color}{head+" "+dirty+staged+untracked:<10}{Color.end}'
+ return f'{head+" "+dirty+staged+untracked:<10}'
-def _get_repo_status(path: str) -> Tuple[str]:
+def _get_repo_status(path: str, no_colors: bool) -> Tuple[str]:
"""
Return the status of one repo
"""
@@ -128,19 +167,30 @@ def _get_repo_status(path: str) -> Tuple[str]:
staged = '+' if run_quiet_diff(['--cached']) else ''
untracked = '_' if has_untracked() else ''
+ if no_colors:
+ return dirty, staged, untracked, ''
+
+ colors = get_color_encoding()
diff_returncode = run_quiet_diff(['@{u}', '@{0}'])
has_no_remote = diff_returncode == 128
has_no_diff = diff_returncode == 0
if has_no_remote:
- color = Color.white
+ color = colors['no-remote']
elif has_no_diff:
- color = Color.green
+ color = colors['in-sync']
else:
common_commit = get_common_commit()
outdated = run_quiet_diff(['@{u}', common_commit])
if outdated:
diverged = run_quiet_diff(['@{0}', common_commit])
- color = Color.red if diverged else Color.yellow
+ color = colors['diverged'] if diverged else colors['remote-ahead']
else: # local is ahead of remote
- color = Color.purple
+ color = colors['local-ahead']
return dirty, staged, untracked, color
+
+
+ALL_INFO_ITEMS = {
+ 'branch': get_repo_status,
+ 'commit_msg': get_commit_msg,
+ 'path': get_path,
+ }