1
0
Fork 0

Adding upstream version 0.16.6.1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-11 18:51:07 +01:00
parent 5416a64f41
commit 50453fb690
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
6 changed files with 98 additions and 47 deletions

View file

@ -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

View file

@ -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(

View file

@ -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 = {

View file

@ -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,

View file

@ -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",
} }

View file

@ -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",
), ),
], ],
) )