about summary refs log tree commit diff
path: root/third_party/git/gitweb/static/js/blame_incremental.js
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/git/gitweb/static/js/blame_incremental.js')
-rw-r--r--third_party/git/gitweb/static/js/blame_incremental.js692
1 files changed, 0 insertions, 692 deletions
diff --git a/third_party/git/gitweb/static/js/blame_incremental.js b/third_party/git/gitweb/static/js/blame_incremental.js
deleted file mode 100644
index db6eb50584..0000000000
--- a/third_party/git/gitweb/static/js/blame_incremental.js
+++ /dev/null
@@ -1,692 +0,0 @@
-// Copyright (C) 2007, Fredrik Kuivinen <frekui@gmail.com>
-//               2007, Petr Baudis <pasky@suse.cz>
-//          2008-2011, Jakub Narebski <jnareb@gmail.com>
-
-/**
- * @fileOverview JavaScript side of Ajax-y 'blame_incremental' view in gitweb
- * @license GPLv2 or later
- */
-
-/* ============================================================ */
-/*
- * This code uses DOM methods instead of (nonstandard) innerHTML
- * to modify page.
- *
- * innerHTML is non-standard IE extension, though supported by most
- * browsers; however Firefox up to version 1.5 didn't implement it in
- * a strict mode (application/xml+xhtml mimetype).
- *
- * Also my simple benchmarks show that using elem.firstChild.data =
- * 'content' is slightly faster than elem.innerHTML = 'content'.  It
- * is however more fragile (text element fragment must exists), and
- * less feature-rich (we cannot add HTML).
- *
- * Note that DOM 2 HTML is preferred over generic DOM 2 Core; the
- * equivalent using DOM 2 Core is usually shown in comments.
- */
-
-
-/* ............................................................ */
-/* utility/helper functions (and variables) */
-
-var projectUrl; // partial query + separator ('?' or ';')
-
-// 'commits' is an associative map. It maps SHA1s to Commit objects.
-var commits = {};
-
-/**
- * constructor for Commit objects, used in 'blame'
- * @class Represents a blamed commit
- * @param {String} sha1: SHA-1 identifier of a commit
- */
-function Commit(sha1) {
-	if (this instanceof Commit) {
-		this.sha1 = sha1;
-		this.nprevious = 0; /* number of 'previous', effective parents */
-	} else {
-		return new Commit(sha1);
-	}
-}
-
-/* ............................................................ */
-/* progress info, timing, error reporting */
-
-var blamedLines = 0;
-var totalLines  = '???';
-var div_progress_bar;
-var div_progress_info;
-
-/**
- * Detects how many lines does a blamed file have,
- * This information is used in progress info
- *
- * @returns {Number|String} Number of lines in file, or string '...'
- */
-function countLines() {
-	var table =
-		document.getElementById('blame_table') ||
-		document.getElementsByTagName('table')[0];
-
-	if (table) {
-		return table.getElementsByTagName('tr').length - 1; // for header
-	} else {
-		return '...';
-	}
-}
-
-/**
- * update progress info and length (width) of progress bar
- *
- * @globals div_progress_info, div_progress_bar, blamedLines, totalLines
- */
-function updateProgressInfo() {
-	if (!div_progress_info) {
-		div_progress_info = document.getElementById('progress_info');
-	}
-	if (!div_progress_bar) {
-		div_progress_bar = document.getElementById('progress_bar');
-	}
-	if (!div_progress_info && !div_progress_bar) {
-		return;
-	}
-
-	var percentage = Math.floor(100.0*blamedLines/totalLines);
-
-	if (div_progress_info) {
-		div_progress_info.firstChild.data  = blamedLines + ' / ' + totalLines +
-			' (' + padLeftStr(percentage, 3, '\u00A0') + '%)';
-	}
-
-	if (div_progress_bar) {
-		//div_progress_bar.setAttribute('style', 'width: '+percentage+'%;');
-		div_progress_bar.style.width = percentage + '%';
-	}
-}
-
-
-var t_interval_server = '';
-var cmds_server = '';
-var t0 = new Date();
-
-/**
- * write how much it took to generate data, and to run script
- *
- * @globals t0, t_interval_server, cmds_server
- */
-function writeTimeInterval() {
-	var info_time = document.getElementById('generating_time');
-	if (!info_time || !t_interval_server) {
-		return;
-	}
-	var t1 = new Date();
-	info_time.firstChild.data += ' + (' +
-		t_interval_server + ' sec server blame_data / ' +
-		(t1.getTime() - t0.getTime())/1000 + ' sec client JavaScript)';
-
-	var info_cmds = document.getElementById('generating_cmd');
-	if (!info_time || !cmds_server) {
-		return;
-	}
-	info_cmds.firstChild.data += ' + ' + cmds_server;
-}
-
-/**
- * show an error message alert to user within page (in progress info area)
- * @param {String} str: plain text error message (no HTML)
- *
- * @globals div_progress_info
- */
-function errorInfo(str) {
-	if (!div_progress_info) {
-		div_progress_info = document.getElementById('progress_info');
-	}
-	if (div_progress_info) {
-		div_progress_info.className = 'error';
-		div_progress_info.firstChild.data = str;
-	}
-}
-
-/* ............................................................ */
-/* coloring rows during blame_data (git blame --incremental) run */
-
-/**
- * used to extract N from 'colorN', where N is a number,
- * @constant
- */
-var colorRe = /\bcolor([0-9]*)\b/;
-
-/**
- * return N if <tr class="colorN">, otherwise return null
- * (some browsers require CSS class names to begin with letter)
- *
- * @param {HTMLElement} tr: table row element to check
- * @param {String} tr.className: 'class' attribute of tr element
- * @returns {Number|null} N if tr.className == 'colorN', otherwise null
- *
- * @globals colorRe
- */
-function getColorNo(tr) {
-	if (!tr) {
-		return null;
-	}
-	var className = tr.className;
-	if (className) {
-		var match = colorRe.exec(className);
-		if (match) {
-			return parseInt(match[1], 10);
-		}
-	}
-	return null;
-}
-
-var colorsFreq = [0, 0, 0];
-/**
- * return one of given possible colors (currently least used one)
- * example: chooseColorNoFrom(2, 3) returns 2 or 3
- *
- * @param {Number[]} arguments: one or more numbers
- *        assumes that  1 <= arguments[i] <= colorsFreq.length
- * @returns {Number} Least used color number from arguments
- * @globals colorsFreq
- */
-function chooseColorNoFrom() {
-	// choose the color which is least used
-	var colorNo = arguments[0];
-	for (var i = 1; i < arguments.length; i++) {
-		if (colorsFreq[arguments[i]-1] < colorsFreq[colorNo-1]) {
-			colorNo = arguments[i];
-		}
-	}
-	colorsFreq[colorNo-1]++;
-	return colorNo;
-}
-
-/**
- * given two neighbor <tr> elements, find color which would be different
- * from color of both of neighbors; used to 3-color blame table
- *
- * @param {HTMLElement} tr_prev
- * @param {HTMLElement} tr_next
- * @returns {Number} color number N such that
- * colorN != tr_prev.className && colorN != tr_next.className
- */
-function findColorNo(tr_prev, tr_next) {
-	var color_prev = getColorNo(tr_prev);
-	var color_next = getColorNo(tr_next);
-
-
-	// neither of neighbors has color set
-	// THEN we can use any of 3 possible colors
-	if (!color_prev && !color_next) {
-		return chooseColorNoFrom(1,2,3);
-	}
-
-	// either both neighbors have the same color,
-	// or only one of neighbors have color set
-	// THEN we can use any color except given
-	var color;
-	if (color_prev === color_next) {
-		color = color_prev; // = color_next;
-	} else if (!color_prev) {
-		color = color_next;
-	} else if (!color_next) {
-		color = color_prev;
-	}
-	if (color) {
-		return chooseColorNoFrom((color % 3) + 1, ((color+1) % 3) + 1);
-	}
-
-	// neighbors have different colors
-	// THEN there is only one color left
-	return (3 - ((color_prev + color_next) % 3));
-}
-
-/* ............................................................ */
-/* coloring rows like 'blame' after 'blame_data' finishes */
-
-/**
- * returns true if given row element (tr) is first in commit group
- * to be used only after 'blame_data' finishes (after processing)
- *
- * @param {HTMLElement} tr: table row
- * @returns {Boolean} true if TR is first in commit group
- */
-function isStartOfGroup(tr) {
-	return tr.firstChild.className === 'sha1';
-}
-
-/**
- * change colors to use zebra coloring (2 colors) instead of 3 colors
- * concatenate neighbor commit groups belonging to the same commit
- *
- * @globals colorRe
- */
-function fixColorsAndGroups() {
-	var colorClasses = ['light', 'dark'];
-	var linenum = 1;
-	var tr, prev_group;
-	var colorClass = 0;
-	var table =
-		document.getElementById('blame_table') ||
-		document.getElementsByTagName('table')[0];
-
-	while ((tr = document.getElementById('l'+linenum))) {
-	// index origin is 0, which is table header; start from 1
-	//while ((tr = table.rows[linenum])) { // <- it is slower
-		if (isStartOfGroup(tr, linenum, document)) {
-			if (prev_group &&
-			    prev_group.firstChild.firstChild.href ===
-			            tr.firstChild.firstChild.href) {
-				// we have to concatenate groups
-				var prev_rows = prev_group.firstChild.rowSpan || 1;
-				var curr_rows =         tr.firstChild.rowSpan || 1;
-				prev_group.firstChild.rowSpan = prev_rows + curr_rows;
-				//tr.removeChild(tr.firstChild);
-				tr.deleteCell(0); // DOM2 HTML way
-			} else {
-				colorClass = (colorClass + 1) % 2;
-				prev_group = tr;
-			}
-		}
-		var tr_class = tr.className;
-		tr.className = tr_class.replace(colorRe, colorClasses[colorClass]);
-		linenum++;
-	}
-}
-
-
-/* ============================================================ */
-/* main part: parsing response */
-
-/**
- * Function called for each blame entry, as soon as it finishes.
- * It updates page via DOM manipulation, adding sha1 info, etc.
- *
- * @param {Commit} commit: blamed commit
- * @param {Object} group: object representing group of lines,
- *                        which blame the same commit (blame entry)
- *
- * @globals blamedLines
- */
-function handleLine(commit, group) {
-	/*
-	   This is the structure of the HTML fragment we are working
-	   with:
-
-	   <tr id="l123" class="">
-	     <td class="sha1" title=""><a href=""> </a></td>
-	     <td class="linenr"><a class="linenr" href="">123</a></td>
-	     <td class="pre"># times (my ext3 doesn&#39;t).</td>
-	   </tr>
-	*/
-
-	var resline = group.resline;
-
-	// format date and time string only once per commit
-	if (!commit.info) {
-		/* e.g. 'Kay Sievers, 2005-08-07 21:49:46 +0200' */
-		commit.info = commit.author + ', ' +
-			formatDateISOLocal(commit.authorTime, commit.authorTimezone);
-	}
-
-	// color depends on group of lines, not only on blamed commit
-	var colorNo = findColorNo(
-		document.getElementById('l'+(resline-1)),
-		document.getElementById('l'+(resline+group.numlines))
-	);
-
-	// loop over lines in commit group
-	for (var i = 0; i < group.numlines; i++, resline++) {
-		var tr = document.getElementById('l'+resline);
-		if (!tr) {
-			break;
-		}
-		/*
-			<tr id="l123" class="">
-			  <td class="sha1" title=""><a href=""> </a></td>
-			  <td class="linenr"><a class="linenr" href="">123</a></td>
-			  <td class="pre"># times (my ext3 doesn&#39;t).</td>
-			</tr>
-		*/
-		var td_sha1  = tr.firstChild;
-		var a_sha1   = td_sha1.firstChild;
-		var a_linenr = td_sha1.nextSibling.firstChild;
-
-		/* <tr id="l123" class=""> */
-		var tr_class = '';
-		if (colorNo !== null) {
-			tr_class = 'color'+colorNo;
-		}
-		if (commit.boundary) {
-			tr_class += ' boundary';
-		}
-		if (commit.nprevious === 0) {
-			tr_class += ' no-previous';
-		} else if (commit.nprevious > 1) {
-			tr_class += ' multiple-previous';
-		}
-		tr.className = tr_class;
-
-		/* <td class="sha1" title="?" rowspan="?"><a href="?">?</a></td> */
-		if (i === 0) {
-			td_sha1.title = commit.info;
-			td_sha1.rowSpan = group.numlines;
-
-			a_sha1.href = projectUrl + 'a=commit;h=' + commit.sha1;
-			if (a_sha1.firstChild) {
-				a_sha1.firstChild.data = commit.sha1.substr(0, 8);
-			} else {
-				a_sha1.appendChild(
-					document.createTextNode(commit.sha1.substr(0, 8)));
-			}
-			if (group.numlines >= 2) {
-				var fragment = document.createDocumentFragment();
-				var br   = document.createElement("br");
-				var match = commit.author.match(/\b([A-Z])\B/g);
-				if (match) {
-					var text = document.createTextNode(
-							match.join(''));
-				}
-				if (br && text) {
-					var elem = fragment || td_sha1;
-					elem.appendChild(br);
-					elem.appendChild(text);
-					if (fragment) {
-						td_sha1.appendChild(fragment);
-					}
-				}
-			}
-		} else {
-			//tr.removeChild(td_sha1); // DOM2 Core way
-			tr.deleteCell(0); // DOM2 HTML way
-		}
-
-		/* <td class="linenr"><a class="linenr" href="?">123</a></td> */
-		var linenr_commit =
-			('previous' in commit ? commit.previous : commit.sha1);
-		var linenr_filename =
-			('file_parent' in commit ? commit.file_parent : commit.filename);
-		a_linenr.href = projectUrl + 'a=blame_incremental' +
-			';hb=' + linenr_commit +
-			';f='  + encodeURIComponent(linenr_filename) +
-			'#l' + (group.srcline + i);
-
-		blamedLines++;
-
-		//updateProgressInfo();
-	}
-}
-
-// ----------------------------------------------------------------------
-
-/**#@+
- * @constant
- */
-var sha1Re = /^([0-9a-f]{40}) ([0-9]+) ([0-9]+) ([0-9]+)/;
-var infoRe = /^([a-z-]+) ?(.*)/;
-var endRe  = /^END ?([^ ]*) ?(.*)/;
-/**@-*/
-
-var curCommit = new Commit();
-var curGroup  = {};
-
-/**
- * Parse output from 'git blame --incremental [...]', received via
- * XMLHttpRequest from server (blamedataUrl), and call handleLine
- * (which updates page) as soon as blame entry is completed.
- *
- * @param {String[]} lines: new complete lines from blamedata server
- *
- * @globals commits, curCommit, curGroup, t_interval_server, cmds_server
- * @globals sha1Re, infoRe, endRe
- */
-function processBlameLines(lines) {
-	var match;
-
-	for (var i = 0, len = lines.length; i < len; i++) {
-
-		if ((match = sha1Re.exec(lines[i]))) {
-			var sha1 = match[1];
-			var srcline  = parseInt(match[2], 10);
-			var resline  = parseInt(match[3], 10);
-			var numlines = parseInt(match[4], 10);
-
-			var c = commits[sha1];
-			if (!c) {
-				c = new Commit(sha1);
-				commits[sha1] = c;
-			}
-			curCommit = c;
-
-			curGroup.srcline = srcline;
-			curGroup.resline = resline;
-			curGroup.numlines = numlines;
-
-		} else if ((match = infoRe.exec(lines[i]))) {
-			var info = match[1];
-			var data = match[2];
-			switch (info) {
-			case 'filename':
-				curCommit.filename = unquote(data);
-				// 'filename' information terminates the entry
-				handleLine(curCommit, curGroup);
-				updateProgressInfo();
-				break;
-			case 'author':
-				curCommit.author = data;
-				break;
-			case 'author-time':
-				curCommit.authorTime = parseInt(data, 10);
-				break;
-			case 'author-tz':
-				curCommit.authorTimezone = data;
-				break;
-			case 'previous':
-				curCommit.nprevious++;
-				// store only first 'previous' header
-				if (!'previous' in curCommit) {
-					var parts = data.split(' ', 2);
-					curCommit.previous    = parts[0];
-					curCommit.file_parent = unquote(parts[1]);
-				}
-				break;
-			case 'boundary':
-				curCommit.boundary = true;
-				break;
-			} // end switch
-
-		} else if ((match = endRe.exec(lines[i]))) {
-			t_interval_server = match[1];
-			cmds_server = match[2];
-
-		} else if (lines[i] !== '') {
-			// malformed line
-
-		} // end if (match)
-
-	} // end for (lines)
-}
-
-/**
- * Process new data and return pointer to end of processed part
- *
- * @param {String} unprocessed: new data (from nextReadPos)
- * @param {Number} nextReadPos: end of last processed data
- * @return {Number} end of processed data (new value for nextReadPos)
- */
-function processData(unprocessed, nextReadPos) {
-	var lastLineEnd = unprocessed.lastIndexOf('\n');
-	if (lastLineEnd !== -1) {
-		var lines = unprocessed.substring(0, lastLineEnd).split('\n');
-		nextReadPos += lastLineEnd + 1 /* 1 == '\n'.length */;
-
-		processBlameLines(lines);
-	} // end if
-
-	return nextReadPos;
-}
-
-/**
- * Handle XMLHttpRequest errors
- *
- * @param {XMLHttpRequest} xhr: XMLHttpRequest object
- * @param {Number} [xhr.pollTimer] ID of the timeout to clear
- *
- * @globals commits
- */
-function handleError(xhr) {
-	errorInfo('Server error: ' +
-		xhr.status + ' - ' + (xhr.statusText || 'Error contacting server'));
-
-	if (typeof xhr.pollTimer === "number") {
-		clearTimeout(xhr.pollTimer);
-		delete xhr.pollTimer;
-	}
-	commits = {}; // free memory
-}
-
-/**
- * Called after XMLHttpRequest finishes (loads)
- *
- * @param {XMLHttpRequest} xhr: XMLHttpRequest object
- * @param {Number} [xhr.pollTimer] ID of the timeout to clear
- *
- * @globals commits
- */
-function responseLoaded(xhr) {
-	if (typeof xhr.pollTimer === "number") {
-		clearTimeout(xhr.pollTimer);
-		delete xhr.pollTimer;
-	}
-
-	fixColorsAndGroups();
-	writeTimeInterval();
-	commits = {}; // free memory
-}
-
-/**
- * handler for XMLHttpRequest onreadystatechange event
- * @see startBlame
- *
- * @param {XMLHttpRequest} xhr: XMLHttpRequest object
- * @param {Number} xhr.prevDataLength: previous value of xhr.responseText.length
- * @param {Number} xhr.nextReadPos: start of unread part of xhr.responseText
- * @param {Number} [xhr.pollTimer] ID of the timeout (to reset or cancel)
- * @param {Boolean} fromTimer: if handler was called from timer
- */
-function handleResponse(xhr, fromTimer) {
-
-	/*
-	 * xhr.readyState
-	 *
-	 *  Value  Constant (W3C)    Description
-	 *  -------------------------------------------------------------------
-	 *  0      UNSENT            open() has not been called yet.
-	 *  1      OPENED            send() has not been called yet.
-	 *  2      HEADERS_RECEIVED  send() has been called, and headers
-	 *                           and status are available.
-	 *  3      LOADING           Downloading; responseText holds partial data.
-	 *  4      DONE              The operation is complete.
-	 */
-
-	if (xhr.readyState !== 4 && xhr.readyState !== 3) {
-		return;
-	}
-
-	// the server returned error
-	// try ... catch block is to work around bug in IE8
-	try {
-		if (xhr.readyState === 3 && xhr.status !== 200) {
-			return;
-		}
-	} catch (e) {
-		return;
-	}
-	if (xhr.readyState === 4 && xhr.status !== 200) {
-		handleError(xhr);
-		return;
-	}
-
-	// In konqueror xhr.responseText is sometimes null here...
-	if (xhr.responseText === null) {
-		return;
-	}
-
-
-	// extract new whole (complete) lines, and process them
-	if (xhr.prevDataLength !== xhr.responseText.length) {
-		xhr.prevDataLength = xhr.responseText.length;
-		var unprocessed = xhr.responseText.substring(xhr.nextReadPos);
-		xhr.nextReadPos = processData(unprocessed, xhr.nextReadPos);
-	}
-
-	// did we finish work?
-	if (xhr.readyState === 4) {
-		responseLoaded(xhr);
-		return;
-	}
-
-	// if we get from timer, we have to restart it
-	// otherwise onreadystatechange gives us partial response, timer not needed
-	if (fromTimer) {
-		setTimeout(function () {
-			handleResponse(xhr, true);
-		}, 1000);
-
-	} else if (typeof xhr.pollTimer === "number") {
-		clearTimeout(xhr.pollTimer);
-		delete xhr.pollTimer;
-	}
-}
-
-// ============================================================
-// ------------------------------------------------------------
-
-/**
- * Incrementally update line data in blame_incremental view in gitweb.
- *
- * @param {String} blamedataUrl: URL to server script generating blame data.
- * @param {String} bUrl: partial URL to project, used to generate links.
- *
- * Called from 'blame_incremental' view after loading table with
- * file contents, a base for blame view.
- *
- * @globals t0, projectUrl, div_progress_bar, totalLines
-*/
-function startBlame(blamedataUrl, bUrl) {
-
-	var xhr = createRequestObject();
-	if (!xhr) {
-		errorInfo('ERROR: XMLHttpRequest not supported');
-		return;
-	}
-
-	t0 = new Date();
-	projectUrl = bUrl + (bUrl.indexOf('?') === -1 ? '?' : ';');
-	if ((div_progress_bar = document.getElementById('progress_bar'))) {
-		//div_progress_bar.setAttribute('style', 'width: 100%;');
-		div_progress_bar.style.cssText = 'width: 100%;';
-	}
-	totalLines = countLines();
-	updateProgressInfo();
-
-	/* add extra properties to xhr object to help processing response */
-	xhr.prevDataLength = -1;  // used to detect if we have new data
-	xhr.nextReadPos = 0;      // where unread part of response starts
-
-	xhr.onreadystatechange = function () {
-		handleResponse(xhr, false);
-	};
-
-	xhr.open('GET', blamedataUrl);
-	xhr.setRequestHeader('Accept', 'text/plain');
-	xhr.send(null);
-
-	// not all browsers call onreadystatechange event on each server flush
-	// poll response using timer every second to handle this issue
-	xhr.pollTimer = setTimeout(function () {
-		handleResponse(xhr, true);
-	}, 1000);
-}
-
-/* end of blame_incremental.js */