idf_ci_utils.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. # SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
  2. # SPDX-License-Identifier: Apache-2.0
  3. # internal use only for CI
  4. # some CI related util functions
  5. import logging
  6. import os
  7. import subprocess
  8. import sys
  9. from typing import Any, List
  10. IDF_PATH = os.path.abspath(os.getenv('IDF_PATH', os.path.join(os.path.dirname(__file__), '..', '..')))
  11. def get_submodule_dirs(full_path: bool = False) -> List[str]:
  12. """
  13. To avoid issue could be introduced by multi-os or additional dependency,
  14. we use python and git to get this output
  15. :return: List of submodule dirs
  16. """
  17. dirs = []
  18. try:
  19. lines = (
  20. subprocess.check_output(
  21. [
  22. 'git',
  23. 'config',
  24. '--file',
  25. os.path.realpath(os.path.join(IDF_PATH, '.gitmodules')),
  26. '--get-regexp',
  27. 'path',
  28. ]
  29. )
  30. .decode('utf8')
  31. .strip()
  32. .split('\n')
  33. )
  34. for line in lines:
  35. _, path = line.split(' ')
  36. if full_path:
  37. dirs.append(os.path.join(IDF_PATH, path))
  38. else:
  39. dirs.append(path)
  40. except Exception as e: # pylint: disable=W0703
  41. logging.warning(str(e))
  42. return dirs
  43. def _check_git_filemode(full_path: str) -> bool:
  44. try:
  45. stdout = subprocess.check_output(['git', 'ls-files', '--stage', full_path]).strip().decode('utf-8')
  46. except subprocess.CalledProcessError:
  47. return True
  48. mode = stdout.split(' ', 1)[0] # e.g. 100644 for a rw-r--r--
  49. if any([int(i, 8) & 1 for i in mode[-3:]]):
  50. return True
  51. return False
  52. def is_executable(full_path: str) -> bool:
  53. """
  54. os.X_OK will always return true on windows. Use git to check file mode.
  55. :param full_path: file full path
  56. :return: True is it's an executable file
  57. """
  58. if sys.platform == 'win32':
  59. return _check_git_filemode(full_path)
  60. return os.access(full_path, os.X_OK)
  61. def get_git_files(path: str = IDF_PATH, full_path: bool = False) -> List[str]:
  62. """
  63. Get the result of git ls-files
  64. :param path: path to run git ls-files
  65. :param full_path: return full path if set to True
  66. :return: list of file paths
  67. """
  68. try:
  69. # this is a workaround when using under worktree
  70. # if you're using worktree, when running git commit a new environment variable GIT_DIR would be declared,
  71. # the value should be <origin_repo_path>/.git/worktrees/<worktree name>
  72. # This would affect the return value of `git ls-files`, unset this would use the `cwd`value or its parent
  73. # folder if no `.git` folder found in `cwd`.
  74. workaround_env = os.environ.copy()
  75. workaround_env.pop('GIT_DIR', None)
  76. files = (
  77. subprocess.check_output(['git', 'ls-files'], cwd=path, env=workaround_env)
  78. .decode('utf8')
  79. .strip()
  80. .split('\n')
  81. )
  82. except Exception as e: # pylint: disable=W0703
  83. logging.warning(str(e))
  84. files = []
  85. return [os.path.join(path, f) for f in files] if full_path else files
  86. def is_in_directory(file_path: str, folder: str) -> bool:
  87. return os.path.realpath(file_path).startswith(os.path.realpath(folder) + os.sep)
  88. def to_list(s: Any) -> List[Any]:
  89. if isinstance(s, (set, tuple)):
  90. return list(s)
  91. if isinstance(s, list):
  92. return s
  93. return [s]