const CGI = api.cgi
const F = CGI.getFossilInstance()
const out = api.io.output
var version = CGI.getVar('version') || R.routeAfterApp.0 || 'trunk'
const includeBaselineFiles = +CGI.getVar('baseline-files', 0)
const includeBaselineObj = +CGI.getVar('baseline', 0)
const linkRoot = CGI.cgiRoot + 'manifest/'
//CGI.request.ENV.PATH_INFO.substr(1/*trim leading slash*/)
const vLinkRoot = linkRoot
//+ '?version=' + (version ? CGI.urlencode(version) : 'trunk')
+version && (version = +version)
const uuidStr = proc(u){
return u.substr(0,12)
}
const showDeltaTips = proc(){
/* This is ugly, but it works. We use $-call syntax mixed with heredocs
and {squiggly strings} to fake a single line of arguments for $-call
purposes.
*/
$out <<<EOF
<blockquote>
This is a delta manifest. Tips regarding delta manifests:
<ul>
EOF ((!deck.B || includeBaselineFiles) ? '' : <<<XXX
<li>We are only showing this
checkin's files. Use baseline-files=1 to get all files.</li>
XXX) <<<EOF
<li>Use the 'baseline=0|1' parameter to disable/enable loading of the
baseline manifest object. Only delta manifests have baselines and
they are not loaded by default.
<br/>Try it out:
<a href='EOF vLinkRoot <<<EOF&baseline=0'>off</a>
or <a href='EOF vLinkRoot <<<EOF&baseline=1'>on</a>
</li>
<li>Use the 'baseline-files=0|1' parameter to disable/enable loading
of the (inherited) baseline file list. If 0 (the default), only
files included directly in this checkin (not from baseline
manifests) are listed in the "F-card". This only affects delta
manifests.
<br/>Try it out:
<a href='EOF vLinkRoot <<<EOF&baseline-files=0'>off</a>
or <a href='EOF vLinkRoot <<<EOF&baseline-files=1'>on</a>
</li>
</ul>
</blockquote>
EOF
} /* showDeltaTips() */
const showDeck = proc(deck){
out({<div><span class='strong'>Manifests: </span>})
out("[<a href='", linkRoot, 'trunk',
"'>Trunk</a>] ")
(deck.P && deck.P.0) &&
out("[<a href='", linkRoot, deck.P.0,
"'>Parent</a>] ")
(deck.B && deck.B.uuid) &&
out("[<a href='", linkRoot, deck.B.uuid,
"'>Baseline</a>] ")
out({</div>})
var children = array[]
F.db.each(object {
sql: {SELECT uuid, cid, isprim
FROM plink JOIN blob ON cid=rid
WHERE pid=%1$d
ORDER BY isprim DESC, mtime DESC}.applyFormat(deck.rid),
callback: proc(){
//print(this)
children.push(this.0)
}
})
if(children.length()){
$out {<div><span class='strong'>Children: </span>}
$children.eachIndex proc(v,i){
i && out(', ')
out("[<a class='uuid' href='", linkRoot, v,
"'>", uuidStr(v), "</a>]")
}.importSymbols('out','linkRoot')
out({</div>})
}
$out {<div>}
const versionLabel = version ?
(Fossil.isUuid(version) ? "%1$.12s".applyFormat(version) : version)
: version;
const reportByUserLink =
CGI.html.createAnchor( CGI.cgiRoot + 'timeline?user=' + CGI.urlencode(deck.U),
deck.U)
out(CGI.html.createAnchor(
CGI.cgiRoot.concat('download/uuid/',deck.uuid,
'?name=manfiest-',uuidStr(deck.uuid), '.txt'),
'Manifest'),
' of [',
Fossil.client.linkToProject('', F.getProjectName()),
'] repository version [', {<span class='uuid'>},
Fossil.client.linkToProject('/info/'+version, versionLabel),
{</span>},
'] checked in at ',
Fossil.time.julianToHuman(deck.D),
' by ', reportByUserLink)
deck.C && scope {
const comment = F.selectVal({SELECT coalesce(ecomment, comment) FROM event WHERE objid=?},
deck.rid, deck.C)
out({, who commented:},
{<blockquote class='timeline-checkin-comment'>},
CGI.htmlEscape(comment),
{</blockquote>})
}
$out {</div>}
const DeckDiff = api.import('DeckDiff')
DeckDiff.showDeckFileChangeList(F, deck, true)
if(0){
deck.B && showDeltaTips()
$out {<textarea rows="30" cols="80" readonly>}
CGI.printJSON(deck)
$out {</textarea>}
}
}.importSymbols('F', 'uuidStr')/*showDeck()*/
const ob = api.ob
ob.push() /* start output buffering */
var err = catch{
const deck = F.loadManifest(version, includeBaselineFiles, includeBaselineObj)
Fossil.sorter(deck, true)
showDeck(deck)
}/*catch*/
if(err){
err = CGI.scrubException(err)
ob.clear() /* discard buffered output */
out("Error rendering manifest: <pre>",CGI.htmlEscape(CGI.toJSONString(err)),"</pre>\n")
}else{
$out <<<EOF
<script>try {(function(){
/* for sbs diffs, keep their side-scrolling components synchronized... */
var SCROLL_LEN = 25;
function initSbsDiff(diff){
var txtCols = diff.querySelectorAll('.fsl-diff-text-col');
var txtPres = diff.querySelectorAll('.fsl-diff-text-col pre');
var width = Math.max(txtPres[0].scrollWidth, txtPres[1].scrollWidth);
for(var i=0; i<2; i++){
txtPres[i].style.width = width + 'px';
txtCols[i].onscroll = function(e){
txtCols[0].scrollLeft = txtCols[1].scrollLeft = this.scrollLeft;
};
}
diff.tabIndex = 0;
diff.onkeydown = function(e){
e = e || event;
var len = {37: -SCROLL_LEN, 39: SCROLL_LEN}[e.keyCode];
if( !len ) return;
txtCols[0].scrollLeft += len;
return false;
};
}
var diffs = document.querySelectorAll('.fsl-sbsdiff-cols');
for(var i=0; i<diffs.length; i++){
initSbsDiff(diffs[i]);
}
}())} catch(e){/*ignore*/}</script>
EOF
}
ob.flush()
ob.pop()