Login
timeline.s2 at [9fb6fae4f8]
Login

File bindings/s2/timeline.s2 artifact ea76b4c237 part of check-in 9fb6fae4f8


#!/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);
    });
});