]> gitweb.ps.run Git - ps-cgit/blob - ui-diff.c
Handle empty/malformed commit messages
[ps-cgit] / ui-diff.c
1 /* ui-diff.c: show diff between two blobs
2  *
3  * Copyright (C) 2006 Lars Hjemli
4  *
5  * Licensed under GNU General Public License v2
6  *   (see COPYING for full license text)
7  */
8
9 #include "cgit.h"
10 #include "xdiff.h"
11
12 char *diff_buffer;
13 int diff_buffer_size;
14
15
16 /*
17  * print a single line returned from xdiff
18  */
19 static void print_line(char *line, int len)
20 {
21         char *class = "ctx";
22         char c = line[len-1];
23
24         if (line[0] == '+')
25                 class = "add";
26         else if (line[0] == '-')
27                 class = "del";
28         else if (line[0] == '@')
29                 class = "hunk";
30
31         htmlf("<div class='%s'>", class);
32         line[len-1] = '\0';
33         html_txt(line);
34         html("</div>");
35         line[len-1] = c;
36 }
37
38 /*
39  * Receive diff-buffers from xdiff and concatenate them as
40  * needed across multiple callbacks.
41  *
42  * This is basically a copy of xdiff-interface.c/xdiff_outf(),
43  * ripped from git and modified to use globals instead of
44  * a special callback-struct.
45  */
46 int diff_cb(void *priv_, mmbuffer_t *mb, int nbuf)
47 {
48         int i;
49
50         for (i = 0; i < nbuf; i++) {
51                 if (mb[i].ptr[mb[i].size-1] != '\n') {
52                         /* Incomplete line */
53                         diff_buffer = xrealloc(diff_buffer,
54                                                diff_buffer_size + mb[i].size);
55                         memcpy(diff_buffer + diff_buffer_size,
56                                mb[i].ptr, mb[i].size);
57                         diff_buffer_size += mb[i].size;
58                         continue;
59                 }
60
61                 /* we have a complete line */
62                 if (!diff_buffer) {
63                         print_line(mb[i].ptr, mb[i].size);
64                         continue;
65                 }
66                 diff_buffer = xrealloc(diff_buffer,
67                                        diff_buffer_size + mb[i].size);
68                 memcpy(diff_buffer + diff_buffer_size, mb[i].ptr, mb[i].size);
69                 print_line(diff_buffer, diff_buffer_size + mb[i].size);
70                 free(diff_buffer);
71                 diff_buffer = NULL;
72                 diff_buffer_size = 0;
73         }
74         if (diff_buffer) {
75                 print_line(diff_buffer, diff_buffer_size);
76                 free(diff_buffer);
77                 diff_buffer = NULL;
78                 diff_buffer_size = 0;
79         }
80         return 0;
81 }
82
83 static int load_mmfile(mmfile_t *file, const unsigned char *sha1)
84 {
85         char type[20];
86
87         if (is_null_sha1(sha1)) {
88                 file->ptr = (char *)"";
89                 file->size = 0;
90         } else {
91                 file->ptr = read_sha1_file(sha1, type, &file->size);
92         }
93         return 1;
94 }
95
96 static void run_diff(const unsigned char *sha1, const unsigned char *sha2)
97 {
98         mmfile_t file1, file2;
99         xpparam_t diff_params;
100         xdemitconf_t emit_params;
101         xdemitcb_t emit_cb;
102
103         if (!load_mmfile(&file1, sha1) || !load_mmfile(&file2, sha2)) {
104                 cgit_print_error("Unable to load files for diff");
105                 return;
106         }
107
108         diff_params.flags = XDF_NEED_MINIMAL;
109
110         emit_params.ctxlen = 3;
111         emit_params.flags = XDL_EMIT_FUNCNAMES;
112
113         emit_cb.outf = diff_cb;
114
115         xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb);
116 }
117
118
119
120 void cgit_print_diff(const char *old_hex, const char *new_hex)
121 {
122         unsigned char sha1[20], sha2[20];
123
124         get_sha1(old_hex, sha1);
125         get_sha1(new_hex, sha2);
126
127         html("<h2>diff</h2>\n");
128         html("<table class='diff'><tr><td>");
129         run_diff(sha1, sha2);
130         html("</td></tr></table>");
131 }