Browse Source

ci: Replace the judgment file modification mechanism of bsp_building.… (#10314)

ci: Replace the judgment file modification mechanism of bsp_building.yml and incorporate the PR status show into bsp_building.yml
hydevcode 1 month ago
parent
commit
51b6df9c16

+ 11 - 48
.github/workflows/bsp_buildings.yml

@@ -41,66 +41,29 @@ permissions:
 jobs:
 jobs:
   generate-matrix:
   generate-matrix:
     runs-on: ubuntu-22.04
     runs-on: ubuntu-22.04
+    name: 🔍 Summary of Git Diff Changes
     outputs:
     outputs:
       filtered_matrix: ${{ steps.filter.outputs.filtered_matrix }}
       filtered_matrix: ${{ steps.filter.outputs.filtered_matrix }}
     steps:
     steps:
       - name: Checkout repo
       - name: Checkout repo
         uses: actions/checkout@main
         uses: actions/checkout@main
         with:
         with:
-          sparse-checkout: .github/ALL_BSP_COMPILE.json
           persist-credentials: false
           persist-credentials: false
-      - name: Read matrix config
-        id: read-config
-        run: |
-          #读取ALL_BSP_COMPILE.json文件
-          raw_matrix_base64=$(cat .github/ALL_BSP_COMPILE.json |egrep -v '^//'|base64 -w 0)
-          echo "raw_matrix=$raw_matrix_base64" >> $GITHUB_OUTPUT
-      - name: Get changed files
-        id: changed_files
-        if: github.event_name == 'pull_request'
-        run: |
-          changed_files=$(curl -s \
-            "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files" | \
-            jq -r '.[].filename') 
-          prefix=$(echo "$changed_files" | cut -d'/' -f1 | sort -u )
-          has_bsp=true
-          for r in "$prefix"; do
-            if [[ ! "$r" == "bsp" ]]; then
-                has_bsp=false
-                break
-            fi
-          done
-          if [[ $has_bsp == true ]]; then
-            changed_files=$(echo "${changed_files}"| cut -d'/' -f2 | sort -u| tr '\n' ',' | sed 's/,$//')
-            echo "CHANGED_FILES=[${changed_files}]" >> $GITHUB_OUTPUT
-          fi
-          #获取修改文件的路径,如果有bsp以外的文件夹则编译全部bsp,否则获取对应文件夹名
-
-          echo "${changed_files}"
+          fetch-depth: 0
       - name: Filter matrix
       - name: Filter matrix
         id: filter
         id: filter
         run: |
         run: |
-          raw_matrix=$(echo "${{ steps.read-config.outputs.raw_matrix }}" | base64 --decode)
-
-          CHANGED_FILES=${{ steps.changed_files.outputs.CHANGED_FILES }}
-          CHANGED_FILES=$(echo "$CHANGED_FILES" | sed 's/\[\|\]//g')
-          # 将修改的文件路径与ALL_BSP_COMPILE.json文件的SUB_RTT_BSP进行判断,判断是否包含
-          filtered_matrix=[]
-          echo "${CHANGED_FILES}"
-          if [[ -z "$CHANGED_FILES" ]]; then
-              FILTER_CONDITION='.legs[]'
-              filtered_matrix=$(jq -c "{legs: [$FILTER_CONDITION]}" <<< "$raw_matrix")
-          else
-            CONDITIONS=$(echo "$CHANGED_FILES" | awk 'BEGIN { RS="," } { printf "contains(\"%s\") or ", $1 }')
-            CONDITIONS=${CONDITIONS% or }
-
-            FILTER_CONDITION=".legs[] | select(any(.SUB_RTT_BSP[]; $CONDITIONS))"
-
-            filtered_matrix=$(jq -c "{legs: [$FILTER_CONDITION]}" <<< "$raw_matrix")
-          fi
+          git config --global http.postBuffer 524288000
+          git remote -v
+          git fetch origin
+          git branch
+          git branch -a
+          python tools/ci/git_diff_show.py origin/master
+          raw_matrix=$(cat .github/ALL_BSP_COMPILE_TEMP.json)
 
 
+          FILTER_CONDITION='.legs[]'
+          filtered_matrix=$(jq -c "{legs: [$FILTER_CONDITION]}" <<< "$raw_matrix")
           echo "filtered_matrix=${filtered_matrix}" >> $GITHUB_OUTPUT
           echo "filtered_matrix=${filtered_matrix}" >> $GITHUB_OUTPUT
-          
           echo ${filtered_matrix}
           echo ${filtered_matrix}
   build:
   build:
     runs-on: ubuntu-22.04
     runs-on: ubuntu-22.04

+ 0 - 50
.github/workflows/git_diff_status_show.yml

@@ -1,50 +0,0 @@
-#
-# Copyright (c) 2006-2023, RT-Thread Development Team
-#
-# SPDX-License-Identifier: Apache-2.0
-#
-# Change Logs:
-# Date           Author       Notes
-# 2025-05-15     Supper Thomas show the PR size 
-#
-
-name: PR status
-
-# 这个ci主要用来显示当前的PR对于master节点上的增加的code size有多大
-on:
-  pull_request:
-    branches:
-      - master
-
-permissions:
-  contents: read # to fetch code (actions/checkout)
-
-jobs:
-  build:
-    runs-on: ubuntu-24.04
-    name: PR status show
-
-    steps:
-      - uses: actions/checkout@main
-        with:
-          fetch-depth: 0
-      - name: Set up Python
-        uses: actions/setup-python@main
-        with:
-          python-version: 3.8
-
-      - name: fetch origin
-        shell: bash
-        run: |
-          git config --global http.postBuffer 524288000
-          git remote -v
-          git fetch origin
-          git branch
-          git branch -a
-
-      - name: PR status show
-        if: ${{ success() }}
-        shell: bash
-        run: |
-          python tools/ci/git_diff_status_show.py origin/master
-

+ 372 - 0
tools/ci/git_diff_show.py

@@ -0,0 +1,372 @@
+# 
+# Copyright (c) 2025, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Change Logs:
+# Date           Author       Notes
+# 2025-05-15     supperthomas add PR status show
+# 2025-05-22     hydevcode    替换bsp_building.yml的判断文件修改机制,并将PR status show合并进bsp_building.yml
+import subprocess
+import sys
+import os
+import re
+import argparse
+import locale
+from typing import List, Dict
+
+import json
+from typing import List
+class FileDiff:
+    def __init__(self, path: str, status: str, size_change: int = 0, old_size: int = 0, new_size: int = 0):
+        self.path = path
+        self.status = status  # A (added), M (modified), D (deleted), R (renamed)
+        self.size_change = size_change
+        self.old_size = old_size
+        self.new_size = new_size
+        
+    def __str__(self):
+        if self.status == 'A':
+            return f"Added {self.path}: {self.size_change} bytes"
+        elif self.status == 'D':
+            return f"Deleted {self.path}: was {self.old_size} bytes"
+        elif self.status == 'M' or self.status == 'R':
+            return f"Modified {self.path}: {self.size_change} bytes change"
+        else:
+            return f"{self.status} {self.path}"
+            
+class GitDiffAnalyzer:
+    def __init__(self, target_branch: str):
+        self.target_branch = target_branch
+        self.encoding = locale.getpreferredencoding()
+
+    def get_diff_files(self) -> List[FileDiff]:
+        """获取当前分支与目标分支之间的差异文件"""
+        # 找到当前分支和目标分支的最近共同祖先
+        merge_base = self.get_merge_base()
+        if not merge_base:
+            print("No common ancestor found between current branch and target branch")
+            sys.exit(1)
+            
+        # 获取差异文件列表
+        diff_cmd = f"git diff --name-status {merge_base} HEAD"
+        print(diff_cmd)
+        try:
+            output = subprocess.check_output(diff_cmd.split(), stderr=subprocess.STDOUT)
+            output = output.decode(self.encoding).strip()
+            print(output)
+        except subprocess.CalledProcessError as e:
+            print(f"Error executing git diff: {e.output.decode(self.encoding)}")
+            sys.exit(1)
+            
+        if not output:
+            print("No differences between current branch and target branch")
+            sys.exit(0)
+            
+        # 处理可能的换行符问题
+        output = output.replace('\r\n', '\n')
+        lines = output.split('\n')
+        
+        file_diffs = []
+        for line in lines:
+            line = line.strip()
+            if not line:
+                continue
+                
+            parts = line.split('\t')
+            if len(parts) < 2:
+                # 可能是重命名文件,格式为 "RXXX\told_path\tnew_path"
+                match = re.match(r'R(\d+)\t(.+)\t(.+)', line)
+                if match:
+                    status = 'R'
+                    old_path = match.group(2)
+                    new_path = match.group(3)
+                    # 计算重命名文件的修改大小
+                    old_size = self.get_file_size(old_path, self.target_branch)
+                    new_size = self.get_file_size(new_path, 'HEAD')
+                    size_change = new_size - old_size if old_size > 0 else new_size
+                    file_diffs.append(FileDiff(new_path, status, size_change, old_size, new_size))
+            else:
+                status = parts[0][0]  # 取状态码的第一个字符
+                path = parts[1]
+                
+                if status == 'A':
+                    # 新增文件,计算大小
+                    size = self.get_file_size(path, 'HEAD')
+                    file_diffs.append(FileDiff(path, status, size, 0, size))
+                elif status == 'D':
+                    # 删除文件,计算原大小
+                    size = self.get_file_size(path, self.target_branch)
+                    file_diffs.append(FileDiff(path, status, 0, size, 0))
+                elif status == 'M':
+                    # 修改文件,计算大小变化
+                    old_size = self.get_file_size(path, self.target_branch)
+                    new_size = self.get_file_size(path, 'HEAD')
+                    size_change = new_size - old_size
+                    file_diffs.append(FileDiff(path, status, size_change, old_size, new_size))
+                    
+        return file_diffs
+
+    def get_merge_base(self) -> str:
+        """获取当前分支和目标分支的最近共同祖先"""
+        try:
+            cmd = f"git merge-base {self.target_branch} HEAD"
+            print(cmd)
+            output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
+            return output.decode(self.encoding).strip()
+        except subprocess.CalledProcessError as e:
+            print(f"Error executing git merge-base: {e.output.decode(self.encoding)}")
+            return None
+
+    def get_file_size(self, path: str, ref: str) -> int:
+        """获取指定分支上文件的大小"""
+        try:
+            # 使用 git cat-file 来获取文件内容,然后计算其大小
+            cmd = f"git cat-file blob {ref}:{path}"
+            output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
+            return len(output)
+        except subprocess.CalledProcessError:
+            # 如果文件不存在或无法获取,返回0
+            return 0
+
+def format_size(size: int) -> str:
+    """将字节大小转换为人类可读的格式"""
+    if size >= 0:
+        if size < 1024:
+            return f"{size} bytes"
+        elif size < 1024 * 1024:
+            return f"{size / 1024:.1f} KB"
+        elif size < 1024 * 1024 * 1024:
+            return f"{size / (1024 * 1024):.1f} MB"
+        else:
+            return f"{size / (1024 * 1024 * 1024):.1f} GB"
+    else:
+        temp_size=abs(size)
+        if temp_size < 1024:
+            return f"-{temp_size} bytes"
+        elif temp_size < 1024 * 1024:
+            return f"-{temp_size / 1024:.1f} KB"
+        elif temp_size < 1024 * 1024 * 1024:
+            return f"-{temp_size / (1024 * 1024):.1f} MB"
+        else:
+            return f"-{temp_size / (1024 * 1024 * 1024):.1f} GB"
+
+def is_bsp(path):
+    return os.path.isfile(os.path.join(path, "rtconfig.h"))
+
+def filter_bsp_config(file_diffs: List[FileDiff], config_path: str):
+    # 读取原始JSON配置
+    with open(config_path, 'r', encoding='utf-8') as f:
+        config = json.load(f)
+
+    # 获取所有修改的文件路径(统一使用Linux风格路径)
+    modified_paths = [diff.path.replace('\\', '/') for diff in file_diffs]
+    print(modified_paths)
+    if not modified_paths:
+        print("master分支运行")
+        return
+
+    bsp_paths = set()
+    bsp_in_but_not_bsp_paths = set()
+    all_print_paths = set()
+    for modified_path in modified_paths:
+        parts = modified_path.strip(os.sep).split('/')
+        if not parts:
+            continue
+        first_level = parts[0]
+        first_level_path = os.path.join(os.getcwd(), first_level)
+
+        #处理bsp路径的逻辑
+        if first_level == "bsp":
+            temp_path=os.path.join(os.getcwd(), modified_path)
+            # 判断是否是文件
+            if not os.path.isdir(modified_path):
+                temp_path = os.path.dirname(temp_path)
+
+            #循环搜索每一级是否有rtconfig.h
+            while temp_path !=first_level_path:
+                if is_bsp(temp_path):
+                    bsp_paths.add(temp_path)
+        
+                    break
+                temp_path=os.path.dirname(temp_path)
+
+            if temp_path ==first_level_path:
+                bsp_in_but_not_bsp_paths.add(parts[1])
+
+        else:
+            #非bsp路径逻辑
+            all_print_paths.add(first_level_path)
+
+    # 变成相对路径
+    bsp_list = set()
+    for path in sorted(bsp_paths):
+        current_working_dir = os.path.join(os.getcwd(), "bsp/")
+        if path.startswith(current_working_dir):
+            bsp_list.add(path[len(current_working_dir):].lstrip(os.sep))
+        else:
+            bsp_list.add(path)  # 如果 first_level_path 不以 current_working_dir 开头,则保持不变
+
+    # 处理修改了bsp外的文件的情况
+    filtered_bsp = [
+        path for path in bsp_list
+        if path.split('/')[0] not in bsp_in_but_not_bsp_paths
+    ]
+
+    merged_result = filtered_bsp + list(bsp_in_but_not_bsp_paths)
+
+    filtered_legs = []
+    for leg in config["legs"]:
+        matched_paths = [
+            path for path in leg.get("SUB_RTT_BSP", [])
+            if any(keyword in path for keyword in merged_result)
+        ]
+        if matched_paths:
+            filtered_legs.append({**leg, "SUB_RTT_BSP": matched_paths})
+
+    # 生成新的配置
+    new_config = {"legs": filtered_legs}
+
+    # 判断有没有修改到bsp外的文件,有的话则编译全部
+    if not all_print_paths:
+        print(new_config)
+        file_name = ".github/ALL_BSP_COMPILE_TEMP.json"
+
+        # 将 new_config 写入文件
+        with open(file_name, "w", encoding="utf-8") as file:
+            json.dump(new_config, file, ensure_ascii=False, indent=4)
+
+
+def main():
+        # 源文件路径
+    source_file = ".github/ALL_BSP_COMPILE.json"  # 替换为你的文件路径
+
+    # 目标文件路径
+    target_file = ".github/ALL_BSP_COMPILE_TEMP.json"  # 替换为你的目标文件路径
+
+    # 读取源文件并过滤掉带有 // 的行
+    with open(source_file, "r", encoding="utf-8") as infile, open(target_file, "w", encoding="utf-8") as outfile:
+        for line in infile:
+            if not line.lstrip().startswith("//"):
+                outfile.write(line)
+    
+    parser = argparse.ArgumentParser(description='Compare current branch with target branch and show file differences.')
+    parser.add_argument('target_branch', help='Target branch to compare against (e.g., master)')
+    args = parser.parse_args()
+    
+    analyzer = GitDiffAnalyzer(args.target_branch)
+    file_diffs = analyzer.get_diff_files()
+
+    # 生成报告
+    generate_report(file_diffs, args.target_branch)
+
+    filter_bsp_config(file_diffs,".github/ALL_BSP_COMPILE_TEMP.json")
+
+    
+def add_summary(text):
+    """
+    add summary to github action.
+    """
+    if "GITHUB_STEP_SUMMARY" in os.environ:
+        summary_path = os.environ["GITHUB_STEP_SUMMARY"]  # 获取摘要文件路径
+
+        # 将 text 写入摘要文件(追加模式)
+        with open(summary_path, "a") as f:  # "a" 表示追加模式
+            f.write(text + "\n")  # 写入文本并换行
+    else:
+        print("Environment variable $GITHUB_STEP_SUMMARY is not set.")
+
+def summarize_diff(label, count, size=None):
+    """格式化输出变更摘要"""
+    line = f"  {label:<12} {count:>3} files"
+    if size is not None:
+        line += f" ({format_size(size)})"
+    add_summary(line)
+
+def generate_report(file_diffs: List[FileDiff], target_branch: str):
+    """生成差异报告"""
+
+    add_summary(f"# 📊 **Comparison between {target_branch} and Current Branch**\n")
+    
+    # 分类统计
+    added_files         = [f for f in file_diffs if f.status.startswith('A')]
+    removed_files       = [f for f in file_diffs if f.status.startswith('D')]
+    modified_files      = [f for f in file_diffs if f.status.startswith('M')]
+    renamed_files       = [f for f in file_diffs if f.status.startswith('R')]
+    copied_files        = [f for f in file_diffs if f.status.startswith('C')]
+    unmerged_files      = [f for f in file_diffs if f.status.startswith('U')]
+    type_changed_files  = [f for f in file_diffs if f.status.startswith('T')]
+    
+    # 计算总变化量
+    total_added         = sum(f.size_change for f in added_files)
+    total_removed       = sum(f.old_size for f in removed_files)
+    total_modified      = sum(f.size_change for f in modified_files)
+    total_copied        = sum(f.size_change for f in copied_files)
+    total_renamed       = sum(f.old_size for f in renamed_files)
+    total_type_changed  = sum(f.size_change for f in type_changed_files)
+
+    total_size_change   = sum(f.size_change for f in file_diffs)
+    # === 汇总输出 ===
+    summarize_diff("Total:", len(file_diffs))
+    summarize_diff("Added:", len(added_files), total_added)
+    summarize_diff("Removed:", len(removed_files), total_removed)
+    summarize_diff("Modified:", len(modified_files), total_modified)
+    summarize_diff("Renamed:", len(renamed_files), total_renamed)
+    summarize_diff("Copied:", len(copied_files), total_copied)
+    summarize_diff("Type Changed:", len(type_changed_files), total_type_changed)
+    summarize_diff("Unmerged:", len(unmerged_files))
+
+
+    if total_size_change > 0:
+        change_desc = f"📈 **Increase of {format_size(total_size_change)}**"
+    elif total_size_change < 0:
+        change_desc = f"📉 **Reduction of {format_size(abs(total_size_change))}**"
+    else:
+        change_desc = "➖ **No net size change**"
+
+    add_summary(f"\n### 📦 **Total Size Change:** {change_desc} (Excluding removed files)")
+
+    
+    # 显示详细差异文件内容
+    add_summary("\n## 📂 **Detailed File Changes**\n")
+
+    for diff in file_diffs:
+        add_summary(f"📄 {diff.path} —  **[{diff.status}]**")
+
+        # 文件状态处理
+        if diff.status.startswith('A'):
+            add_summary(f"📦 Size: {format_size(diff.new_size)}")
+
+        elif diff.status.startswith(('M', 'R')):  # 修改或重命名
+            add_summary(f"📏 Original size: {format_size(diff.old_size)}")
+            add_summary(f"📐 New size: {format_size(diff.new_size)}")
+
+            delta = diff.size_change
+            if delta > 0:
+                change_str = f"📈 Increased by {format_size(delta)}"
+            elif delta < 0:
+                change_str = f"📉 Reduced by {format_size(abs(delta))}"
+            else:
+                change_str = "➖ No size change"
+
+            add_summary(f"📊 Size change: {change_str}")
+
+        elif diff.status.startswith('D'):
+            add_summary(f"🗑️ Original size: {format_size(diff.old_size)}")
+
+        elif diff.status.startswith('C'):
+            add_summary(f"📎 Copied from size: {format_size(diff.old_size)} → {format_size(diff.new_size)}")
+
+        elif diff.status.startswith('T'):
+            add_summary("⚙️ File type changed")
+
+        elif diff.status.startswith('U'):
+            add_summary("⚠️ Unmerged conflict detected")
+
+        else:
+            add_summary("❓ Unknown change type")
+
+        add_summary("\n\n")
+
+if __name__ == "__main__":
+    main()

+ 0 - 201
tools/ci/git_diff_status_show.py

@@ -1,201 +0,0 @@
-# 
-# Copyright (c) 2025, RT-Thread Development Team
-#
-# SPDX-License-Identifier: Apache-2.0
-#
-# Change Logs:
-# Date           Author       Notes
-# 2025-05-15     supperthomas add PR status show
-#
-#!/usr/bin/env python3
-import subprocess
-import sys
-import os
-import re
-import argparse
-import locale
-from typing import List, Dict
-
-class FileDiff:
-    def __init__(self, path: str, status: str, size_change: int = 0, old_size: int = 0, new_size: int = 0):
-        self.path = path
-        self.status = status  # A (added), M (modified), D (deleted), R (renamed)
-        self.size_change = size_change
-        self.old_size = old_size
-        self.new_size = new_size
-        
-    def __str__(self):
-        if self.status == 'A':
-            return f"Added {self.path}: {self.size_change} bytes"
-        elif self.status == 'D':
-            return f"Deleted {self.path}: was {self.old_size} bytes"
-        elif self.status == 'M' or self.status == 'R':
-            return f"Modified {self.path}: {self.size_change} bytes change"
-        else:
-            return f"{self.status} {self.path}"
-            
-class GitDiffAnalyzer:
-    def __init__(self, target_branch: str):
-        self.target_branch = target_branch
-        self.encoding = locale.getpreferredencoding()
-
-    def get_diff_files(self) -> List[FileDiff]:
-        """获取当前分支与目标分支之间的差异文件"""
-        # 找到当前分支和目标分支的最近共同祖先
-        merge_base = self.get_merge_base()
-        if not merge_base:
-            print("No common ancestor found between current branch and target branch")
-            sys.exit(1)
-            
-        # 获取差异文件列表
-        diff_cmd = f"git diff --name-status {merge_base} "
-        print(diff_cmd)
-        try:
-            output = subprocess.check_output(diff_cmd.split(), stderr=subprocess.STDOUT)
-            output = output.decode(self.encoding).strip()
-            print(output)
-        except subprocess.CalledProcessError as e:
-            print(f"Error executing git diff: {e.output.decode(self.encoding)}")
-            sys.exit(1)
-            
-        if not output:
-            print("No differences between current branch and target branch")
-            sys.exit(0)
-            
-        # 处理可能的换行符问题
-        output = output.replace('\r\n', '\n')
-        lines = output.split('\n')
-        
-        file_diffs = []
-        for line in lines:
-            line = line.strip()
-            if not line:
-                continue
-                
-            parts = line.split('\t')
-            if len(parts) < 2:
-                # 可能是重命名文件,格式为 "RXXX\told_path\tnew_path"
-                match = re.match(r'R(\d+)\t(.+)\t(.+)', line)
-                if match:
-                    status = 'R'
-                    old_path = match.group(2)
-                    new_path = match.group(3)
-                    # 计算重命名文件的修改大小
-                    old_size = self.get_file_size(old_path, self.target_branch)
-                    new_size = self.get_file_size(new_path, 'HEAD')
-                    size_change = new_size - old_size if old_size > 0 else new_size
-                    file_diffs.append(FileDiff(new_path, status, size_change, old_size, new_size))
-            else:
-                status = parts[0][0]  # 取状态码的第一个字符
-                path = parts[1]
-                
-                if status == 'A':
-                    # 新增文件,计算大小
-                    size = self.get_file_size(path, 'HEAD')
-                    file_diffs.append(FileDiff(path, status, size, 0, size))
-                elif status == 'D':
-                    # 删除文件,计算原大小
-                    size = self.get_file_size(path, self.target_branch)
-                    file_diffs.append(FileDiff(path, status, 0, size, 0))
-                elif status == 'M':
-                    # 修改文件,计算大小变化
-                    old_size = self.get_file_size(path, self.target_branch)
-                    new_size = self.get_file_size(path, 'HEAD')
-                    size_change = new_size - old_size
-                    file_diffs.append(FileDiff(path, status, size_change, old_size, new_size))
-                    
-        return file_diffs
-
-    def get_merge_base(self) -> str:
-        """获取当前分支和目标分支的最近共同祖先"""
-        try:
-            cmd = f"git merge-base {self.target_branch} HEAD"
-            print(cmd)
-            output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
-            return output.decode(self.encoding).strip()
-        except subprocess.CalledProcessError as e:
-            print(f"Error executing git merge-base: {e.output.decode(self.encoding)}")
-            return None
-
-    def get_file_size(self, path: str, ref: str) -> int:
-        """获取指定分支上文件的大小"""
-        try:
-            # 使用 git cat-file 来获取文件内容,然后计算其大小
-            cmd = f"git cat-file blob {ref}:{path}"
-            output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
-            return len(output)
-        except subprocess.CalledProcessError:
-            # 如果文件不存在或无法获取,返回0
-            return 0
-
-def format_size(size: int) -> str:
-    """将字节大小转换为人类可读的格式"""
-    if size < 1024:
-        return f"{size} bytes"
-    elif size < 1024 * 1024:
-        return f"{size / 1024:.1f} KB"
-    elif size < 1024 * 1024 * 1024:
-        return f"{size / (1024 * 1024):.1f} MB"
-    else:
-        return f"{size / (1024 * 1024 * 1024):.1f} GB"
-
-def main():
-    parser = argparse.ArgumentParser(description='Compare current branch with target branch and show file differences.')
-    parser.add_argument('target_branch', help='Target branch to compare against (e.g., master)')
-    args = parser.parse_args()
-    
-    analyzer = GitDiffAnalyzer(args.target_branch)
-    file_diffs = analyzer.get_diff_files()
-    
-    # 生成报告
-    generate_report(file_diffs, args.target_branch)
-    
-
-        
-def generate_report(file_diffs: List[FileDiff], target_branch: str):
-    """生成差异报告"""
-    print(f"\n=== Comparison between {target_branch} and current branch ===\n")
-    
-    # 分类统计
-    added_files = [f for f in file_diffs if f.status == 'A']
-    removed_files = [f for f in file_diffs if f.status == 'D']
-    modified_files = [f for f in file_diffs if f.status == 'M']
-    renamed_files = [f for f in file_diffs if f.status == 'R']
-    
-    # 计算总变化量
-    total_added = sum(f.size_change for f in added_files)
-    total_removed = sum(f.old_size for f in removed_files)
-    total_modified = sum(abs(f.size_change) for f in modified_files)
-    # 计算总的大小变化
-    total_size_change = sum(f.size_change for f in file_diffs)
-
-    print(f"Total changes: {len(file_diffs)} files")
-    print(f"Added: {len(added_files)} files ({format_size(total_added)})")
-    print(f"Removed: {len(removed_files)} files ({format_size(total_removed)})")
-    print(f"Modified: {len(modified_files)} files ({format_size(total_modified)})")
-    print(f"Renamed: {len(renamed_files)} files")
-    print(f"\nTotal size change: {format_size(total_size_change)}")
-    print("\n" + "="*60 + "\n")
-    
-    # 显示详细差异
-    for diff in file_diffs:
-        print(diff)
-        
-        # 详细展示修改和新增的文件大小
-        if diff.status == 'A':
-            print(f"  Size: {format_size(diff.new_size)}")
-        elif diff.status == 'M':
-            print(f"  Original size: {format_size(diff.old_size)}")
-            print(f"  New size: {format_size(diff.new_size)}")
-            print(f"  Size change: {format_size(abs(diff.size_change))}")
-        elif diff.status == 'R':
-            print(f"  Original size: {format_size(diff.old_size)}")
-            print(f"  New size: {format_size(diff.new_size)}")
-            print(f"  Size change: {format_size(abs(diff.size_change))}")
-        elif diff.status == 'D':
-            print(f"  Original size: {format_size(diff.old_size)}")
-            
-        print("-" * 50)
-
-if __name__ == "__main__":
-    main()