跳转至

repo-scan

每个生态系统都有自己的依赖管理器,但没有工具能够跨 C++、Android、iOS、Web 告诉你“哪些代码真正属于自己,哪些是第三方代码,哪些是多余的负担”。

适用场景

  • 需要接手大型遗留代码库并掌握整体结构时
  • 大规模重构之前——识别核心代码、重复代码和废弃代码
  • 审计未通过包管理器声明、直接嵌入源码的第三方依赖
  • 为单体仓库重组准备架构决策记录

安装

# Clone first so the pinned commit can be reviewed before installation
set -euo pipefail

REPO_SCAN_COMMIT=2742664ebcad1450c208eda0ae45d3c17fad5dd8
REPO_SCAN_INSTALL_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills/repo-scan"
REPO_SCAN_INSTALL_PARENT="$(dirname "$REPO_SCAN_INSTALL_DIR")"
mkdir -p "$REPO_SCAN_INSTALL_PARENT"
REPO_SCAN_TMP="$(mktemp -d "$REPO_SCAN_INSTALL_PARENT/.repo-scan-install.XXXXXX")"
REPO_SCAN_TOKEN="${REPO_SCAN_TMP##*.}"
REPO_SCAN_STAGE="$REPO_SCAN_TMP/stage-$REPO_SCAN_TOKEN"
REPO_SCAN_BACKUP="$REPO_SCAN_TMP/backup-$REPO_SCAN_TOKEN"
REPO_SCAN_LOCK="$REPO_SCAN_INSTALL_PARENT/.repo-scan-install.lock"
REPO_SCAN_KEEP_TMP=0
REPO_SCAN_LOCK_HELD=0
REPO_SCAN_MV_HAS_NO_TARGET=0
cleanup_repo_scan_install() {
  if [ "$REPO_SCAN_KEEP_TMP" -eq 0 ]; then
    rm -rf -- "$REPO_SCAN_TMP"
  fi
  if [ "$REPO_SCAN_LOCK_HELD" -eq 1 ] && ! rmdir -- "$REPO_SCAN_LOCK"; then
    printf 'Could not release installation lock at %s\n' "$REPO_SCAN_LOCK" >&2
  fi
}
trap cleanup_repo_scan_install EXIT
mkdir "$REPO_SCAN_TMP/mv-probe-source"
if mv -T -- "$REPO_SCAN_TMP/mv-probe-source" \
  "$REPO_SCAN_TMP/mv-probe-destination" 2>/dev/null; then
  REPO_SCAN_MV_HAS_NO_TARGET=1
  rmdir "$REPO_SCAN_TMP/mv-probe-destination"
else
  rmdir "$REPO_SCAN_TMP/mv-probe-source"
