abe_setup.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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(path, remote, ref=None, func=None):
  27. if func != None:
  28. yield func( path, remote, ref)
  29. subm = get_abe_submodules( path )
  30. import os
  31. import urllib.parse
  32. url = urllib.parse.urlparse(remote)
  33. for su in subm:
  34. newpath = os.path.normpath(os.path.join( path, su.subdir))
  35. newurl = url._replace(path=su.remote).geturl()
  36. print(f"Repo: \"{path}\" has Submodule: \"{newpath}\" Type: \"{su.subtype}\" From: \"{newurl}\"") if DEBUG else None
  37. for ret in recurse_abe_submodules( newpath, newurl, su.ref, func):
  38. yield ret
  39. def cache_path(cache, remote):
  40. import os.path
  41. for url in remote:
  42. return os.path.join( cache, str(url).replace('/','_').replace( '@', '_at_'))
  43. def real_relpath(dest, source='.'):
  44. import os.path
  45. real_dest = os.path.realpath(dest)
  46. real_source = os.path.realpath(source)
  47. return os.path.relpath(real_dest, real_source)
  48. from git import RemoteProgress
  49. class ProgressPrinter(RemoteProgress):
  50. def update(self,op_code,cur_count,max_count=None,message=''):
  51. cur_count_int = round(cur_count)
  52. max_count_int = round(max_count or 100)
  53. print(f"\033[2K{cur_count_int}/{max_count_int}", str(round(100*cur_count / (max_count or 100)))+'%', end="\r")
  54. def clone_repo_cached( cache_dir=None, bare=False):
  55. def clone_repo(path, remote, ref=None, cache_dir=cache_dir, bare=bare):
  56. print('Repo:', path) if DEBUG>1 else None
  57. from git import Repo
  58. repo = Repo.init(path, bare=bare)
  59. if 'origin' in repo.remotes:
  60. origin = repo.remotes['origin']
  61. else:
  62. origin = repo.create_remote('origin', remote)
  63. if cache_dir != None:
  64. cache_repo_path = cache_path(cache_dir, origin.urls)
  65. print(f"Cacheing from: {cache_repo_path}") if DEBUG else None
  66. clone_repo_cached(cache_dir=None, bare=True)( cache_repo_path, remote, ref)
  67. if 'cache' in repo.remotes:
  68. cache = repo.remotes['cache']
  69. else:
  70. cache = repo.create_remote('cache', real_relpath( cache_repo_path, path))
  71. cache.set_url("no_push" , '--push')
  72. cache.fetch(refspec="+refs/remotes/origin/*:refs/remotes/origin/*",progress=ProgressPrinter())
  73. print()
  74. else:
  75. origin.fetch(progress=ProgressPrinter())
  76. print()
  77. if not bare:
  78. print('Refs:', origin.refs) if DEBUG>1 else None
  79. print('Heads:', repo.heads) if DEBUG>1 else None
  80. if ref in repo.tags:
  81. tracking_branch_name = 'local_tag_branch/'+ref
  82. tracking_ref = repo.tags[ref]
  83. if tracking_branch_name in repo.heads:
  84. active_branch = repo.heads[tracking_branch_name]
  85. else:
  86. active_branch = repo.create_head('local_tag_branch/'+ref, tracking_ref)
  87. elif ref in repo.heads:
  88. tracking_ref = origin.refs[ref]
  89. active_branch = repo.heads[ref]
  90. active_branch.set_tracking_branch(tracking_ref)
  91. elif ref in origin.refs:
  92. tracking_ref = origin.refs[ref]
  93. active_branch = repo.create_head(ref, tracking_ref)
  94. active_branch.set_tracking_branch(tracking_ref)
  95. elif ref in origin.refs:
  96. tracking_ref = origin.refs[ref]
  97. active_branch = repo.create_head(ref, tracking_ref)
  98. active_branch.set_tracking_branch(tracking_ref)
  99. else:
  100. try:
  101. tracking_ref = ref
  102. tracking_branch_name = 'local_commit_branch/'+ref
  103. active_branch = repo.create_head(tracking_branch_name, tracking_ref)
  104. except Exception:
  105. raise Exception(f"Branch/Tag/Commit \"{ref}\" not found")
  106. print('Active Branch:', active_branch) if DEBUG else None
  107. print('Tracking Ref:', tracking_ref, '\n') if DEBUG else None
  108. active_branch.checkout()
  109. repo.head.reset( tracking_ref, index=True, working_tree=False)
  110. return repo
  111. return clone_repo
  112. from enum import Enum
  113. class AbeSubType(Enum):
  114. SUBMODULE = 1
  115. BOOTLOADER = 2
  116. BSP = 3
  117. class AbeSubmodule():
  118. subtype = AbeSubType.SUBMODULE
  119. def __init__(self, sub_info, subtype=None):
  120. if subtype != None:
  121. self.subtype = subtype
  122. self.subdir = sub_info[0]
  123. self.remote = sub_info[1]
  124. self.ref = sub_info[2]
  125. if self.subtype == AbeSubType.BSP:
  126. self.remote = 'bsp/' + self.remote
  127. if self.subtype == AbeSubType.BOOTLOADER:
  128. self.remote = 'bootloader/' + self.remote
  129. def __repr__(self):
  130. return f"AbeSubmodule(['{self.subdir}','{self.remote}','{self.ref}'], {self.subtype})"
  131. def get_abe_submodules(repo_dir):
  132. import os
  133. import itertools
  134. subfile_generators = []
  135. subfile_path = os.path.join(repo_dir, '.abe', 'submodules')
  136. if os.path.isfile(subfile_path):
  137. subfile_generators.append(parse_abe_subfile(subfile_path, subtype=AbeSubType.SUBMODULE))
  138. bspfile_path = os.path.join(repo_dir, '.abe', 'bsps')
  139. if os.path.isfile(bspfile_path):
  140. subfile_generators.append(parse_abe_subfile(bspfile_path, subtype=AbeSubType.BSP))
  141. bootloaderfile_path = os.path.join(repo_dir, '.abe', 'bootloaders')
  142. if os.path.isfile(bootloaderfile_path):
  143. subfile_generators.append(parse_abe_subfile(bootloaderfile_path, subtype=AbeSubType.BOOTLOADER))
  144. return itertools.chain(*subfile_generators)
  145. def parse_abe_subfile(subfile_path, subtype=AbeSubType.SUBMODULE):
  146. with open(subfile_path) as subfile:
  147. for line in subfile.readlines():
  148. strline = line.strip()
  149. if strline.startswith('#'):
  150. continue
  151. sline = strline.split()
  152. if len(sline) < 3:
  153. continue
  154. print('Submodule:', sline) if DEBUG>1 else None
  155. sub = AbeSubmodule(sline, subtype)
  156. yield sub
  157. if __name__=='__main__':
  158. main()