diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-01-09 07:44:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-01-09 07:44:03 +0000 |
commit | bdce5ac931e8dd6f2a19c3e34a951e7189343bc7 (patch) | |
tree | 172912a41a67579a096fe92fb35972618854f33d /gita/utils.py | |
parent | Adding upstream version 0.15.9. (diff) | |
download | gita-5e404aae9c5aa7dd56765c769f66cb43b59a86cb.tar.xz gita-5e404aae9c5aa7dd56765c769f66cb43b59a86cb.zip |
Adding upstream version 0.16.1.upstream/0.16.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gita/utils.py')
-rw-r--r-- | gita/utils.py | 100 |
1 files changed, 36 insertions, 64 deletions
diff --git a/gita/utils.py b/gita/utils.py index 2431fde..8e7d9c4 100644 --- a/gita/utils.py +++ b/gita/utils.py @@ -38,14 +38,12 @@ def get_relative_path(kid: str, parent: str) -> Union[List[str], None]: @lru_cache() -def get_repos(root=None) -> Dict[str, Dict[str, str]]: +def get_repos() -> Dict[str, Dict[str, str]]: """ Return a `dict` of repo name to repo absolute path and repo type - @param root: Use local config if set. If None, use either global or local - config depending on cwd. """ - path_file = common.get_config_fname('repos.csv', root) + path_file = common.get_config_fname('repos.csv') repos = {} if os.path.isfile(path_file) and os.stat(path_file).st_size > 0: with open(path_file) as f: @@ -54,13 +52,7 @@ def get_repos(root=None) -> Dict[str, Dict[str, str]]: repos = {r['name']: {'path': r['path'], 'type': r['type'], 'flags': r['flags'].split()} - for r in rows if is_git(r['path'], is_bare=True)} - if root is None: # detect if inside a main path - cwd = os.getcwd() - for prop in repos.values(): - path = prop['path'] - if prop['type'] == 'm' and get_relative_path(cwd, path) != MAX_INT: - return get_repos(path) + for r in rows if is_git(r['path'], include_bare=True)} return repos @@ -82,7 +74,6 @@ def get_context() -> Union[Path, None]: ctx = matches[0] if ctx.stem == 'auto': cwd = str(Path.cwd()) - repos = get_repos() # The context is set to be the group with minimal distance to cwd candidate = None min_dist = MAX_INT @@ -102,7 +93,7 @@ def get_context() -> Union[Path, None]: @lru_cache() -def get_groups() -> Dict[str, Dict]: +def get_groups() -> Dict[str, Dict[str, Union[str, List]]]: """ Return a `dict` of group name to group properties such as repo names and group path. @@ -152,7 +143,7 @@ def replace_context(old: Union[Path, None], new: str): # ctx.rename(ctx.with_stem(new_name)) # only works in py3.9 old.rename(old.with_name(f'{new}.context')) else: - open(auto.with_name(f'{new}.context'), 'w').close() + Path(auto.with_name(f'{new}.context')).write_text('') def get_choices() -> List[Union[str, None]]: @@ -170,7 +161,16 @@ def get_choices() -> List[Union[str, None]]: return choices -def is_git(path: str, is_bare=False) -> bool: +def is_submodule_repo(p: Path) -> bool: + """ + + """ + if p.is_file() and '.git/modules' in p.read_text(): + return True + return False + + +def is_git(path: str, include_bare=False, exclude_submodule=False) -> bool: """ Return True if the path is a git repo. """ @@ -178,16 +178,18 @@ def is_git(path: str, is_bare=False) -> bool: return False # An alternative is to call `git rev-parse --is-inside-work-tree` # I don't see why that one is better yet. - # For a regular git repo, .git is a folder, for a worktree repo, .git is a file. - # However, git submodule repo also has .git as a file. + # For a regular git repo, .git is a folder. For a worktree repo and + # submodule repo, .git is a file. # A more reliable way to differentiable regular and worktree repos is to # compare the result of `git rev-parse --git-dir` and # `git rev-parse --git-common-dir` loc = os.path.join(path, '.git') # TODO: we can display the worktree repos in a different font. if os.path.exists(loc): + if exclude_submodule and is_submodule_repo(Path(loc)): + return False return True - if not is_bare: + if not include_bare: return False # detect bare repo got = subprocess.run('git rev-parse --is-bare-repository'.split(), @@ -209,37 +211,26 @@ def rename_repo(repos: Dict[str, Dict[str, str]], repo: str, new_name: str): prop = repos[repo] del repos[repo] repos[new_name] = prop - # write to local config if inside a main path - main_paths = (prop['path'] for prop in repos.values() if prop['type'] == 'm') - cwd = os.getcwd() - is_local_config = True - # TODO: delete - for p in main_paths: - if get_relative_path(cwd, p) != MAX_INT: - write_to_repo_file(repos, 'w', p) - break - else: # global config - write_to_repo_file(repos, 'w') - is_local_config = False - # update groups only when outside any main repos - if is_local_config: - return + write_to_repo_file(repos, 'w') + groups = get_groups() - for g, members in groups.items(): + for g, values in groups.items(): + members = values['repos'] if repo in members: members.remove(repo) members.append(new_name) - groups[g] = sorted(members) + groups[g]['repos'] = sorted(members) write_to_groups_file(groups, 'w') -def write_to_repo_file(repos: Dict[str, Dict[str, str]], mode: str, root=None): +def write_to_repo_file(repos: Dict[str, Dict[str, str]], mode: str): """ @param repos: each repo is {name: {properties}} """ - data = [(prop['path'], name, prop['type'], ' '.join(prop['flags'])) + # The 3rd column is repo type; unused field + data = [(prop['path'], name, '', ' '.join(prop['flags'])) for name, prop in repos.items()] - fname = common.get_config_fname('repos.csv', root) + fname = common.get_config_fname('repos.csv') os.makedirs(os.path.dirname(fname), exist_ok=True) with open(fname, mode, newline='') as f: writer = csv.writer(f, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) @@ -254,7 +245,7 @@ def write_to_groups_file(groups: Dict[str, Dict], mode: str): fname = common.get_config_fname('groups.csv') os.makedirs(os.path.dirname(fname), exist_ok=True) if not groups: # all groups are deleted - open(fname, 'w').close() + Path(fname).write_text('') else: # delete the group if there are no repos for name in list(groups): @@ -285,27 +276,17 @@ def _make_name(path: str, repos: Dict[str, Dict[str, str]], return name -# TODO: delete -def _get_repo_type(path, repo_type, root) -> str: - """ - - """ - if repo_type != '': # explicitly set - return repo_type - if root is not None and os.path.normpath(root) == os.path.normpath(path): - return 'm' - return '' - - def add_repos(repos: Dict[str, Dict[str, str]], new_paths: List[str], - repo_type='', root=None, is_bare=False) -> Dict[str, Dict[str, str]]: + include_bare=False, + exclude_submodule=False, + ) -> Dict[str, Dict[str, str]]: """ Write new repo paths to file; return the added repos. @param repos: name -> path """ existing_paths = {prop['path'] for prop in repos.values()} - new_paths = {p for p in new_paths if is_git(p, is_bare)} + new_paths = {p for p in new_paths if is_git(p, include_bare, exclude_submodule)} new_paths = new_paths - existing_paths new_repos = {} if new_paths: @@ -315,12 +296,9 @@ def add_repos(repos: Dict[str, Dict[str, str]], new_paths: List[str], ) new_repos = {_make_name(path, repos, name_counts): { 'path': path, - 'type': _get_repo_type(path, repo_type, root), 'flags': '', } for path in new_paths} - # When root is not None, we could optionally set its type to 'm', i.e., - # main repo. - write_to_repo_file(new_repos, 'a+', root) + write_to_repo_file(new_repos, 'a+') else: print('No new repos found!') return new_repos @@ -442,13 +420,7 @@ def describe(repos: Dict[str, Dict[str, str]], no_colors: bool = False) -> str: for name in sorted(repos): info_items = ' '.join(f(repos[name]) for f in funcs) - if repos[name]['type'] == 'm': - # ANSI color code also takes length in Python - name = f'{info.Color.underline}{name}{info.Color.end}' - width = name_width + 8 - yield f'{name:<{width}}{info_items}' - else: - yield f'{name:<{name_width}}{info_items}' + yield f'{name:<{name_width}}{info_items}' def get_cmds_from_files() -> Dict[str, Dict[str, str]]: |