repo-scan 是做什么的?
每个生态系统都有自己的依赖管理器,但没有任何工具能够跨 C++、Android、iOS 和 Web 告诉你:真正属于你的代码有多少,哪些是第三方的,哪些是多余的负担。
何时使用
- 接手大型遗留代码库,需要结构概览
- 在进行重大重构之前——识别核心代码、重复代码和无用代码
- 审计直接嵌入在源码中的第三方依赖(而非在包管理器中声明)
- 为单体仓库重组准备架构决策记录
安装
# 先克隆,以便在安装前审查固定的提交
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 '无法释放安装锁 %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 '移动冲突恢复失败;暂存数据仍保留在 %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"
# 在批准安装前审查 "$REPO_SCAN_TMP/source"。
printf '输入 install 以在审查固定源后替换 %s:' \
"$REPO_SCAN_INSTALL_DIR" >&2
read -r REPO_SCAN_CONFIRM
if [ "$REPO_SCAN_CONFIRM" != install ]; then
printf '安装已取消。\n' >&2
exit 1
fi
if ! mkdir -- "$REPO_SCAN_LOCK" 2>/dev/null; then
printf '另一个 repo-scan 安装持有锁 %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 '替换失败且目标已重新创建;之前的安装保留在 %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 '替换和回滚均失败;之前的安装保留在 %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…)并提取版本 |
| 四级判定 | 核心资产 / 提取合并 / 重新构建 / 弃用 |
| HTML 报告 | 交互式深色主题页面,支持钻取导航 |
| 单体仓库支持 | 分层扫描,提供摘要 + 子项目报告 |
分析深度级别
| 级别 | 读取文件数 | 用例 |
|---|---|---|
fast | 每个模块 1-2 个 | 大型目录的快速盘点 |
standard | 每个模块 2-5 个 | 默认审计,包含完整的依赖和架构检查 |
deep | 每个模块 5-10 个 | 增加线程安全、内存管理、API 一致性检查 |
full | 所有文件 | 合并前的全面审查 |
工作原理
- 分类代码库表面:枚举文件,然后将每个文件标记为项目代码、嵌入的第三方代码或构建产物。
- 检测嵌入的库:检查目录名称、头文件、许可证文件和版本标记,以识别捆绑的依赖项及其可能版本。
- 为每个模块评分:将文件按模块或子系统分组,然后根据所有权、重复和维护成本分配四种判定之一。
- 突出结构风险:指出无用的构建产物、重复的包装器、过时的供应商代码以及应提取、重建或弃用的模块。
- 生成报告:返回简洁的摘要以及交互式 HTML 输出,支持每个模块的钻取,以便异步审查审计结果。
示例
在一个包含 50,000 个文件的 C++ 单体仓库上:
- 发现仍处于生产环境的 FFmpeg 2.x(2015 年版本)
- 发现同一个 SDK 包装器重复了 3 次
- 识别出 636 MB 已提交的 Debug/ipch/obj 构建产物
- 分类:3 MB 项目代码 vs 596 MB 第三方代码
最佳实践
- 首次审计从
standard深度开始 - 对于超过 100 个模块的单体仓库,使用
fast进行快速盘点 - 对标记为重构的模块增量运行
deep - 审查跨模块分析,以检测子项目间的重复