##// END OF EJS Templates
manifest: persist the manifestfulltext cache...
manifest: persist the manifestfulltext cache Reconstructing the manifest from the revlog takes time, so much so that there already is a LRU cache to avoid having to load a manifest multiple times. This patch persists that LRU cache in the .hg/cache directory, so we can re-use this cache across hg commands. Commit benchmark (run on Macos 10.13 on a 2017-model Macbook Pro with Core i7 2.9GHz and flash drive), testing without and with patch run 5 times, baseline is r2a227782e754: * committing to an existing file, against the mozilla-central repository. Baseline real time average 1.9692, with patch 1.3786. A new debugcommand "hg debugmanifestfulltextcache" lets you inspect the cache, clear it, or add specific manifest nodeids to it. When calling repo.updatecaches(), the manifest(s) for the working copy parents are added to the cache. The hg perfmanifest command has an additional --clear-disk switch to clear this cache when testing manifest loading performance. Using this command to test performance on the firefox repository for revision f947d902ed91, whose manifest has a delta chain length of 60540, we see: $ hg perfmanifest f947d902ed91 --clear-disk ! wall 0.972253 comb 0.970000 user 0.850000 sys 0.120000 (best of 10) $ hg debugmanifestfulltextcache -a `hg log --debug -r f947d902ed91 | grep manifest | cut -d: -f3` Cache contains 1 manifest entries, in order of most to least recent: id: 0294517df4aad07c70701db43bc7ff24c3ce7dbc, size 25.6 MB Total cache data size 25.6 MB, on-disk 0 bytes $ hg perfmanifest f947d902ed91 ! wall 0.036748 comb 0.040000 user 0.020000 sys 0.020000 (best of 100) Worst-case scenario: a manifest text loaded from a single delta; in the firefox repository manifest node 9a1246ff762e is the chain base for the manifest attached to revision f947d902ed91. Loading this from a full cache file is just as fast as without the cache; the extra node ids ensure a big full cache: $ for node in 9a1246ff762e 1a1922c14a3e 54a31d11a36a 0294517df4aa; do > hgd debugmanifestfulltextcache -a $node > /dev/null > done $ hgd perfmanifest -m 9a1246ff762e ! wall 0.077513 comb 0.080000 user 0.030000 sys 0.050000 (best of 100) $ hgd perfmanifest -m 9a1246ff762e --clear-disk ! wall 0.078547 comb 0.080000 user 0.070000 sys 0.010000 (best of 100)

File last commit:

