aboutsummaryrefslogtreecommitdiffstats
path: root/english/devel/website/stats/diffstat.js
blob: 83ff3ada57ac0c0f7400555bc693bece2828a7d5 (plain) (blame)
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
60
61
62
63
64
65
66
67
68
69
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
100
101
102
103
104
105
106
107
// GETs the given url, and schedules the callback to be invoked with the
// response body when it arrives.
//
// In case of problems the callback is invoked with an Error() argument,
// containing the error message.
// TODO: This is ugly, but how else to asynchronously deliver an exceptional
// condition?
//
// Args:
//   url: the url to GET
//   callback: the function to be invoked with the body or Error as an argument
function getTextAsync(url, callback) {
	var request = new XMLHttpRequest();
	request.onreadystatechange = function() {
		if (request.readyState !== 4)
			return;
		if (request.status === 200) {
			var type = request.getResponseHeader("Content-Type");
			if (type.match(/^text/))
				callback(request.responseText);
			else
				// TODO: i18nize
				callback(Error('Non-text response received'));
		} else	{
			if (request.statusText == "")
				// TODO: i18nize
				callback(Error("Unknown error"));
			else
				callback(Error(request.statusText));
		}
	};
	request.open("GET", url);
	request.send(null);
}

// Calculate the number of additions and removals in a diff text.
// Args:
//   diff: the text of the diff, optionally including the diff header (i.e. the
//   ---/+++ or other lines)
// Returns:
//   an array of two elements: number of added lines, number of removed lines.
//   On error a null is returned instead of the array
function diffstat(diff) {
	if (diff == null)
		return null;
	var first_hunk_offset = diff.indexOf("\n@@");
	var diff_text;
	if (first_hunk_offset > 0) {
		// Skip the ---/+++ in diff header.
		diff_text = diff.substring(first_hunk_offset);
	} else {
		diff_text = diff;
	}
	var changes = diff_text.match(/\n[+-]/g);
	if (changes == null) {
		return null;
	}
	function count_adds(i, str) { return str == "\n+" ? i + 1 : i }
	function count_dels(i, str) { return str == "\n-" ? i + 1 : i }
	var additions = changes.reduce(count_adds, 0);
	var removals = changes.reduce(count_dels, 0);
	return [additions, removals];
}

// Returns an HTML element presenting the given diff text or error object.
//
// Args:
//   diff_or_error: the diff text to pass to diffstat() or an error message
// Returns:
//   an HTML element, containing information about the argument
function diffstat_pretty(diff_or_error) {
	var topspan = document.createElement('span');
	topspan.setAttribute('style', 'font-family: monospace');
	if (diff_or_error instanceof Error) {
		var ret;
		ret = document.createElement('span');
		ret.setAttribute('title', diff_or_error.message);
		ret.innerHTML = ':-(';
		topspan.appendChild(ret);
	} else {
		var counts = diffstat(diff_or_error);
		if (counts == null) {
			var ret;
			ret = document.createElement('span');
			ret.setAttribute('title', 'parse error');
			ret.innerHTML = ':-(';
			topspan.appendChild(ret);
		} else {
			var ret;

			ret = document.createElement('span');
			ret.setAttribute('style', 'color: green');
			ret.innerHTML = '+' + counts[0];
			topspan.appendChild(ret);

		//	ret = document.createElement('br');
			ret = document.createTextNode('/');
			topspan.appendChild(ret);

			ret = document.createElement('span');
			ret.setAttribute('style', 'color: red');
			ret.innerHTML = '-' + counts[1];
			topspan.appendChild(ret);
		}
	}
	return topspan;
}	

© 2014-2024 Faster IT GmbH | imprint | privacy policy