forked from yyjeqhc/spec-formatter
This branch is 13 commits behind yyjeqhc/spec-formatter:main
Spec Formatter
一个用 Rust 编写的高性能 RPM spec 文件格式化和规范化工具,支持按区域分别处理头部定义和脚本/文件区段。
功能特性
1. 智能格式化
- 统一头部: 自动添加 SPDX 标准的文件头部(从现有文件提取贡献者信息或使用配置默认值)
- 统一尾部: 自动添加标准的
%changelog结尾,防止重复格式化时空行累积 - 字段对齐:
- 主要字段内容统一从第 16 列开始(Name、Version、Release、License、URL、Source0、BuildRequires、Requires 等)
- BuildOption 后固定 2 个空格
- %package 行特殊间距规则(
-n参数 5 个空格) - %description 行特殊间距规则
- 自动添加 RemoteAsset: 在 URL 和第一个 Source 之间自动插入
#!RemoteAsset标记 - %description 前空行: 确保每个 %description 前有一个空行
- Tab 转换: 自动将 Tab 转换为 4 个空格
2. 区域化处理
- 头部定义区(从开始到最后一个 %description 后):
- 应用格式化规则
- 对齐字段
- 应用依赖替换
- 拆分多依赖行(BuildRequires)
- 脚本/文件区(%prep、%build、%install、%files 等):
- 保持原始格式,不进行对齐
- 仅在 %files 区段应用路径替换
3. 字符串替换(scope 支持)
- dependencies(默认): 只在 BuildRequires/Requires 行生效
- 包名替换(如
ninja-build→ninja) - devel 包转 pkgconfig(如
libxml2-devel→pkgconfig(libxml-2.0)) - 正则表达式替换(如
qt6-qt*→qt6-*)
- 包名替换(如
- files: 只在 %files 区段生效
- 路径变量替换(如
_qt6_headerdir→_qt6_includedir) - 确保不影响其他区域的宏变量
- 路径变量替换(如
- all: 全局替换(谨慎使用)
- skip_lines: 支持条件跳过(如跳过 Provides: 行)
4. 行删除
- 全局删除匹配的行(在区域分离前执行)
- 支持正则表达式和字符串匹配
- 常见用例:
- 删除过时的
%ldconfig_scriptlets - 删除不规范的
Group:字段
- 删除过时的
5. 固定替换
- Release 行固定替换为
Release: %autorelease - 跳过已经是正确格式的行
6. 多依赖拆分
- 自动将 BuildRequires 中多个空格分隔的包名拆分为多行
- 智能处理版本比较符(>=、<=、==)
- 只处理 BuildRequires,不拆分 Requires(保留版本约束)
安装
从源码编译
cd spec-formatter
cargo build --release
sudo cp target/release/spec-formatter /usr/local/bin/
安装配置文件
sudo mkdir -p /etc/spec-formatter
sudo cp config.yaml /etc/spec-formatter/
或者放到用户目录:
mkdir -p ~/.config/spec-formatter
cp config.yaml ~/.config/spec-formatter/
使用方法
基本用法
处理当前目录下的所有 .spec 文件:
spec-formatter
处理指定的文件或目录:
spec-formatter /path/to/file.spec
spec-formatter /path/to/specs/
spec-formatter *.spec
指定配置文件
spec-formatter --config ~/.config/spec-formatter/config.yaml file.spec
spec-formatter -c /path/to/custom-config.yaml *.spec
在 Git Hook 中使用
在 .git/hooks/pre-commit 中:
#!/bin/bash
spec-formatter --config ~/.config/spec-formatter/config.yaml $(git diff --cached --name-only --diff-filter=ACM | grep '\.spec$')
配置文件
配置文件搜索路径(按优先级):
- 命令行指定的
--config路径(如果提供) - 可执行文件所在目录的
spec-formatter.yaml或config.yaml - 当前工作目录的
spec-formatter.yaml或config.yaml /etc/spec-formatter/config.yaml(系统配置)
配置示例
# 作者信息(用于 SPDX-FileContributor)
contributor: "Your Name <your.email@example.com>"
# 字符串替换规则
replacements:
# === 依赖包替换(默认 scope: dependencies,只在 BuildRequires/Requires 行生效) ===
- pattern: "ninja-build"
replace: "ninja"
skip_lines: []
# 正则表达式替换
- pattern: "qt6-qt([a-z]+)"
replace: "qt6-$1"
skip_lines: ["Provides:"]
is_regex: true
# devel 包转 pkgconfig
- pattern: "libxml2-devel"
replace: "pkgconfig(libxml-2.0)"
skip_lines: []
# === 文件路径替换(scope: files,只在 %files 区段生效) ===
- pattern: "_qt6_headerdir"
replace: "_qt6_includedir"
scope: "files"
skip_lines: []
# 删除规则(全局生效)
deletions:
# 正则表达式删除(行首可选空格 + 可选% + ldconfig_scriptlets)
- pattern: "^\\s*%?ldconfig_scriptlets"
is_regex: true
# 字符串删除(行中包含即删除)
- pattern: "Group:"
is_regex: true
# 固定替换规则(完全替换整行)
fixed_replacements:
- pattern: "^Release:.*$"
replace: "Release: %autorelease"
is_regex: true
# 格式化配置
formatting:
# 对齐基准字段
align_base: "BuildSystem:"
# 基准字段后的空格数
base_spacing: 4
# BuildOption 后的空格数
build_option_spacing: 2
# 需要对齐的字段(内容从第 16 列开始)
align_fields:
- "Name:"
- "Version:"
- "Release:"
- "Summary:"
- "License:"
- "URL:"
- "Source0:"
- "BuildSystem:"
- "BuildRequires:"
- "Requires:"
- "Provides:"
- "BuildArch:"
# Source/Patch 字段对齐
source_patch_align: true
配置说明
替换规则(replacements)
- pattern: 要匹配的字符串或正则表达式
- replace: 替换后的字符串(支持正则捕获组,如
$1) - scope: 作用范围
dependencies(默认):只在 BuildRequires/Requires 行生效files:只在 %files 区段生效all:全局生效(谨慎使用)
- skip_lines: 跳过包含这些前缀的行
- is_regex: 是否为正则表达式(默认 false)
删除规则(deletions)
- pattern: 匹配模式
- is_regex:
true: 正则匹配整行false: 字符串匹配(行中包含即删除)
输出示例
正在处理文件: example.spec
==================================================
原始行: BuildRequires: ninja-build
修改为: BuildRequires: ninja
---
原始行: BuildRequires: libxml2-devel
修改为: BuildRequires: pkgconfig(libxml-2.0)
---
删除行: %ldconfig_scriptlets
---
✓ 文件处理完成,共 3 处修改
==================================================
注意事项
- 备份重要文件: 工具会直接修改文件,建议在 Git 仓库中使用或先备份
- 配置文件语法: YAML 格式,注意缩进和特殊字符转义(如正则中的
\要写成\\) - scope 设置:
- 依赖替换默认不需要写
scope - 路径替换必须设置
scope: "files"
- 依赖替换默认不需要写
- 重复格式化: 工具设计为幂等的,多次运行结果一致(不会累积空行)
- %files 区段: 只替换路径变量,不进行格式化对齐,保持原始结构
开发
构建
cargo build
cargo run -- test.spec
测试
cargo test
许可证
MulanPSL-2.0
Description
Languages
Rust
96.3%
Shell
3.7%