The Mercurial version control system
can provide the repository commit log in a machine readable format – XML.
We will transform this XML to relations using the relpipe-in-xmltable
and then filter records using the SQL language in the relpipe-tr-sql
tool.
Everything on-the-fly, in a single shell pipeline. Of course, we can cache intermediate products in a file if needed.
#!/bin/bash
relpipe-in-hglog() {
# on repositories with long history
# it is good to process just a subset of the log using hg log parameters
hg log --template xml \
| relpipe-in-xmltable \
--relation hg_log \
--records "/log/logentry" \
--attribute "revision" integer "@revision" \
--attribute "date" string "date" \
--attribute "hash" string "@node" \
--attribute "hash_short" string "substring(@node,1,12)" \
--attribute "branch" string "branch" \
--attribute "author_name" string "author" \
--attribute "message" string "msg"
# --attribute "author_email" string "author/@email" \
}
relpipe-in-hgtags() {
hg tags \
| sed -E 's/([^ \s]+)\s+([0-9]+):(.*)/\1\n\2\n\3/g' \
| tr \\n \\0 \
| relpipe-in-cli \
--relation "hg_tags" \
--attribute "tag" string \
--attribute "revision" integer \
--attribute "hash_short" string
}
# just view everything:
# (relpipe-in-hglog; relpipe-in-hgtags) | relpipe-out-tabular | less -RSi
# filter and JOIN data, do some statistics:
(relpipe-in-hglog; relpipe-in-hgtags) \
| relpipe-tr-sql \
--relation "tags" \
"SELECT
t.*,
l.date
FROM hg_tags AS t
JOIN hg_log AS l USING (hash_short)" \
--relation "filtered_log" \
"SELECT
revision,
date,
hash_short,
branch,
author_name
FROM hg_log
ORDER BY revision DESC
LIMIT ?" \
--parameter 10 \
--relation "author_statistics" \
"SELECT
author_name,
branch,
count(*) AS count,
min(date) AS first_commit,
max(date) AS last_commit
-- TODO: user proper data type for date
FROM hg_log
GROUP BY author_name, branch
ORDER BY count" \
| relpipe-out-tabular
This script will generate several lovely relations:
tags:
╭───────────────┬───────────────────┬─────────────────────┬───────────────────────────╮
│ tag (string) │ revision (string) │ hash_short (string) │ date (string) │
├───────────────┼───────────────────┼─────────────────────┼───────────────────────────┤
│ tip │ 263 │ 8bf13358a50a │ 2019-07-25T22:16:12+02:00 │
│ relpipe-v0.12 │ 258 │ 2868d772c27e │ 2019-05-28T21:18:20+02:00 │
│ relpipe-v0.11 │ 256 │ 822ffd23d679 │ 2019-04-09T17:14:05+02:00 │
│ relpipe-v0.10 │ 250 │ d16336d1c61f │ 2019-02-20T11:46:10+01:00 │
│ relpipe-v0.9 │ 241 │ f71d300205b7 │ 2019-01-18T21:34:58+01:00 │
│ relpipe-v0.8 │ 219 │ a94eb371f77e │ 2018-12-20T01:42:36+01:00 │
│ v0.4 │ 114 │ 9302cf6856ea │ 2012-07-06T17:04:13+02:00 │
│ v0.3 │ 78 │ 7e478bfa5694 │ 2012-01-08T17:26:24+01:00 │
│ v0.2 │ 36 │ 5be21d1ef5f8 │ 2011-08-23T20:05:56+02:00 │
│ v0.1 │ 19 │ b81b96475fe0 │ 2011-04-30T20:20:54+02:00 │
╰───────────────┴───────────────────┴─────────────────────┴───────────────────────────╯
Record count: 10
filtered_log:
╭───────────────────┬───────────────────────────┬─────────────────────┬─────────────────┬──────────────────────╮
│ revision (string) │ date (string) │ hash_short (string) │ branch (string) │ author_name (string) │
├───────────────────┼───────────────────────────┼─────────────────────┼─────────────────┼──────────────────────┤
│ 263 │ 2019-07-25T22:16:12+02:00 │ 8bf13358a50a │ v_0 │ František Kučera │
│ 262 │ 2019-07-24T14:18:42+02:00 │ 846510a73535 │ v_0 │ František Kučera │
│ 261 │ 2019-05-28T22:19:59+02:00 │ ffaf18970f2b │ v_0 │ František Kučera │
│ 260 │ 2019-05-28T22:19:45+02:00 │ 66dffc56bd43 │ v_0 │ František Kučera │
│ 259 │ 2019-05-28T21:52:15+02:00 │ 13a521e9d34d │ v_0 │ František Kučera │
│ 258 │ 2019-05-28T21:18:20+02:00 │ 2868d772c27e │ v_0 │ František Kučera │
│ 257 │ 2019-04-09T22:53:40+02:00 │ a39066264509 │ v_0 │ František Kučera │
│ 256 │ 2019-04-09T17:14:05+02:00 │ 822ffd23d679 │ v_0 │ František Kučera │
│ 255 │ 2019-04-08T13:37:35+02:00 │ 94b533007e77 │ v_0 │ František Kučera │
│ 254 │ 2019-04-08T11:56:24+02:00 │ 23247d93a012 │ v_0 │ František Kučera │
╰───────────────────┴───────────────────────────┴─────────────────────┴─────────────────┴──────────────────────╯
Record count: 10
author_statistics:
╭──────────────────────┬─────────────────┬────────────────┬───────────────────────────┬───────────────────────────╮
│ author_name (string) │ branch (string) │ count (string) │ first_commit (string) │ last_commit (string) │
├──────────────────────┼─────────────────┼────────────────┼───────────────────────────┼───────────────────────────┤
│ František Kučera │ v_0 │ 128 │ 2018-11-21T23:52:13+01:00 │ 2019-07-25T22:16:12+02:00 │
│ František Kučera │ │ 136 │ 2011-04-02T15:36:52+02:00 │ 2014-09-11T20:30:46+02:00 │
╰──────────────────────┴─────────────────┴────────────────┴───────────────────────────┴───────────────────────────╯
Record count: 2
Using different output filter than relpipe-out-tabular
,
we can serialize the relational output into other formats (XML, CSV, Recfile, ODS, ASN.1 BER etc.),
display them in a GUI or execute some shell command for each record.
Relational pipes, open standard and free software © 2018-2022 GlobalCode