submodules.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. """Functions for working with QMK's submodules.
  2. """
  3. from milc import cli
  4. def status():
  5. """Returns a dictionary of submodules.
  6. Each entry is a dict of the form:
  7. {
  8. 'name': 'submodule_name',
  9. 'status': None/False/True,
  10. 'githash': '<sha-1 hash for the submodule>'
  11. 'shorthash': '<short hash for the submodule>'
  12. 'describe': '<output of `git describe --tags`>'
  13. 'last_log_message': 'log message'
  14. 'last_log_timestamp': 'timestamp'
  15. }
  16. status is None when the submodule doesn't exist, False when it's out of date, and True when it's current
  17. """
  18. submodules = {}
  19. git_cmd = cli.run(['git', 'submodule', 'status'], timeout=30)
  20. for line in git_cmd.stdout.split('\n'):
  21. if not line:
  22. continue
  23. status = line[0]
  24. githash, submodule = line[1:].split()[:2]
  25. submodules[submodule] = {'name': submodule, 'githash': githash}
  26. if status == '-':
  27. submodules[submodule]['status'] = None
  28. elif status == '+':
  29. submodules[submodule]['status'] = False
  30. elif status == ' ':
  31. submodules[submodule]['status'] = True
  32. else:
  33. raise ValueError('Unknown `git submodule status` sha-1 prefix character: "%s"' % status)
  34. submodule_logs = cli.run(['git', 'submodule', '-q', 'foreach', 'git --no-pager log --pretty=format:"$sm_path%x01%h%x01%ad%x01%s%x0A" --date=iso -n1'])
  35. for log_line in submodule_logs.stdout.split('\n'):
  36. if not log_line:
  37. continue
  38. r = log_line.split('\x01')
  39. submodule = r[0]
  40. submodules[submodule]['shorthash'] = r[1] if len(r) > 1 else ''
  41. submodules[submodule]['last_log_timestamp'] = r[2] if len(r) > 2 else ''
  42. submodules[submodule]['last_log_message'] = r[3] if len(r) > 3 else ''
  43. submodule_tags = cli.run(['git', 'submodule', '-q', 'foreach', '\'echo $sm_path `git describe --tags`\''])
  44. for log_line in submodule_tags.stdout.split('\n'):
  45. if not log_line:
  46. continue
  47. r = log_line.split()
  48. submodule = r[0]
  49. submodules[submodule]['describe'] = r[1] if len(r) > 1 else ''
  50. return submodules
  51. def update(submodules=None):
  52. """Update the submodules.
  53. submodules
  54. A string containing a single submodule or a list of submodules.
  55. """
  56. git_sync_cmd = ['git', 'submodule', 'sync']
  57. git_update_cmd = ['git', 'submodule', 'update', '--init']
  58. if submodules is None:
  59. # Update everything
  60. git_sync_cmd.append('--recursive')
  61. git_update_cmd.append('--recursive')
  62. cli.run(git_sync_cmd, check=True)
  63. cli.run(git_update_cmd, check=True)
  64. else:
  65. if isinstance(submodules, str):
  66. # Update only a single submodule
  67. git_sync_cmd.append(submodules)
  68. git_update_cmd.append(submodules)
  69. cli.run(git_sync_cmd, check=True)
  70. cli.run(git_update_cmd, check=True)
  71. else:
  72. # Update submodules in a list
  73. for submodule in submodules:
  74. cli.run([*git_sync_cmd, submodule], check=True)
  75. cli.run([*git_update_cmd, submodule], check=True)