Skip to content

Commit

Permalink
add groups in gita freeze output (#272)
Browse files Browse the repository at this point in the history
* enhance freeze and clone for groups

* update github actions

* fix unit tests
  • Loading branch information
nosarthur committed Jun 4, 2024
1 parent e4e7879 commit daa02c5
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 29 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/nos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
matrix:
os: [ubuntu-20.04, macos-latest, windows-latest]
python-version: [3.6, 3.7, 3.8, 3.9, "3.10", "3.11"]
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.7, 3.8, 3.9, "3.10", "3.11"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
Expand Down
37 changes: 27 additions & 10 deletions gita/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
from itertools import chain
from pathlib import Path
import glob
from typing import Dict, Optional

from . import utils, info, common, get_version
from . import utils, info, common, io, get_version


def _group_name(name: str, exclude_old_names=True) -> str:
Expand Down Expand Up @@ -152,7 +153,7 @@ def f_clone(args: argparse.Namespace):

if args.dry_run:
if args.from_file:
for url, repo_name, abs_path in utils.parse_clone_config(args.clonee):
for url, repo_name, abs_path in io.parse_clone_config(args.clonee):

Check warning on line 156 in gita/__main__.py

View check run for this annotation

Codecov / codecov/patch

gita/__main__.py#L156

Added line #L156 was not covered by tests
print(f"git clone {url} {abs_path}")
else:
print(f"git clone {args.clonee}")
Expand All @@ -172,28 +173,35 @@ def f_clone(args: argparse.Namespace):
f_add(args)
return

# TODO: add repos to group too
repos, groups = io.parse_clone_config(args.clonee)
if args.preserve_path:
utils.exec_async_tasks(
utils.run_async(repo_name, path, ["git", "clone", url, abs_path])
for url, repo_name, abs_path in utils.parse_clone_config(args.clonee)
utils.run_async(repo_name, path, ["git", "clone", r["url"], r["path"]])
for repo_name, r in repos.items()
)
else:
utils.exec_async_tasks(
utils.run_async(repo_name, path, ["git", "clone", url])
for url, repo_name, _ in utils.parse_clone_config(args.clonee)
utils.run_async(repo_name, path, ["git", "clone", r["url"]])
for repo_name, r in repos.items()
)


def f_freeze(args):
repos = utils.get_repos()
"""
print repo and group information for future cloning
"""
ctx = utils.get_context()
if args.group is None and ctx:
args.group = ctx.stem
repos = utils.get_repos()
group_name = args.group
group_repos = None
if args.group: # only display repos in this group
group_repos = utils.get_groups()[args.group]["repos"]
if group_name: # only display repos in this group
group_repos = utils.get_groups()[group_name]["repos"]

Check warning on line 201 in gita/__main__.py

View check run for this annotation

Codecov / codecov/patch

gita/__main__.py#L201

Added line #L201 was not covered by tests
repos = {k: repos[k] for k in group_repos if k in repos}
seen = {""}
# print(repos)
for name, prop in repos.items():
path = prop["path"]
url = ""
Expand All @@ -211,7 +219,16 @@ def f_freeze(args):
url = parts[1]
if url not in seen:
seen.add(url)
print(f"{url},{name},{path}")
# TODO: add another field to distinguish regular repo or worktree or submodule
print(f"{url},{name},{path},")

Check warning on line 223 in gita/__main__.py

View check run for this annotation

Codecov / codecov/patch

gita/__main__.py#L223

Added line #L223 was not covered by tests
# group information: these lines don't have URL
if group_name:
group_path = utils.get_groups()[group_name]["path"]
print(f",{group_name},{group_path},{'|'.join(group_repos)}")

Check warning on line 227 in gita/__main__.py

View check run for this annotation

Codecov / codecov/patch

gita/__main__.py#L226-L227

Added lines #L226 - L227 were not covered by tests
else: # show all groups
for gname, g in utils.get_groups().items():
group_repos = "|".join(g["repos"])
print(f",{gname},{g['path']},{group_repos}")

Check warning on line 231 in gita/__main__.py

View check run for this annotation

Codecov / codecov/patch

gita/__main__.py#L230-L231

Added lines #L230 - L231 were not covered by tests


def f_ll(args: argparse.Namespace):
Expand Down
33 changes: 33 additions & 0 deletions gita/io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import os
import csv
from typing import Tuple


def parse_clone_config(fname: str) -> Tuple:
"""
Return the repo information (url, name, path, type) and group information
(, name, path, repos) saved in `fname`.
"""
repos = {}
groups = {}
if os.path.isfile(fname) and os.stat(fname).st_size > 0:
with open(fname) as f:
rows = csv.DictReader(

Check warning on line 15 in gita/io.py

View check run for this annotation

Codecov / codecov/patch

gita/io.py#L11-L15

Added lines #L11 - L15 were not covered by tests
f, ["url", "name", "path", "type", "flags"], restval=""
) # it's actually a reader
for r in rows:
if r["url"]:
repos[r["name"]] = {

Check warning on line 20 in gita/io.py

View check run for this annotation

Codecov / codecov/patch

gita/io.py#L18-L20

Added lines #L18 - L20 were not covered by tests
"path": r["path"],
"type": r["type"],
"flags": r["flags"].split(),
"url": r["url"],
}
else:
groups[r["name"]] = {

Check warning on line 27 in gita/io.py

View check run for this annotation

Codecov / codecov/patch

gita/io.py#L27

Added line #L27 was not covered by tests
"path": r["path"],
"repos": [
repo for repo in r["type"].split("|") if repo in repos
],
}
return repos, groups

Check warning on line 33 in gita/io.py

View check run for this annotation

Codecov / codecov/patch

gita/io.py#L33

Added line #L33 was not covered by tests
11 changes: 1 addition & 10 deletions gita/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import subprocess
from functools import lru_cache
from pathlib import Path
from typing import List, Dict, Coroutine, Union, Iterator, Tuple
from typing import List, Dict, Coroutine, Union, Tuple
from collections import Counter, defaultdict
from concurrent.futures import ThreadPoolExecutor
import multiprocessing
Expand Down Expand Up @@ -367,15 +367,6 @@ def auto_group(repos: Dict[str, Dict[str, str]], paths: List[str]) -> Dict[str,
return new_groups


def parse_clone_config(fname: str) -> Iterator[List[str]]:
"""
Return the url, name, and path of all repos in `fname`.
"""
with open(fname) as f:
for line in f:
yield line.strip().split(",")


async def run_async(repo_name: str, path: str, cmds: List[str]) -> Union[None, str]:
"""
Run `cmds` asynchronously in `path` directory. Return the `path` if
Expand Down
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"Topic :: Software Development :: Version Control :: Git",
"Topic :: Terminals",
"Topic :: Utilities",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
Expand Down
14 changes: 10 additions & 4 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,11 @@ def test_clone_with_url(mock_run):


@patch(
"gita.utils.parse_clone_config",
return_value=[["[email protected]:user/repo.git", "repo", "/a/repo"]],
"gita.io.parse_clone_config",
return_value=(
{"repo": {"url": "[email protected]:user/repo.git", "path": "/a/repo"}},
{},
),
)
@patch("gita.utils.run_async", new=async_mock())
@patch("subprocess.run")
Expand All @@ -217,8 +220,11 @@ def test_clone_with_config_file(*_):


@patch(
"gita.utils.parse_clone_config",
return_value=[["[email protected]:user/repo.git", "repo", "/a/repo"]],
"gita.io.parse_clone_config",
return_value=(
{"repo": {"url": "[email protected]:user/repo.git", "path": "/a/repo"}},
{},
),
)
@patch("gita.utils.run_async", new=async_mock())
@patch("subprocess.run")
Expand Down

0 comments on commit daa02c5

Please sign in to comment.