gitmirror.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. from subprocess import run,Popen, PIPE
  5. source_server="git@git.annax.de"
  6. local_base=f"./repositories"
  7. mirror_base=f"{local_base}/{source_server}"
  8. COM=sys.argv[0]
  9. def git_info(source_server):
  10. proc = Popen(
  11. ["ssh",source_server,"info"],
  12. stdout=PIPE,
  13. stderr=PIPE,
  14. encoding="utf-8")
  15. for line in proc.stdout.readlines():
  16. yield line
  17. def repos_from_lines(lines):
  18. for line in lines:
  19. if line.find("gitolite") >= 0:
  20. continue
  21. fields = line.split()
  22. if len(fields) < 3:
  23. continue
  24. yield fields[2]
  25. def run_threaded(target, args=[], procs=4, debug=False):
  26. import threading
  27. import queue
  28. inq = queue.Queue()
  29. outq = queue.Queue()
  30. jobs = []
  31. j = 0
  32. i = 0
  33. def worker(j):
  34. import time
  35. while True:
  36. arg = inq.get(block=True)
  37. if arg == None:
  38. break
  39. j += 1
  40. print(f"{COM}: mirror task ({j}/{i}): {source_repo(arg)} => {local_repo(arg)}")
  41. outq.put(target(source_repo(arg), local_repo(arg)))
  42. while len(jobs) < procs:
  43. th = threading.Thread(target=worker, args=(j,))
  44. th.start()
  45. jobs.append(th)
  46. i = 0
  47. for arg in args:
  48. i += 1
  49. inq.put(arg)
  50. for job in jobs:
  51. inq.put(None)
  52. for job in jobs:
  53. job.join()
  54. def main():
  55. repos = repos_from_lines(git_info(source_server))
  56. from multiprocessing import Pool
  57. pool = Pool(processes=4)
  58. pool.map(pull_repo, repos)
  59. def main3():
  60. repos = repos_from_lines(git_info(source_server))
  61. run_threaded(mirror_repo, repos, debug=True)
  62. def main2():
  63. lines = git_info(source_server)
  64. repos = repos_from_lines(lines)
  65. for repo in repos:
  66. mirror_repo(repo)
  67. def source_repo(repo):
  68. return f"{source_server}:{repo}"
  69. def local_repo(repo):
  70. return f"{mirror_base}/{repo}.git"
  71. processed = 0
  72. def pull_repo(repo):
  73. global processed
  74. processed += 1
  75. print(f"{COM}: mirror task {processed}: {source_repo(repo)} => {local_repo(repo)}")
  76. return mirror_repo(source_repo(repo), local_repo(repo))
  77. def mirror_repo(source_repo,local_repo):
  78. if os.path.isdir(f"{local_repo}/refs"):
  79. update_local_repo(local_repo)
  80. else:
  81. clone_repo(source_repo, local_repo)
  82. return True
  83. def update_local_repo(local_repo):
  84. proc = run(["git","fetch","-p","origin"], cwd=local_repo)
  85. if not proc.returncode == 0:
  86. print(f"Error: {proc}, {local_repo}")
  87. _rm(local_repo)
  88. def clone_repo(source_repo, local_repo):
  89. run(["rm","-rf",local_repo])
  90. run(["mkdir","-p",local_repo])
  91. proc = run(["git","clone","--bare",source_repo,"."], cwd=local_repo)
  92. if not proc.returncode == 0:
  93. print(f"Error: {proc}, {local_repo}")
  94. _rm(local_repo)
  95. def _rm(di):
  96. run(["rm","-rf",local_repo])
  97. if __name__ == "__main__":
  98. main()