summaryrefslogtreecommitdiffstatshomepage
path: root/ui-patch.c
blob: 25dc9fed9913fd396ff4ff6de6979b50bd28a000 (plain)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* ui-patch.c: generate patch view
 *
 * Copyright (C) 2007 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"

static void print_line(char *line, int len)
{
	char c = line[len-1];

	line[len-1] = '\0';
	htmlf("%s\n", line);
	line[len-1] = c;
}

static void header(unsigned char *sha1, char *path1, int mode1,
		   unsigned char *sha2, char *path2, int mode2)
{
	char *abbrev1, *abbrev2;
	int subproject;

	subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2));
	htmlf("diff --git a/%s b/%s\n", path1, path2);

	if (is_null_sha1(sha1))
		path1 = "dev/null";
	if (is_null_sha1(sha2))
		path2 = "dev/null";

	if (mode1 == 0)
		htmlf("new file mode %.6o\n", mode2);

	if (mode2 == 0)
		htmlf("deleted file mode %.6o\n", mode1);

	if (!subproject) {
		abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV));
		abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV));
		htmlf("index %s..%s", abbrev1, abbrev2);
		free(abbrev1);
		free(abbrev2);
		if (mode1 != 0 && mode2 != 0) {
			htmlf(" %.6o", mode1);
			if (mode2 != mode1)
				htmlf("..%.6o", mode2);
		}
		htmlf("\n--- a/%s\n", path1);
		htmlf("+++ b/%s\n", path2);
	}
}

static void filepair_cb(struct diff_filepair *pair)
{
	unsigned long old_size = 0;
	unsigned long new_size = 0;
	int binary = 0;

	header(pair->one->sha1, pair->one->path, pair->one->mode,
	       pair->two->sha1, pair->two->path, pair->two->mode);
	if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) {
		if (S_ISGITLINK(pair->one->mode))
			print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52);
		if (S_ISGITLINK(pair->two->mode))
			print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52);
		return;
	}
	if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size,
			    &new_size, &binary, print_line))
		html("Error running diff");
	if (binary)
		html("Binary files differ\n");
}

