test_submodules.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. # SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  2. # SPDX-License-Identifier: Apache-2.0
  3. import os
  4. from subprocess import run
  5. from typing import Dict, List
  6. def run_cmd(cmd: List[str]) -> str:
  7. """Simple helper to run command and return it's stdout."""
  8. proc = run(cmd, capture_output=True, check=True, text=True)
  9. return proc.stdout.strip()
  10. def get_gitwdir() -> str:
  11. """Return absolute path to the current git working tree."""
  12. return run_cmd(['git', 'rev-parse', '--show-toplevel'])
  13. def get_submodules_info() -> List[Dict[str,str]]:
  14. """Return list of submodules, where each submodule is represented
  15. as dictionary with name, path and hash keys."""
  16. cmd = ['git', 'submodule', '--quiet', 'foreach','echo "$name,$sm_path,$sha1"']
  17. out = run_cmd(cmd)
  18. submodules = []
  19. for line in out.splitlines():
  20. name, sm_path, sha1 = line.split(',')
  21. submodules += [{'name': name, 'path': sm_path, 'hash': sha1}]
  22. return submodules
  23. def get_submodules_config() -> Dict[str,str]:
  24. """Return dictionary, where key is variable name and value
  25. is variable value in git's --list(dot) format. Only variables
  26. starting with "submodule." are returned and this prefix is removed
  27. to make it simple to match against the submodule info dictionary."""
  28. gitmodules_fn = os.path.join(get_gitwdir(), '.gitmodules')
  29. gitmodules_data = run_cmd(['git', 'config', '--list', '--file', gitmodules_fn])
  30. prefix = 'submodule.'
  31. config = {}
  32. for line in gitmodules_data.splitlines():
  33. var, val = line.split('=', maxsplit=1)
  34. if not var.startswith(prefix):
  35. continue
  36. # remove "submodule." prefix
  37. var = var[len(prefix):]
  38. config[var] = val
  39. return config
  40. def test_sha() -> None:
  41. """ Check that submodule SHA1 in git-tree and .gitmodules match
  42. if sbom-hash variable is available in the .gitmodules file.
  43. """
  44. submodules = get_submodules_info()
  45. config = get_submodules_config()
  46. for submodule in submodules:
  47. sbom_hash = config.get(submodule['name'] + '.sbom-hash')
  48. if not sbom_hash:
  49. continue
  50. msg = (f'Submodule \"{submodule["name"]}\" SHA \"{submodule["hash"]}\" in git '
  51. f'tree does not match SHA \"{sbom_hash}\" recorded in .gitmodules. '
  52. f'Please update \"sbom-hash\" in .gitmodules for \"{submodule["name"]}\" '
  53. f'and also please do not forget to update version and other submodule '
  54. f'information if necessary. It is important to keep this information '
  55. f'up-to-date for SBOM generation.')
  56. assert submodule['hash'] == sbom_hash, msg
  57. if __name__ == '__main__':
  58. test_sha()