aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/AUTHORS
blob: 031de338f904f26d0571e99db476d83e14fb1cc4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
Maintainer:
	Jason A. Donenfeld <Jason@zx2c4.com>

Contributors:
	Jason A. Donenfeld <Jason@zx2c4.com>
	Lukas Fleischer <cgit@cryptocrack.de>
	Johan Herland <johan@herland.net>
	Lars Hjemli <hjemli@gmail.com>
	Ferry Huberts <ferry.huberts@pelagic.nl>
	John Keeping <john@keeping.me.uk>

Previous Maintainer:
	Lars Hjemli <hjemli@gmail.com>
ackground-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/* ui-atom.c: functions for atom feeds
 *
 * Copyright (C) 2008 Lars Hjemli
 *
 * Licensed under GNU General Public License v2
 *   (see COPYING for full license text)
 */

#include "cgit.h"
#include "html.h"
#include "ui-shared.h"

void add_entry(struct commit *commit, char *host)
{
	char delim = '&';
	char *hex;
	char *mail, *t, *t2;
	struct commitinfo *info;

	info = cgit_parse_commit(commit);
	hex = sha1_to_hex(commit->object.sha1);
	html("<entry>\n");
	htmlpre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#include "cgit.h"
#include "html.h"
#include "ui-shared.h"

extern int use_ssdiff;

static int current_old_line, current_new_line;

struct deferred_lines {
	int line_no;
	char *line;
	struct deferred_lines *next;
};

static struct deferred_lines *deferred_old, *deferred_old_last;
static struct deferred_lines *deferred_new, *deferred_new_last;

static char *longest_common_subsequence(char *A, char *B)
{
	int i, j, ri;
	int m = strlen(A);
	int n = strlen(B);
	int L[m + 1][n + 1];
	int tmp1, tmp2;
	int lcs_length;
	char *result;

	for (i = m; i >= 0; i--) {
		for (j = n; j >= 0; j--) {
			if (A[i] == '\0' || B[j] == '\0') {
				L[i][j] = 0;
			} else if (A[i] == B[j]) {
				L[i][j] = 1 + L[i + 1][j + 1];
			} else {
				tmp1 = L[i + 1][j];
				tmp2 = L[i][j + 1];
				L[i][j] = (tmp1 > tmp2 ? tmp1 : tmp2);
			}
		}
	}

	lcs_length = L[0][0];
	result = xmalloc(lcs_length + 2);
	memset(result, 0, sizeof(*result) * (lcs_length + 2));

	ri = 0;
	i = 0;
	j = 0;
	while (i < m && j < n) {
		if (A[i] == B[j]) {
			result[ri] = A[i];
			ri += 1;
			i += 1;
			j += 1;
		} else if (L[i + 1][j] >= L[i][j + 1]) {
			i += 1;
		} else {
			j += 1;
		}
	}
	return result;
}

static int line_from_hunk(char *line, char type)
{
	char *buf1, *buf2;
	int len;

	buf1 = strchr(line, type);
	if (buf1 == NULL)
		return 0;
	buf1 += 1;
	buf2 = strchr(buf1, ',');
	if (buf2 == NULL)
		return 0;
	len = buf2 - buf1;
	buf2 = xmalloc(len + 1);
	strncpy(buf2, buf1, len);
	buf2[len] = '\0';
	int res = atoi(buf2);
	free(buf2);
	return res;
}

static char *replace_tabs(char *line)
{
	char *prev_buf = line;
	char *cur_buf;
	int linelen = strlen(line);
	int n_tabs = 0;
	int i;
	char *result;
	char *spaces = "        ";

	if (linelen == 0) {
		result = xmalloc(1);
		result[0] = '\0';
		return result;
	}

	for (i = 0; i < linelen; i++)
		if (line[i] == '\t')
			n_tabs += 1;
	result = xmalloc(linelen + n_tabs * 8 + 1);
	result[0] = '\0';

	while (1) {
		cur_buf = strchr(prev_buf, '\t');
		if (!cur_buf) {
			strcat(result, prev_buf);
			break;
		} else {
			strcat(result, " ");
			strncat(result, spaces, 8 - (strlen(result) % 8));
			strncat(result, prev_buf, cur_buf - prev_buf);
		}
		prev_buf = cur_buf + 1;
	}
	return result;
}

static int calc_deferred_lines(struct deferred_lines *start)
{
	struct deferred_lines *item = start;
	int result = 0;
	while (item) {
		result += 1;
		item = item->next;
	}
	return result;
}

static void deferred_old_add(char *line, int line_no)
{
	struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines));
	item->line = xstrdup(line);
	item->line_no = line_no;
	item->next = NULL;
	if (deferred_old) {
		deferred_old_last->next = item;
		deferred_old_last = item;
	} else {
		deferred_old = deferred_old_last = item;
	}
}

static void deferred_new_add(char *line, int line_no)
{
	struct deferred_lines *item = xmalloc(sizeof(struct deferred_lines));
	item->line = xstrdup(line);
	item->line_no = line_no;
	item->next = NULL;
	if (deferred_new) {
		deferred_new_last->next = item;
		deferred_new_last = item;
	} else {
		deferred_new = deferred_new_last = item;
	}
}

static void print_part_with_lcs(char *class, char *line, char *lcs)
{
	int line_len = strlen(line);
	int i, j;
	char c[2] = " ";
	int same = 1;

	j = 0;
	for (i = 0; i < line_len; i++) {
		c[0] = line[i];
		if (same) {
			if (line[i] == lcs[j])
				j += 1;
			else {
				same = 0;
				htmlf("<span class='%s'>", class);
			}
		} else if (line[i] == lcs[j]) {
			same = 1;
			htmlf("</span>");
			j += 1;
		}
		html_txt(c);
	}
}

