author | Lars Hjemli <hjemli@gmail.com> | 2006-12-20 21:48:27 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2006-12-20 21:48:27 (UTC) |
commit | 36aba00273e7af1b94bf8c5dd5068709d983d01e (patch) (unidiff) | |
tree | d9be4e6f27b115a799af40cad43445f63fbf2238 | |
parent | a53042865a4ac8b1fa1d6b37720787601e181495 (diff) | |
download | cgit-36aba00273e7af1b94bf8c5dd5068709d983d01e.zip cgit-36aba00273e7af1b94bf8c5dd5068709d983d01e.tar.gz cgit-36aba00273e7af1b94bf8c5dd5068709d983d01e.tar.bz2 |
Add basic diff view
Finally, xdiff is used to show per-file diffs via commit view.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cgit.c | 2 | ||||
-rw-r--r-- | cgit.css | 25 | ||||
-rw-r--r-- | cgit.h | 2 | ||||
-rw-r--r-- | shared.c | 4 | ||||
-rw-r--r-- | ui-diff.c | 131 | ||||
-rw-r--r-- | xdiff.h | 105 |
7 files changed, 270 insertions, 1 deletions
@@ -1,30 +1,30 @@ | |||
1 | CGIT_VERSION = 0.1-pre | 1 | CGIT_VERSION = 0.1-pre |
2 | 2 | ||
3 | INSTALL_BIN = /var/www/htdocs/cgit.cgi | 3 | INSTALL_BIN = /var/www/htdocs/cgit.cgi |
4 | INSTALL_CSS = /var/www/htdocs/cgit.css | 4 | INSTALL_CSS = /var/www/htdocs/cgit.css |
5 | CACHE_ROOT = /var/cache/cgit | 5 | CACHE_ROOT = /var/cache/cgit |
6 | 6 | ||
7 | EXTLIBS = ../git/libgit.a ../git/xdiff/lib.a -lz -lcrypto | 7 | EXTLIBS = ../git/libgit.a ../git/xdiff/lib.a -lz -lcrypto |
8 | OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \ | 8 | OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \ |
9 | ui-summary.o ui-log.o ui-view.c ui-tree.c ui-commit.c | 9 | ui-summary.o ui-log.o ui-view.c ui-tree.c ui-commit.c ui-diff.o |
10 | 10 | ||
11 | CFLAGS += -Wall | 11 | CFLAGS += -Wall |
12 | 12 | ||
13 | all: cgit | 13 | all: cgit |
14 | 14 | ||
15 | install: all clean-cache | 15 | install: all clean-cache |
16 | install cgit $(INSTALL_BIN) | 16 | install cgit $(INSTALL_BIN) |
17 | install cgit.css $(INSTALL_CSS) | 17 | install cgit.css $(INSTALL_CSS) |
18 | 18 | ||
19 | cgit: cgit.c cgit.h git.h $(OBJECTS) | 19 | cgit: cgit.c cgit.h git.h $(OBJECTS) |
20 | $(CC) $(CFLAGS) -DCGIT_VERSION='"$(CGIT_VERSION)"' cgit.c -o cgit \ | 20 | $(CC) $(CFLAGS) -DCGIT_VERSION='"$(CGIT_VERSION)"' cgit.c -o cgit \ |
21 | $(OBJECTS) $(EXTLIBS) | 21 | $(OBJECTS) $(EXTLIBS) |
22 | 22 | ||
23 | $(OBJECTS): cgit.h git.h | 23 | $(OBJECTS): cgit.h git.h |
24 | 24 | ||
25 | .PHONY: clean | 25 | .PHONY: clean |
26 | clean: | 26 | clean: |
27 | rm -f cgit *.o | 27 | rm -f cgit *.o |
28 | 28 | ||
29 | clean-cache: | 29 | clean-cache: |
30 | rm -rf $(CACHE_ROOT)/* | 30 | rm -rf $(CACHE_ROOT)/* |
@@ -1,134 +1,136 @@ | |||
1 | /* cgit.c: cgi for the git scm | 1 | /* cgit.c: cgi for the git scm |
2 | * | 2 | * |
3 | * Copyright (C) 2006 Lars Hjemli | 3 | * Copyright (C) 2006 Lars Hjemli |
4 | * | 4 | * |
5 | * Licensed under GNU General Public License v2 | 5 | * Licensed under GNU General Public License v2 |
6 | * (see COPYING for full license text) | 6 | * (see COPYING for full license text) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "cgit.h" | 9 | #include "cgit.h" |
10 | 10 | ||
11 | const char cgit_version[] = CGIT_VERSION; | 11 | const char cgit_version[] = CGIT_VERSION; |
12 | 12 | ||
13 | static void cgit_print_repo_page(struct cacheitem *item) | 13 | static void cgit_print_repo_page(struct cacheitem *item) |
14 | { | 14 | { |
15 | if (chdir(fmt("%s/%s", cgit_root, cgit_query_repo)) || | 15 | if (chdir(fmt("%s/%s", cgit_root, cgit_query_repo)) || |
16 | cgit_read_config("info/cgit", cgit_repo_config_cb)) { | 16 | cgit_read_config("info/cgit", cgit_repo_config_cb)) { |
17 | char *title = fmt("%s - %s", cgit_root_title, "Bad request"); | 17 | char *title = fmt("%s - %s", cgit_root_title, "Bad request"); |
18 | cgit_print_docstart(title, item); | 18 | cgit_print_docstart(title, item); |
19 | cgit_print_pageheader(title); | 19 | cgit_print_pageheader(title); |
20 | cgit_print_error(fmt("Unable to scan repository: %s", | 20 | cgit_print_error(fmt("Unable to scan repository: %s", |
21 | strerror(errno))); | 21 | strerror(errno))); |
22 | cgit_print_docend(); | 22 | cgit_print_docend(); |
23 | return; | 23 | return; |
24 | } | 24 | } |
25 | setenv("GIT_DIR", fmt("%s/%s", cgit_root, cgit_query_repo), 1); | 25 | setenv("GIT_DIR", fmt("%s/%s", cgit_root, cgit_query_repo), 1); |
26 | char *title = fmt("%s - %s", cgit_repo_name, cgit_repo_desc); | 26 | char *title = fmt("%s - %s", cgit_repo_name, cgit_repo_desc); |
27 | cgit_print_docstart(title, item); | 27 | cgit_print_docstart(title, item); |
28 | cgit_print_pageheader(title); | 28 | cgit_print_pageheader(title); |
29 | if (!cgit_query_page) { | 29 | if (!cgit_query_page) { |
30 | cgit_print_summary(); | 30 | cgit_print_summary(); |
31 | } else if (!strcmp(cgit_query_page, "log")) { | 31 | } else if (!strcmp(cgit_query_page, "log")) { |
32 | cgit_print_log(cgit_query_head, cgit_query_ofs, 100); | 32 | cgit_print_log(cgit_query_head, cgit_query_ofs, 100); |
33 | } else if (!strcmp(cgit_query_page, "tree")) { | 33 | } else if (!strcmp(cgit_query_page, "tree")) { |
34 | cgit_print_tree(cgit_query_sha1); | 34 | cgit_print_tree(cgit_query_sha1); |
35 | } else if (!strcmp(cgit_query_page, "commit")) { | 35 | } else if (!strcmp(cgit_query_page, "commit")) { |
36 | cgit_print_commit(cgit_query_sha1); | 36 | cgit_print_commit(cgit_query_sha1); |
37 | } else if (!strcmp(cgit_query_page, "view")) { | 37 | } else if (!strcmp(cgit_query_page, "view")) { |
38 | cgit_print_view(cgit_query_sha1); | 38 | cgit_print_view(cgit_query_sha1); |
39 | } else if (!strcmp(cgit_query_page, "diff")) { | ||
40 | cgit_print_diff(cgit_query_sha1, cgit_query_sha2); | ||
39 | } | 41 | } |
40 | cgit_print_docend(); | 42 | cgit_print_docend(); |
41 | } | 43 | } |
42 | 44 | ||
43 | static void cgit_fill_cache(struct cacheitem *item) | 45 | static void cgit_fill_cache(struct cacheitem *item) |
44 | { | 46 | { |
45 | static char buf[PATH_MAX]; | 47 | static char buf[PATH_MAX]; |
46 | 48 | ||
47 | getcwd(buf, sizeof(buf)); | 49 | getcwd(buf, sizeof(buf)); |
48 | htmlfd = item->fd; | 50 | htmlfd = item->fd; |
49 | item->st.st_mtime = time(NULL); | 51 | item->st.st_mtime = time(NULL); |
50 | if (cgit_query_repo) | 52 | if (cgit_query_repo) |
51 | cgit_print_repo_page(item); | 53 | cgit_print_repo_page(item); |
52 | else | 54 | else |
53 | cgit_print_repolist(item); | 55 | cgit_print_repolist(item); |
54 | chdir(buf); | 56 | chdir(buf); |
55 | } | 57 | } |
56 | 58 | ||
57 | static void cgit_check_cache(struct cacheitem *item) | 59 | static void cgit_check_cache(struct cacheitem *item) |
58 | { | 60 | { |
59 | int i = 0; | 61 | int i = 0; |
60 | 62 | ||
61 | cache_prepare(item); | 63 | cache_prepare(item); |
62 | top: | 64 | top: |
63 | if (++i > cgit_max_lock_attempts) { | 65 | if (++i > cgit_max_lock_attempts) { |
64 | die("cgit_refresh_cache: unable to lock %s: %s", | 66 | die("cgit_refresh_cache: unable to lock %s: %s", |
65 | item->name, strerror(errno)); | 67 | item->name, strerror(errno)); |
66 | } | 68 | } |
67 | if (!cache_exist(item)) { | 69 | if (!cache_exist(item)) { |
68 | if (!cache_lock(item)) { | 70 | if (!cache_lock(item)) { |
69 | sleep(1); | 71 | sleep(1); |
70 | goto top; | 72 | goto top; |
71 | } | 73 | } |
72 | if (!cache_exist(item)) { | 74 | if (!cache_exist(item)) { |
73 | cgit_fill_cache(item); | 75 | cgit_fill_cache(item); |
74 | cache_unlock(item); | 76 | cache_unlock(item); |
75 | } else { | 77 | } else { |
76 | cache_cancel_lock(item); | 78 | cache_cancel_lock(item); |
77 | } | 79 | } |
78 | } else if (cache_expired(item) && cache_lock(item)) { | 80 | } else if (cache_expired(item) && cache_lock(item)) { |
79 | if (cache_expired(item)) { | 81 | if (cache_expired(item)) { |
80 | cgit_fill_cache(item); | 82 | cgit_fill_cache(item); |
81 | cache_unlock(item); | 83 | cache_unlock(item); |
82 | } else { | 84 | } else { |
83 | cache_cancel_lock(item); | 85 | cache_cancel_lock(item); |
84 | } | 86 | } |
85 | } | 87 | } |
86 | } | 88 | } |
87 | 89 | ||
88 | static void cgit_print_cache(struct cacheitem *item) | 90 | static void cgit_print_cache(struct cacheitem *item) |
89 | { | 91 | { |
90 | static char buf[4096]; | 92 | static char buf[4096]; |
91 | ssize_t i; | 93 | ssize_t i; |
92 | 94 | ||
93 | int fd = open(item->name, O_RDONLY); | 95 | int fd = open(item->name, O_RDONLY); |
94 | if (fd<0) | 96 | if (fd<0) |
95 | die("Unable to open cached file %s", item->name); | 97 | die("Unable to open cached file %s", item->name); |
96 | 98 | ||
97 | while((i=read(fd, buf, sizeof(buf))) > 0) | 99 | while((i=read(fd, buf, sizeof(buf))) > 0) |
98 | write(STDOUT_FILENO, buf, i); | 100 | write(STDOUT_FILENO, buf, i); |
99 | 101 | ||
100 | close(fd); | 102 | close(fd); |
101 | } | 103 | } |
102 | 104 | ||
103 | static void cgit_parse_args(int argc, const char **argv) | 105 | static void cgit_parse_args(int argc, const char **argv) |
104 | { | 106 | { |
105 | int i; | 107 | int i; |
106 | 108 | ||
107 | for (i = 1; i < argc; i++) { | 109 | for (i = 1; i < argc; i++) { |
108 | if (!strncmp(argv[i], "--root=", 7)) { | 110 | if (!strncmp(argv[i], "--root=", 7)) { |
109 | cgit_root = xstrdup(argv[i]+7); | 111 | cgit_root = xstrdup(argv[i]+7); |
110 | } | 112 | } |
111 | if (!strncmp(argv[i], "--cache=", 8)) { | 113 | if (!strncmp(argv[i], "--cache=", 8)) { |
112 | cgit_cache_root = xstrdup(argv[i]+8); | 114 | cgit_cache_root = xstrdup(argv[i]+8); |
113 | } | 115 | } |
114 | if (!strcmp(argv[i], "--nocache")) { | 116 | if (!strcmp(argv[i], "--nocache")) { |
115 | cgit_nocache = 1; | 117 | cgit_nocache = 1; |
116 | } | 118 | } |
117 | if (!strncmp(argv[i], "--query=", 8)) { | 119 | if (!strncmp(argv[i], "--query=", 8)) { |
118 | cgit_querystring = xstrdup(argv[i]+8); | 120 | cgit_querystring = xstrdup(argv[i]+8); |
119 | } | 121 | } |
120 | if (!strncmp(argv[i], "--repo=", 7)) { | 122 | if (!strncmp(argv[i], "--repo=", 7)) { |
121 | cgit_query_repo = xstrdup(argv[i]+7); | 123 | cgit_query_repo = xstrdup(argv[i]+7); |
122 | } | 124 | } |
123 | if (!strncmp(argv[i], "--page=", 7)) { | 125 | if (!strncmp(argv[i], "--page=", 7)) { |
124 | cgit_query_page = xstrdup(argv[i]+7); | 126 | cgit_query_page = xstrdup(argv[i]+7); |
125 | } | 127 | } |
126 | if (!strncmp(argv[i], "--head=", 7)) { | 128 | if (!strncmp(argv[i], "--head=", 7)) { |
127 | cgit_query_head = xstrdup(argv[i]+7); | 129 | cgit_query_head = xstrdup(argv[i]+7); |
128 | cgit_query_has_symref = 1; | 130 | cgit_query_has_symref = 1; |
129 | } | 131 | } |
130 | if (!strncmp(argv[i], "--sha1=", 7)) { | 132 | if (!strncmp(argv[i], "--sha1=", 7)) { |
131 | cgit_query_sha1 = xstrdup(argv[i]+7); | 133 | cgit_query_sha1 = xstrdup(argv[i]+7); |
132 | cgit_query_has_sha1 = 1; | 134 | cgit_query_has_sha1 = 1; |
133 | } | 135 | } |
134 | if (!strncmp(argv[i], "--ofs=", 6)) { | 136 | if (!strncmp(argv[i], "--ofs=", 6)) { |
@@ -1,166 +1,191 @@ | |||
1 | body { | 1 | body { |
2 | font-family: arial; | 2 | font-family: arial; |
3 | font-size: normal; | 3 | font-size: normal; |
4 | background: white; | 4 | background: white; |
5 | padding: 0em; | 5 | padding: 0em; |
6 | margin: 0.5em 1em; | 6 | margin: 0.5em 1em; |
7 | } | 7 | } |
8 | 8 | ||
9 | 9 | ||
10 | h2 { | 10 | h2 { |
11 | font-size: normal; | 11 | font-size: normal; |
12 | font-weight: bold; | 12 | font-weight: bold; |
13 | margin-bottom: 0.1em; | 13 | margin-bottom: 0.1em; |
14 | } | 14 | } |
15 | 15 | ||
16 | a { | 16 | a { |
17 | color: blue; | 17 | color: blue; |
18 | text-decoration: none; | 18 | text-decoration: none; |
19 | } | 19 | } |
20 | 20 | ||
21 | a:hover { | 21 | a:hover { |
22 | text-decoration: underline; | 22 | text-decoration: underline; |
23 | } | 23 | } |
24 | 24 | ||
25 | table.list { | 25 | table.list { |
26 | border: solid 1px black; | 26 | border: solid 1px black; |
27 | border-collapse: collapse; | 27 | border-collapse: collapse; |
28 | border: solid 1px #aaa; | 28 | border: solid 1px #aaa; |
29 | } | 29 | } |
30 | table.list tr { | 30 | table.list tr { |
31 | background: white; | 31 | background: white; |
32 | } | 32 | } |
33 | table.list tr:hover { | 33 | table.list tr:hover { |
34 | background: #eee; | 34 | background: #eee; |
35 | } | 35 | } |
36 | table.list th { | 36 | table.list th { |
37 | font-weight: bold; | 37 | font-weight: bold; |
38 | background: #ddd; | 38 | background: #ddd; |
39 | border-bottom: solid 1px #aaa; | 39 | border-bottom: solid 1px #aaa; |
40 | padding: 0.1em 0.5em 0.1em 0.5em; | 40 | padding: 0.1em 0.5em 0.1em 0.5em; |
41 | vertical-align: baseline; | 41 | vertical-align: baseline; |
42 | } | 42 | } |
43 | table.list td { | 43 | table.list td { |
44 | border: none; | 44 | border: none; |
45 | padding: 0.1em 0.5em 0.1em 0.5em; | 45 | padding: 0.1em 0.5em 0.1em 0.5em; |
46 | } | 46 | } |
47 | img { | 47 | img { |
48 | border: none; | 48 | border: none; |
49 | } | 49 | } |
50 | 50 | ||
51 | 51 | ||
52 | div#header { | 52 | div#header { |
53 | background-color: #eee; | 53 | background-color: #eee; |
54 | padding: 0.25em 0.25em 0.25em 0.5em; | 54 | padding: 0.25em 0.25em 0.25em 0.5em; |
55 | font-size: 150%; | 55 | font-size: 150%; |
56 | font-weight: bold; | 56 | font-weight: bold; |
57 | border: solid 1px #ccc; | 57 | border: solid 1px #ccc; |
58 | vertical-align: middle; | 58 | vertical-align: middle; |
59 | } | 59 | } |
60 | div#header img#logo { | 60 | div#header img#logo { |
61 | float: right; | 61 | float: right; |
62 | } | 62 | } |
63 | div#header a { | 63 | div#header a { |
64 | color: black; | 64 | color: black; |
65 | } | 65 | } |
66 | 66 | ||
67 | div#content { | 67 | div#content { |
68 | margin: 0.5em 0.5em; | 68 | margin: 0.5em 0.5em; |
69 | } | 69 | } |
70 | 70 | ||
71 | div#blob { | 71 | div#blob { |
72 | border: solid 1px black; | 72 | border: solid 1px black; |
73 | } | 73 | } |
74 | 74 | ||
75 | div.error { | 75 | div.error { |
76 | color: red; | 76 | color: red; |
77 | font-weight: bold; | 77 | font-weight: bold; |
78 | margin: 1em 2em; | 78 | margin: 1em 2em; |
79 | } | 79 | } |
80 | div.ls-blob, div.ls-dir { | ||
81 | font-family: monospace; | ||
82 | } | ||
80 | div.ls-dir a { | 83 | div.ls-dir a { |
81 | font-weight: bold; | 84 | font-weight: bold; |
82 | } | 85 | } |
83 | th.filesize, td.filesize { | 86 | th.filesize, td.filesize { |
84 | text-align: right; | 87 | text-align: right; |
85 | } | 88 | } |
89 | td.filesize { | ||
90 | font-family: monospace; | ||
91 | } | ||
86 | td.filemode { | 92 | td.filemode { |
87 | font-family: monospace; | 93 | font-family: monospace; |
88 | } | 94 | } |
89 | 95 | ||
90 | td.blob { | 96 | td.blob { |
91 | white-space: pre; | 97 | white-space: pre; |
92 | font-family: courier; | 98 | font-family: courier; |
93 | font-size: 100%; | 99 | font-size: 100%; |
94 | background-color: white; | 100 | background-color: white; |
95 | } | 101 | } |
96 | 102 | ||
97 | table.log td { | 103 | table.log td { |
98 | white-space: nowrap; | 104 | white-space: nowrap; |
99 | } | 105 | } |
100 | 106 | ||
101 | table.commit-info { | 107 | table.commit-info { |
102 | border-collapse: collapse; | 108 | border-collapse: collapse; |
103 | margin-top: 1.5em; | 109 | margin-top: 1.5em; |
104 | } | 110 | } |
105 | table.commit-info th { | 111 | table.commit-info th { |
106 | text-align: left; | 112 | text-align: left; |
107 | font-weight: normal; | 113 | font-weight: normal; |
108 | padding: 0.1em 1em 0.1em 0.1em; | 114 | padding: 0.1em 1em 0.1em 0.1em; |
109 | } | 115 | } |
110 | table.commit-info td { | 116 | table.commit-info td { |
111 | font-weight: normal; | 117 | font-weight: normal; |
112 | padding: 0.1em 1em 0.1em 0.1em; | 118 | padding: 0.1em 1em 0.1em 0.1em; |
113 | } | 119 | } |
114 | div.commit-subject { | 120 | div.commit-subject { |
115 | font-weight: bold; | 121 | font-weight: bold; |
116 | font-size: 125%; | 122 | font-size: 125%; |
117 | margin: 1.5em 0em 0.5em 0em; | 123 | margin: 1.5em 0em 0.5em 0em; |
118 | padding: 0em; | 124 | padding: 0em; |
119 | } | 125 | } |
120 | div.commit-msg { | 126 | div.commit-msg { |
121 | white-space: pre; | 127 | white-space: pre; |
122 | font-family: monospace; | 128 | font-family: monospace; |
123 | } | 129 | } |
124 | table.diffstat { | 130 | table.diffstat { |
125 | border-collapse: collapse; | 131 | border-collapse: collapse; |
126 | margin-top: 1.5em; | 132 | margin-top: 1.5em; |
127 | } | 133 | } |
128 | table.diffstat th { | 134 | table.diffstat th { |
129 | font-weight: normal; | 135 | font-weight: normal; |
130 | text-align: left; | 136 | text-align: left; |
131 | text-decoration: underline; | 137 | text-decoration: underline; |
132 | padding: 0.1em 1em 0.1em 0.1em; | 138 | padding: 0.1em 1em 0.1em 0.1em; |
133 | font-size: 100%; | 139 | font-size: 100%; |
134 | } | 140 | } |
135 | table.diffstat td { | 141 | table.diffstat td { |
136 | padding: 0.1em 1em 0.1em 0.1em; | 142 | padding: 0.1em 1em 0.1em 0.1em; |
137 | font-size: 100%; | 143 | font-size: 100%; |
138 | } | 144 | } |
139 | table.diffstat td span.modechange { | 145 | table.diffstat td span.modechange { |
140 | padding-left: 1em; | 146 | padding-left: 1em; |
141 | color: red; | 147 | color: red; |
142 | } | 148 | } |
143 | table.diffstat td.add a { | 149 | table.diffstat td.add a { |
144 | color: green; | 150 | color: green; |
145 | } | 151 | } |
146 | table.diffstat td.del a { | 152 | table.diffstat td.del a { |
147 | color: red; | 153 | color: red; |
148 | } | 154 | } |
149 | table.diffstat td.upd a { | 155 | table.diffstat td.upd a { |
150 | color: blue; | 156 | color: blue; |
151 | } | 157 | } |
152 | table.diffstat td.summary { | 158 | table.diffstat td.summary { |
153 | /* border-top: solid 1px black; */ | 159 | /* border-top: solid 1px black; */ |
154 | color: #888; | 160 | color: #888; |
155 | padding-top: 0.5em; | 161 | padding-top: 0.5em; |
156 | } | 162 | } |
163 | |||
164 | table.diff td { | ||
165 | border: solid 1px black; | ||
166 | font-family: monospace; | ||
167 | white-space: pre; | ||
168 | } | ||
169 | |||
170 | table.diff td div.hunk { | ||
171 | background: #ccc; | ||
172 | } | ||
173 | |||
174 | table.diff td div.add { | ||
175 | color: green; | ||
176 | } | ||
177 | |||
178 | table.diff td div.del { | ||
179 | color: red; | ||
180 | } | ||
181 | |||
157 | .sha1 { | 182 | .sha1 { |
158 | font-family: courier; | 183 | font-family: courier; |
159 | font-size: 90%; | 184 | font-size: 90%; |
160 | } | 185 | } |
161 | .left { | 186 | .left { |
162 | text-align: left; | 187 | text-align: left; |
163 | } | 188 | } |
164 | .right { | 189 | .right { |
165 | text-align: right; | 190 | text-align: right; |
166 | } | 191 | } |
@@ -1,108 +1,110 @@ | |||
1 | #ifndef CGIT_H | 1 | #ifndef CGIT_H |
2 | #define CGIT_H | 2 | #define CGIT_H |
3 | 3 | ||
4 | #include "git.h" | 4 | #include "git.h" |
5 | #include <openssl/sha.h> | 5 | #include <openssl/sha.h> |
6 | #include <ctype.h> | 6 | #include <ctype.h> |
7 | #include <sched.h> | 7 | #include <sched.h> |
8 | 8 | ||
9 | typedef void (*configfn)(const char *name, const char *value); | 9 | typedef void (*configfn)(const char *name, const char *value); |
10 | 10 | ||
11 | struct cacheitem { | 11 | struct cacheitem { |
12 | char *name; | 12 | char *name; |
13 | struct stat st; | 13 | struct stat st; |
14 | int ttl; | 14 | int ttl; |
15 | int fd; | 15 | int fd; |
16 | }; | 16 | }; |
17 | 17 | ||
18 | struct commitinfo { | 18 | struct commitinfo { |
19 | struct commit *commit; | 19 | struct commit *commit; |
20 | char *author; | 20 | char *author; |
21 | char *author_email; | 21 | char *author_email; |
22 | unsigned long author_date; | 22 | unsigned long author_date; |
23 | char *committer; | 23 | char *committer; |
24 | char *committer_email; | 24 | char *committer_email; |
25 | unsigned long committer_date; | 25 | unsigned long committer_date; |
26 | char *subject; | 26 | char *subject; |
27 | char *msg; | 27 | char *msg; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | extern const char cgit_version[]; | 30 | extern const char cgit_version[]; |
31 | 31 | ||
32 | extern char *cgit_root; | 32 | extern char *cgit_root; |
33 | extern char *cgit_root_title; | 33 | extern char *cgit_root_title; |
34 | extern char *cgit_css; | 34 | extern char *cgit_css; |
35 | extern char *cgit_logo; | 35 | extern char *cgit_logo; |
36 | extern char *cgit_logo_link; | 36 | extern char *cgit_logo_link; |
37 | extern char *cgit_virtual_root; | 37 | extern char *cgit_virtual_root; |
38 | extern char *cgit_cache_root; | 38 | extern char *cgit_cache_root; |
39 | 39 | ||
40 | extern int cgit_nocache; | 40 | extern int cgit_nocache; |
41 | extern int cgit_max_lock_attempts; | 41 | extern int cgit_max_lock_attempts; |
42 | extern int cgit_cache_root_ttl; | 42 | extern int cgit_cache_root_ttl; |
43 | extern int cgit_cache_repo_ttl; | 43 | extern int cgit_cache_repo_ttl; |
44 | extern int cgit_cache_dynamic_ttl; | 44 | extern int cgit_cache_dynamic_ttl; |
45 | extern int cgit_cache_static_ttl; | 45 | extern int cgit_cache_static_ttl; |
46 | extern int cgit_cache_max_create_time; | 46 | extern int cgit_cache_max_create_time; |
47 | 47 | ||
48 | extern char *cgit_repo_name; | 48 | extern char *cgit_repo_name; |
49 | extern char *cgit_repo_desc; | 49 | extern char *cgit_repo_desc; |
50 | extern char *cgit_repo_owner; | 50 | extern char *cgit_repo_owner; |
51 | 51 | ||
52 | extern int cgit_query_has_symref; | 52 | extern int cgit_query_has_symref; |
53 | extern int cgit_query_has_sha1; | 53 | extern int cgit_query_has_sha1; |
54 | 54 | ||
55 | extern char *cgit_querystring; | 55 | extern char *cgit_querystring; |
56 | extern char *cgit_query_repo; | 56 | extern char *cgit_query_repo; |
57 | extern char *cgit_query_page; | 57 | extern char *cgit_query_page; |
58 | extern char *cgit_query_head; | 58 | extern char *cgit_query_head; |
59 | extern char *cgit_query_sha1; | 59 | extern char *cgit_query_sha1; |
60 | extern char *cgit_query_sha2; | ||
60 | extern int cgit_query_ofs; | 61 | extern int cgit_query_ofs; |
61 | 62 | ||
62 | extern int htmlfd; | 63 | extern int htmlfd; |
63 | 64 | ||
64 | extern void cgit_global_config_cb(const char *name, const char *value); | 65 | extern void cgit_global_config_cb(const char *name, const char *value); |
65 | extern void cgit_repo_config_cb(const char *name, const char *value); | 66 | extern void cgit_repo_config_cb(const char *name, const char *value); |
66 | extern void cgit_querystring_cb(const char *name, const char *value); | 67 | extern void cgit_querystring_cb(const char *name, const char *value); |
67 | 68 | ||
68 | extern void *cgit_free_commitinfo(struct commitinfo *info); | 69 | extern void *cgit_free_commitinfo(struct commitinfo *info); |
69 | 70 | ||
70 | extern char *fmt(const char *format,...); | 71 | extern char *fmt(const char *format,...); |
71 | 72 | ||
72 | extern void html(const char *txt); | 73 | extern void html(const char *txt); |
73 | extern void htmlf(const char *format,...); | 74 | extern void htmlf(const char *format,...); |
74 | extern void html_txt(char *txt); | 75 | extern void html_txt(char *txt); |
75 | extern void html_attr(char *txt); | 76 | extern void html_attr(char *txt); |
76 | extern void html_link_open(char *url, char *title, char *class); | 77 | extern void html_link_open(char *url, char *title, char *class); |
77 | extern void html_link_close(void); | 78 | extern void html_link_close(void); |
78 | extern void html_filemode(unsigned short mode); | 79 | extern void html_filemode(unsigned short mode); |
79 | 80 | ||
80 | extern int cgit_read_config(const char *filename, configfn fn); | 81 | extern int cgit_read_config(const char *filename, configfn fn); |
81 | extern int cgit_parse_query(char *txt, configfn fn); | 82 | extern int cgit_parse_query(char *txt, configfn fn); |
82 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); | 83 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); |
83 | 84 | ||
84 | extern void cache_prepare(struct cacheitem *item); | 85 | extern void cache_prepare(struct cacheitem *item); |
85 | extern int cache_lock(struct cacheitem *item); | 86 | extern int cache_lock(struct cacheitem *item); |
86 | extern int cache_unlock(struct cacheitem *item); | 87 | extern int cache_unlock(struct cacheitem *item); |
87 | extern int cache_cancel_lock(struct cacheitem *item); | 88 | extern int cache_cancel_lock(struct cacheitem *item); |
88 | extern int cache_exist(struct cacheitem *item); | 89 | extern int cache_exist(struct cacheitem *item); |
89 | extern int cache_expired(struct cacheitem *item); | 90 | extern int cache_expired(struct cacheitem *item); |
90 | 91 | ||
91 | extern char *cgit_repourl(const char *reponame); | 92 | extern char *cgit_repourl(const char *reponame); |
92 | extern char *cgit_pageurl(const char *reponame, const char *pagename, | 93 | extern char *cgit_pageurl(const char *reponame, const char *pagename, |
93 | const char *query); | 94 | const char *query); |
94 | 95 | ||
95 | extern void cgit_print_error(char *msg); | 96 | extern void cgit_print_error(char *msg); |
96 | extern void cgit_print_date(unsigned long secs); | 97 | extern void cgit_print_date(unsigned long secs); |
97 | extern void cgit_print_docstart(char *title, struct cacheitem *item); | 98 | extern void cgit_print_docstart(char *title, struct cacheitem *item); |
98 | extern void cgit_print_docend(); | 99 | extern void cgit_print_docend(); |
99 | extern void cgit_print_pageheader(char *title); | 100 | extern void cgit_print_pageheader(char *title); |
100 | 101 | ||
101 | extern void cgit_print_repolist(struct cacheitem *item); | 102 | extern void cgit_print_repolist(struct cacheitem *item); |
102 | extern void cgit_print_summary(); | 103 | extern void cgit_print_summary(); |
103 | extern void cgit_print_log(const char *tip, int ofs, int cnt); | 104 | extern void cgit_print_log(const char *tip, int ofs, int cnt); |
104 | extern void cgit_print_view(const char *hex); | 105 | extern void cgit_print_view(const char *hex); |
105 | extern void cgit_print_tree(const char *hex); | 106 | extern void cgit_print_tree(const char *hex); |
106 | extern void cgit_print_commit(const char *hex); | 107 | extern void cgit_print_commit(const char *hex); |
108 | extern void cgit_print_diff(const char *old_hex, const char *new_hex); | ||
107 | 109 | ||
108 | #endif /* CGIT_H */ | 110 | #endif /* CGIT_H */ |
@@ -1,100 +1,104 @@ | |||
1 | /* shared.c: global vars + some callback functions | 1 | /* shared.c: global vars + some callback functions |
2 | * | 2 | * |
3 | * Copyright (C) 2006 Lars Hjemli | 3 | * Copyright (C) 2006 Lars Hjemli |
4 | * | 4 | * |
5 | * Licensed under GNU General Public License v2 | 5 | * Licensed under GNU General Public License v2 |
6 | * (see COPYING for full license text) | 6 | * (see COPYING for full license text) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "cgit.h" | 9 | #include "cgit.h" |
10 | 10 | ||
11 | char *cgit_root = "/usr/src/git"; | 11 | char *cgit_root = "/usr/src/git"; |
12 | char *cgit_root_title = "Git repository browser"; | 12 | char *cgit_root_title = "Git repository browser"; |
13 | char *cgit_css = "/cgit.css"; | 13 | char *cgit_css = "/cgit.css"; |
14 | char *cgit_logo = "/git-logo.png"; | 14 | char *cgit_logo = "/git-logo.png"; |
15 | char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/"; | 15 | char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/"; |
16 | char *cgit_virtual_root = NULL; | 16 | char *cgit_virtual_root = NULL; |
17 | 17 | ||
18 | char *cgit_cache_root = "/var/cache/cgit"; | 18 | char *cgit_cache_root = "/var/cache/cgit"; |
19 | 19 | ||
20 | int cgit_nocache = 0; | 20 | int cgit_nocache = 0; |
21 | int cgit_max_lock_attempts = 5; | 21 | int cgit_max_lock_attempts = 5; |
22 | int cgit_cache_root_ttl = 5; | 22 | int cgit_cache_root_ttl = 5; |
23 | int cgit_cache_repo_ttl = 5; | 23 | int cgit_cache_repo_ttl = 5; |
24 | int cgit_cache_dynamic_ttl = 5; | 24 | int cgit_cache_dynamic_ttl = 5; |
25 | int cgit_cache_static_ttl = -1; | 25 | int cgit_cache_static_ttl = -1; |
26 | int cgit_cache_max_create_time = 5; | 26 | int cgit_cache_max_create_time = 5; |
27 | 27 | ||
28 | char *cgit_repo_name = NULL; | 28 | char *cgit_repo_name = NULL; |
29 | char *cgit_repo_desc = NULL; | 29 | char *cgit_repo_desc = NULL; |
30 | char *cgit_repo_owner = NULL; | 30 | char *cgit_repo_owner = NULL; |
31 | 31 | ||
32 | int cgit_query_has_symref = 0; | 32 | int cgit_query_has_symref = 0; |
33 | int cgit_query_has_sha1 = 0; | 33 | int cgit_query_has_sha1 = 0; |
34 | 34 | ||
35 | char *cgit_querystring = NULL; | 35 | char *cgit_querystring = NULL; |
36 | char *cgit_query_repo = NULL; | 36 | char *cgit_query_repo = NULL; |
37 | char *cgit_query_page = NULL; | 37 | char *cgit_query_page = NULL; |
38 | char *cgit_query_head = NULL; | 38 | char *cgit_query_head = NULL; |
39 | char *cgit_query_sha1 = NULL; | 39 | char *cgit_query_sha1 = NULL; |
40 | char *cgit_query_sha2 = NULL; | ||
40 | int cgit_query_ofs = 0; | 41 | int cgit_query_ofs = 0; |
41 | 42 | ||
42 | int htmlfd = 0; | 43 | int htmlfd = 0; |
43 | 44 | ||
44 | void cgit_global_config_cb(const char *name, const char *value) | 45 | void cgit_global_config_cb(const char *name, const char *value) |
45 | { | 46 | { |
46 | if (!strcmp(name, "root")) | 47 | if (!strcmp(name, "root")) |
47 | cgit_root = xstrdup(value); | 48 | cgit_root = xstrdup(value); |
48 | else if (!strcmp(name, "root-title")) | 49 | else if (!strcmp(name, "root-title")) |
49 | cgit_root_title = xstrdup(value); | 50 | cgit_root_title = xstrdup(value); |
50 | else if (!strcmp(name, "css")) | 51 | else if (!strcmp(name, "css")) |
51 | cgit_css = xstrdup(value); | 52 | cgit_css = xstrdup(value); |
52 | else if (!strcmp(name, "logo")) | 53 | else if (!strcmp(name, "logo")) |
53 | cgit_logo = xstrdup(value); | 54 | cgit_logo = xstrdup(value); |
54 | else if (!strcmp(name, "logo-link")) | 55 | else if (!strcmp(name, "logo-link")) |
55 | cgit_logo_link = xstrdup(value); | 56 | cgit_logo_link = xstrdup(value); |
56 | else if (!strcmp(name, "virtual-root")) | 57 | else if (!strcmp(name, "virtual-root")) |
57 | cgit_virtual_root = xstrdup(value); | 58 | cgit_virtual_root = xstrdup(value); |
58 | else if (!strcmp(name, "nocache")) | 59 | else if (!strcmp(name, "nocache")) |
59 | cgit_nocache = atoi(value); | 60 | cgit_nocache = atoi(value); |
60 | else if (!strcmp(name, "cache-root")) | 61 | else if (!strcmp(name, "cache-root")) |
61 | cgit_cache_root = xstrdup(value); | 62 | cgit_cache_root = xstrdup(value); |
62 | } | 63 | } |
63 | 64 | ||
64 | void cgit_repo_config_cb(const char *name, const char *value) | 65 | void cgit_repo_config_cb(const char *name, const char *value) |
65 | { | 66 | { |
66 | if (!strcmp(name, "name")) | 67 | if (!strcmp(name, "name")) |
67 | cgit_repo_name = xstrdup(value); | 68 | cgit_repo_name = xstrdup(value); |
68 | else if (!strcmp(name, "desc")) | 69 | else if (!strcmp(name, "desc")) |
69 | cgit_repo_desc = xstrdup(value); | 70 | cgit_repo_desc = xstrdup(value); |
70 | else if (!strcmp(name, "owner")) | 71 | else if (!strcmp(name, "owner")) |
71 | cgit_repo_owner = xstrdup(value); | 72 | cgit_repo_owner = xstrdup(value); |
72 | } | 73 | } |
73 | 74 | ||
74 | void cgit_querystring_cb(const char *name, const char *value) | 75 | void cgit_querystring_cb(const char *name, const char *value) |
75 | { | 76 | { |
76 | if (!strcmp(name,"r")) { | 77 | if (!strcmp(name,"r")) { |
77 | cgit_query_repo = xstrdup(value); | 78 | cgit_query_repo = xstrdup(value); |
78 | } else if (!strcmp(name, "p")) { | 79 | } else if (!strcmp(name, "p")) { |
79 | cgit_query_page = xstrdup(value); | 80 | cgit_query_page = xstrdup(value); |
80 | } else if (!strcmp(name, "h")) { | 81 | } else if (!strcmp(name, "h")) { |
81 | cgit_query_head = xstrdup(value); | 82 | cgit_query_head = xstrdup(value); |
82 | cgit_query_has_symref = 1; | 83 | cgit_query_has_symref = 1; |
83 | } else if (!strcmp(name, "id")) { | 84 | } else if (!strcmp(name, "id")) { |
84 | cgit_query_sha1 = xstrdup(value); | 85 | cgit_query_sha1 = xstrdup(value); |
85 | cgit_query_has_sha1 = 1; | 86 | cgit_query_has_sha1 = 1; |
87 | } else if (!strcmp(name, "id2")) { | ||
88 | cgit_query_sha2 = xstrdup(value); | ||
89 | cgit_query_has_sha1 = 1; | ||
86 | } else if (!strcmp(name, "ofs")) { | 90 | } else if (!strcmp(name, "ofs")) { |
87 | cgit_query_ofs = atoi(value); | 91 | cgit_query_ofs = atoi(value); |
88 | } | 92 | } |
89 | } | 93 | } |
90 | 94 | ||
91 | void *cgit_free_commitinfo(struct commitinfo *info) | 95 | void *cgit_free_commitinfo(struct commitinfo *info) |
92 | { | 96 | { |
93 | free(info->author); | 97 | free(info->author); |
94 | free(info->author_email); | 98 | free(info->author_email); |
95 | free(info->committer); | 99 | free(info->committer); |
96 | free(info->committer_email); | 100 | free(info->committer_email); |
97 | free(info->subject); | 101 | free(info->subject); |
98 | free(info); | 102 | free(info); |
99 | return NULL; | 103 | return NULL; |
100 | } | 104 | } |
diff --git a/ui-diff.c b/ui-diff.c new file mode 100644 index 0000000..0bd9ade --- a/dev/null +++ b/ui-diff.c | |||
@@ -0,0 +1,131 @@ | |||
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 | } | ||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * LibXDiff by Davide Libenzi ( File Differential Library ) | ||
3 | * Copyright (C) 2003 Davide Libenzi | ||
4 | * | ||
5 | * This library is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation; either | ||
8 | * version 2.1 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This library is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this library; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | * Davide Libenzi <davidel@xmailserver.org> | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #if !defined(XDIFF_H) | ||
24 | #define XDIFF_H | ||
25 | |||
26 | #ifdef __cplusplus | ||
27 | extern "C" { | ||
28 | #endif /* #ifdef __cplusplus */ | ||
29 | |||
30 | |||
31 | #define XDF_NEED_MINIMAL (1 << 1) | ||
32 | #define XDF_IGNORE_WHITESPACE (1 << 2) | ||
33 | #define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3) | ||
34 | #define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE) | ||
35 | |||
36 | #define XDL_PATCH_NORMAL '-' | ||
37 | #define XDL_PATCH_REVERSE '+' | ||
38 | #define XDL_PATCH_MODEMASK ((1 << 8) - 1) | ||
39 | #define XDL_PATCH_IGNOREBSPACE (1 << 8) | ||
40 | |||
41 | #define XDL_EMIT_FUNCNAMES (1 << 0) | ||
42 | #define XDL_EMIT_COMMON (1 << 1) | ||
43 | |||
44 | #define XDL_MMB_READONLY (1 << 0) | ||
45 | |||
46 | #define XDL_MMF_ATOMIC (1 << 0) | ||
47 | |||
48 | #define XDL_BDOP_INS 1 | ||
49 | #define XDL_BDOP_CPY 2 | ||
50 | #define XDL_BDOP_INSB 3 | ||
51 | |||
52 | #define XDL_MERGE_MINIMAL 0 | ||
53 | #define XDL_MERGE_EAGER 1 | ||
54 | #define XDL_MERGE_ZEALOUS 2 | ||
55 | |||
56 | typedef struct s_mmfile { | ||
57 | char *ptr; | ||
58 | long size; | ||
59 | } mmfile_t; | ||
60 | |||
61 | typedef struct s_mmbuffer { | ||
62 | char *ptr; | ||
63 | long size; | ||
64 | } mmbuffer_t; | ||
65 | |||
66 | typedef struct s_xpparam { | ||
67 | unsigned long flags; | ||
68 | } xpparam_t; | ||
69 | |||
70 | typedef struct s_xdemitcb { | ||
71 | void *priv; | ||
72 | int (*outf)(void *, mmbuffer_t *, int); | ||
73 | } xdemitcb_t; | ||
74 | |||
75 | typedef struct s_xdemitconf { | ||
76 | long ctxlen; | ||
77 | unsigned long flags; | ||
78 | } xdemitconf_t; | ||
79 | |||
80 | typedef struct s_bdiffparam { | ||
81 | long bsize; | ||
82 | } bdiffparam_t; | ||
83 | |||
84 | |||
85 | #define xdl_malloc(x) malloc(x) | ||
86 | #define xdl_free(ptr) free(ptr) | ||
87 | #define xdl_realloc(ptr,x) realloc(ptr,x) | ||
88 | |||
89 | void *xdl_mmfile_first(mmfile_t *mmf, long *size); | ||
90 | void *xdl_mmfile_next(mmfile_t *mmf, long *size); | ||
91 | long xdl_mmfile_size(mmfile_t *mmf); | ||
92 | |||
93 | int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, | ||
94 | xdemitconf_t const *xecfg, xdemitcb_t *ecb); | ||
95 | |||
96 | int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1, | ||
97 | mmfile_t *mf2, const char *name2, | ||
98 | xpparam_t const *xpp, int level, mmbuffer_t *result); | ||
99 | |||
100 | #ifdef __cplusplus | ||
101 | } | ||
102 | #endif /* #ifdef __cplusplus */ | ||
103 | |||
104 | #endif /* #if !defined(XDIFF_H) */ | ||
105 | |||