fi
move_repo_scan_dir() {
  REPO_SCAN_MOVE_SOURCE=$1
  REPO_SCAN_MOVE_DESTINATION=$2
  REPO_SCAN_MOVE_NAME=${REPO_SCAN_MOVE_SOURCE##*/}
  if [ -e "$REPO_SCAN_MOVE_DESTINATION" ] || [ -L "$REPO_SCAN_MOVE_DESTINATION" ]; then
    return 1
  fi
  if [ "$REPO_SCAN_MV_HAS_NO_TARGET" -eq 1 ]; then
    mv -T -- "$REPO_SCAN_MOVE_SOURCE" "$REPO_SCAN_MOVE_DESTINATION"
    return
  fi
  if ! mv -- "$REPO_SCAN_MOVE_SOURCE" "$REPO_SCAN_MOVE_DESTINATION"; then
    return 1
  fi
  if [ -e "$REPO_SCAN_MOVE_DESTINATION/$REPO_SCAN_MOVE_NAME" ] || \
    [ -L "$REPO_SCAN_MOVE_DESTINATION/$REPO_SCAN_MOVE_NAME" ]; then
    if ! mv -- "$REPO_SCAN_MOVE_DESTINATION/$REPO_SCAN_MOVE_NAME" \
      "$REPO_SCAN_MOVE_SOURCE"; then
      REPO_SCAN_KEEP_TMP=1
      printf 'Move conflict recovery failed; staged data remains at %s\n' \
        "$REPO_SCAN_MOVE_DESTINATION/$REPO_SCAN_MOVE_NAME" >&2
    fi
    return 1
  fi
}

git clone --filter=blob:none --no-checkout \
  https://github.com/haibindev/repo-scan.git "$REPO_SCAN_TMP/source"
git -C "$REPO_SCAN_TMP/source" checkout --detach "$REPO_SCAN_COMMIT"
mkdir -p "$REPO_SCAN_STAGE"
git -C "$REPO_SCAN_TMP/source" archive "$REPO_SCAN_COMMIT" | \
  tar -xf - -C "$REPO_SCAN_STAGE"

# Review "$REPO_SCAN_TMP/source" before approving installation.
printf 'Type install to replace %s after reviewing the pinned source: ' \
  "$REPO_SCAN_INSTALL_DIR" >&2
read -r REPO_SCAN_CONFIRM
if [ "$REPO_SCAN_CONFIRM" != install ]; then
  printf 'Installation cancelled.\n' >&2
  exit 1
fi
if ! mkdir -- "$REPO_SCAN_LOCK" 2>/dev/null; then
  printf 'Another repo-scan installation holds the lock at %s\n' \
    "$REPO_SCAN_LOCK" >&2
  exit 1
fi
REPO_SCAN_LOCK_HELD=1

if [ -e "$REPO_SCAN_INSTALL_DIR" ] || [ -L "$REPO_SCAN_INSTALL_DIR" ]; then
  move_repo_scan_dir "$REPO_SCAN_INSTALL_DIR" "$REPO_SCAN_BACKUP"
fi
if ! move_repo_scan_dir "$REPO_SCAN_STAGE" "$REPO_SCAN_INSTALL_DIR"; then
  if [ -e "$REPO_SCAN_BACKUP" ] || [ -L "$REPO_SCAN_BACKUP" ]; then
    if [ -e "$REPO_SCAN_INSTALL_DIR" ] || [ -L "$REPO_SCAN_INSTALL_DIR" ]; then
      REPO_SCAN_KEEP_TMP=1
      printf 'Replacement failed and target was recreated; previous installation preserved at %s\n' \
        "$REPO_SCAN_BACKUP" >&2
    elif ! move_repo_scan_dir "$REPO_SCAN_BACKUP" "$REPO_SCAN_INSTALL_DIR"; then
      REPO_SCAN_KEEP_TMP=1
      printf 'Replacement and rollback failed; previous installation preserved at %s\n' \
        "$REPO_SCAN_BACKUP" >&2
    fi
  fi
  exit 1
fi

在安装代理技能之前,请审查源代码。

安装后,请重新加载代理框架,然后再次调用 repo-scan。此 ECC 指针仅安装外部技能,不会执行扫描本身。

核心功能

功能 说明
跨栈扫描 一次性扫描 C/C++、Java/Android、iOS(OC/Swift)、Web(TS/JS/Vue)
文件分类 将每个文件标记为项目代码、第三方代码或构建产物
库检测 识别 50 多个已知库(FFmpeg、Boost、OpenSSL…)并提取版本号
4 级判定 核心资产 / 提取整合 / 重建 / 废弃
HTML 报告 支持层级下钻导航的交互式深色主题页面
单体仓库支持 通过层级扫描生成摘要 + 子项目报告

分析深度级别

级别 读取文件数 适用场景
fast 每个模块 1〜2 个 快速盘点大型目录
standard 每个模块 2〜5 个 默认审计,完整依赖 + 架构检查
deep 每个模块 5〜10 个 额外检查线程安全性、内存管理和 API 一致性
full 所有文件 合并前的全面审查

工作原理

  1. 分类仓库表面:列出文件,并将每个文件标记为项目代码、嵌入式第三方代码或构建产物。
  2. 检测嵌入式库:检查目录名、头文件、许可证文件和版本标记,识别捆绑的依赖项及其可能的版本。
  3. 为每个模块评分:将文件分组为模块或子系统,并基于所有权、重复度和维护成本分配四种判定之一。
  4. 突出结构性风险:指出冗余产物、重复的包装器、过时的供应商代码,以及应提取、重建或废弃的模块。
  5. 生成报告:返回简洁摘要和交互式 HTML 输出,可通过按模块下钻异步审查审计结果。

示例

在一个包含 50,000 个文件的 C++ 单体仓库中:

  • 发现仍在使用的 FFmpeg 2.x(2015 年版)
  • 发现同一个 SDK 包装器重复了 3 次
  • 识别出 636 MB 已提交的 Debug/ipch/obj 构建产物
  • 分类结果:3 MB 项目代码 vs 596 MB 第三方代码

最佳实践

  • 首次审计从 standard 深度开始
  • 对于包含 100 个以上模块的单体仓库,使用 fast 快速盘点
  • 对标记为需要重构的模块逐步执行 deep
  • 审查跨模块分析结果,检测子项目之间的重复代码

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC