Skip to content

Commit 20a310e

Browse files
committed
feat: support for renamed subtrees
1 parent e6a0ddf commit 20a310e

File tree

1 file changed

+45
-24
lines changed

1 file changed

+45
-24
lines changed

glv/vcs/__init__.py

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,59 @@
11
''' Helper functions for doing things vcs(1) does '''
2-
32
import configparser
3+
import functools
4+
import glob
5+
import logging
6+
import os
47
import os.path
58
import subprocess
69
import sys
7-
from typing import List, Set
10+
from typing import Dict, List, Set
811

912
from pygit2 import Commit # pylint: disable=no-name-in-module
1013
from pygit2 import Repository # pylint: disable=no-name-in-module
1114

15+
LOG = logging.getLogger('glv')
1216

13-
def modules(repo: Repository) -> List[str]:
14-
''' Return list of all .gitsubtrees modules in repository '''
15-
def subtree_config_files() -> List[str]:
16-
result = subprocess.run( # pylint: disable=subprocess-run-check
17-
['git', 'ls-files', '*/.gitsubtrees', '.gitsubtrees'],
18-
stdout=subprocess.PIPE,
19-
cwd=repo.workdir)
20-
if result.returncode != 0:
21-
raise Exception("No gitsubtree files")
2217

23-
return result.stdout.decode('utf-8').splitlines()
18+
@functools.lru_cache()
19+
def subtree_config_files(repo: Repository) -> List[str]:
20+
''' Return all the `.gitsubtree` files from a repository using git(1)‼ '''
21+
os.chdir(repo.workdir)
22+
files = glob.glob('**/.gitsubtrees', recursive=True)
23+
if os.path.exists('.gitsubtrees'):
24+
files += ['.gitsubtrees']
25+
return files
2426

25-
files = subtree_config_files()
26-
result: List[str] = []
27+
28+
@functools.lru_cache()
29+
def modules(repo: Repository) -> Dict[str, str]:
30+
''' Return list of all .gitsubtrees modules in repository '''
31+
32+
files = subtree_config_files(repo)
33+
LOG.debug("Found subtree config files: %s", files)
34+
result: Dict[str] = {}
2735
for _file in files:
2836
conf = configparser.ConfigParser()
2937
conf.read(os.path.join(repo.workdir, _file))
3038
path = ''
3139
if '/' in _file:
3240
parts = _file.split('/')[:-1]
33-
path = '/'.join(parts) + '/'
34-
result += ["%s%s" % (path, key) for key in conf.sections()]
35-
result.sort()
41+
path = '/'.join(parts)
42+
for key in conf.sections():
43+
_path = os.path.join(path, key)
44+
name = _path
45+
result[_path] = name
46+
if conf[key].get('previous'):
47+
previous = [
48+
x.strip() for x in conf[key].get('previous').split(',')
49+
]
50+
for sth in previous:
51+
if sth.startswith('/'):
52+
_path = sth.lstrip('/')
53+
else:
54+
_path = os.path.join(path, sth)
55+
result[_path] = name
56+
LOG.debug("Found subprojects in : %s", result.keys())
3657
return result
3758

3859

@@ -56,14 +77,14 @@ def changed_files(commit: Commit) -> Set[str]:
5677

5778
def changed_modules(repo: Repository, commit: Commit) -> Set[str]:
5879
''' Return all .gisubtrees modules which were changed in the specified commit '''
59-
dirs = modules(repo)
60-
dirs.sort(reverse=True)
61-
files = {name: True for name in changed_files(commit)}
80+
_modules = modules(repo)
81+
changed = changed_files(commit)
82+
files = {name: True for name in changed}
6283
result: List[str] = []
63-
for directory in dirs:
84+
for directory in sorted(_modules, reverse=True):
6485
matches = [_file for _file in files if _file.startswith(directory)]
6586
if matches:
66-
result.append(directory)
67-
for _file in matches:
68-
del files[_file]
87+
result.append(_modules[directory])
88+
files = {k: True for k in files if k not in matches}
89+
6990
return set(result)

0 commit comments

Comments
 (0)