Adding upstream version 0.16.6.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
5416a64f41
commit
50453fb690
6 changed files with 98 additions and 47 deletions
12
README.md
12
README.md
|
@ -333,8 +333,18 @@ For example, the default setting corresponds to
|
||||||
branch,commit_msg,commit_time
|
branch,commit_msg,commit_time
|
||||||
```
|
```
|
||||||
|
|
||||||
Here `branch` includes both branch name and status. To get the branch name alone, use `branch_name`.
|
Here `branch` includes both branch name and status.
|
||||||
|
The status symbols are similar to the ones used in [spaceship-prompt](https://spaceship-prompt.sh/sections/git/#Git-status-git_status).
|
||||||
|
|
||||||
|
To customize these symbols, add a file in `$XDG_CONFIG_HOME/gita/symbols.csv`.
|
||||||
|
The default settings corresponds to
|
||||||
|
|
||||||
|
```csv
|
||||||
|
dirty,staged,untracked,local_ahead,remote_ahead,diverged,in_sync,no_remote
|
||||||
|
*,+,?,↑,↓,⇕,,∅
|
||||||
|
```
|
||||||
|
Only the symbols to be overridden need to be defined.
|
||||||
|
You can search unicode symbols [here](https://www.compart.com/en/unicode/).
|
||||||
|
|
||||||
### customize git command flags
|
### customize git command flags
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,11 @@ def f_clone(args: argparse.Namespace):
|
||||||
|
|
||||||
if not args.from_file:
|
if not args.from_file:
|
||||||
subprocess.run(["git", "clone", args.clonee], cwd=path)
|
subprocess.run(["git", "clone", args.clonee], cwd=path)
|
||||||
|
# add the cloned repo to gita; group is also supported
|
||||||
|
cloned_path = os.path.join(path, args.clonee.split("/")[-1].split(".")[0])
|
||||||
|
args.paths = [cloned_path]
|
||||||
|
args.recursive = args.auto_group = args.bare = args.skip_submodule = False
|
||||||
|
f_add(args)
|
||||||
return
|
return
|
||||||
|
|
||||||
if args.preserve_path:
|
if args.preserve_path:
|
||||||
|
@ -496,12 +501,6 @@ def main(argv=None):
|
||||||
"--directory",
|
"--directory",
|
||||||
help="Change to DIRECTORY before doing anything.",
|
help="Change to DIRECTORY before doing anything.",
|
||||||
)
|
)
|
||||||
p_clone.add_argument(
|
|
||||||
"-f",
|
|
||||||
"--from-file",
|
|
||||||
action="store_true",
|
|
||||||
help="If set, clone repos in a config file rendered from `gita freeze`",
|
|
||||||
)
|
|
||||||
p_clone.add_argument(
|
p_clone.add_argument(
|
||||||
"-p",
|
"-p",
|
||||||
"--preserve-path",
|
"--preserve-path",
|
||||||
|
@ -515,6 +514,19 @@ def main(argv=None):
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="If set, show command without execution",
|
help="If set, show command without execution",
|
||||||
)
|
)
|
||||||
|
xgroup = p_clone.add_mutually_exclusive_group()
|
||||||
|
xgroup.add_argument(
|
||||||
|
"-g",
|
||||||
|
"--group",
|
||||||
|
choices=utils.get_groups(),
|
||||||
|
help="If set, add repo to the specified group after cloning, otherwise add to gita without group.",
|
||||||
|
)
|
||||||
|
xgroup.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--from-file",
|
||||||
|
action="store_true",
|
||||||
|
help="If set, clone repos in a config file rendered from `gita freeze`",
|
||||||
|
)
|
||||||
p_clone.set_defaults(func=f_clone)
|
p_clone.set_defaults(func=f_clone)
|
||||||
|
|
||||||
p_rename = subparsers.add_parser(
|
p_rename = subparsers.add_parser(
|
||||||
|
|
82
gita/info.py
82
gita/info.py
|
@ -1,8 +1,8 @@
|
||||||
import os
|
|
||||||
import csv
|
import csv
|
||||||
import subprocess
|
import subprocess
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from collections import namedtuple
|
||||||
from functools import lru_cache, partial
|
from functools import lru_cache, partial
|
||||||
from typing import Tuple, List, Callable, Dict
|
from typing import Tuple, List, Callable, Dict
|
||||||
|
|
||||||
|
@ -41,11 +41,11 @@ class Color(Enum):
|
||||||
|
|
||||||
|
|
||||||
default_colors = {
|
default_colors = {
|
||||||
"no-remote": Color.white.name,
|
"no_remote": Color.white.name,
|
||||||
"in-sync": Color.green.name,
|
"in_sync": Color.green.name,
|
||||||
"diverged": Color.red.name,
|
"diverged": Color.red.name,
|
||||||
"local-ahead": Color.purple.name,
|
"local_ahead": Color.purple.name,
|
||||||
"remote-ahead": Color.yellow.name,
|
"remote_ahead": Color.yellow.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -195,49 +195,75 @@ def get_commit_time(prop: Dict[str, str]) -> str:
|
||||||
return f"({result.stdout.strip()})"
|
return f"({result.stdout.strip()})"
|
||||||
|
|
||||||
|
|
||||||
|
default_symbols = {
|
||||||
|
"dirty": "*",
|
||||||
|
"staged": "+",
|
||||||
|
"untracked": "?",
|
||||||
|
"local_ahead": "↑",
|
||||||
|
"remote_ahead": "↓",
|
||||||
|
"diverged": "⇕",
|
||||||
|
"in_sync": "",
|
||||||
|
"no_remote": "∅",
|
||||||
|
"": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache()
|
||||||
|
def get_symbols() -> Dict[str, str]:
|
||||||
|
"""
|
||||||
|
return status symbols with customization
|
||||||
|
"""
|
||||||
|
custom = {}
|
||||||
|
csv_config = Path(common.get_config_fname("symbols.csv"))
|
||||||
|
if csv_config.is_file():
|
||||||
|
with open(csv_config, "r") as f:
|
||||||
|
reader = csv.DictReader(f)
|
||||||
|
custom = next(reader)
|
||||||
|
default_symbols.update(custom)
|
||||||
|
return default_symbols
|
||||||
|
|
||||||
|
|
||||||
def get_repo_status(prop: Dict[str, str], no_colors=False) -> str:
|
def get_repo_status(prop: Dict[str, str], no_colors=False) -> str:
|
||||||
head = get_head(prop["path"])
|
branch = get_head(prop["path"])
|
||||||
dirty, staged, untracked, color = _get_repo_status(prop, no_colors)
|
dirty, staged, untracked, situ = _get_repo_status(prop)
|
||||||
info = f"{head:<10} [{dirty+staged+untracked}]"
|
symbols = get_symbols()
|
||||||
if color:
|
info = f"{branch:<10} [{symbols[dirty]+symbols[staged]+symbols[untracked]+symbols[situ]}]"
|
||||||
return f"{color}{info:<17}{Color.end}"
|
|
||||||
return f"{info:<17}"
|
if no_colors:
|
||||||
|
return f"{info:<18}"
|
||||||
|
colors = {situ: Color[name].value for situ, name in get_color_encoding().items()}
|
||||||
|
color = colors[situ]
|
||||||
|
return f"{color}{info:<18}{Color.end}"
|
||||||
|
|
||||||
|
|
||||||
def get_repo_branch(prop: Dict[str, str]) -> str:
|
def get_repo_branch(prop: Dict[str, str]) -> str:
|
||||||
return get_head(prop["path"])
|
return get_head(prop["path"])
|
||||||
|
|
||||||
|
|
||||||
def _get_repo_status(prop: Dict[str, str], no_colors: bool) -> Tuple[str]:
|
def _get_repo_status(prop: Dict[str, str]) -> Tuple[str, str, str, str]:
|
||||||
"""
|
"""
|
||||||
Return the status of one repo
|
Return the status of one repo
|
||||||
"""
|
"""
|
||||||
path = prop["path"]
|
path = prop["path"]
|
||||||
flags = prop["flags"]
|
flags = prop["flags"]
|
||||||
dirty = "*" if run_quiet_diff(flags, [], path) else ""
|
dirty = "dirty" if run_quiet_diff(flags, [], path) else ""
|
||||||
staged = "+" if run_quiet_diff(flags, ["--cached"], path) else ""
|
staged = "staged" if run_quiet_diff(flags, ["--cached"], path) else ""
|
||||||
untracked = "?" if has_untracked(flags, path) else ""
|
untracked = "untracked" if has_untracked(flags, path) else ""
|
||||||
|
|
||||||
if no_colors:
|
|
||||||
return dirty, staged, untracked, ""
|
|
||||||
|
|
||||||
colors = {situ: Color[name].value for situ, name in get_color_encoding().items()}
|
|
||||||
diff_returncode = run_quiet_diff(flags, ["@{u}", "@{0}"], path)
|
diff_returncode = run_quiet_diff(flags, ["@{u}", "@{0}"], path)
|
||||||
has_no_remote = diff_returncode == 128
|
if diff_returncode == 128:
|
||||||
has_no_diff = diff_returncode == 0
|
situ = "no_remote"
|
||||||
if has_no_remote:
|
elif diff_returncode == 0:
|
||||||
color = colors["no-remote"]
|
situ = "in_sync"
|
||||||
elif has_no_diff:
|
|
||||||
color = colors["in-sync"]
|
|
||||||
else:
|
else:
|
||||||
common_commit = get_common_commit(path)
|
common_commit = get_common_commit(path)
|
||||||
outdated = run_quiet_diff(flags, ["@{u}", common_commit], path)
|
outdated = run_quiet_diff(flags, ["@{u}", common_commit], path)
|
||||||
if outdated:
|
if outdated:
|
||||||
diverged = run_quiet_diff(flags, ["@{0}", common_commit], path)
|
diverged = run_quiet_diff(flags, ["@{0}", common_commit], path)
|
||||||
color = colors["diverged"] if diverged else colors["remote-ahead"]
|
situ = "diverged" if diverged else "remote_ahead"
|
||||||
else: # local is ahead of remote
|
else: # local is ahead of remote
|
||||||
color = colors["local-ahead"]
|
situ = "local_ahead"
|
||||||
return dirty, staged, untracked, color
|
return dirty, staged, untracked, situ
|
||||||
|
|
||||||
|
|
||||||
ALL_INFO_ITEMS = {
|
ALL_INFO_ITEMS = {
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -7,7 +7,7 @@ with open("README.md", encoding="utf-8") as f:
|
||||||
setup(
|
setup(
|
||||||
name="gita",
|
name="gita",
|
||||||
packages=["gita"],
|
packages=["gita"],
|
||||||
version="0.16.5",
|
version="0.16.6",
|
||||||
license="MIT",
|
license="MIT",
|
||||||
description="Manage multiple git repos with sanity",
|
description="Manage multiple git repos with sanity",
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
|
|
|
@ -130,18 +130,21 @@ class TestLsLl:
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
PATH_FNAME,
|
PATH_FNAME,
|
||||||
"repo1 cmaster [dsu] \x1b[0m msg \nrepo2 cmaster [dsu] \x1b[0m msg \nxxx cmaster [dsu] \x1b[0m msg \n",
|
"repo1 \x1b[31mmaster [*+?⇕] \x1b[0m msg \nrepo2 \x1b[31mmaster [*+?⇕] \x1b[0m msg \nxxx \x1b[31mmaster [*+?⇕] \x1b[0m msg \n",
|
||||||
),
|
),
|
||||||
(PATH_FNAME_EMPTY, ""),
|
(PATH_FNAME_EMPTY, ""),
|
||||||
(
|
(
|
||||||
PATH_FNAME_CLASH,
|
PATH_FNAME_CLASH,
|
||||||
"repo1 cmaster [dsu] \x1b[0m msg \nrepo2 cmaster [dsu] \x1b[0m msg \n",
|
"repo1 \x1b[31mmaster [*+?⇕] \x1b[0m msg \nrepo2 \x1b[31mmaster [*+?⇕] \x1b[0m msg \n",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@patch("gita.utils.is_git", return_value=True)
|
@patch("gita.utils.is_git", return_value=True)
|
||||||
@patch("gita.info.get_head", return_value="master")
|
@patch("gita.info.get_head", return_value="master")
|
||||||
@patch("gita.info._get_repo_status", return_value=("d", "s", "u", "c"))
|
@patch(
|
||||||
|
"gita.info._get_repo_status",
|
||||||
|
return_value=("dirty", "staged", "untracked", "diverged"),
|
||||||
|
)
|
||||||
@patch("gita.info.get_commit_msg", return_value="msg")
|
@patch("gita.info.get_commit_msg", return_value="msg")
|
||||||
@patch("gita.info.get_commit_time", return_value="")
|
@patch("gita.info.get_commit_time", return_value="")
|
||||||
@patch("gita.common.get_config_fname")
|
@patch("gita.common.get_config_fname")
|
||||||
|
@ -566,7 +569,7 @@ def test_set_color(mock_get_fname, tmpdir):
|
||||||
args = argparse.Namespace()
|
args = argparse.Namespace()
|
||||||
args.color_cmd = "set"
|
args.color_cmd = "set"
|
||||||
args.color = "b_white"
|
args.color = "b_white"
|
||||||
args.situation = "no-remote"
|
args.situation = "no_remote"
|
||||||
with tmpdir.as_cwd():
|
with tmpdir.as_cwd():
|
||||||
csv_config = Path.cwd() / "colors.csv"
|
csv_config = Path.cwd() / "colors.csv"
|
||||||
mock_get_fname.return_value = csv_config
|
mock_get_fname.return_value = csv_config
|
||||||
|
@ -576,11 +579,11 @@ def test_set_color(mock_get_fname, tmpdir):
|
||||||
items = info.get_color_encoding()
|
items = info.get_color_encoding()
|
||||||
info.get_color_encoding.cache_clear() # avoid side effect
|
info.get_color_encoding.cache_clear() # avoid side effect
|
||||||
assert items == {
|
assert items == {
|
||||||
"no-remote": "b_white",
|
"no_remote": "b_white",
|
||||||
"in-sync": "green",
|
"in_sync": "green",
|
||||||
"diverged": "red",
|
"diverged": "red",
|
||||||
"local-ahead": "purple",
|
"local_ahead": "purple",
|
||||||
"remote-ahead": "yellow",
|
"remote_ahead": "yellow",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -115,17 +115,17 @@ def test_auto_group(repos, paths, expected):
|
||||||
(
|
(
|
||||||
[{"abc": {"path": "/root/repo/", "type": "", "flags": []}}, False],
|
[{"abc": {"path": "/root/repo/", "type": "", "flags": []}}, False],
|
||||||
True,
|
True,
|
||||||
"abc \x1b[31mrepo [*+?] \x1b[0m msg xx",
|
"abc \x1b[31mrepo [*+?⇕] \x1b[0m msg xx",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
[{"abc": {"path": "/root/repo/", "type": "", "flags": []}}, True],
|
[{"abc": {"path": "/root/repo/", "type": "", "flags": []}}, True],
|
||||||
True,
|
True,
|
||||||
"abc repo [*+?] msg xx",
|
"abc repo [*+?⇕] msg xx",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
[{"repo": {"path": "/root/repo2/", "type": "", "flags": []}}, False],
|
[{"repo": {"path": "/root/repo2/", "type": "", "flags": []}}, False],
|
||||||
False,
|
False,
|
||||||
"repo \x1b[32mrepo [?] \x1b[0m msg xx",
|
"repo \x1b[32mrepo [?] \x1b[0m msg xx",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue