summaryrefslogtreecommitdiffabout
path: root/ui-snapshot.c
authorNatanael Copa <natanael.copa@gmail.com>2008-11-30 05:49:07 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2008-11-30 12:39:53 (UTC)
commit314d9ea5a3bc60ec518e314bb0bf8072123dc08f (patch) (unidiff)
treeca65f83e89b301ff6df228785c73c8413a072361 /ui-snapshot.c
parent7b5cee65fd9cf31e4f19ce4ff613778cb95512a9 (diff)
downloadcgit-314d9ea5a3bc60ec518e314bb0bf8072123dc08f.zip
cgit-314d9ea5a3bc60ec518e314bb0bf8072123dc08f.tar.gz
cgit-314d9ea5a3bc60ec518e314bb0bf8072123dc08f.tar.bz2
Set prefix in snapshots when using dwimmery
This patch sets the directory prefix in archives to be the filename, excluding the suffix (.tar.gz, .tar.bz2 etc). The patch also removes the prefix parameter in cgit_print_snapshot() as the prefix might differ. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'ui-snapshot.c') (more/less context) (ignore whitespace changes)
-rw-r--r--ui-snapshot.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/ui-snapshot.c b/ui-snapshot.c
index 9c4d086..76457d6 100644
--- a/ui-snapshot.c
+++ b/ui-snapshot.c
@@ -1,188 +1,198 @@
1/* ui-snapshot.c: generate snapshot of a commit 1/* ui-snapshot.c: generate snapshot of a commit
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#include "html.h" 10#include "html.h"
11#include "ui-shared.h" 11#include "ui-shared.h"
12 12
13static int write_compressed_tar_archive(struct archiver_args *args,const char *filter) 13static int write_compressed_tar_archive(struct archiver_args *args,const char *filter)
14{ 14{
15 int rw[2]; 15 int rw[2];
16 pid_t gzpid; 16 pid_t gzpid;
17 int stdout2; 17 int stdout2;
18 int status; 18 int status;
19 int rv; 19 int rv;
20 20
21 stdout2 = chk_non_negative(dup(STDIN_FILENO), "Preserving STDOUT before compressing"); 21 stdout2 = chk_non_negative(dup(STDIN_FILENO), "Preserving STDOUT before compressing");
22 chk_zero(pipe(rw), "Opening pipe from compressor subprocess"); 22 chk_zero(pipe(rw), "Opening pipe from compressor subprocess");
23 gzpid = chk_non_negative(fork(), "Forking compressor subprocess"); 23 gzpid = chk_non_negative(fork(), "Forking compressor subprocess");
24 if(gzpid==0) { 24 if(gzpid==0) {
25 /* child */ 25 /* child */
26 chk_zero(close(rw[1]), "Closing write end of pipe in child"); 26 chk_zero(close(rw[1]), "Closing write end of pipe in child");
27 chk_zero(close(STDIN_FILENO), "Closing STDIN"); 27 chk_zero(close(STDIN_FILENO), "Closing STDIN");
28 chk_non_negative(dup2(rw[0],STDIN_FILENO), "Redirecting compressor input to stdin"); 28 chk_non_negative(dup2(rw[0],STDIN_FILENO), "Redirecting compressor input to stdin");
29 execlp(filter,filter,NULL); 29 execlp(filter,filter,NULL);
30 _exit(-1); 30 _exit(-1);
31 } 31 }
32 /* parent */ 32 /* parent */
33 chk_zero(close(rw[0]), "Closing read end of pipe"); 33 chk_zero(close(rw[0]), "Closing read end of pipe");
34 chk_non_negative(dup2(rw[1],STDOUT_FILENO), "Redirecting output to compressor"); 34 chk_non_negative(dup2(rw[1],STDOUT_FILENO), "Redirecting output to compressor");
35 35
36 rv = write_tar_archive(args); 36 rv = write_tar_archive(args);
37 37
38 chk_zero(close(STDOUT_FILENO), "Closing STDOUT redirected to compressor"); 38 chk_zero(close(STDOUT_FILENO), "Closing STDOUT redirected to compressor");
39 chk_non_negative(dup2(stdout2,STDOUT_FILENO), "Restoring uncompressed STDOUT"); 39 chk_non_negative(dup2(stdout2,STDOUT_FILENO), "Restoring uncompressed STDOUT");
40 chk_zero(close(stdout2), "Closing uncompressed STDOUT"); 40 chk_zero(close(stdout2), "Closing uncompressed STDOUT");
41 chk_zero(close(rw[1]), "Closing write end of pipe in parent"); 41 chk_zero(close(rw[1]), "Closing write end of pipe in parent");
42 chk_positive(waitpid(gzpid,&status,0), "Waiting on compressor process"); 42 chk_positive(waitpid(gzpid,&status,0), "Waiting on compressor process");
43 if(! ( WIFEXITED(status) && WEXITSTATUS(status)==0 ) ) 43 if(! ( WIFEXITED(status) && WEXITSTATUS(status)==0 ) )
44 cgit_print_error("Failed to compress archive"); 44 cgit_print_error("Failed to compress archive");
45 45
46 return rv; 46 return rv;
47} 47}
48 48
49static int write_tar_gzip_archive(struct archiver_args *args) 49static int write_tar_gzip_archive(struct archiver_args *args)
50{ 50{
51 return write_compressed_tar_archive(args,"gzip"); 51 return write_compressed_tar_archive(args,"gzip");
52} 52}
53 53
54static int write_tar_bzip2_archive(struct archiver_args *args) 54static int write_tar_bzip2_archive(struct archiver_args *args)
55{ 55{
56 return write_compressed_tar_archive(args,"bzip2"); 56 return write_compressed_tar_archive(args,"bzip2");
57} 57}
58 58
59const struct cgit_snapshot_format cgit_snapshot_formats[] = { 59const struct cgit_snapshot_format cgit_snapshot_formats[] = {
60 { ".zip", "application/x-zip", write_zip_archive, 0x1 }, 60 { ".zip", "application/x-zip", write_zip_archive, 0x1 },
61 { ".tar.gz", "application/x-tar", write_tar_gzip_archive, 0x2 }, 61 { ".tar.gz", "application/x-tar", write_tar_gzip_archive, 0x2 },
62 { ".tar.bz2", "application/x-tar", write_tar_bzip2_archive, 0x4 }, 62 { ".tar.bz2", "application/x-tar", write_tar_bzip2_archive, 0x4 },
63 { ".tar", "application/x-tar", write_tar_archive, 0x8 }, 63 { ".tar", "application/x-tar", write_tar_archive, 0x8 },
64 {} 64 {}
65}; 65};
66 66
67static const struct cgit_snapshot_format *get_format(const char *filename) 67static const struct cgit_snapshot_format *get_format(const char *filename)
68{ 68{
69 const struct cgit_snapshot_format *fmt; 69 const struct cgit_snapshot_format *fmt;
70 int fl, sl; 70 int fl, sl;
71 71
72 fl = strlen(filename); 72 fl = strlen(filename);
73 for(fmt = cgit_snapshot_formats; fmt->suffix; fmt++) { 73 for(fmt = cgit_snapshot_formats; fmt->suffix; fmt++) {
74 sl = strlen(fmt->suffix); 74 sl = strlen(fmt->suffix);
75 if (sl >= fl) 75 if (sl >= fl)
76 continue; 76 continue;
77 if (!strcmp(fmt->suffix, filename + fl - sl)) 77 if (!strcmp(fmt->suffix, filename + fl - sl))
78 return fmt; 78 return fmt;
79 } 79 }
80 return NULL; 80 return NULL;
81} 81}
82 82
83static int make_snapshot(const struct cgit_snapshot_format *format, 83static int make_snapshot(const struct cgit_snapshot_format *format,
84 const char *hex, const char *prefix, 84 const char *hex, const char *prefix,
85 const char *filename) 85 const char *filename)
86{ 86{
87 struct archiver_args args; 87 struct archiver_args args;
88 struct commit *commit; 88 struct commit *commit;
89 unsigned char sha1[20]; 89 unsigned char sha1[20];
90 90
91 if(get_sha1(hex, sha1)) { 91 if(get_sha1(hex, sha1)) {
92 cgit_print_error(fmt("Bad object id: %s", hex)); 92 cgit_print_error(fmt("Bad object id: %s", hex));
93 return 1; 93 return 1;
94 } 94 }
95 commit = lookup_commit_reference(sha1); 95 commit = lookup_commit_reference(sha1);
96 if(!commit) { 96 if(!commit) {
97 cgit_print_error(fmt("Not a commit reference: %s", hex)); 97 cgit_print_error(fmt("Not a commit reference: %s", hex));
98 return 1; 98 return 1;
99 } 99 }
100 memset(&args, 0, sizeof(args)); 100 memset(&args, 0, sizeof(args));
101 if (prefix) { 101 if (prefix) {
102 args.base = fmt("%s/", prefix); 102 args.base = fmt("%s/", prefix);
103 args.baselen = strlen(prefix) + 1; 103 args.baselen = strlen(prefix) + 1;
104 } else { 104 } else {
105 args.base = ""; 105 args.base = "";
106 args.baselen = 0; 106 args.baselen = 0;
107 } 107 }
108 args.tree = commit->tree; 108 args.tree = commit->tree;
109 args.time = commit->date; 109 args.time = commit->date;
110 ctx.page.mimetype = xstrdup(format->mimetype); 110 ctx.page.mimetype = xstrdup(format->mimetype);
111 ctx.page.filename = xstrdup(filename); 111 ctx.page.filename = xstrdup(filename);
112 cgit_print_http_headers(&ctx); 112 cgit_print_http_headers(&ctx);
113 format->write_func(&args); 113 format->write_func(&args);
114 return 0; 114 return 0;
115} 115}
116 116
117char *dwim_filename = NULL; 117char *dwim_filename = NULL;
118const char *dwim_refname = NULL; 118const char *dwim_refname = NULL;
119 119
120static int ref_cb(const char *refname, const unsigned char *sha1, int flags, 120static int ref_cb(const char *refname, const unsigned char *sha1, int flags,
121 void *cb_data) 121 void *cb_data)
122{ 122{
123 const char *r = refname; 123 const char *r = refname;
124 while (r && *r) { 124 while (r && *r) {
125 fprintf(stderr, " cmp %s with %s:", dwim_filename, r); 125 fprintf(stderr, " cmp %s with %s:", dwim_filename, r);
126 if (!strcmp(dwim_filename, r)) { 126 if (!strcmp(dwim_filename, r)) {
127 fprintf(stderr, "MATCH!\n"); 127 fprintf(stderr, "MATCH!\n");
128 dwim_refname = refname; 128 dwim_refname = refname;
129 return 1; 129 return 1;
130 } 130 }
131 fprintf(stderr, "no match\n"); 131 fprintf(stderr, "no match\n");
132 if (isdigit(*r)) 132 if (isdigit(*r))
133 break; 133 break;
134 r++; 134 r++;
135 } 135 }
136 return 0; 136 return 0;
137} 137}
138 138
139/* Try to guess the requested revision by combining repo name and tag name 139/* Try to guess the requested revision by combining repo name and tag name
140 * and comparing this to the requested snapshot name. E.g. the requested 140 * and comparing this to the requested snapshot name. E.g. the requested
141 * snapshot is "cgit-0.7.2.tar.gz" while repo name is "cgit" and tag name 141 * snapshot is "cgit-0.7.2.tar.gz" while repo name is "cgit" and tag name
142 * is "v0.7.2". First, the reponame is stripped off, leaving "-0.7.2.tar.gz". 142 * is "v0.7.2". First, the reponame is stripped off, leaving "-0.7.2.tar.gz".
143 * Next, any '-' and '_' characters are stripped, leaving "0.7.2.tar.gz". 143 * Next, any '-' and '_' characters are stripped, leaving "0.7.2.tar.gz".
144 * Finally, the requested format suffix is removed and we end up with "0.7.2". 144 * Finally, the requested format suffix is removed and we end up with "0.7.2".
145 * Then we test each tag against this dwimmed filename, and for each tag 145 * Then we test each tag against this dwimmed filename, and for each tag
146 * we even try to remove any leading characters which are non-digits. I.e. 146 * we even try to remove any leading characters which are non-digits. I.e.
147 * we first compare with "v0.7.2", then with "0.7.2" and we've got a match. 147 * we first compare with "v0.7.2", then with "0.7.2" and we've got a match.
148 */ 148 */
149static const char *get_ref_from_filename(const char *url, const char *filename, 149static const char *get_ref_from_filename(const char *url, const char *filename,
150 const struct cgit_snapshot_format *fmt) 150 const struct cgit_snapshot_format *fmt)
151{ 151{
152 const char *reponame = cgit_repobasename(url); 152 const char *reponame = cgit_repobasename(url);
153 fprintf(stderr, "reponame=%s, filename=%s\n", reponame, filename); 153 fprintf(stderr, "reponame=%s, filename=%s\n", reponame, filename);
154 if (prefixcmp(filename, reponame)) 154 if (prefixcmp(filename, reponame))
155 return NULL; 155 return NULL;
156 filename += strlen(reponame); 156 filename += strlen(reponame);
157 while (filename && (*filename == '-' || *filename == '_')) 157 while (filename && (*filename == '-' || *filename == '_'))
158 filename++; 158 filename++;
159 dwim_filename = xstrdup(filename); 159 dwim_filename = xstrdup(filename);
160 dwim_filename[strlen(filename) - strlen(fmt->suffix)] = '\0'; 160 dwim_filename[strlen(filename) - strlen(fmt->suffix)] = '\0';
161 for_each_tag_ref(ref_cb, NULL); 161 for_each_tag_ref(ref_cb, NULL);
162 return dwim_refname; 162 return dwim_refname;
163} 163}
164 164
165void cgit_print_snapshot(const char *head, const char *hex, const char *prefix, 165void cgit_print_snapshot(const char *head, const char *hex,
166 const char *filename, int snapshots, int dwim) 166 const char *filename, int snapshots, int dwim)
167{ 167{
168 const struct cgit_snapshot_format* f; 168 const struct cgit_snapshot_format* f;
169 char *prefix = NULL;
169 170
170 f = get_format(filename); 171 f = get_format(filename);
171 if (!f) { 172 if (!f) {
172 ctx.page.mimetype = "text/html"; 173 ctx.page.mimetype = "text/html";
173 cgit_print_http_headers(&ctx); 174 cgit_print_http_headers(&ctx);
174 cgit_print_docstart(&ctx); 175 cgit_print_docstart(&ctx);
175 cgit_print_pageheader(&ctx); 176 cgit_print_pageheader(&ctx);
176 cgit_print_error(fmt("Unsupported snapshot format: %s", filename)); 177 cgit_print_error(fmt("Unsupported snapshot format: %s", filename));
177 cgit_print_docend(); 178 cgit_print_docend();
178 return; 179 return;
179 } 180 }
180 181
181 if (!hex && dwim) 182 if (!hex && dwim) {
182 hex = get_ref_from_filename(ctx.repo->url, filename, f); 183 hex = get_ref_from_filename(ctx.repo->url, filename, f);
184 if (hex != NULL) {
185 prefix = xstrdup(filename);
186 prefix[strlen(filename) - strlen(f->suffix)] = '\0';
187 }
188 }
183 189
184 if (!hex) 190 if (!hex)
185 hex = head; 191 hex = head;
186 192
193 if (!prefix)
194 prefix = xstrdup(cgit_repobasename(ctx.repo->url));
195
187 make_snapshot(f, hex, prefix, filename); 196 make_snapshot(f, hex, prefix, filename);
197 free(prefix);
188} 198}