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 authored Apr 4, 2024
1 parent 1b6319b commit 8c17759
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 30 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 @@ -25,8 +25,9 @@
from itertools import chain
from pathlib import Path
import glob
from typing import Dict, Optional

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


def _group_name(name: str, exclude_old_names=True) -> str:
Expand Down Expand Up @@ -153,7 +154,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):
print(f"git clone {url} {abs_path}")
else:
print(f"git clone {args.clonee}")
Expand All @@ -173,28 +174,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"]
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 @@ -212,7 +220,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},")
# 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)}")
else: # show all groups
for gname, g in utils.get_groups().items():
group_repos = "|".join(g["repos"])
print(f",{gname},{g['path']},{group_repos}")


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(
f, ["url", "name", "path", "type", "flags"], restval=""
) # it's actually a reader
for r in rows:
if r["url"]:
repos[r["name"]] = {
"path": r["path"],
"type": r["type"],
"flags": r["flags"].split(),
"url": r["url"],
}
else:
groups[r["name"]] = {
"path": r["path"],
"repos": [
repo for repo in r["type"].split("|") if repo in repos
],
}
return repos, groups
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
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
setup(
name="gita",
packages=["gita"],
version="0.16.6.5",
version="0.16.7",
license="MIT",
description="Manage multiple git repos with sanity",
long_description=long_description,
Expand All @@ -30,10 +30,11 @@
"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",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
],
include_package_data=True,
)
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 8c17759

Please sign in to comment.