r37509:685ad41f default
r38803:0a57945a default
Show More
followlines.js
286 lines | 10.6 KiB | application/javascript | JavascriptLexer
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 // followlines.js - JavaScript utilities for followlines UI
//
// Copyright 2017 Logilab SA <contact@logilab.fr>
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
//** Install event listeners for line block selection and followlines action */
document.addEventListener('DOMContentLoaded', function() {
var sourcelines = document.getElementsByClassName('sourcelines')[0];
if (typeof sourcelines === 'undefined') {
return;
}
// URL to complement with "linerange" query parameter
var targetUri = sourcelines.dataset.logurl;
av6
hgweb: use strict equals, remove non-breaking space in followlines.js...
r35157 if (typeof targetUri === 'undefined') {
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 return;
}
Denis Laxalde
hgweb: parameterize the tag name of elements holding followlines selection...
r32993 // Tag of children of "sourcelines" element on which to add "line
// selection" style.
var selectableTag = sourcelines.dataset.selectabletag;
if (typeof selectableTag === 'undefined') {
return;
}
Denis Laxalde
hgweb: do not show "descending" link in followlines UI for filelog heads...
r32070 var isHead = parseInt(sourcelines.dataset.ishead || "0");
Denis Laxalde
hgweb: position the "followlines" box close to latest cursor position
r31849 //* position "element" on top-right of cursor */
function positionTopRight(element, event) {
var x = (event.clientX + 10) + 'px',
y = (event.clientY - 20) + 'px';
element.style.top = y;
element.style.left = x;
}
Denis Laxalde
hgweb: parameterize the tag name of elements holding followlines selection...
r32993 // retrieve all direct *selectable* children of class="sourcelines"
// element
var selectableElements = Array.prototype.filter.call(
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 sourcelines.children,
av6
hgweb: add missing semicolons to followlines.js...
r35027 function(x) { return x.tagName === selectableTag; });
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 var btnTitleStart = 'start following lines history from here';
var btnTitleEnd = 'terminate line block selection here';
//** return a <button> element with +/- spans */
function createButton() {
var btn = document.createElement('button');
btn.title = btnTitleStart;
btn.classList.add('btn-followlines');
var plusSpan = document.createElement('span');
plusSpan.classList.add('followlines-plus');
plusSpan.textContent = '+';
btn.appendChild(plusSpan);
var br = document.createElement('br');
btn.appendChild(br);
var minusSpan = document.createElement('span');
minusSpan.classList.add('followlines-minus');
minusSpan.textContent = '−';
btn.appendChild(minusSpan);
return btn;
}
// extend DOM with CSS class for selection highlight and action buttons
av6
hgweb: add missing semicolons to followlines.js...
r35027 var followlinesButtons = [];
Denis Laxalde
hgweb: parameterize the tag name of elements holding followlines selection...
r32993 for (var i = 0; i < selectableElements.length; i++) {
selectableElements[i].classList.add('followlines-select');
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 var btn = createButton();
followlinesButtons.push(btn);
// insert the <button> as child of `selectableElements[i]` unless the
// latter has itself a child with a "followlines-btn-parent" class
// (annotate view)
var btnSupportElm = selectableElements[i];
var childSupportElms = btnSupportElm.getElementsByClassName(
'followlines-btn-parent');
if ( childSupportElms.length > 0 ) {
btnSupportElm = childSupportElms[0];
}
av6
hgweb: insert followlines buttons before any children, including text nodes...
r37509 var refNode = btnSupportElm.childNodes[0]; // node to insert <button> before
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 btnSupportElm.insertBefore(btn, refNode);
}
// ** re-initialize followlines buttons */
function resetButtons() {
for (var i = 0; i < followlinesButtons.length; i++) {
var btn = followlinesButtons[i];
btn.title = btnTitleStart;
btn.classList.remove('btn-followlines-end');
btn.classList.remove('btn-followlines-hidden');
}
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 }
var lineSelectedCSSClass = 'followlines-selected';
Denis Laxalde
hgweb: parameterize the tag name of elements holding followlines selection...
r32993 //** add CSS class on selectable elements in `from`-`to` line range */
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 function addSelectedCSSClass(from, to) {
for (var i = from; i <= to; i++) {
Denis Laxalde
hgweb: parameterize the tag name of elements holding followlines selection...
r32993 selectableElements[i].classList.add(lineSelectedCSSClass);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 }
}
//** remove CSS class from previously selected lines */
function removeSelectedCSSClass() {
var elements = sourcelines.getElementsByClassName(
lineSelectedCSSClass);
while (elements.length) {
elements[0].classList.remove(lineSelectedCSSClass);
}
}
Denis Laxalde
hgweb: parameterize the tag name of elements holding followlines selection...
r32993 // ** return the element of type "selectableTag" parent of `element` */
function selectableParent(element) {
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 var parent = element.parentElement;
if (parent === null) {
return null;
}
av6
hgweb: use strict equals, remove non-breaking space in followlines.js...
r35157 if (element.tagName === selectableTag && parent.isSameNode(sourcelines)) {
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 return element;
}
Denis Laxalde
hgweb: parameterize the tag name of elements holding followlines selection...
r32993 return selectableParent(parent);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 }
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 // ** update buttons title and style upon first click */
function updateButtons(selectable) {
for (var i = 0; i < followlinesButtons.length; i++) {
var btn = followlinesButtons[i];
btn.title = btnTitleEnd;
btn.classList.add('btn-followlines-end');
}
// on clicked button, change title to "cancel"
var clicked = selectable.getElementsByClassName('btn-followlines')[0];
clicked.title = 'cancel';
clicked.classList.remove('btn-followlines-end');
}
//** add `listener` on "click" event for all `followlinesButtons` */
function buttonsAddEventListener(listener) {
for (var i = 0; i < followlinesButtons.length; i++) {
followlinesButtons[i].addEventListener('click', listener);
}
}
//** remove `listener` on "click" event for all `followlinesButtons` */
function buttonsRemoveEventListener(listener) {
for (var i = 0; i < followlinesButtons.length; i++) {
followlinesButtons[i].removeEventListener('click', listener);
}
}
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 //** event handler for "click" on the first line of a block */
function lineSelectStart(e) {
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 var startElement = selectableParent(e.target.parentElement);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 if (startElement === null) {
Denis Laxalde
hgweb: parameterize the tag name of elements holding followlines selection...
r32993 // not a "selectable" element (maybe <a>): abort, keeping event
// listener registered for other click with a "selectable" target
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 return;
}
Denis Laxalde
hgweb: add a floating tooltip to invite on followlines action...
r31848
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 // update button tooltip text and CSS
updateButtons(startElement);
Denis Laxalde
hgweb: add a floating tooltip to invite on followlines action...
r31848
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 var startId = parseInt(startElement.id.slice(1));
startElement.classList.add(lineSelectedCSSClass); // CSS
// remove this event listener
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 buttonsRemoveEventListener(lineSelectStart);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785
//** event handler for "click" on the last line of the block */
function lineSelectEnd(e) {
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 var endElement = selectableParent(e.target.parentElement);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 if (endElement === null) {
// not a <span> (maybe <a>): abort, keeping event listener
// registered for other click with <span> target
return;
}
// remove this event listener
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 buttonsRemoveEventListener(lineSelectEnd);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 // reset button tooltip text
resetButtons();
Denis Laxalde
hgweb: add a floating tooltip to invite on followlines action...
r31848
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 // compute line range (startId, endId)
var endId = parseInt(endElement.id.slice(1));
av6
hgweb: use strict equals, remove non-breaking space in followlines.js...
r35157 if (endId === startId) {
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 // clicked twice the same line, cancel and reset initial state
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 // (CSS, event listener for selection start)
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 removeSelectedCSSClass();
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 buttonsAddEventListener(lineSelectStart);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 return;
}
var inviteElement = endElement;
if (endId < startId) {
var tmp = endId;
endId = startId;
startId = tmp;
inviteElement = startElement;
}
addSelectedCSSClass(startId - 1, endId -1); // CSS
// append the <div id="followlines"> element to last line of the
// selection block
Denis Laxalde
hgweb: do not show "descending" link in followlines UI for filelog heads...
r32070 var divAndButton = followlinesBox(targetUri, startId, endId, isHead);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 var div = divAndButton[0],
button = divAndButton[1];
inviteElement.appendChild(div);
Denis Laxalde
hgweb: position the "followlines" box close to latest cursor position
r31849 // set position close to cursor (top-right)
positionTopRight(div, e);
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 // hide all buttons
for (var i = 0; i < followlinesButtons.length; i++) {
followlinesButtons[i].classList.add('btn-followlines-hidden');
}
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785
//** event handler for cancelling selection */
function cancel() {
// remove invite box
div.parentNode.removeChild(div);
// restore initial event listeners
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 buttonsAddEventListener(lineSelectStart);
buttonsRemoveEventListener(cancel);
for (var i = 0; i < followlinesButtons.length; i++) {
followlinesButtons[i].classList.remove('btn-followlines-hidden');
}
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 // remove styles on selected lines
removeSelectedCSSClass();
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 resetButtons();
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 }
// bind cancel event to click on <button>
button.addEventListener('click', cancel);
// as well as on an click on any source line
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 buttonsAddEventListener(cancel);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 }
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 buttonsAddEventListener(lineSelectEnd);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785
}
Denis Laxalde
hgweb: re-implement followlines UI selection using buttons...
r33390 buttonsAddEventListener(lineSelectStart);
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785
//** return a <div id="followlines"> and inner cancel <button> elements */
Denis Laxalde
hgweb: do not show "descending" link in followlines UI for filelog heads...
r32070 function followlinesBox(targetUri, fromline, toline, isHead) {
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 // <div id="followlines">
var div = document.createElement('div');
div.id = 'followlines';
// <div class="followlines-cancel">
var buttonDiv = document.createElement('div');
buttonDiv.classList.add('followlines-cancel');
// <button>x</button>
var button = document.createElement('button');
button.textContent = 'x';
buttonDiv.appendChild(button);
div.appendChild(buttonDiv);
// <div class="followlines-link">
var aDiv = document.createElement('div');
aDiv.classList.add('followlines-link');
Denis Laxalde
hgweb: add a link to followlines in descending direction...
r31940 aDiv.textContent = 'follow history of lines ' + fromline + ':' + toline + ':';
var linesep = document.createElement('br');
aDiv.appendChild(linesep);
// link to "ascending" followlines
var aAsc = document.createElement('a');
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 var url = targetUri + '?patch=&linerange=' + fromline + ':' + toline;
Denis Laxalde
hgweb: add a link to followlines in descending direction...
r31940 aAsc.setAttribute('href', url);
Denis Laxalde
hgweb: change text of followlines links to "older / newer"...
r32071 aAsc.textContent = 'older';
Denis Laxalde
hgweb: add a link to followlines in descending direction...
r31940 aDiv.appendChild(aAsc);
Denis Laxalde
hgweb: do not show "descending" link in followlines UI for filelog heads...
r32070
if (!isHead) {
var sep = document.createTextNode(' / ');
aDiv.appendChild(sep);
// link to "descending" followlines
var aDesc = document.createElement('a');
aDesc.setAttribute('href', url + '&descend=');
Denis Laxalde
hgweb: change text of followlines links to "older / newer"...
r32071 aDesc.textContent = 'newer';
Denis Laxalde
hgweb: do not show "descending" link in followlines UI for filelog heads...
r32070 aDiv.appendChild(aDesc);
}
Denis Laxalde
hgweb: add a link to followlines in descending direction...
r31940
Denis Laxalde
hgweb: rename linerangelog.js as followlines.js...
r31785 div.appendChild(aDiv);
return [div, button];
}
}, false);