static void print_ssdiff_line(char *class,
			      int old_line_no,
			      char *old_line,
			      int new_line_no,
			      char *new_line, int individual_chars)
{
	char *lcs = NULL;
	if (old_line)
		old_line = replace_tabs(old_line + 1);
	if (new_line)
		new_line = replace_tabs(new_line + 1);
	if (individual_chars && old_line && new_line)
		lcs = longest_common_subsequence(old_line, new_line);
	html("<tr>");
	if (old_line_no > 0)
		htmlf("<td class='lineno'>%d</td><td class='%s'>",
		      old_line_no, class);
	else if (old_line)
		htmlf("<td class='lineno'></td><td class='%s'>", class);
	else
		htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
	if (old_line) {
		if (lcs)
			print_part_with_lcs("del", old_line, lcs);
		else
			html_txt(old_line);
	}

	html("</td>");
	if (new_line_no > 0)
		htmlf("<td class='lineno'>%d</td><td class='%s'>",
		      new_line_no, class);
	else if (new_line)
		htmlf("<td class='lineno'></td><td class='%s'>", class);
	else
		htmlf("<td class='lineno'></td><td class='%s_dark'>", class);
	if (new_line) {
		if (lcs)
			print_part_with_lcs("add", new_line, lcs);
		else
			html_txt(new_line);
	}

	html("</td></tr>");
	if (lcs)
		free(lcs);
	if (new_line)
		free(new_line);
	if (old_line)
		free(old_line);
}

static void print_deferred_old_lines()
{
	struct deferred_lines *iter_old, *tmp;
	iter_old = deferred_old;
	while (iter_old) {
		print_ssdiff_line("del", iter_old->line_no,
				  iter_old->line, -1, NULL, 0);
		tmp = iter_old->next;
		free(iter_old);
		iter_old = tmp;
	}
}

static void print_deferred_new_lines()
{
	struct deferred_lines *iter_new, *tmp;
	iter_new = deferred_new;
	while (iter_new) {
		print_ssdiff_line("add", -1, NULL,
				  iter_new->line_no, iter_new->line, 0);
		tmp = iter_new->next;
		free(iter_new);
		iter_new = tmp;
	}
}

static void print_deferred_changed_lines()
{
	struct deferred_lines *iter_old, *iter_new, *tmp;
	int n_old_lines = calc_deferred_lines(deferred_old);
	int n_new_lines = calc_deferred_lines(deferred_new);
	int individual_chars = (n_old_lines == n_new_lines ? 1 : 0);

	iter_old = deferred_old;
	iter_new = deferred_new;
	while (iter_old || iter_new) {
		if (iter_old && iter_new)
			print_ssdiff_line("changed", iter_old->line_no,
					  iter_old->line,
					  iter_new->line_no, iter_new->line,
					  individual_chars);
		else if (iter_old)
			print_ssdiff_line("changed", iter_old->line_no,
					  iter_old->line, -1, NULL, 0);
		else if (iter_new)
			print_ssdiff_line("changed", -1, NULL,
					  iter_new->line_no, iter_new->line, 0);
		if (iter_old) {
			tmp = iter_old->next;
			free(iter_old);
			iter_old = tmp;
		}

		if (iter_new) {
			tmp = iter_new->next;
			free(iter_new);
			iter_new = tmp;
		}
	}
}

void cgit_ssdiff_print_deferred_lines()
{
	if (!deferred_old && !deferred_new)
		return;
	if (deferred_old && !deferred_new)
		print_deferred_old_lines();
	else if (!deferred_old && deferred_new)
		print_deferred_new_lines();
	else
		print_deferred_changed_lines();
	deferred_old = deferred_old_last = NULL;
	deferred_new = deferred_new_last = NULL;
}

/*
 * print a single line returned from xdiff
 */
void cgit_ssdiff_line_cb(char *line, int len)
{
	char c = line[len - 1];
	line[len - 1] = '\0';
	if (line[0] == '@') {
		current_old_line = line_from_hunk(line, '-');
		current_new_line = line_from_hunk(line, '+');
	}

	if (line[0] == ' ') {
		if (deferred_old || deferred_new)
			cgit_ssdiff_print_deferred_lines();
		print_ssdiff_line("ctx", current_old_line, line,
				  current_new_line, line, 0);
		current_old_line += 1;
		current_new_line += 1;
	} else if (line[0] == '+') {
		deferred_new_add(line, current_new_line);
		current_new_line += 1;
	} else if (line[0] == '-') {
		deferred_old_add(line, current_old_line);
		current_old_line += 1;
	} else if (line[0] == '@') {
		html("<tr><td colspan='4' class='hunk'>");
		html_txt(line);
		html("</td></tr>");
	} else {
		html("<tr><td colspan='4' class='ctx'>");
		html_txt(line);
		html("</td></tr>");
	}
	line[len - 1] = c;
}

void cgit_ssdiff_header_begin()
{
	current_old_line = -1;
	current_new_line = -1;
	html("<tr><td class='space' colspan='4'><div></div></td></tr>");
	html("<tr><td class='head' colspan='4'>");
}

void cgit_ssdiff_header_end()
{
	html("</td><tr>");
}

void cgit_ssdiff_footer()
{
	if (deferred_old || deferred_new)
		cgit_ssdiff_print_deferred_lines();
	html("<tr><td class='foot' colspan='4'></td></tr>");
}