void cgit_print_patch(char *hex, const char *prefix)
{
	struct commit *commit;
	struct commitinfo *info;
	unsigned char sha1[20], old_sha1[20];
	char *patchname;

	if (!hex)
		hex = ctx.qry.head;

	if (get_sha1(hex, sha1)) {
		cgit_print_error(fmt("Bad object id: %s", hex));
		return;
	}
	commit = lookup_commit_reference(sha1);
	if (!commit) {
		cgit_print_error(fmt("Bad commit reference: %s", hex));
		return;
	}
	info = cgit_parse_commit(commit);

	if (commit->parents && commit->parents->item)
		hashcpy(old_sha1, commit->parents->item->object.sha1);
	else
		hashclr(old_sha1);

	patchname = fmt("%s.patch", sha1_to_hex(sha1));
	ctx.page.mimetype = "text/plain";
	ctx.page.filename = patchname;
	cgit_print_http_headers(&ctx);
	htmlf("From %s Mon Sep 17 00:00:00 2001\n", sha1_to_hex(sha1));
	htmlf("From: %s", info->author);
	if (!ctx.cfg.noplainemail) {
		htmlf(" %s", info->author_email);
	}
	html("\n");
	html("Date: ");
	cgit_print_date(info->author_date, "%a, %d %b %Y %H:%M:%S %z%n", ctx.cfg.local_time);
	htmlf("Subject: %s\n\n", info->subject);
	if (info->msg && *info->msg) {
		htmlf("%s", info->msg);
		if (info->msg[strlen(info->msg) - 1] != '\n')
			html("\n");
	}
	html("---\n");
	if (prefix)
		htmlf("(limited to '%s')\n\n", prefix);
	cgit_diff_tree(old_sha1, sha1, filepair_cb, prefix);
	html("--\n");
	htmlf("cgit %s\n", CGIT_VERSION);
	cgit_free_commitinfo(info);
}
class="w"> table#header td.main a { color: #000; } div#cgit table#header td.form { text-align: right; vertical-align: bottom; padding-right: 1em; padding-bottom: 2px; white-space: nowrap; } div#cgit table#header td.form form, div#cgit table#header td.form input, div#cgit table#header td.form select { font-size: 90%; } div#cgit table#header td.sub { color: #777; border-top: solid 1px #ccc; padding-left: 10px; } div#cgit table.tabs { border-bottom: solid 3px #ccc; border-collapse: collapse; margin-top: 2em; margin-bottom: 0px; width: 100%; } div#cgit table.tabs td { padding: 0px 1em; vertical-align: bottom; } div#cgit table.tabs td a { padding: 2px 0.75em; color: #777; font-size: 110%; } div#cgit table.tabs td a.active { color: #000; background-color: #ccc; } div#cgit table.tabs td.form { text-align: right; } div#cgit table.tabs td.form form { padding-bottom: 2px; font-size: 90%; white-space: nowrap; } div#cgit table.tabs td.form input, div#cgit table.tabs td.form select { font-size: 90%; } div#cgit div.path { margin: 0px; padding: 5px 2em 2px 2em; color: #000; background-color: #eee; } div#cgit div.content { margin: 0px; padding: 2em; border-bottom: solid 3px #ccc; } div#cgit table.list { width: 100%; border: none; border-collapse: collapse; } div#cgit table.list tr { background: white; } div#cgit table.list tr.logheader { background: #eee; } div#cgit table.list tr:hover { background: #eee; } div#cgit table.list tr.nohover:hover { background: white; } div#cgit table.list th { font-weight: bold; /* color: #888; border-top: dashed 1px #888; border-bottom: dashed 1px #888; */ padding: 0.1em 0.5em 0.05em 0.5em; vertical-align: baseline; } div#cgit table.list td { border: none; padding: 0.1em 0.5em 0.1em 0.5em; } div#cgit table.list td.commitgraph { font-family: monospace; white-space: pre; } div#cgit table.list td.commitgraph .column1 { color: #a00; } div#cgit table.list td.commitgraph .column2 { color: #0a0; } div#cgit table.list td.commitgraph .column3 { color: #aa0; } div#cgit table.list td.commitgraph .column4 { color: #00a; } div#cgit table.list td.commitgraph .column5 { color: #a0a; } div#cgit table.list td.commitgraph .column6 { color: #0aa; } div#cgit table.list td.logsubject { font-family: monospace; font-weight: bold; } div#cgit table.list td.logmsg { font-family: monospace; white-space: pre; padding: 0 0.5em; } div#cgit table.list td a { color: black; } div#cgit table.list td a.ls-dir { font-weight: bold; color: #00f; } div#cgit table.list td a:hover { color: #00f; } div#cgit img { border: none; } div#cgit input#switch-btn { margin: 2px 0px 0px 0px; } div#cgit td#sidebar input.txt { width: 100%; margin: 2px 0px 0px 0px; } div#cgit table#grid { margin: 0px; } div#cgit td#content { vertical-align: top; padding: 1em 2em 1em 1em; border: none; } div#cgit div#summary { vertical-align: top; margin-bottom: 1em; } div#cgit table#downloads { float: right; border-collapse: collapse; border: solid 1px #777; margin-left: 0.5em; margin-bottom: 0.5em; } div#cgit table#downloads th { background-color: #ccc; } div#cgit div#blob { border: solid 1px black; } div#cgit div.error { color: red; font-weight: bold; margin: 1em 2em; } div#cgit a.ls-blob, div#cgit a.ls-dir, div#cgit .ls-mod { font-family: monospace; } div#cgit td.ls-size { text-align: right; font-family: monospace; width: 10em; } div#cgit td.ls-mode { font-family: monospace; width: 10em; } div#cgit table.blob { margin-top: 0.5em; border-top: solid 1px black; } div#cgit table.blob td.lines { margin: 0; padding: 0 0 0 0.5em; vertical-align: top; color: black; } div#cgit table.blob td.linenumbers { margin: 0; padding: 0 0.5em 0 0.5em; vertical-align: top; text-align: right; border-right: 1px solid gray; } div#cgit table.blob pre { padding: 0; margin: 0; } div#cgit table.blob td.linenumbers a, div#cgit table.ssdiff td.lineno a { color: gray; text-align: right; text-decoration: none; } div#cgit table.blob td.linenumbers a:hover, div#cgit table.ssdiff td.lineno a:hover { color: black; } div#cgit table.bin-blob { margin-top: 0.5em; border: solid 1px black; } div#cgit table.bin-blob th { font-family: monospace; white-space: pre; border: solid 1px #777; padding: 0.5em 1em; } div#cgit table.bin-blob td { font-family: monospace; white-space: pre; border-left: solid 1px #777; padding: 0em 1em; } div#cgit table.nowrap td { white-space: nowrap; } div#cgit table.commit-info { border-collapse: collapse; margin-top: 1.5em; } div#cgit div.cgit-panel { float: right; margin-top: 1.5em; } div#cgit div.cgit-panel table { border-collapse: collapse; border: solid 1px #aaa; background-color: #eee; } div#cgit div.cgit-panel th { text-align: center; } div#cgit div.cgit-panel td { padding: 0.25em 0.5em; } div#cgit div.cgit-panel td.label { padding-right: 0.5em; } div#cgit div.cgit-panel td.ctrl { padding-left: 0.5em; } div#cgit table.commit-info th { text-align: left; font-weight: normal; padding: 0.1em 1em 0.1em 0.1em; vertical-align: top; } div#cgit table.commit-info td { font-weight: normal; padding: 0.1em 1em 0.1em 0.1em; } div#cgit div.commit-subject { font-weight: bold; font-size: 125%; margin: 1.5em 0em 0.5em 0em; padding: 0em; } div#cgit div.commit-msg { white-space: pre; font-family: monospace; } div#cgit div.notes-header { font-weight: bold; padding-top: 1.5em; } div#cgit div.notes { white-space: pre; font-family: monospace; border: solid 1px #ee9; background-color: #ffd; padding: 0.3em 2em 0.3em 1em; float: left; } div#cgit div.notes-footer { clear: left; } div#cgit div.diffstat-header { font-weight: bold; padding-top: 1.5em; } div#cgit table.diffstat { border-collapse: collapse; border: solid 1px #aaa; background-color: #eee; } div#cgit table.diffstat th { font-weight: normal; text-align: left; text-decoration: underline; padding: 0.1em 1em 0.1em 0.1em; font-size: 100%; } div#cgit table.diffstat td { padding: 0.2em 0.2em 0.1em 0.1em; font-size: 100%; border: none; } div#cgit table.diffstat td.mode { white-space: nowrap; } div#cgit table.diffstat td span.modechange { padding-left: 1em; color: red; } div#cgit table.diffstat td.add a { color: green; } div#cgit table.diffstat td.del a { color: red; } div#cgit table.diffstat td.upd a { color: blue; } div#cgit table.diffstat td.graph { width: 500px; vertical-align: middle; } div#cgit table.diffstat td.graph table { border: none; } div#cgit table.diffstat td.graph td { padding: 0px; border: 0px; height: 7pt; } div#cgit table.diffstat td.graph td.add { background-color: #5c5; } div#cgit table.diffstat td.graph td.rem { background-color: #c55; } div#cgit div.diffstat-summary { color: #888; padding-top: 0.5em; } div#cgit table.diff { width: 100%; } div#cgit table.diff td { font-family: monospace; white-space: pre; } div#cgit table.diff td div.head { font-weight: bold; margin-top: 1em; color: black; } div#cgit table.diff td div.hunk { color: #009; } div#cgit table.diff td div.add { color: green; } div#cgit table.diff td div.del { color: red; } div#cgit .sha1 { font-family: monospace; font-size: 90%; } div#cgit .left { text-align: left; } div#cgit .right { text-align: right; } div#cgit table.list td.reposection { font-style: italic; color: #888; } div#cgit a.button { font-size: 80%; padding: 0em 0.5em; } div#cgit a.primary { font-size: 100%; } div#cgit a.secondary { font-size: 90%; } div#cgit td.toplevel-repo { } div#cgit table.list td.sublevel-repo { padding-left: 1.5em; } div#cgit ul.pager { list-style-type: none; text-align: center; margin: 1em 0em 0em 0em; padding: 0; } div#cgit ul.pager li { display: inline-block; margin: 0.25em 0.5em; } div#cgit ul.pager a { color: #777; } div#cgit ul.pager .current { font-weight: bold; } div#cgit span.age-mins { font-weight: bold; color: #080; } div#cgit span.age-hours { color: #080; } div#cgit span.age-days { color: #040; } div#cgit span.age-weeks { color: #444; } div#cgit span.age-months { color: #888; } div#cgit span.age-years { color: #bbb; } div#cgit div.footer { margin-top: 0.5em; text-align: center; font-size: 80%; color: #ccc; } div#cgit div.footer a { color: #ccc; text-decoration: none; } div#cgit div.footer a:hover { text-decoration: underline; } div#cgit a.branch-deco { color: #000; margin: 0px 0.5em; padding: 0px 0.25em; background-color: #88ff88; border: solid 1px #007700; } div#cgit a.tag-deco { color: #000; margin: 0px 0.5em; padding: 0px 0.25em; background-color: #ffff88; border: solid 1px #777700; } div#cgit a.remote-deco { color: #000; margin: 0px 0.5em; padding: 0px 0.25em; background-color: #ccccff; border: solid 1px #000077; } div#cgit a.deco { color: #000; margin: 0px 0.5em; padding: 0px 0.25em; background-color: #ff8888; border: solid 1px #770000; } div#cgit div.commit-subject a.branch-deco, div#cgit div.commit-subject a.tag-deco, div#cgit div.commit-subject a.remote-deco, div#cgit div.commit-subject a.deco { margin-left: 1em; font-size: 75%; } div#cgit table.stats { border: solid 1px black; border-collapse: collapse; } div#cgit table.stats th { text-align: left; padding: 1px 0.5em; background-color: #eee; border: solid 1px black; } div#cgit table.stats td { text-align: right; padding: 1px 0.5em; border: solid 1px black; } div#cgit table.stats td.total { font-weight: bold; text-align: left; } div#cgit table.stats td.sum { color: #c00; font-weight: bold; /* background-color: #eee; */ } div#cgit table.stats td.left { text-align: left; } div#cgit table.vgraph { border-collapse: separate; border: solid 1px black; height: 200px; } div#cgit table.vgraph th { background-color: #eee; font-weight: bold; border: solid 1px white; padding: 1px 0.5em; } div#cgit table.vgraph td { vertical-align: bottom; padding: 0px 10px; } div#cgit table.vgraph div.bar { background-color: #eee; } div#cgit table.hgraph { border: solid 1px black; width: 800px; } div#cgit table.hgraph th { background-color: #eee; font-weight: bold; border: solid 1px black; padding: 1px 0.5em; } div#cgit table.hgraph td { vertical-align: middle; padding: 2px 2px; } div#cgit table.hgraph div.bar { background-color: #eee; height: 1em; } div#cgit table.ssdiff { width: 100%; } div#cgit table.ssdiff td { font-size: 75%; font-family: monospace; white-space: pre; padding: 1px 4px 1px 4px; border-left: solid 1px #aaa; border-right: solid 1px #aaa; } div#cgit table.ssdiff td.add { color: black; background: #cfc; min-width: 50%; } div#cgit table.ssdiff td.add_dark { color: black; background: #aca; min-width: 50%; } div#cgit table.ssdiff span.add { background: #cfc; font-weight: bold; } div#cgit table.ssdiff td.del { color: black; background: #fcc; min-width: 50%; } div#cgit table.ssdiff td.del_dark { color: black; background: #caa; min-width: 50%; } div#cgit table.ssdiff span.del { background: #fcc; font-weight: bold; } div#cgit table.ssdiff td.changed { color: black; background: #ffc; min-width: 50%; } div#cgit table.ssdiff td.changed_dark { color: black; background: #cca; min-width: 50%; } div#cgit table.ssdiff td.lineno { color: black; background: #eee; text-align: right; width: 3em; min-width: 3em; } div#cgit table.ssdiff td.hunk { color: black; background: #ccf; border-top: solid 1px #aaa; border-bottom: solid 1px #aaa; } div#cgit table.ssdiff td.head { border-top: solid 1px #aaa; border-bottom: solid 1px #aaa; } div#cgit table.ssdiff td.head div.head { font-weight: bold; color: black; } div#cgit table.ssdiff td.foot { border-top: solid 1px #aaa; border-left: none; border-right: none; border-bottom: none; } div#cgit table.ssdiff td.space { border: none; } div#cgit table.ssdiff td.space div { min-height: 3em; }