Apache Gump live r1939132 元数据与命令详解
详解 Apache Gump live r1939132 的元数据对象模型与命令体系:workspace/module/project/repository 四类 XML 的 DTD 属性表与实测校验行为、metadata/validate 校验工具链逐段解析、./gump 包装脚本与 bin/integrate.py 命令行选项实测回显,并如实记录 DTD 与实现不同步、check_env_pylib 的 Python 2 遗留缺陷等发现。
Apache Gump live r1939132 元数据与命令详解
目标:把 Gump 的两套核心语法讲透——元数据 XML(workspace/module/project/repository 四类对象,以官方 DTD 为准逐属性说明)与命令体系(
./gump包装脚本、bin/*.py独立入口、metadata/validate校验工具链),全部属性与回显以 r1939132 快照实测为准,如实记录 DTD 与实现之间已实测确认的不同步点;本文在 Ubuntu 22.04 + Python 3.10.12 上实测通过。
Gump 的全部行为由元数据驱动:workspace 回答「这一轮跑什么」,module/project 回答「项目怎么取、怎么建、谁依赖谁」,repository 回答「代码从哪来」。四类对象各有 DTD(metadata/dtd/),官方自带的校验脚本用 xmllint 强校验。命令体系分三层:Bash 包装脚本 ./gump(服务端视角的 run/test/validate)、Python 独立入口 bin/*.py(integrate/update/build 等)、以及被前两者调用的校验脚本。读懂这两套语法,就能给自己的项目写元数据并验证。
一、环境信息
- 组件:Apache Gump live,SVN r1939132(2026-08-31 提交);元数据与源码同仓库经
svn:externals检出 - 参考系统:Ubuntu 22.04.5 LTS,Python 3.10.12,xmllint libxml 20913,xsltproc libxslt 10134(CentOS 8 + Python 3.6.8 实测结论一致,见第 2 篇)
- 源码目录:
/root/gump;元数据目录:/root/gump/metadata/
官方仓库自带的元数据规模(实时统计):
ls /root/gump/metadata/project/*.xml | wc -l
grep -c "<module " /root/gump/metadata/profile/gump.xml
grep -c "<project " /root/gump/metadata/profile/gump.xml
grep -c "<repository " /root/gump/metadata/profile/gump.xml
72
70
28
16
解读:metadata/project/ 下有 72 个项目定义文件;官方主 profile(profile/gump.xml)通过 href 引用聚合了 70 个 module、28 个直接 project、16 个 repository。本文的自定义示例沿用第 3 篇的 /root/gump-meta-test 工作区。
二、元数据对象模型总览
2.1 四类对象与职责
| 对象 | 文件位置 | 职责 | 对应 DTD |
|---|---|---|---|
| workspace | 自定义(通常 metadata/<主机名>.xml) | 一轮运行的范围、产物目录、运行参数 | workspace.dtd |
| repository | metadata/repository/*.xml | 代码托管源(GitBox/SVN/GitHub 等类型的站点定义) | repository.dtd |
| module | metadata/project/*.xml | 一个可检出的仓库单元,内含一至多个 project | project.dtd |
| project | module 内的 <project> 元素 | 构建与依赖的最小单位(buildable 单元) | project.dtd |
2.2 引用关系与解析顺序
实测确认的解析链:workspace 通过 <module href>/<repository href> 引入元数据文件;module 通过 <git repository="..."> 等元素的 repository 属性关联 repository 定义;project 通过 <depend project="..."> 的名称引用其他 project(跨模块亦可)。第 3 篇的加载自检输出即为证据——workspace 名称、模块、项目、依赖边全部还原。
2.3 DTD 文件与元素规模
ls /root/gump/metadata/dtd/
profile.dtd
project.dtd
README.txt
repository.dtd
workspace.dtd
project.dtd 是最大的一份,含 47 个元素(实测统计),覆盖 module/project 外层定义、8 种构建器、2 种依赖、产物与杂项元素,详见下文第四、五节。
三、workspace.xml 详解
3.1 DTD 属性表(实测取自 workspace.dtd)
<!ATTLIST workspace
name CDATA #REQUIRED
VERSION CDATA #REQUIRED
basedir CDATA #IMPLIED
pkgdir CDATA #IMPLIED
logdir CDATA #IMPLIED
cvsdir CDATA #IMPLIED
jardir CDATA #IMPLIED
sync CDATA #IMPLIED
bootclass CDATA #IMPLIED
makeCommand CDATA #IMPLIED
mvnRepoProxyPort CDATA #IMPLIED>
| 属性 | 必填 | 含义 | 实测说明 |
|---|---|---|---|
| name | 是 | 运行名 | 出现在 Run GUID 中(第 3 篇实测 gump-ubuntu:mytest:20261015084708) |
| VERSION | 是 | workspace 语法版本 | 见 3.2 大小写专项实测 |
| basedir | 否 | 源码检出根目录 | 相对路径实测按 $GUMP_HOME 解析,产物落 /root/gump/work*/ |
| pkgdir / jardir / logdir | 否 | 包/Jar/日志目录 | logdir 即日志站生成位置 |
| cvsdir | 否 | SCM 工作区 | 实测 git 检出落在 workspace/cvs/<模块名> |
| sync / bootclass / makeCommand / mvnRepoProxyPort | 否 | 同步开关/引导类路径/make 命令名/Maven 仓库代理端口 | 本文未使用,低频维护属性 |
3.2 version 大小写专项实测(重要)
DTD 声明大写 VERSION(#REQUIRED),但官方样例与 Python 实现均用小写。两种写法的实测行为:
sed -e "2i\\
<!DOCTYPE workspace SYSTEM \"dtd/workspace.dtd\">" < /root/gump/metadata/minimal-workspace.xml > ws-check.xml
xmllint --valid --noout ws-check.xml 2>&1 | head -3
ws-check.xml:8: element workspace: validity error : Element workspace does not carry attribute VERSION
ws-check.xml:6: element workspace: validity error : No declaration for attribute version of element workspace
ws-check.xml:6: element workspace: validity error : Element workspace does not carry attribute VERSION
官方自带的 minimal-workspace.xml(用小写 version="0.4")按 DTD 严格校验不通过;而用大写 VERSION 的 workspace 能过 DTD,却会让 Python 端 getVersion() 读到 None,在第 3 篇实测中触发 bin/build.py 的 TypeError: '>=' not supported between instances of 'NoneType' and 'str'(runner.py 第 105 行)。结论:workspace 校验与 workspace 加载是两套规则,实践上遵循加载器——统一写小写 version="0.4",并接受它对 DTD 的既有偏差。
3.3 workspace 内元素
实测可用的子元素(均出现在官方样例与本文运行中):
<property name value>:传给构建的环境属性,官方样例内置<property name="build.sysclasspath" value="only"/>;<module href="...">、<repository href="...">:引入元数据文件,href 相对 workspace 文件所在目录解析(绝对路径实测会被重复拼接前缀,务必用相对路径);<database database passwd driver jar>:服务端统计库配置(正式部署用;单机实验可省略,密码示例passwd="q1w2e3r4")。
3.4 默认 workspace 约定与实测报错
./gump run 不带 -w 时按 metadata/<socket.gethostname()>.xml 找 workspace,实测(本机主机名 gump-centos):
RuntimeError:
No workspace at /root/gump/metadata/gump-centos.xml!
Maybe you need to check out the metadata from svn?
See the file metadata/FILLME for more information...
该报错出自 cron/gump.py 第 352 行附近,可用环境变量 GUMP_WORKSPACE 或命令行 -w 覆盖(实现均已实测确认存在)。
四、module.xml 详解
4.1 module 外层定义与 SCM 元素
module 文件顶层是 <module name>,实测可用子元素:<url>、<description>、SCM 声明、以及一至多个 <project>。SCM 元素均来自 project.dtd(47 元素清单包含 cvs/svn/p4/git/hg),以本文实测用过的 git 为例,完整属性表:
<!ATTLIST git
branch CDATA #IMPLIED
dir CDATA #IMPLIED
repository CDATA #IMPLIED
debug CDATA #IMPLIED
verbose CDATA #IMPLIED >
| 属性 | 含义 | 本文实测用法 |
|---|---|---|
| repository | 关联 repository 定义的名称 | repository="myrepo"(第 3 篇真实拉取 commons-io.git 的关联方式) |
| dir | 仓库相对路径/名称 | dir="commons-io.git",更新器拼出 git clone .../commons-io.git |
| branch | 分支 | 实测默认 master(更新命令 git clone --quiet --recursive --branch master ...) |
| debug / verbose | 输出开关 | 未使用 |
其余 SCM 元素同理(hg 属性与 git 完全同名;svn/cvs/p4 各有 url/path 等差异属性)。svn 类型实测可用(官方大量使用),git 类型已在第 3 篇对 GitBox 真实验证。
4.2 一个完整 module 的结构(本文实测样本)
<module name="hello-gump">
<url href="http://gump.apache.org"/>
<description>Minimal Gump module for validation testing.</description>
<git repository="myrepo" dir="hello-gump.git"/>
<project name="hello-gump-core"> ... </project>
<project name="hello-gump-test"> ... </project>
</module>
要点:<url> 是项目主页(出现在报告页链接里);<description> 原文出现在日志站项目页(第 3 篇 3.4 节实测提取到了这段文字);两个 <project> 的依赖关系构成聚合顺序(core 先于 test)。
五、project.xml 详解
5.1 project 元素实测属性表(取自 project.dtd)
<!ATTLIST project
name CDATA #REQUIRED
bundle CDATA #IMPLIED
...>
核心属性是 name(#REQUIRED,全局唯一的项目标识,被 <depend project="..."> 引用)。project 的内容元素分四类,以下属性表均从 project.dtd 实测摘录。
5.2 构建器元素(8 种)
| 元素 | 关键属性(DTD 摘录) | 适用 | 本文实测 |
|---|---|---|---|
| ant | target、buildfile、basedir | Ant 项目 | 已用(<ant target="jar">),构建调用形如 java org.apache.tools.ant.Main |
| maven | pom、goal、basedir | Maven 1 | 未实测 |
| mvn / mvn1 / mvn2 / mvn3 | mvn3: goal、profile、separateLocalRepository、timeout、buildfile、basedir、target、verbose、debug | Maven 2/3 | mvn3 在官方元数据中广泛使用 |
| mvn3install | basedir、file、packaging、version、artifactId | 把第三方包安装进 Maven 本地仓 | 见 5.5 既有报错专项 |
| gradle | (见 DTD) | Gradle 项目 | env.py 实测会探测 gradle --version |
| make / configure / script | make: target、basedir | 非 Java 项目 | env.py 实测探测 make |
构建器可携带 <property name value>、<sysproperty>、<jvmarg> 子元素(.dtd 中均有声明)。
💡 技术拓展:ant 与 mvn3 的选择对比——
维度 <ant><mvn3>依赖解析 交给 Ant classpath(配合 <depend>注入 jar)Maven 自行解析 pom 离线友好 高(jar 由上游 Gump 项目供给) 低(需本地仓/代理,workspace 提供 mvnRepoProxyPort) 现代项目适配 多数 Apache 项目已迁 Maven,build.xml 不复存在 官方元数据主流写法 本文示例采用
<ant>(hello-gump 与 commons-io-live),为的是走通最小链路;接入现代项目时官方实践是<mvn3>+mvn3install安装预置件。
5.3 依赖元素
<depend project>:强依赖,被依赖项失败则本项目不构建(属性含 artifactId/groupId/id/ids,供 Maven 构件级依赖);<option project>:软依赖,仅参与构建排序,不阻断(本文 hello-gump-test 对 junit 即用 option,实测运行不因 junit 缺失而报错)。
两者在依赖图中的实测语义已在第 3 篇加载自检中体现(hello-gump-test depends: ['hello-gump-core'])。
5.4 产物与杂项元素
| 元素 | 用途 | 实测说明 |
|---|---|---|
<jar name id> | 声明本项目产出的 jar,id 供下游 depend 引用 | commons-io-live 示例 jar name="commons-io-*.jar" id="commons-io" |
<home nested> | 项目主目录(嵌套路径) | 已用 |
<package> | Java 包前缀 | 已用 |
<license name> | 许可证文件 | 已用 |
<nag to from subject> | 失败通知邮件 | 未实测(服务端邮件链路) |
<javadoc> / <junitreport> / <report> | 文档与报告产物 | 未实测 |
<noclasspath> / <work> / <pom> 等 | 特殊构建语义 | 见 project.dtd |
5.5 官方元数据的既有 DTD 报错(如实记录)
官方 live 元数据自身有两处 DTD 不合规,两套系统(Ubuntu py3.10 / CentOS py3.6)实测回显逐字一致:
./tmp/./project/easymock.xml:30: element mvn3install: validity error : No declaration for attribute allowPropertyReferenceInVersion of element mvn3install
./tmp/./project/junit.xml:48: element mvn3: validity error : Element mvn3 content does not follow the DTD, expecting (property | depend | jvmarg)*, got (sysproperty )
解读:easymock 用到的 allowPropertyReferenceInVersion 属性确实不在 mvn3install 的 ATTLIST 里;junit 的 mvn3 内嵌 sysproperty 不符合 mvn3 内容模型(DTD 允许 property/depend/jvmarg)。这是 DTD 与实际用法脱节的直接证据——新增项目时不要模仿这两处写法。
六、repository.xml 详解
repository 定义托管站点,实测样本(第 3 篇真实使用):
<repository name="myrepo" type="git">
<title>My Demo Repository</title>
<home-page>http://gitbox.apache.org/repos/asf/</home-page>
<url>http://gitbox.apache.org/repos/asf/</url>
<redistributable/>
</repository>
| 项 | 说明 | 实测依据 |
|---|---|---|
type 属性 | 仓库类型(git/svn 等),决定 SCM 元素拼 URL 的方式 | type="git" 实测拼出 http://gitbox.apache.org/repos/asf/commons-io.git |
<url> | 仓库基址,module 的 dir 拼在其后 | commons-io-live 检出成功即验证 |
<home-page> | 展示用链接 | 出现在报告页 |
<redistributable/> | 允许转发构件(Gump 构件再分发策略标记) | 官方仓库定义普遍携带 |
官方主 profile 关联的 16 个 repository(实测统计)覆盖 GitBox/SVN/GitHub 等站点,自定义 repository 时直接仿写官方文件最稳妥。
七、校验工具链详解:metadata/validate
./gump validate 实际执行 metadata/validate Bash 脚本,逐段解析(与 4.5/4.6 节实测行为对应):
- 临时目录与文件复制:把 repository/profile/project 三类 XML 复制进
./tmp/(实测回显的报错路径前缀./tmp/./project/即来源于此),dtd/目录随行; - DOCTYPE 注入:对每个文件用 sed 注入
<!DOCTYPE ... SYSTEM "dtd/xxx.dtd">(官方元数据文件本体不带 DOCTYPE),随后xmllint --valid逐个强校验;repository/profile/project 三段各自循环,失败的打印 validity error 与行号; - 外部项目段:
xsltproc ./tools/externals.xslt ./profile/gump.xml枚举需远程拉取校验的外部文件再逐个 xmllint——实测当前快照该输出为 0 行(官方 profile 未登记外部校验项),该段静默通过。
全程实测耗时 0.8s(72 个本地文件 + 三段循环)。校验通过判据:除既有 2 处报错外无新增 validity error 行。该脚本不校验 workspace.xml(workspace 的校验方式见 3.2 节手工 DOCTYPE 法)。
八、命令详解
8.1 ./gump 包装脚本(Bash 层)
实测命令表(./gump help 输出与源码核对一致):
| 命令 | 作用 | 依赖检查(实测) |
|---|---|---|
| run | 完整运行(cron 链路) | GUMP_HOME、JAVA_HOME、python、pkill;并检查 python 库 rdflib、MySQLdb |
| test | 单元测试 | GUMP_HOME、python |
| validate | 元数据 DTD 校验 | xmllint、xsltproc、curl |
| site / site-publish | Forrest 文档构建 / SSH 发布 | forrest(本文未使用,帮助原文:Use Apache Forrest to build the documentation.) |
| help | 帮助 | 无 |
另实测确认一个未列入帮助的隐藏命令 experimental-tests(源码 case 分支存在)。
已知缺陷(实测确认):check_env_pylib 是 Python 2 语法——它生成临时文件 pycmd.tmp.py,内容为:
try:
import rdflib
except:
print "error"
在 Python 3 下执行时必然报错(Ubuntu 3.10.12 实测回显):
File "/root/gump/pycmd.tmp.py", line 4
print "error"
^^^^^^^^^^^^^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?
因此 ./gump run 在 Python 3 上的库预检环节是坏的(报错后脚本继续走主流程)。绕过方式:直接调 bin/integrate.py(第 3 篇已验证完整可用)。
8.2 Python 优先级:cron/gump.sh
服务端启动脚本实测按 python3 优先选择解释器:
export GUMP_PYTHON="`which python3`"
取不到时回退 python,两者皆无则报 No Python (python3 nor python) found in path.(源码第 45-49 行)。Ubuntu 22.04 天然满足;CentOS 8 需先补 python 软链(第 2 篇)。
8.3 bin/*.py 独立入口与命令行选项
bin/integrate.py、bin/update.py、bin/build.py 等共用 gump/core/commandLine.py 的 handleArgv。实测 -h 完整回显(integrate/build 相同):
Usage: python gump.core.commandLine.py -w {workspaceFile} [OPTION] [PROJECT]
Mandatory arguments to long options are mandatory for short options too.
Startup:
-V, --version display the version of Apache Gump(TM) and exit.
-h, --help print this help.
-w, --workspace use this workspace for Gump.
General:
-v, --verbose verbose logging.
-d, --debug debug logging.
Not relevent to all scripts:
-O, --official Full run, publishing notifications, etc.
-D, --dated Dated log files.
-c, --cache Use local cache (do not download over HTTP).
-t, --text Use text not xdocs.
-X, --xdocs Output xdocs, not XHTML.
For bug reports use JIRA: http://issues.apache.org/.
For suggestions: <general@gump.apache.org/>.
-V 实测回显(横幅即版本展示):
_____
| __|_ Apache_ ___
| | | | | | . |
|_____|___|_|_|_| _|
|_| ~ v. 2.3 ~
实测选项行为备注:
-w必须是第一个参数(handleArgv仅对 argv[1] 做 workspace 识别,实测-X -w <file>报No workspace defined with -w.);- 帮助文本写
-X, --xdocs,但解析分支实测只注册了小写-x(大写-X被当作项目表达式吞掉)——帮助文本与实现不一致,用小写-x; - 位置参数是项目表达式:
all或单个项目名(实测两者均有效)。
8.4 各入口适用性实测结论(r1939132 快照)
| 入口 | Python 3 实测结果 | 建议 |
|---|---|---|
bin/integrate.py | 完整可用,离线退出码 0,产出 HTML/RSS/Atom | 首选(官方服务端同款链路) |
bin/update.py / bin/build.py | 初始化阶段 RuntimeError: Not Implemented on TextResolver: getFile.(RSS 联合分发器时序缺陷,py3.10 与 py3.6 复现一致) | 避免独立调用,能力由 integrate 覆盖 |
./gump validate / ./gump test | 正常 | 元数据工作与开发自测用 |
./gump run | 库预检的 py2 语法报错后继续,可用 -w 正常驱动 | 可用但建议直连 integrate |
8.5 运行日志的固定格式(实测样本)
./gump run 与 cron 链路产生的运行日志(实测回显节选):
- GUMP run by Python : '3.6.8 ...'
- GUMP run by Gump : 2.0.2-alpha-0003
- GUMP run on OS : 'posix'
- GUMP run in env :
GUMP_HOME -> [/root/gump]
JAVA_HOME -> [/usr/lib/jvm/java-11-openjdk-11.0.13.0.8-4.el8_5.x86_64]
...
版本双轨:命令行横幅是 v. 2.3(python/gump/core/config.py 的 setting.VERSION),cron 链路自报 2.0.2-alpha-0003(cron/gump.py 的 GUMP_VERSION)——两处指同一份代码的内部版本串,阅读日志时注意区分。
九、常见问题(FAQ)
Q1:写新项目元数据应该抄哪个官方文件?
选与目标项目同构建器的:Ant 项目抄 metadata/project/ant.xml,Maven 项目抄 metadata/project/easymock.xml(注意规避 5.5 节两处既有报错写法)。本文自定义样本(repository + module 双文件)也可直接作为模板。
Q2:workspace 校验总报 workspace 不携带 VERSION 属性?
DTD 要求大写、样例用小写是快照内的既知偏差(3.2 节实测复现)。给 workspace 做严格 DTD 校验时临时用大写,运行时统一小写 version="0.4";或如官方现状一样只校验 repository/profile/project 三类。
Q3:<depend> 与 <option> 到底差在哪?
<depend> 决定「构建不了」(被依赖项失败则跳过本项目),<option> 只决定「构建顺序」。测试框架类(junit)等可选增强用 option,库依赖用 depend——本文两处实测行为与此一致。
Q4:为什么 -X 没生效?
解析器只认小写 -x(8.3 节实测),帮助文本的大写写法与实现不符。参数顺序上 -w 必须放在第一个位置参数之前。
Q5:validate 报 easymock/junit 的 error,我需要修吗? 那是官方元数据的既有问题(5.5 节),不属于你的安装或修改。提交元数据变更时保证自己新增的文件无新增 validity error 即可。
Q6:哪里能看到这轮运行的完整环境与版本?
跑一次 ./gump run(或 cron 链路)看运行日志头部:GUMP 版本(2.0.2-alpha-0003)、Python 版本、JAVA_HOME 与全部环境变量逐行列出(8.5 节实测样本);HTML 报告的 index.html 也会记录 Run GUID 与 Gump Version 2.3。
十、参考链接
- 官方元数据对象模型(对象/属性权威描述):https://gump.apache.org/metadata/index.html
- workspace 元素文档:https://gump.apache.org/metadata/workspace.html
- project/module/repository DTD 原文(随源码检出):https://svn.apache.org/repos/asf/gump/live/metadata/dtd/
- 校验脚本与外部项目转换表(随源码检出):https://svn.apache.org/repos/asf/gump/live/metadata/validate
- Python Gump 命令行文档:https://gump.apache.org/python/usage.html
- 官方 vmgump 实例(元数据实践样例库):http://vmgump.apache.org/