Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch tooltips Excluding Merge-Ins
This is equivalent to a diff from e0186fdb to b406b414
2019-05-20
| ||
08:14 | Make the "click to show tooltip" action more "discoverable" with a changing mouse cursor, similar to the timeline nodes. This example uses the "pointer" cursor, but the "help" cursor may also be an option. ... (check-in: 8b8eaad8 user: florian tags: tooltip-experiments) | |
2019-05-18
| ||
21:08 | Merge the windows build fix from trunk into the tooltips branch. ... (Closed-Leaf check-in: b406b414 user: drh tags: tooltips) | |
21:05 | Back out check-in [344a3331d34d896] because it does not work with openssl-1.0.1. ... (check-in: f08b93da user: drh tags: trunk) | |
18:57 | Improvements to branch linkage from the tooltip. Branch linkage now works even from a file history graph. And the source check-in is always highlighted in the linked timeline. ... (check-in: a27ca27f user: drh tags: tooltips) | |
2019-05-17
| ||
19:49 | Improvements to the timeline graph layout: (1) Use a dotted vertical line to indicate a gab of one or more check-ins in a branch. (2) Do not necessarily draw branch lines all the way to the top or bottom of the page. Leave space for the rail to be reused by other branches. ... (check-in: d14590db user: drh tags: trunk) | |
19:30 | In the graph layout, make sure that the idxTop value is properly relayed across gaps. ... (Closed-Leaf check-in: e0186fdb user: drh tags: graph-improvements) | |
13:54 | Merge the %j string formatter enhancement from trunk. ... (check-in: 78d812e2 user: drh tags: graph-improvements) | |
Changes to src/default_css.txt.
︙ | ︙ | |||
193 194 195 196 197 198 199 200 201 202 203 204 205 206 | } .tl-line.dotted.v { width: 0px; border-left-width: 2px; border-left-style: dotted; background: rgba(255,255,255,0); } span.tagDsp { font-weight: bold; } span.wikiError { font-weight: bold; color: red; } | > > > > > > > > > > > > > > > | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | } .tl-line.dotted.v { width: 0px; border-left-width: 2px; border-left-style: dotted; background: rgba(255,255,255,0); } .tl-tooltip { background-color: #fecd4b; color: black; text-align: center; padding: 5px 1em; border: 1px solid black; border-radius: 6px; position: absolute; z-index: 100; } .tl-tooltip a { background-color: #fecd4b; color: black; } span.tagDsp { font-weight: bold; } span.wikiError { font-weight: bold; color: red; } |
︙ | ︙ |
Changes to src/export.c.
︙ | ︙ | |||
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | Stmt q; /* An SQL query */ char *zBranch; /* The branch of the check-in */ char *zMark; /* The Git-name of the check-in */ Blob sql; /* String of SQL for part of the query */ Blob comment; /* The comment text for the check-in */ int nErr = 0; /* Number of errors */ int bPhantomOk; /* True if phantom files should be ignored */ pMan = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pMan==0 ){ /* Must be a phantom. Return without doing anything, and in particular ** without creating a mark for this check-in. */ gitmirror_message(VERB_NORMAL, "missing check-in: %s\n", zUuid); return 0; | > | 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 | Stmt q; /* An SQL query */ char *zBranch; /* The branch of the check-in */ char *zMark; /* The Git-name of the check-in */ Blob sql; /* String of SQL for part of the query */ Blob comment; /* The comment text for the check-in */ int nErr = 0; /* Number of errors */ int bPhantomOk; /* True if phantom files should be ignored */ char buf[24]; pMan = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pMan==0 ){ /* Must be a phantom. Return without doing anything, and in particular ** without creating a mark for this check-in. */ gitmirror_message(VERB_NORMAL, "missing check-in: %s\n", zUuid); return 0; |
︙ | ︙ | |||
1132 1133 1134 1135 1136 1137 1138 | /* Export the check-in */ fprintf(xCmd, "commit refs/heads/%s\n", zBranch); fossil_free(zBranch); zMark = gitmirror_find_mark(zUuid,0,1); fprintf(xCmd, "mark %s\n", zMark); fossil_free(zMark); | > > > | | < | 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 | /* Export the check-in */ fprintf(xCmd, "commit refs/heads/%s\n", zBranch); fossil_free(zBranch); zMark = gitmirror_find_mark(zUuid,0,1); fprintf(xCmd, "mark %s\n", zMark); fossil_free(zMark); sqlite3_snprintf(sizeof(buf), buf, "%lld", (sqlite3_int64)((pMan->rDate-2440587.5)*86400.0) ); fprintf(xCmd, "committer %s <%s@noemail.net> %s +0000\n", pMan->zUser, pMan->zUser, buf ); blob_init(&comment, pMan->zComment, -1); if( blob_size(&comment)==0 ){ blob_append(&comment, "(no comment)", -1); } blob_appendf(&comment, "\n\nFossilOrigin-Name: %s", zUuid); fprintf(xCmd, "data %d\n%s\n", blob_size(&comment), blob_str(&comment)); |
︙ | ︙ |
Changes to src/graph.js.
︙ | ︙ | |||
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | if( css!=="" ){ var style = document.createElement("style"); style.textContent = css; document.querySelector("head").appendChild(style); } amendCssOnce = 0; } function TimelineGraph(tx){ var topObj = document.getElementById("timelineTable"+tx.iTableId); amendCss(tx.circleNodes, tx.showArrowheads); var canvasDiv; var railPitch; var mergeOffset; var node, arrow, arrowSmall, line, mArrow, mLine, wArrow, wLine; function initGraph(){ var parent = topObj.rows[0].cells[1]; parent.style.verticalAlign = "top"; canvasDiv = document.createElement("div"); canvasDiv.className = "tl-canvas"; canvasDiv.style.position = "absolute"; parent.appendChild(canvasDiv); | > > > > > > > > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | if( css!=="" ){ var style = document.createElement("style"); style.textContent = css; document.querySelector("head").appendChild(style); } amendCssOnce = 0; } var tooltipObj = document.createElement("span"); tooltipObj.className = "tl-tooltip"; tooltipObj.style.visibility = "hidden"; document.getElementsByClassName("content")[0].appendChild(tooltipObj); /* Construct that graph corresponding to the timeline-data-N object */ function TimelineGraph(tx){ var topObj = document.getElementById("timelineTable"+tx.iTableId); amendCss(tx.circleNodes, tx.showArrowheads); topObj.onclick = clickOnGraph topObj.ondblclick = dblclickOnGraph var canvasDiv; var railPitch; var mergeOffset; var node, arrow, arrowSmall, line, mArrow, mLine, wArrow, wLine; function initGraph(){ var parent = topObj.rows[0].cells[1]; parent.style.verticalAlign = "top"; canvasDiv = document.createElement("div"); canvasDiv.className = "tl-canvas"; canvasDiv.style.position = "absolute"; parent.appendChild(canvasDiv); |
︙ | ︙ | |||
161 162 163 164 165 166 167 | if( h ) n.style.height = h+"px"; if( color ) n.style.backgroundColor = color; n.className = "tl-"+cls; canvasDiv.appendChild(n); return n; } function absoluteY(obj){ | | < | | | > | > > > > > | | | > | > | > > > > | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | if( h ) n.style.height = h+"px"; if( color ) n.style.backgroundColor = color; n.className = "tl-"+cls; canvasDiv.appendChild(n); return n; } function absoluteY(obj){ var y = 0; do{ y += obj.offsetTop; }while( obj = obj.offsetParent ); return y; } function absoluteX(obj){ var x = 0; do{ x += obj.offsetLeft; }while( obj = obj.offsetParent ); return x; } function miLineY(p){ return p.y + node.h - mLine.w - 1; } function drawLine(elem,color,x0,y0,x1,y1){ var cls = elem.cls + " "; if( x1===null ){ x1 = x0+elem.w; cls += "v"; }else{ y1 = y0+elem.w; cls += "h"; } return drawBox(cls,color,x0,y0,x1,y1); } function drawUpArrow(from,to,color,id){ var y = to.y + node.h; var arrowSpace = from.y - y + (!from.id || from.r!=to.r ? node.h/2 : 0); var arw = arrowSpace < arrow.h*1.5 ? arrowSmall : arrow; var x = to.x + (node.w-line.w)/2; var y0 = from.y + node.h/2; var y1 = Math.ceil(to.y + node.h + arw.h/2); var n = drawLine(line,color,x,y0,null,y1); addToolTip(n,id) x = to.x + (node.w-arw.w)/2; n = drawBox(arw.cls,null,x,y); if(color) n.style.borderBottomColor = color; addToolTip(n,id) } function drawDotted(from,to,color,id){ var x = to.x + (node.w-line.w)/2; var y0 = from.y + node.h/2; var y1 = Math.ceil(to.y + node.h); var n = drawLine(dotLine,null,x,y0,null,y1) if( color ) n.style.borderColor = color addToolTip(n,id) } function addToolTip(n,id){ if( id ) n.setAttribute("data-ix",id-tx.iTopRow) } /* Draw thin horizontal or vertical lines representing merges */ function drawMergeLine(x0,y0,x1,y1){ drawLine(mLine,null,x0,y0,x1,y1); } function drawCherrypickLine(x0,y0,x1,y1){ drawLine(cpLine,null,x0,y0,x1,y1); |
︙ | ︙ | |||
241 242 243 244 245 246 247 | if( p.bg ){ var e = document.getElementById("mc"+p.id); if(e) e.style.backgroundColor = p.bg; e = document.getElementById("md"+p.id); if(e) e.style.backgroundColor = p.bg; } if( p.r<0 ) return; | | | > > | | | | | | | 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | if( p.bg ){ var e = document.getElementById("mc"+p.id); if(e) e.style.backgroundColor = p.bg; e = document.getElementById("md"+p.id); if(e) e.style.backgroundColor = p.bg; } if( p.r<0 ) return; if( p.u>0 ) drawUpArrow(p,tx.rowinfo[p.u-tx.iTopRow],p.fg,p.id); if( p.sb>0 ) drawDotted(p,tx.rowinfo[p.sb-tx.iTopRow],p.fg,p.id); var cls = node.cls; if( p.hasOwnProperty('mi') && p.mi.length ) cls += " merge"; if( p.f&1 ) cls += " leaf"; var n = drawBox(cls,p.bg,p.x,p.y); n.id = "tln"+p.id; addToolTip(n,p.id) n.onclick = clickOnNode; n.ondblclick = dblclickOnNode; n.style.zIndex = 10; if( !tx.omitDescenders ){ if( p.u==0 ){ if( p.hasOwnProperty('mo') && p.r==p.mo ){ var ix = p.hasOwnProperty('cu') ? p.cu : p.mu; var top = tx.rowinfo[ix-tx.iTopRow] drawUpArrow(p,{x: p.x, y: top.y-node.h}, p.fg, p.id); }else if( p.y>100 ){ drawUpArrow(p,{x: p.x, y: p.y-50}, p.fg, p.id); }else{ drawUpArrow(p,{x: p.x, y: 0},p.fg, p.id); } } if( p.hasOwnProperty('d') ){ if( p.y + 150 >= btm ){ drawUpArrow({x: p.x, y: btm - node.h/2},p,p.fg,p.id); }else{ drawUpArrow({x: p.x, y: p.y+50},p,p.fg,p.id); drawDotted({x: p.x, y: p.y+63},{x: p.x, y: p.y+50-node.h/2},p.fg,p.id); } } } if( p.hasOwnProperty('mo') ){ var x0 = p.x + node.w/2; var x1 = p.mo*railPitch + node.w/2; var u = tx.rowinfo[p.mu-tx.iTopRow]; |
︙ | ︙ | |||
324 325 326 327 328 329 330 | x0 = Math.ceil(x0); x1 += line.w; } var y0 = p.y + (node.h-line.w)/2; var u = tx.rowinfo[p.au[i+1]-tx.iTopRow]; if( u.id<p.id ){ drawLine(line,u.fg,x0,y0,x1,null); | | | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | x0 = Math.ceil(x0); x1 += line.w; } var y0 = p.y + (node.h-line.w)/2; var u = tx.rowinfo[p.au[i+1]-tx.iTopRow]; if( u.id<p.id ){ drawLine(line,u.fg,x0,y0,x1,null); drawUpArrow(p,u,u.fg,u.id); }else{ var y1 = u.y + (node.h-line.w)/2; drawLine(wLine,u.fg,x0,y0,x1,null); drawLine(wLine,u.fg,x1-line.w,y0,null,y1+line.w); drawLine(wLine,u.fg,x1,y1,u.x-wArrow.w/2,null); var x = u.x-wArrow.w; var y = u.y+(node.h-wArrow.h)/2; |
︙ | ︙ | |||
388 389 390 391 392 393 394 | var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight; for( var i=0; i<tx.nrail; i++) mergeBtm[i] = btm; for( var i=tx.rowinfo.length-1; i>=0; i-- ){ drawNode(tx.rowinfo[i], btm); } } var selRow; | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight; for( var i=0; i<tx.nrail; i++) mergeBtm[i] = btm; for( var i=tx.rowinfo.length-1; i>=0; i-- ){ drawNode(tx.rowinfo[i], btm); } } var selRow; function clickOnNode(e){ tooltipObj.style.display = "none" var p = tx.rowinfo[parseInt(this.id.match(/\d+$/)[0], 10)-tx.iTopRow]; if( !selRow ){ selRow = p; this.className += " sel"; canvasDiv.className += " sel"; }else if( selRow==p ){ selRow = null; this.className = this.className.replace(" sel", ""); canvasDiv.className = canvasDiv.className.replace(" sel", ""); }else{ if( tx.fileDiff ){ location.href=tx.baseUrl + "/fdiff?v1="+selRow.h+"&v2="+p.h }else{ location.href=tx.baseUrl + "/vdiff?from="+selRow.h+"&to="+p.h } } e.stopPropagation() } function dblclickOnNode(e){ var p = tx.rowinfo[parseInt(this.id.match(/\d+$/)[0], 10)-tx.iTopRow]; window.location.href = tx.baseUrl+"/info/"+p.h e.stopPropagation() } function findTxIndex(e){ /* Look at all the graph elements. If any graph elements that is near ** the click-point "e" and has a "data-ix" attribute, then return ** the value of that attribute. Otherwise return -1 */ var x = e.x + window.pageXOffset - absoluteX(canvasDiv); var y = e.y + window.pageYOffset - absoluteY(canvasDiv); var aNode = canvasDiv.childNodes var nNode = aNode.length; var i; for(i=0;i<nNode;i++){ var n = aNode[i] if( !n.hasAttribute("data-ix") ) continue; if( x<n.offsetLeft-5 ) continue; if( x>n.offsetLeft+n.offsetWidth+5 ) continue; if( y<n.offsetTop-5 ) continue; if( y>n.offsetTop+n.offsetHeight ) continue; return n.getAttribute("data-ix") } return -1 } /* Compute the hyperlink for the branch graph for tx.rowinfo[ix] */ function branchHyperlink(ix){ var br = tx.rowinfo[ix].br var dest = tx.baseUrl + "/timeline?r=" + encodeURIComponent(br) dest += tx.fileDiff ? "&m&cf=" : "&m&c=" dest += encodeURIComponent(tx.rowinfo[ix].h) return dest } function clickOnGraph(e){ var ix = findTxIndex(e); if( ix<0 ){ tooltipObj.style.display = "none" }else{ var br = tx.rowinfo[ix].br var dest = branchHyperlink(ix) var hbr = br.replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """) .replace(/'/g, "'"); tooltipObj.innerHTML = "<a href=\""+dest+"\">"+hbr+"</a>" tooltipObj.style.display = "inline" tooltipObj.style.position = "absolute" var x = e.x + 4 + window.pageXOffset tooltipObj.style.left = x+"px" var y = e.y + window.pageYOffset - tooltipObj.clientHeight - 4 tooltipObj.style.top = y+"px" tooltipObj.style.visibility = "visible" } } function dblclickOnGraph(e){ var ix = findTxIndex(e); var dest = branchHyperlink(ix) tooltipObj.style.display = "none" window.location.href = dest } function changeDisplay(selector,value){ var x = document.getElementsByClassName(selector); var n = x.length; for(var i=0; i<n; i++) {x[i].style.display = value;} } function changeDisplayById(id,value){ |
︙ | ︙ |
Changes to src/http.c.
︙ | ︙ | |||
284 285 286 287 288 289 290 | if( g.zHttpAuth ) free(g.zHttpAuth); } g.zHttpAuth = prompt_for_httpauth_creds(); transport_close(&g.url); return http_exchange(pSend, pReply, useLogin, maxRedirect); } } | | | | | 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | if( g.zHttpAuth ) free(g.zHttpAuth); } g.zHttpAuth = prompt_for_httpauth_creds(); transport_close(&g.url); return http_exchange(pSend, pReply, useLogin, maxRedirect); } } if( rc!=200 && rc!=301 && rc!=302 && rc!=307 && rc!=308 ){ int ii; for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} while( zLine[ii]==' ' ) ii++; fossil_warning("server says: %s", &zLine[ii]); goto write_err; } if( iHttpVersion==0 ){ closeConnection = 1; }else{ closeConnection = 0; } }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err; if( rc!=200 && rc!=301 && rc!=302 && rc!=307 && rc!=308 ){ int ii; for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} while( zLine[ii]==' ' ) ii++; fossil_warning("server says: %s", &zLine[ii]); goto write_err; } closeConnection = 0; }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){ for(i=15; fossil_isspace(zLine[i]); i++){} iLength = atoi(&zLine[i]); }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){ char c; for(i=11; fossil_isspace(zLine[i]); i++){} c = zLine[i]; if( c=='c' || c=='C' ){ closeConnection = 1; }else if( c=='k' || c=='K' ){ closeConnection = 0; } }else if( ( rc==301 || rc==302 || rc==307 || rc==308 ) && fossil_strnicmp(zLine, "location:", 9)==0 ){ int i, j; if ( --maxRedirect == 0){ fossil_warning("redirect limit exceeded"); goto write_err; } |
︙ | ︙ | |||
343 344 345 346 347 348 349 | fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); url_parse(&zLine[i], 0); transport_close(&g.url); transport_global_shutdown(&g.url); fSeenHttpAuth = 0; if( g.zHttpAuth ) free(g.zHttpAuth); g.zHttpAuth = get_httpauth(); | | | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); url_parse(&zLine[i], 0); transport_close(&g.url); transport_global_shutdown(&g.url); fSeenHttpAuth = 0; if( g.zHttpAuth ) free(g.zHttpAuth); g.zHttpAuth = get_httpauth(); if( rc==301 || rc==308 ) url_remember(); return http_exchange(pSend, pReply, useLogin, maxRedirect); }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){ isCompressed = 0; }else if( fossil_strnicmp(&zLine[14], "application/x-fossil-uncompressed", -1)==0 ){ isCompressed = 0; |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
786 787 788 789 790 791 792 793 794 795 796 797 798 799 | length = strlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; } case etJSONSTR: { int limit = flag_alternateform ? va_arg(ap,int) : -1; char *zMem = va_arg(ap,char*); if( zMem==0 ) zMem = ""; zExtra = bufpt = encode_json_string_literal(zMem); length = strlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; } case etWIKISTR: { | > > > > > | 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 | length = strlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; } case etJSONSTR: { int limit = flag_alternateform ? va_arg(ap,int) : -1; char *zMem = va_arg(ap,char*); if( limit!=0 ){ /* Ignore the limit flag, if set, for JSON string ** output. This block exists to squelch the associated ** "unused variable" compiler warning. */ } if( zMem==0 ) zMem = ""; zExtra = bufpt = encode_json_string_literal(zMem); length = strlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; } case etWIKISTR: { |
︙ | ︙ |
Changes to src/style.c.
︙ | ︙ | |||
576 577 578 579 580 581 582 583 584 585 586 587 588 589 | if( needHrefJs ){ int nDelay = db_get_int("auto-hyperlink-delay",0); int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0); @ <script id='href-data' type='application/json'>\ @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script> } @ <script nonce="%h(style_nonce())"> if( needHrefJs ){ cgi_append_content(builtin_text("href.js"),-1); } if( needSortJs ){ cgi_append_content(builtin_text("sorttable.js"),-1); } if( needGraphJs ){ | > > > > | 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 | if( needHrefJs ){ int nDelay = db_get_int("auto-hyperlink-delay",0); int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0); @ <script id='href-data' type='application/json'>\ @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script> } @ <script nonce="%h(style_nonce())"> @ function debugMsg(msg){ @ var n = document.getElementById("debugMsg"); @ if(n){n.textContent=msg;} @ } if( needHrefJs ){ cgi_append_content(builtin_text("href.js"),-1); } if( needSortJs ){ cgi_append_content(builtin_text("sorttable.js"),-1); } if( needGraphJs ){ |
︙ | ︙ | |||
626 627 628 629 630 631 632 633 634 635 636 637 638 639 | */ cgi_destination(CGI_HEADER); if( nSubmenu+nSubmenuCtrl>0 ){ int i; if( nSubmenuCtrl ){ @ <form id='f01' method='GET' action='%R/%s(g.zPath)'> @ <input type='hidden' name='udc' value='1'> } @ <div class="submenu"> if( nSubmenu>0 ){ qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare); for(i=0; i<nSubmenu; i++){ struct Submenu *p = &aSubmenu[i]; if( p->zLink==0 ){ | > | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | */ cgi_destination(CGI_HEADER); if( nSubmenu+nSubmenuCtrl>0 ){ int i; if( nSubmenuCtrl ){ @ <form id='f01' method='GET' action='%R/%s(g.zPath)'> @ <input type='hidden' name='udc' value='1'> cgi_tag_query_parameter("udc"); } @ <div class="submenu"> if( nSubmenu>0 ){ qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare); for(i=0; i<nSubmenu; i++){ struct Submenu *p = &aSubmenu[i]; if( p->zLink==0 ){ |
︙ | ︙ | |||
740 741 742 743 744 745 746 | @ </div> }else{ if( zAd ){ @ <div class="adunit_banner"> cgi_append_content(zAd, -1); @ </div> } | | | 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 | @ </div> }else{ if( zAd ){ @ <div class="adunit_banner"> cgi_append_content(zAd, -1); @ </div> } @ <div class="content"><span id="debugMsg"></span> } cgi_destination(CGI_BODY); if( sideboxUsed ){ /* Put the footer at the bottom of the page. ** the additional clear/both is needed to extend the content ** part to the end of an optional sidebox. |
︙ | ︙ |
Changes to src/timeline.c.
︙ | ︙ | |||
900 901 902 903 904 905 906 907 908 909 910 911 912 913 | ** negative, then the rail position is the absolute value of mi[] ** and a thin merge-arrow descender is drawn to the bottom of ** the screen. This array is omitted if there are no inbound ** merges. ** ci: "cherrypick-in". Like "mi" except for cherrypick merges. ** omitted if there are no cherrypick merges. ** h: The artifact hash of the object being graphed */ for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ int k = 0; cgi_printf("{\"id\":%d,", pRow->idx); cgi_printf("\"bg\":\"%s\",", pRow->zBgClr); cgi_printf("\"r\":%d,", pRow->iRail); if( pRow->bDescender ){ | > | 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 | ** negative, then the rail position is the absolute value of mi[] ** and a thin merge-arrow descender is drawn to the bottom of ** the screen. This array is omitted if there are no inbound ** merges. ** ci: "cherrypick-in". Like "mi" except for cherrypick merges. ** omitted if there are no cherrypick merges. ** h: The artifact hash of the object being graphed * br: The branch to which the artifact belongs */ for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ int k = 0; cgi_printf("{\"id\":%d,", pRow->idx); cgi_printf("\"bg\":\"%s\",", pRow->zBgClr); cgi_printf("\"r\":%d,", pRow->iRail); if( pRow->bDescender ){ |
︙ | ︙ | |||
973 974 975 976 977 978 979 980 981 982 983 984 985 986 | } k++; cgi_printf("%c%d", cSep, mi); cSep = ','; } } if( k ) cgi_printf("],"); cgi_printf("\"h\":\"%!S\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "]\n"); } @ }</script> style_graph_generator(); graph_free(pGraph); } | > | 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 | } k++; cgi_printf("%c%d", cSep, mi); cSep = ','; } } if( k ) cgi_printf("],"); cgi_printf("\"br\":\"%j\",", pRow->zBranch ? pRow->zBranch : ""); cgi_printf("\"h\":\"%!S\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "]\n"); } @ }</script> style_graph_generator(); graph_free(pGraph); } |
︙ | ︙ | |||
1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 | ** WEBPAGE: timeline ** ** Query parameters: ** ** a=TIMEORTAG After this event ** b=TIMEORTAG Before this event ** c=TIMEORTAG "Circa" this event ** m=TIMEORTAG Mark this event ** n=COUNT Maximum number of events. "all" for no limit ** p=CHECKIN Parents and ancestors of CHECKIN ** d=CHECKIN Children and descendants of CHECKIN ** dp=CHECKIN The same as d=CHECKIN&p=CHECKIN ** t=TAG Show only check-ins with the given TAG ** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel | > | 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 | ** WEBPAGE: timeline ** ** Query parameters: ** ** a=TIMEORTAG After this event ** b=TIMEORTAG Before this event ** c=TIMEORTAG "Circa" this event ** cf=FILEHASH "Circa" the first use of the file with FILEHASH ** m=TIMEORTAG Mark this event ** n=COUNT Maximum number of events. "all" for no limit ** p=CHECKIN Parents and ancestors of CHECKIN ** d=CHECKIN Children and descendants of CHECKIN ** dp=CHECKIN The same as d=CHECKIN&p=CHECKIN ** t=TAG Show only check-ins with the given TAG ** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel |
︙ | ︙ | |||
1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 | } if( zType[0]=='a' || zType[0]=='c' ){ cookie_write_parameter("y","y",zType); } cookie_render(); url_initialize(&url, "timeline"); cgi_query_parameters_to_url(&url); /* Convert r=TAG to t=TAG&rel. */ if( zBrName && !related ){ cgi_delete_query_parameter("r"); cgi_set_query_parameter("t", zBrName); cgi_set_query_parameter("rel", "1"); zTagName = zBrName; | > > > > > > > > > > > > | 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 | } if( zType[0]=='a' || zType[0]=='c' ){ cookie_write_parameter("y","y",zType); } cookie_render(); url_initialize(&url, "timeline"); cgi_query_parameters_to_url(&url); /* Convert the cf=FILEHASH query parameter into a c=CHECKINHASH value */ if( P("cf")!=0 ){ zCirca = db_text(0, "SELECT (SELECT uuid FROM blob WHERE rid=mlink.mid)" " FROM mlink, event" " WHERE mlink.fid=(SELECT rid FROM blob WHERE uuid LIKE '%q%%')" " AND event.objid=mlink.mid" " ORDER BY event.mtime LIMIT 1", P("cf") ); } /* Convert r=TAG to t=TAG&rel. */ if( zBrName && !related ){ cgi_delete_query_parameter("r"); cgi_set_query_parameter("t", zBrName); cgi_set_query_parameter("rel", "1"); zTagName = zBrName; |
︙ | ︙ | |||
1992 1993 1994 1995 1996 1997 1998 1999 | } if( zYearMonth ){ zYearMonth = timeline_expand_datetime(zYearMonth); blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%m',event.mtime) ", zYearMonth); } else if( zYearWeek ){ zYearWeek = timeline_expand_datetime(zYearWeek); | > | | 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 | } if( zYearMonth ){ zYearMonth = timeline_expand_datetime(zYearMonth); blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%m',event.mtime) ", zYearMonth); } else if( zYearWeek ){ char *z; zYearWeek = timeline_expand_datetime(zYearWeek); z = db_text(0, "SELECT strftime('%%Y-%%W',%Q)", zYearWeek); if( z && z[0] ){ zYearWeekStart = db_text(0, "SELECT date(%Q,'-6 days','weekday 1')", zYearWeek); zYearWeek = z; }else{ if( strlen(zYearWeek)==7 ){ zYearWeekStart = db_text(0, |
︙ | ︙ |
Changes to src/user.c.
︙ | ︙ | |||
496 497 498 499 500 501 502 503 504 505 506 507 508 509 | ** (7) Try the USERNAME environment variable. ** ** (8) Check if the user can be extracted from the remote URL. ** ** The user name is stored in g.zLogin. The uid is in g.userUid. */ void user_select(void){ if( g.userUid ) return; if( g.zLogin ){ if( attempt_user(g.zLogin)==0 ){ fossil_fatal("no such user: %s", g.zLogin); }else{ return; } | > | 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 | ** (7) Try the USERNAME environment variable. ** ** (8) Check if the user can be extracted from the remote URL. ** ** The user name is stored in g.zLogin. The uid is in g.userUid. */ void user_select(void){ UrlData url; if( g.userUid ) return; if( g.zLogin ){ if( attempt_user(g.zLogin)==0 ){ fossil_fatal("no such user: %s", g.zLogin); }else{ return; } |
︙ | ︙ | |||
517 518 519 520 521 522 523 | if( attempt_user(fossil_getenv("USER")) ) return; if( attempt_user(fossil_getenv("LOGNAME")) ) return; if( attempt_user(fossil_getenv("USERNAME")) ) return; | > | | | 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 | if( attempt_user(fossil_getenv("USER")) ) return; if( attempt_user(fossil_getenv("LOGNAME")) ) return; if( attempt_user(fossil_getenv("USERNAME")) ) return; memset(&url, 0, sizeof(url)); url_parse_local(0, 0, &url); if( url.user && attempt_user(url.user) ) return; fossil_print( "Cannot figure out who you are! Consider using the --user\n" "command line option, setting your USER environment variable,\n" "or setting a default user with \"fossil user default USER\".\n" ); fossil_fatal("cannot determine user"); |
︙ | ︙ |
Changes to www/changes.wiki.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <title>Change Log</title> <a name='v2_9'></a> <h2>Changes for Version 2.9 (pending)</h2> * Added the [/help?cmd=git|fossil git export] command and instructions for [./mirrortogithub.md|creating a GitHub mirror of a Fossil project]. * Improved handling of relative hyperlinks on the [/help?cmd=/artifact|/artifact] pages for wiki. For example, hyperlinks and the lizard <img> now work correctly for both [/artifact/2ff24ab0887cf522] and [/doc/0d7ac90d575004c2415/www/index.wiki]. * Many documentation enhancements. * For the "[/help?cmd=update|fossil update]" and "[/help?cmd=checkout|fossil checkout]" commands, if a managed file is removed because it is no longer part of the target check-in and the directory containing the file is empty after the file is removed and the directory is not the current working directory and is not on the [/help?cmd=empty-dirs|empty-dirs] list, then also remove the directory. * Update internal Unicode character tables, used in regular expression handling, from version 11.0 to 12.1. * In "[/help?cmd=regexp|fossil regexp]", "[/help?cmd=grep|fossil grep]" and the TH1 "regexp" command, the -nocase option now removes multiple diacritics from the same character (derived from SQLite's remove_diacritics=2) * Added the [/help?cmd=/secureraw|/secureraw] page that requires the complete SHA1 or SHA3 hash, not just a prefix, before it will deliver content. * Accept purely numeric ISO8601 date/time strings as long as they do not conflict with a hash. Example: "20190510134217" instead of | > > | > | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <title>Change Log</title> <a name='v2_9'></a> <h2>Changes for Version 2.9 (pending)</h2> * Added the [/help?cmd=git|fossil git export] command and instructions for [./mirrortogithub.md|creating a GitHub mirror of a Fossil project]. * Improved handling of relative hyperlinks on the [/help?cmd=/artifact|/artifact] pages for wiki. For example, hyperlinks and the lizard <img> now work correctly for both [/artifact/2ff24ab0887cf522] and [/doc/0d7ac90d575004c2415/www/index.wiki]. * Enhancements to the timeline graph layout, to show more information with less clutter. * Many documentation enhancements. * For the "[/help?cmd=update|fossil update]" and "[/help?cmd=checkout|fossil checkout]" commands, if a managed file is removed because it is no longer part of the target check-in and the directory containing the file is empty after the file is removed and the directory is not the current working directory and is not on the [/help?cmd=empty-dirs|empty-dirs] list, then also remove the directory. * Update internal Unicode character tables, used in regular expression handling, from version 11.0 to 12.1. * In "[/help?cmd=regexp|fossil regexp]", "[/help?cmd=grep|fossil grep]" and the TH1 "regexp" command, the -nocase option now removes multiple diacritics from the same character (derived from SQLite's remove_diacritics=2) * Added the [/help?cmd=/secureraw|/secureraw] page that requires the complete SHA1 or SHA3 hash, not just a prefix, before it will deliver content. * Accept purely numeric ISO8601 date/time strings as long as they do not conflict with a hash. Example: "20190510134217" instead of "2019-05-10 13:42:17". This helps keep URLs shorter and less complicated * Support both "1)" and "1." for numbered lists in markdown, as commonmark does. * The sync and clone HTTP requests omit the extra /xfer path element from the end of the request URI. All servers since 2010 know that the HTTP request is for a sync or clone from the mimetype so the extra path element is not needed. * If an automatic sync gets a permanent redirect request, then update the saved remote URL to the new address. * Temporary filenames (for example used for external "diff" commands) try to preserve the suffix of the original file. * Added the [/help?cmd=/thisdayinhistory|/thisdayinhistory] web page. * Enhanced parsing of [/help?cmd=/timeline|/timeline] query parameters "ymd=", "ym=", and "yw=". All arguments are option (in which case they default to the current time) and all accept ISO8601 date/times without punctuation. * Automatically disapprove pending moderation requests for a user when that user is deleted. This helps in dealing with spam-bots. * Improvements to the "Capability Summary" section in the [/help?cmd=/secaudit0|Security Audit] web-page. <a name='v2_8'></a> <h2>Changes for Version 2.8 (2019-02-20)</h2> * Show cherry-pick merges as dotted lines on the timeline graph. |
︙ | ︙ |