abe_setup.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #!/usr/bin/env python3
  2. #
  3. # A script to setup a Working tree from abe git submodules
  4. DEBUG = 1
  5. def main():
  6. global DEBUG
  7. p = parser()
  8. args = p.parse_args()
  9. DEBUG = args.debug
  10. DEBUG = DEBUG - (1 if args.quiet else 0)
  11. print(args) if DEBUG>1 else None
  12. if args.source_url and args.source_url.find('://') < 0 and args.source_url.find( ':' ) > 0:
  13. args.source_url = 'ssh://' + args.source_url.replace( ':', '/', 1)
  14. for ret in recurse_abe_submodules( args.output_dir, args.source_url, args.tag, clone_repo_cached(cache_dir=args.cache_dir)):
  15. pass
  16. def parser():
  17. import argparse
  18. p = argparse.ArgumentParser()
  19. p.add_argument('-d', '--debug', action='count', default=1)
  20. p.add_argument('-q', '--quiet', action='store_true')
  21. p.add_argument('-o', '--output_dir', default='.')
  22. p.add_argument('-c', '--cache_dir', default=None)
  23. p.add_argument('-t', '--tag', default='master')
  24. p.add_argument('-s', '--source_url', default=None)
  25. return p
  26. def recurse_abe_submodules( parent, func=None):
  27. if func != None:
  28. yield func( parent )
  29. subm = get_abe_submodules( parent.subdir )
  30. import os
  31. import urllib.parse
  32. for su in subm:
  33. print(f"Repo: \"{parent.path}\" has Submodule: \"{su.subdir}\" Type: \"{su.subtype}\" From: \"{newurl}\"") if DEBUG else None
  34. for ret in recurse_abe_submodules( subm.full_path(), newurl, su.ref, func):
  35. yield ret
  36. def cache_path(cache, remote):
  37. import os.path
  38. for url in remote:
  39. sane_url = str(url).replace('/','_').replace( '@', '_').replace(':', '_')
  40. return os.path.join( cache, sane_url)
  41. def real_relpath(dest, source='.'):
  42. import os.path
  43. real_dest = os.path.realpath(dest)
  44. real_source = os.path.realpath(source)
  45. return os.path.relpath(real_dest, real_source)
  46. from git import RemoteProgress
  47. class ProgressPrinter(RemoteProgress):
  48. def update(self,op_code,cur_count,max_count=None,message=''):
  49. cur_count_int = round(cur_count)
  50. max_count_int = round(max_count or 100)
  51. print(f"\033[2K{cur_count_int}/{max_count_int}", str(round(100*cur_count / (max_count or 100)))+'%', end="\r")
  52. def clone_repo_cached( cache_dir=None, bare=False):
  53. def clone_repo(path, remote, ref=None, cache_dir=cache_dir, bare=bare):
  54. print('Repo:', path) if DEBUG>1 else None
  55. from git import Repo
  56. repo = Repo.init(path, bare=bare)
  57. if 'origin' in repo.remotes:
  58. origin = repo.remotes['origin']
  59. else:
  60. origin = repo.create_remote('origin', remote)
  61. if cache_dir != None:
  62. cache_repo_path = cache_path(cache_dir, origin.urls)
  63. print(f"Cacheing from: {cache_repo_path}") if DEBUG else None
  64. clone_repo_cached(cache_dir=None, bare=True)( cache_repo_path, remote, ref)
  65. if 'cache' in repo.remotes:
  66. cache = repo.remotes['cache']
  67. else:
  68. cache = repo.create_remote('cache', real_relpath( cache_repo_path, path))
  69. cache.set_url("no_push" , '--push')
  70. cache.fetch(refspec="+refs/remotes/origin/*:refs/remotes/origin/*",progress=ProgressPrinter())
  71. print()
  72. else:
  73. origin.fetch(progress=ProgressPrinter())
  74. print()
  75. if not bare:
  76. print('Refs:', origin.refs) if DEBUG>1 else None
  77. print('Heads:', repo.heads) if DEBUG>1 else None
  78. if ref in repo.tags:
  79. tracking_branch_name = 'local_tag_branch/'+ref
  80. tracking_ref = repo.tags[ref]
  81. if tracking_branch_name in repo.heads:
  82. active_branch = repo.heads[tracking_branch_name]
  83. else:
  84. active_branch = repo.create_head('local_tag_branch/'+ref, tracking_ref)
  85. elif ref in repo.heads:
  86. tracking_ref = origin.refs[ref]
  87. active_branch = repo.heads[ref]
  88. active_branch.set_tracking_branch(tracking_ref)
  89. elif ref in origin.refs:
  90. tracking_ref = origin.refs[ref]
  91. active_branch = repo.create_head(ref, tracking_ref)
  92. active_branch.set_tracking_branch(tracking_ref)
  93. elif ref in origin.refs:
  94. tracking_ref = origin.refs[ref]
  95. active_branch = repo.create_head(ref, tracking_ref)
  96. active_branch.set_tracking_branch(tracking_ref)
  97. else:
  98. try:
  99. tracking_ref = ref
  100. tracking_branch_name = 'local_commit_branch/'+ref
  101. active_branch = repo.create_head(tracking_branch_name, tracking_ref)
  102. except Exception:
  103. raise Exception(f"Branch/Tag/Commit \"{ref}\" not found")
  104. print('Active Branch:', active_branch) if DEBUG else None
  105. print('Tracking Ref:', tracking_ref, '\n') if DEBUG else None
  106. active_branch.checkout()
  107. repo.head.reset( tracking_ref, index=True, working_tree=False)
  108. return repo
  109. return clone_repo
  110. from enum import Enum
  111. class AbeSubType(Enum):
  112. SUBMODULE = 1
  113. BOOTLOADER = 2
  114. BSP = 3
  115. from urllib.parse import urlparse
  116. class AbeSubmodule():
  117. subtype = AbeSubType.SUBMODULE
  118. def __init__(self, sub_info, subtype=None):
  119. if subtype != None:
  120. self.subtype = subtype
  121. self.subdir = sub_info[0]
  122. self.remote = sub_info[1]
  123. self.ref = sub_info[2]
  124. if self.subtype == AbeSubType.BSP:
  125. self.remote = 'bsp/' + self.remote
  126. if self.subtype == AbeSubType.BOOTLOADER:
  127. self.remote = 'bootloader/' + self.remote
  128. def __repr__(self):
  129. return f"AbeSubmodule(['{self.subdir}','{self.remote}','{self.ref}'], {self.subtype})"
  130. def full_url(self, parent=None):
  131. selfurl = urlparse(self.remote)
  132. if not parent:
  133. return selfurl.geturl()
  134. purl = urlparse(parent.remote)
  135. newurl = purl._replace( path = selfurl.path )
  136. if selfurl.netloc:
  137. newurl = url._replace( netloc = selfurl.netloc )
  138. if selfurl.scheme:
  139. newurl = url._replace( scheme = selfurl.scheme )
  140. return newurl
  141. def full_path(self, parent=None):
  142. if not parent:
  143. return self.subdir
  144. import os.path
  145. return os.path.normpath(
  146. os.path.join( parent.full_path(),self.subdir)
  147. )
  148. def get_abe_submodules(repo_dir):
  149. import os
  150. import itertools
  151. subfile_generators = []
  152. subfile_path = os.path.join(repo_dir, '.abe', 'submodules')
  153. if os.path.isfile(subfile_path):
  154. subfile_generators.append(parse_abe_subfile(subfile_path, subtype=AbeSubType.SUBMODULE))
  155. bspfile_path = os.path.join(repo_dir, '.abe', 'bsps')
  156. if os.path.isfile(bspfile_path):
  157. subfile_generators.append(parse_abe_subfile(bspfile_path, subtype=AbeSubType.BSP))
  158. bootloaderfile_path = os.path.join(repo_dir, '.abe', 'bootloaders')
  159. if os.path.isfile(bootloaderfile_path):
  160. subfile_generators.append(parse_abe_subfile(bootloaderfile_path, subtype=AbeSubType.BOOTLOADER))
  161. return itertools.chain(*subfile_generators)
  162. def parse_abe_subfile(subfile_path, subtype=AbeSubType.SUBMODULE):
  163. with open(subfile_path) as subfile:
  164. for line in subfile.readlines():
  165. strline = line.strip()
  166. if strline.startswith('#'):
  167. continue
  168. sline = strline.split()
  169. if len(sline) < 3:
  170. continue
  171. print('Submodule:', sline) if DEBUG>1 else None
  172. sub = AbeSubmodule(sline, subtype)
  173. yield sub
  174. if __name__=='__main__':
  175. main()