//print(__FILE,':',__LINE,": Hi, world.");
/* Intended to be import()ed by unit-test.th1ish.
Extend the Fossil bits a bit...
*/
/* Reminder: CLI args:
The th1ish shell passed flags _after_ -- (two dashes)
on to the script. It expects them to be in one of these
forms:
-f (boolean flag)
-f=xxx (value - it tries to determine the type automatically)
Any number of '-' may preceed a flag - they are all equivalent.
Any such flags are stored as properties in ARGV.flags. Any
arguments which do not start with a dash are presumed to be filenames
or app commands and are added to ARGV.nonFlags.
ARGV flags supported by this code:
-R=/path/to/repo.fsl tells it to open a repository db.
-S (boolean) enables fossil-level SQL tracing. This applies to any
DBs opened via a Fossil context (as opposed to directly opening them
with Fossil.Db.open().
-C (boolean) suppresses the automatic attempt to open an existing
checkout under the current directory. Implied by -R.
*/
0 && scope {
assert api.prototypes.Exception
assert api.Exception
assert api.PathFinder === api.prototypes.PathFinder
assert api.prototypes.Array
assert 'function' === typename import
assert api
assert 'function' === typename api.import
assert api.PathFinder
assert 'PathFinder' === typename api.PathFinder
assert 'PathFinder' === typename api.import.path
assert Fossil
assert Fossil.Context
assert Fossil.Db
assert Fossil.Db.Stmt
assert 'Db' === typename Fossil.Db
assert 'Stmt' === typename Fossil.Db.Stmt
assert 'function' === typename Fossil.Db.open
assert 'function' === typename Fossil.deltaCreate
assert 'function' === typename Fossil.deltaApply
assert 'function' === typename Fossil.deltaAppliedLength
assert Fossil.file
assert 'function' === typename Fossil.file.isAccessible
assert 'function' === typename Fossil.file.size
assert 'function' === typename Fossil.file.mtime
assert 'function' === typename Fossil.file.isFile
assert 'function' === typename Fossil.file.isDir
assert 'function' === typename Fossil.file.canonicalName
assert 'function' === typename Fossil.file.unlink
}
/**
createContext() extends the Context constructor
to support more options. obj may be a falsy value
or an Object with any of these properties:
repoDb: path to repository DB. Default is ARGV.flags.R.
traceSql: if true, enable SQL tracing on the context.
Default is ARGV.flags.S.
checkout: a path to look for a checkout in. Not used if repoDb
is set. Default is getenv('PWD') unless ARGV.flags.C is truthy,
in which case no checkout is opened by default.
*/
Fossil.createContext = function(obj = null){
if(!obj){
const rdb = ARGV.flags.R
obj = object{
repoDb: rdb,
traceSql: !!ARGV.flags.S,
checkout: rdb ? undefined
: (ARGV.flags.C ? undefined : getenv('PWD'))
}
}
var f = this.Context(obj)
obj || return f
if('string'===typename obj.repoDb){
[f.openRepo obj.repoDb]
// run it again to test an exception:
//[f.openRepo obj.repoDb]
}
else if('string'===typename obj.checkout){
[f.openCheckout obj.checkout]
// run it again to test an exception:
//[f.openCheckout obj.checkout]
}
return f
}
/**
SELECT's the first column of the first row
of the result set of the given SQL.
If the bind argument is passed in then
it is passed on to the Stmt.bind() method
of the underlying statement. Use an array to
bind multiple values.
*/
Fossil.Context.selectVal = proc(sql,bind){
const st = [this.db.prepare sql]
var rc
const ex = catch {
if(1<argv.length()){
if('array' === typename bind){
st.bind(bind)
}else{
st.bind(1,bind)
}
}
[st.step] && (rc = [st.get 0])
}
[st.finalize]
ex ? throw ex : return rc;
}
/**
Given a SELECT-style query and optional bind parameters
(either a single value for a single param or an array
of multiple params), this routine simply dumps out
the results of the query.
*/
Fossil.Context.dumpQuery = proc(sql,bind, separator='\t'){
const params object{
sql:sql,
bind:bind, // note that undefined value is treated as non-existent here
callback:proc(){
(1===rowNumber) && [print [columnNames.join separator]]
[print [this.join separator]]
}
}
[this.db.each params]
}
/**
Stmt.each() loops over this.step(),
calling func(this, N) on each iteration,
where N is the current row number (1-based).
If func() returns a literal false, looping
stops without an error.
*/
Fossil.Db.Stmt.each = proc(func){
var rowNum = 0
var rc
while(this.step()){
(false === func(this, rowNum += 1)) && break
}
}
//Fossil.cx = Fossil.createContext()
Fossil.cx && scope {
const cx = Fossil.cx
assert cx inherits Fossil.Context
assert 'FossilContext' === typename cx
assert 'function' === typename cx.finalize
assert 'function' === typename cx.closeCheckout
assert 'function' === typename cx.closeRepo
assert 'function' === typename cx.openRepo
assert 'function' === typename cx.openCheckout
assert 'function' === typename cx.openDb
assert 'function' === typename cx.symToUuid
}