#!/usr/bin/env f-s2sh
/**
A very basic timeline application implemented in s2.
Optional flags, passed after '--' on the CLI:
-f|--files lists files changed by each commit.
-R|--repo-db=DBNAME specifies a repository db (default=current checkout).
*/
assert Fossil.require;
Fossil.require(
['fsl/db/repoOrCheckout', // opens -R|--repo-db REPOFILE db or the current checkout
'fsl/timeline/basic', // array of recent event table entries
'cliargs' // flags passed after '--' are "script flags", and this module assists in using them
],
proc(db,tl,cli){
const showFiles = cli.takeFlag('f', cli.takeFlag('files'));
if(cli.hasFlags()){
throw "Unexpected flags(s): "+{}.toJSONString.call(cli.flags);
}else if(cli.hasNonFlags()){
throw "Unexpected non-flag(s): "+cli.nonFlags.toJSONString();
}
const j2h = Fossil.time.julianToHuman;
const showFilesChangedBy = proc(uuid){
affirm 'string' === typename uuid;
eachCallback.gotOne = false;
db.each({
sql,
bind: uuid,
mode: 0,
callback:eachCallback
});
if(eachCallback.gotOne) print("") /*spacing */;
} using {
sql:<<<EOSQL
SELECT bf.uuid, filename.name fname, mlink.pid pid, mlink.fid fid, bf.size size
FROM mlink, filename LEFT JOIN blob bf -- FILE blob
ON bf.rid=mlink.fid LEFT JOIN blob bm -- MANIFEST/checkin blob
ON bm.rid=mlink.mid
WHERE bm.uuid = ?1
AND filename.fnid=mlink.fnid AND bf.rid=mlink.fid
AND bm.rid=mlink.mid
ORDER BY filename.name EOSQL,
eachCallback:proc f(){
if(1===rowNumber){
print("\t%1$-12s %2$-10s %3$10s Name".applyFormat(
"File", "UUID", "Size"
));
f.gotOne=true;
}
print("\t%1$-10s %2$.10s %3$10d %4$s".applyFormat(
(!this.fid ? "removed" : (!this.pid ? "added" : "modified")),
this.uuid|||"",
this.size|||0,
this.fname
));
}
};
const lineFmt = "%1$-8s %2$.10s @ %3$s by %4$s\n\t%5$s";
const typeMap = { // maps event.type labels to strings
g: 'tag', w: 'wiki', ci: 'checkin',
e: 'event', t: 'ticket', f: 'forum'
};
tl.eachIndex(proc(v){
print(lineFmt.applyFormat(typeMap[v.type]|||'???',
v.uuid,
j2h(v.mtime),
v.user,
v.comment));
showFiles && showFilesChangedBy(v.uuid);
});
});