version_utils.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. 版本工具脚本
  5. 提供版本相关的通用功能
  6. """
  7. import json
  8. import subprocess
  9. from pathlib import Path
  10. from typing import List, Dict, Optional
  11. def load_versions_config(project_root: Path = None) -> Dict:
  12. """加载版本配置文件"""
  13. if project_root is None:
  14. project_root = Path.cwd()
  15. while project_root != project_root.parent:
  16. if (project_root / '.github' / 'versions.json').exists():
  17. break
  18. project_root = project_root.parent
  19. else:
  20. raise FileNotFoundError("找不到 .github/versions.json 文件")
  21. versions_file = project_root / '.github' / 'versions.json'
  22. try:
  23. with open(versions_file, 'r', encoding='utf-8') as f:
  24. config = json.load(f)
  25. return config
  26. except Exception as e:
  27. print(f"错误: 无法加载版本配置: {e}")
  28. return {'versions': [], 'default_version': '', 'latest_version': ''}
  29. def get_version_configs(project_root: Path = None) -> List[Dict]:
  30. """获取版本配置列表"""
  31. config = load_versions_config(project_root)
  32. return config.get('versions', [])
  33. def get_current_branch() -> Optional[str]:
  34. """获取当前分支名称"""
  35. try:
  36. result = subprocess.run(
  37. ['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
  38. capture_output=True, text=True, check=True
  39. )
  40. return result.stdout.strip()
  41. except subprocess.CalledProcessError:
  42. return None
  43. def get_branch_for_version(version_name: str, project_root: Path = None) -> Optional[str]:
  44. """根据版本名称获取对应的分支"""
  45. versions = get_version_configs(project_root)
  46. for version in versions:
  47. if version['name'] == version_name:
  48. return version['branch']
  49. return None
  50. def get_version_for_branch(branch_name: str, project_root: Path = None) -> Optional[Dict]:
  51. """根据分支名称获取对应的版本配置"""
  52. versions = get_version_configs(project_root)
  53. for version in versions:
  54. if version['branch'] == branch_name:
  55. return version
  56. return None
  57. def validate_versions_config(project_root: Path = None) -> bool:
  58. """验证版本配置的有效性"""
  59. try:
  60. config = load_versions_config(project_root)
  61. versions = config.get('versions', [])
  62. if not versions:
  63. print("错误: 没有找到版本配置")
  64. return False
  65. # 检查必需字段
  66. required_fields = ['name', 'display_name', 'branch', 'url_path']
  67. for i, version in enumerate(versions):
  68. for field in required_fields:
  69. if field not in version:
  70. print(f"错误: 版本 {i+1} 缺少必需字段 '{field}'")
  71. return False
  72. # 检查分支是否存在
  73. for version in versions:
  74. branch = version['branch']
  75. try:
  76. result = subprocess.run(
  77. ['git', 'rev-parse', '--verify', f'refs/heads/{branch}'],
  78. capture_output=True, check=True
  79. )
  80. except subprocess.CalledProcessError:
  81. print(f"警告: 分支 '{branch}' 不存在")
  82. # 检查默认版本
  83. default_version = config.get('default_version')
  84. if default_version:
  85. default_exists = any(v['name'] == default_version for v in versions)
  86. if not default_exists:
  87. print(f"警告: 默认版本 '{default_version}' 不在版本列表中")
  88. # 检查最新版本
  89. latest_version = config.get('latest_version')
  90. if latest_version:
  91. latest_exists = any(v['name'] == latest_version for v in versions)
  92. if not latest_exists:
  93. print(f"警告: 最新版本 '{latest_version}' 不在版本列表中")
  94. print(f"✓ 版本配置验证通过: {len(versions)} 个版本")
  95. return True
  96. except Exception as e:
  97. print(f"错误: 版本配置验证失败: {e}")
  98. return False
  99. def create_version_redirect_html(version_config: Dict, target_url: str) -> str:
  100. """创建版本重定向页面"""
  101. return f"""<!DOCTYPE html>
  102. <html lang="zh-CN">
  103. <head>
  104. <meta charset="UTF-8">
  105. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  106. <title>{version_config['display_name']} - SDK 文档</title>
  107. <meta http-equiv="refresh" content="0; url={target_url}">
  108. <style>
  109. body {{
  110. font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  111. display: flex;
  112. justify-content: center;
  113. align-items: center;
  114. height: 100vh;
  115. margin: 0;
  116. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  117. color: white;
  118. }}
  119. .container {{
  120. text-align: center;
  121. background: rgba(255, 255, 255, 0.1);
  122. padding: 40px;
  123. border-radius: 12px;
  124. backdrop-filter: blur(10px);
  125. }}
  126. .spinner {{
  127. border: 3px solid rgba(255, 255, 255, 0.3);
  128. border-top: 3px solid white;
  129. border-radius: 50%;
  130. width: 40px;
  131. height: 40px;
  132. animation: spin 1s linear infinite;
  133. margin: 0 auto 20px;
  134. }}
  135. @keyframes spin {{
  136. 0% {{ transform: rotate(0deg); }}
  137. 100% {{ transform: rotate(360deg); }}
  138. }}
  139. h1 {{
  140. margin: 0 0 10px 0;
  141. font-size: 24px;
  142. }}
  143. p {{
  144. margin: 0;
  145. opacity: 0.9;
  146. }}
  147. a {{
  148. color: white;
  149. text-decoration: underline;
  150. }}
  151. </style>
  152. </head>
  153. <body>
  154. <div class="container">
  155. <div class="spinner"></div>
  156. <h1>{version_config['display_name']}</h1>
  157. <p>正在跳转到文档...</p>
  158. <p><a href="{target_url}">如果页面没有自动跳转,请点击这里</a></p>
  159. </div>
  160. </body>
  161. </html>"""
  162. if __name__ == "__main__":
  163. import argparse
  164. parser = argparse.ArgumentParser(description="版本工具")
  165. parser.add_argument('--validate', action='store_true', help='验证版本配置')
  166. parser.add_argument('--list', action='store_true', help='列出所有版本')
  167. parser.add_argument('--current-branch', action='store_true', help='获取当前分支')
  168. parser.add_argument('--version-for-branch', type=str, help='根据分支获取版本')
  169. parser.add_argument('--branch-for-version', type=str, help='根据版本获取分支')
  170. args = parser.parse_args()
  171. if args.validate:
  172. success = validate_versions_config()
  173. exit(0 if success else 1)
  174. elif args.list:
  175. versions = get_version_configs()
  176. print("版本列表:")
  177. for version in versions:
  178. print(f" - {version['display_name']} ({version['name']}) -> {version['branch']}")
  179. elif args.current_branch:
  180. branch = get_current_branch()
  181. if branch:
  182. print(branch)
  183. else:
  184. print("无法获取当前分支")
  185. exit(1)
  186. elif args.version_for_branch:
  187. version = get_version_for_branch(args.version_for_branch)
  188. if version:
  189. print(json.dumps(version, ensure_ascii=False, indent=2))
  190. else:
  191. print(f"分支 '{args.version_for_branch}' 没有对应的版本配置")
  192. exit(1)
  193. elif args.branch_for_version:
  194. branch = get_branch_for_version(args.branch_for_version)
  195. if branch:
  196. print(branch)
  197. else:
  198. print(f"版本 '{args.branch_for_version}' 没有对应的分支")
  199. exit(1)
  200. else:
  201. parser.print_help()