file_processor.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. 文件处理器模块
  5. 负责复制和处理项目文件
  6. """
  7. import shutil
  8. import os
  9. from pathlib import Path
  10. from typing import List, Dict
  11. class FileProcessor:
  12. def __init__(self, source_dir: str, dest_dir: str, config: Dict):
  13. self.source_dir = Path(source_dir)
  14. self.dest_dir = Path(dest_dir)
  15. self.config = config
  16. self.copy_files = config.get('copy_files', [])
  17. self.copy_dirs = config.get('copy_dirs', [])
  18. self.output_structure = config.get('output_structure', [])
  19. def copy_project_files(self, project_name: str, category: str) -> bool:
  20. """复制项目文件到目标目录"""
  21. source_project = self.source_dir / project_name
  22. dest_project = self.dest_dir / category / project_name
  23. if not source_project.exists():
  24. print(f"警告: 源项目目录不存在: {source_project}")
  25. return False
  26. # 创建目标目录
  27. dest_project.mkdir(parents=True, exist_ok=True)
  28. # 复制指定文件
  29. for file_name in self.copy_files:
  30. source_file = source_project / file_name
  31. if source_file.exists():
  32. shutil.copy2(source_file, dest_project)
  33. print(f"复制文件: {project_name}/{file_name}")
  34. else:
  35. print(f"警告: 文件不存在: {source_file}")
  36. # 复制指定目录
  37. for dir_name in self.copy_dirs:
  38. source_dir_path = source_project / dir_name
  39. if source_dir_path.exists() and source_dir_path.is_dir():
  40. dest_dir_path = dest_project / dir_name
  41. if dest_dir_path.exists():
  42. shutil.rmtree(dest_dir_path)
  43. shutil.copytree(source_dir_path, dest_dir_path)
  44. print(f"复制目录: {project_name}/{dir_name}")
  45. return True
  46. def get_readme_title(self, project_name: str, category: str, language: str = 'zh') -> str:
  47. """从README文件中提取一级标题"""
  48. if language == 'en':
  49. readme_path = self.dest_dir / category / project_name / "README.md"
  50. else:
  51. readme_path = self.dest_dir / category / project_name / "README_zh.md"
  52. if readme_path.exists():
  53. try:
  54. with open(readme_path, 'r', encoding='utf-8') as f:
  55. content = f.read()
  56. # 查找第一个一级标题
  57. lines = content.split('\n')
  58. for line in lines:
  59. line = line.strip()
  60. if line.startswith('# ') and len(line) > 2:
  61. return line[2:].strip() # 移除 "# " 前缀
  62. except Exception as e:
  63. print(f"读取 {project_name}/README{'._zh' if language == 'zh' else ''}.md 标题时出错: {e}")
  64. # 如果无法读取标题,使用项目名称作为后备
  65. return project_name.replace("etherkit_", "").replace("_", " ").title()
  66. def cleanup_dest_dir(self):
  67. """清理目标目录"""
  68. if self.dest_dir.exists():
  69. # 保存Sphinx必需的文件
  70. sphinx_files = {}
  71. for file_name in ['conf.py', 'requirements.txt', 'config.yaml']:
  72. file_path = self.dest_dir / file_name
  73. if file_path.exists():
  74. with open(file_path, 'r', encoding='utf-8') as f:
  75. sphinx_files[file_name] = f.read()
  76. # 保存静态文件目录中的文件
  77. static_dir = self.dest_dir / '_static'
  78. static_files = {}
  79. if static_dir.exists():
  80. for file_path in static_dir.rglob('*'):
  81. if file_path.is_file():
  82. relative_path = file_path.relative_to(static_dir)
  83. with open(file_path, 'rb') as f:
  84. static_files[str(relative_path)] = f.read()
  85. # 保存模板文件目录中的文件
  86. templates_dir = self.dest_dir / '_templates'
  87. template_files = {}
  88. if templates_dir.exists():
  89. for file_path in templates_dir.rglob('*'):
  90. if file_path.is_file():
  91. relative_path = file_path.relative_to(templates_dir)
  92. with open(file_path, 'r', encoding='utf-8') as f:
  93. template_files[str(relative_path)] = f.read()
  94. # 只删除生成的文档目录,不删除整个目录
  95. categories_to_clean = self.output_structure or ['start', 'basic', 'driver', 'component', 'multimedia', 'multcore']
  96. for category in categories_to_clean:
  97. category_dir = self.dest_dir / category
  98. if category_dir.exists():
  99. shutil.rmtree(category_dir)
  100. print(f"清理目录: {category_dir}")
  101. # 恢复Sphinx必需的文件
  102. for file_name, content in sphinx_files.items():
  103. file_path = self.dest_dir / file_name
  104. with open(file_path, 'w', encoding='utf-8') as f:
  105. f.write(content)
  106. # 重新创建静态文件目录并恢复文件
  107. if static_dir.exists():
  108. shutil.rmtree(static_dir)
  109. static_dir.mkdir(exist_ok=True)
  110. # 恢复静态文件
  111. for file_path, content in static_files.items():
  112. full_path = static_dir / file_path
  113. full_path.parent.mkdir(parents=True, exist_ok=True)
  114. with open(full_path, 'wb') as f:
  115. f.write(content)
  116. # 重新创建模板文件目录并恢复文件
  117. if templates_dir.exists():
  118. shutil.rmtree(templates_dir)
  119. templates_dir.mkdir(exist_ok=True)
  120. # 恢复模板文件
  121. for file_path, content in template_files.items():
  122. full_path = templates_dir / file_path
  123. full_path.parent.mkdir(parents=True, exist_ok=True)
  124. with open(full_path, 'w', encoding='utf-8') as f:
  125. f.write(content)
  126. else:
  127. # 如果目标目录不存在,创建它
  128. self.dest_dir.mkdir(exist_ok=True)
  129. (self.dest_dir / '_static').mkdir(exist_ok=True)
  130. (self.dest_dir / '_templates').mkdir(exist_ok=True)