11''' Helper functions for doing things vcs(1) does '''
2-
32import configparser
3+ import functools
4+ import glob
5+ import logging
6+ import os
47import os .path
58import subprocess
69import sys
7- from typing import List , Set
10+ from typing import Dict , List , Set
811
912from pygit2 import Commit # pylint: disable=no-name-in-module
1013from 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
5778def 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