Fossil SCM

Add the ci=LABEL parameter to the "dir" webpage in order to look at just files within a single check-in. Add a Download link on the artifact and hexdump viewers.

drh 2009-01-28 21:41 UTC trunk
Commit 923d644b89211895883a8442883afed8ee02a6e9
2 files changed +57 -9 +28 -5
+57 -9
--- src/browse.c
+++ src/browse.c
@@ -101,63 +101,108 @@
101101
** WEBPAGE: dir
102102
**
103103
** Query parameters:
104104
**
105105
** name=PATH Directory to display. Required.
106
+** ci=LABEL Show only files in this check-in. Optional.
106107
*/
107108
void page_dir(void){
108109
const char *zD = P("name");
109110
int mxLen;
110111
int nCol, nRow;
111112
int cnt, i;
112113
char *zPrefix;
113114
Stmt q;
115
+ const char *zCI = P("ci");
116
+ int rid = 0;
117
+ Blob content;
118
+ Manifest m;
119
+ const char *zSubdirLink;
114120
115121
login_check_credentials();
116122
if( !g.okHistory ){ login_needed(); return; }
117123
style_header("File List");
118124
sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
119125
pathelementFunc, 0, 0);
120126
121127
/* If the name= parameter is an empty string, make it a NULL pointer */
122128
if( zD && strlen(zD)==0 ){ zD = 0; }
129
+
130
+ /* If a specific check-in is requested, fetch and parse it. */
131
+ if( zCI && (rid = name_to_rid(zCI))!=0 && content_get(rid, &content) ){
132
+ if( !manifest_parse(&m, &content) || m.type!=CFTYPE_MANIFEST ){
133
+ zCI = 0;
134
+ }
135
+ }
123136
124137
/* Compute the title of the page */
125138
if( zD ){
126139
Blob title;
127140
128141
blob_zero(&title);
129142
blob_appendf(&title, "Files in directory ");
130143
hyperlinked_path(zD, &title);
131
- @ <h2>%s(blob_str(&title))</h2>
144
+ @ <h2>%s(blob_str(&title))
132145
blob_reset(&title);
133146
zPrefix = mprintf("%h/", zD);
134147
}else{
135
- @ <h2>Files in the top-level directory</h2>
148
+ @ <h2>Files in the top-level directory
136149
zPrefix = "";
137150
}
151
+ if( zCI ){
152
+ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
153
+ char zShort[20];
154
+ memcpy(zShort, zUuid, 10);
155
+ zShort[10] = 0;
156
+ @ of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>]</h2>
157
+ zSubdirLink = mprintf("%s/dir?ci=%s&name=%T", g.zBaseURL, zUuid, zPrefix);
158
+ if( zD ){
159
+ style_submenu_element("Top", "Top", "%s/dir?ci=%s", g.zBaseURL, zUuid);
160
+ }
161
+ }else{
162
+ @ </h2>
163
+ zSubdirLink = mprintf("%s/dir?name=%T", g.zBaseURL, zPrefix);
164
+ }
138165
139166
/* Compute the temporary table "localfiles" containing the names
140167
** of all files and subdirectories in the zD[] directory.
141168
**
142169
** Subdirectory names begin with "/". This causes them to sort
143170
** first and it also gives us an easy way to distinguish files
144171
** from directories in the loop that follows.
145172
*/
173
+ db_multi_exec(
174
+ "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL, u);"
175
+ "CREATE TEMP TABLE allfiles(x UNIQUE NOT NULL, u);"
176
+ );
177
+ if( zCI ){
178
+ Stmt ins;
179
+ int i;
180
+ db_prepare(&ins, "INSERT INTO allfiles VALUES(:x, :u)");
181
+ for(i=0; i<m.nFile; i++){
182
+ db_bind_text(&ins, ":x", m.aFile[i].zName);
183
+ db_bind_text(&ins, ":u", m.aFile[i].zUuid);
184
+ db_step(&ins);
185
+ db_reset(&ins);
186
+ }
187
+ db_finalize(&ins);
188
+ }else{
189
+ db_multi_exec(
190
+ "INSERT INTO allfiles SELECT name, NULL FROM filename"
191
+ );
192
+ }
146193
if( zD ){
147194
db_multi_exec(
148
- "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL);"
149195
"INSERT OR IGNORE INTO localfiles "
150
- " SELECT pathelement(name,%d) FROM filename"
151
- " WHERE +name GLOB '%q/*'",
196
+ " SELECT pathelement(x,%d), u FROM allfiles"
197
+ " WHERE x GLOB '%q/*'",
152198
strlen(zD)+1, zD
153199
);
154200
}else{
155201
db_multi_exec(
156
- "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL);"
157202
"INSERT OR IGNORE INTO localfiles "
158
- " SELECT pathelement(name,0) FROM filename"
203
+ " SELECT pathelement(x,0), u FROM allfiles"
159204
);
160205
}
161206
162207
/* Generate a multi-column table listing the contents of zD[]
163208
** directory.
@@ -164,11 +209,11 @@
164209
*/
165210
mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles");
166211
cnt = db_int(0, "SELECT count(*) FROM localfiles");
167212
nCol = 4;
168213
nRow = (cnt+nCol-1)/nCol;
169
- db_prepare(&q, "SELECT x FROM localfiles ORDER BY x");
214
+ db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x");
170215
@ <table border="0" width="100%%"><tr><td valign="top" width="25%%">
171216
i = 0;
172217
while( db_step(&q)==SQLITE_ROW ){
173218
const char *zFName;
174219
if( i==nRow ){
@@ -177,16 +222,19 @@
177222
}
178223
i++;
179224
zFName = db_column_text(&q, 0);
180225
if( zFName[0]=='/' ){
181226
zFName++;
182
- @ <li><a href="%s(g.zBaseURL)/dir?name=%T(zPrefix)%T(zFName)">
227
+ @ <li><a href="%s(zSubdirLink)%T(zFName)">
183228
@ %h(zFName)/</a></li>
229
+ }else if( zCI ){
230
+ const char *zUuid = db_column_text(&q, 1);
231
+ @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFName)</a>
184232
}else{
185233
@ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFName)">
186234
@ %h(zFName)</a></li>
187235
}
188236
}
189237
db_finalize(&q);
190238
@ </td></tr></table>
191239
style_footer();
192240
}
193241
--- src/browse.c
+++ src/browse.c
@@ -101,63 +101,108 @@
101 ** WEBPAGE: dir
102 **
103 ** Query parameters:
104 **
105 ** name=PATH Directory to display. Required.
 
106 */
107 void page_dir(void){
108 const char *zD = P("name");
109 int mxLen;
110 int nCol, nRow;
111 int cnt, i;
112 char *zPrefix;
113 Stmt q;
 
 
 
 
 
114
115 login_check_credentials();
116 if( !g.okHistory ){ login_needed(); return; }
117 style_header("File List");
118 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
119 pathelementFunc, 0, 0);
120
121 /* If the name= parameter is an empty string, make it a NULL pointer */
122 if( zD && strlen(zD)==0 ){ zD = 0; }
 
 
 
 
 
 
 
123
124 /* Compute the title of the page */
125 if( zD ){
126 Blob title;
127
128 blob_zero(&title);
129 blob_appendf(&title, "Files in directory ");
130 hyperlinked_path(zD, &title);
131 @ <h2>%s(blob_str(&title))</h2>
132 blob_reset(&title);
133 zPrefix = mprintf("%h/", zD);
134 }else{
135 @ <h2>Files in the top-level directory</h2>
136 zPrefix = "";
137 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
139 /* Compute the temporary table "localfiles" containing the names
140 ** of all files and subdirectories in the zD[] directory.
141 **
142 ** Subdirectory names begin with "/". This causes them to sort
143 ** first and it also gives us an easy way to distinguish files
144 ** from directories in the loop that follows.
145 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146 if( zD ){
147 db_multi_exec(
148 "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL);"
149 "INSERT OR IGNORE INTO localfiles "
150 " SELECT pathelement(name,%d) FROM filename"
151 " WHERE +name GLOB '%q/*'",
152 strlen(zD)+1, zD
153 );
154 }else{
155 db_multi_exec(
156 "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL);"
157 "INSERT OR IGNORE INTO localfiles "
158 " SELECT pathelement(name,0) FROM filename"
159 );
160 }
161
162 /* Generate a multi-column table listing the contents of zD[]
163 ** directory.
@@ -164,11 +209,11 @@
164 */
165 mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles");
166 cnt = db_int(0, "SELECT count(*) FROM localfiles");
167 nCol = 4;
168 nRow = (cnt+nCol-1)/nCol;
169 db_prepare(&q, "SELECT x FROM localfiles ORDER BY x");
170 @ <table border="0" width="100%%"><tr><td valign="top" width="25%%">
171 i = 0;
172 while( db_step(&q)==SQLITE_ROW ){
173 const char *zFName;
174 if( i==nRow ){
@@ -177,16 +222,19 @@
177 }
178 i++;
179 zFName = db_column_text(&q, 0);
180 if( zFName[0]=='/' ){
181 zFName++;
182 @ <li><a href="%s(g.zBaseURL)/dir?name=%T(zPrefix)%T(zFName)">
183 @ %h(zFName)/</a></li>
 
 
 
184 }else{
185 @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFName)">
186 @ %h(zFName)</a></li>
187 }
188 }
189 db_finalize(&q);
190 @ </td></tr></table>
191 style_footer();
192 }
193
--- src/browse.c
+++ src/browse.c
@@ -101,63 +101,108 @@
101 ** WEBPAGE: dir
102 **
103 ** Query parameters:
104 **
105 ** name=PATH Directory to display. Required.
106 ** ci=LABEL Show only files in this check-in. Optional.
107 */
108 void page_dir(void){
109 const char *zD = P("name");
110 int mxLen;
111 int nCol, nRow;
112 int cnt, i;
113 char *zPrefix;
114 Stmt q;
115 const char *zCI = P("ci");
116 int rid = 0;
117 Blob content;
118 Manifest m;
119 const char *zSubdirLink;
120
121 login_check_credentials();
122 if( !g.okHistory ){ login_needed(); return; }
123 style_header("File List");
124 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
125 pathelementFunc, 0, 0);
126
127 /* If the name= parameter is an empty string, make it a NULL pointer */
128 if( zD && strlen(zD)==0 ){ zD = 0; }
129
130 /* If a specific check-in is requested, fetch and parse it. */
131 if( zCI && (rid = name_to_rid(zCI))!=0 && content_get(rid, &content) ){
132 if( !manifest_parse(&m, &content) || m.type!=CFTYPE_MANIFEST ){
133 zCI = 0;
134 }
135 }
136
137 /* Compute the title of the page */
138 if( zD ){
139 Blob title;
140
141 blob_zero(&title);
142 blob_appendf(&title, "Files in directory ");
143 hyperlinked_path(zD, &title);
144 @ <h2>%s(blob_str(&title))
145 blob_reset(&title);
146 zPrefix = mprintf("%h/", zD);
147 }else{
148 @ <h2>Files in the top-level directory
149 zPrefix = "";
150 }
151 if( zCI ){
152 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
153 char zShort[20];
154 memcpy(zShort, zUuid, 10);
155 zShort[10] = 0;
156 @ of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>]</h2>
157 zSubdirLink = mprintf("%s/dir?ci=%s&name=%T", g.zBaseURL, zUuid, zPrefix);
158 if( zD ){
159 style_submenu_element("Top", "Top", "%s/dir?ci=%s", g.zBaseURL, zUuid);
160 }
161 }else{
162 @ </h2>
163 zSubdirLink = mprintf("%s/dir?name=%T", g.zBaseURL, zPrefix);
164 }
165
166 /* Compute the temporary table "localfiles" containing the names
167 ** of all files and subdirectories in the zD[] directory.
168 **
169 ** Subdirectory names begin with "/". This causes them to sort
170 ** first and it also gives us an easy way to distinguish files
171 ** from directories in the loop that follows.
172 */
173 db_multi_exec(
174 "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL, u);"
175 "CREATE TEMP TABLE allfiles(x UNIQUE NOT NULL, u);"
176 );
177 if( zCI ){
178 Stmt ins;
179 int i;
180 db_prepare(&ins, "INSERT INTO allfiles VALUES(:x, :u)");
181 for(i=0; i<m.nFile; i++){
182 db_bind_text(&ins, ":x", m.aFile[i].zName);
183 db_bind_text(&ins, ":u", m.aFile[i].zUuid);
184 db_step(&ins);
185 db_reset(&ins);
186 }
187 db_finalize(&ins);
188 }else{
189 db_multi_exec(
190 "INSERT INTO allfiles SELECT name, NULL FROM filename"
191 );
192 }
193 if( zD ){
194 db_multi_exec(
 
195 "INSERT OR IGNORE INTO localfiles "
196 " SELECT pathelement(x,%d), u FROM allfiles"
197 " WHERE x GLOB '%q/*'",
198 strlen(zD)+1, zD
199 );
200 }else{
201 db_multi_exec(
 
202 "INSERT OR IGNORE INTO localfiles "
203 " SELECT pathelement(x,0), u FROM allfiles"
204 );
205 }
206
207 /* Generate a multi-column table listing the contents of zD[]
208 ** directory.
@@ -164,11 +209,11 @@
209 */
210 mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles");
211 cnt = db_int(0, "SELECT count(*) FROM localfiles");
212 nCol = 4;
213 nRow = (cnt+nCol-1)/nCol;
214 db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x");
215 @ <table border="0" width="100%%"><tr><td valign="top" width="25%%">
216 i = 0;
217 while( db_step(&q)==SQLITE_ROW ){
218 const char *zFName;
219 if( i==nRow ){
@@ -177,16 +222,19 @@
222 }
223 i++;
224 zFName = db_column_text(&q, 0);
225 if( zFName[0]=='/' ){
226 zFName++;
227 @ <li><a href="%s(zSubdirLink)%T(zFName)">
228 @ %h(zFName)/</a></li>
229 }else if( zCI ){
230 const char *zUuid = db_column_text(&q, 1);
231 @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFName)</a>
232 }else{
233 @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFName)">
234 @ %h(zFName)</a></li>
235 }
236 }
237 db_finalize(&q);
238 @ </td></tr></table>
239 style_footer();
240 }
241
+28 -5
--- src/info.c
+++ src/info.c
@@ -324,10 +324,11 @@
324324
}
325325
}
326326
327327
328328
/*
329
+** WEBPAGE: vinfo
329330
** WEBPAGE: ci
330331
** URL: /ci?name=RID|ARTIFACTID
331332
**
332333
** Return information about a baseline
333334
*/
@@ -425,10 +426,11 @@
425426
db_finalize(&q);
426427
@ </td></tr>
427428
@ <tr><th>Commands:</th>
428429
@ <td>
429430
@ <a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a>
431
+ @ | <a href="%s(g.zBaseURL)/dir?ci=%s(zShortUuid)">files</a>
430432
@ | <a href="%s(g.zBaseURL)/zip/%s(zProjName)-%s(zShortUuid).zip?uuid=%s(zUuid)">
431433
@ ZIP archive</a>
432434
@ | <a href="%s(g.zBaseURL)/artifact/%d(rid)">manifest</a>
433435
if( g.okWrite ){
434436
@ | <a href="%s(g.zBaseURL)/ci_edit?r=%d(rid)">edit</a>
@@ -736,11 +738,12 @@
736738
** * date of check-in
737739
** * Comment & user
738740
*/
739741
static void object_description(
740742
int rid, /* The artifact ID */
741
- int linkToView /* Add viewer link if true */
743
+ int linkToView, /* Add viewer link if true */
744
+ Blob *pDownloadName /* Fill with an appropriate download name */
742745
){
743746
Stmt q;
744747
int cnt = 0;
745748
int nWiki = 0;
746749
db_prepare(&q,
@@ -771,10 +774,13 @@
771774
@ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a>
772775
@ uuid %s(zFuuid) part of check-in
773776
hyperlink_to_uuid(zVers);
774777
@ %w(zCom) by %h(zUser) on %s(zDate).
775778
cnt++;
779
+ if( pDownloadName && blob_size(pDownloadName)==0 ){
780
+ blob_append(pDownloadName, zName, -1);
781
+ }
776782
}
777783
db_finalize(&q);
778784
db_prepare(&q,
779785
"SELECT substr(tagname, 6, 10000), datetime(event.mtime),"
780786
" coalesce(event.euser, event.user), uuid"
@@ -798,10 +804,13 @@
798804
}
799805
@ [<a href="%s(g.zBaseURL)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
800806
@ uuid %s(zUuid) by %h(zUser) on %s(zDate).
801807
nWiki++;
802808
cnt++;
809
+ if( pDownloadName && blob_size(pDownloadName)==0 ){
810
+ blob_append(pDownloadName, zPagename, -1);
811
+ }
803812
}
804813
db_finalize(&q);
805814
if( nWiki==0 ){
806815
db_prepare(&q,
807816
"SELECT datetime(mtime), user, comment, uuid, type"
@@ -828,17 +837,23 @@
828837
}else{
829838
@ Control file referencing
830839
}
831840
hyperlink_to_uuid(zUuid);
832841
@ %w(zCom) by %h(zUser) on %s(zDate).
842
+ if( pDownloadName && blob_size(pDownloadName)==0 ){
843
+ blob_append(pDownloadName, zUuid, -1);
844
+ }
833845
cnt++;
834846
}
835847
db_finalize(&q);
836848
}
837849
if( cnt==0 ){
838850
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
839851
@ Control file %s(zUuid).
852
+ if( pDownloadName && blob_size(pDownloadName)==0 ){
853
+ blob_append(pDownloadName, zUuid, -1);
854
+ }
840855
}else if( linkToView ){
841856
@ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a>
842857
}
843858
}
844859
@@ -856,15 +871,15 @@
856871
login_check_credentials();
857872
if( !g.okRead ){ login_needed(); return; }
858873
style_header("Diff");
859874
@ <h2>Differences From:</h2>
860875
@ <blockquote>
861
- object_description(v1, 1);
876
+ object_description(v1, 1, 0);
862877
@ </blockquote>
863878
@ <h2>To:</h2>
864879
@ <blockquote>
865
- object_description(v2, 1);
880
+ object_description(v2, 1, 0);
866881
@ </blockquote>
867882
@ <hr>
868883
@ <blockquote><pre>
869884
content_get(v1, &c1);
870885
content_get(v2, &c2);
@@ -959,10 +974,11 @@
959974
** as preformatted text.
960975
*/
961976
void hexdump_page(void){
962977
int rid;
963978
Blob content;
979
+ Blob downloadName;
964980
965981
rid = name_to_rid(PD("name","0"));
966982
login_check_credentials();
967983
if( !g.okRead ){ login_needed(); return; }
968984
if( rid==0 ){ cgi_redirect("/home"); }
@@ -977,11 +993,14 @@
977993
}
978994
}
979995
style_header("Hex Artifact Content");
980996
@ <h2>Hexadecimal Content Of:</h2>
981997
@ <blockquote>
982
- object_description(rid, 0);
998
+ blob_zero(&downloadName);
999
+ object_description(rid, 0, &downloadName);
1000
+ style_submenu_element("Download", "Download",
1001
+ "%s/raw/%T?name=%d", g.zBaseURL, blob_str(&downloadName), rid);
9831002
@ </blockquote>
9841003
@ <hr>
9851004
content_get(rid, &content);
9861005
@ <blockquote><pre>
9871006
hexdump(&content);
@@ -998,10 +1017,11 @@
9981017
*/
9991018
void artifact_page(void){
10001019
int rid;
10011020
Blob content;
10021021
const char *zMime;
1022
+ Blob downloadName;
10031023
10041024
rid = name_to_rid(PD("name","0"));
10051025
login_check_credentials();
10061026
if( !g.okRead ){ login_needed(); return; }
10071027
if( rid==0 ){ cgi_redirect("/home"); }
@@ -1016,11 +1036,14 @@
10161036
}
10171037
}
10181038
style_header("Artifact Content");
10191039
@ <h2>Content Of:</h2>
10201040
@ <blockquote>
1021
- object_description(rid, 0);
1041
+ blob_zero(&downloadName);
1042
+ object_description(rid, 0, &downloadName);
1043
+ style_submenu_element("Download", "Download",
1044
+ "%s/raw/%T?name=%d", g.zTop, blob_str(&downloadName), rid);
10221045
@ </blockquote>
10231046
@ <hr>
10241047
@ <blockquote>
10251048
content_get(rid, &content);
10261049
zMime = mimetype_from_content(&content);
10271050
--- src/info.c
+++ src/info.c
@@ -324,10 +324,11 @@
324 }
325 }
326
327
328 /*
 
329 ** WEBPAGE: ci
330 ** URL: /ci?name=RID|ARTIFACTID
331 **
332 ** Return information about a baseline
333 */
@@ -425,10 +426,11 @@
425 db_finalize(&q);
426 @ </td></tr>
427 @ <tr><th>Commands:</th>
428 @ <td>
429 @ <a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a>
 
430 @ | <a href="%s(g.zBaseURL)/zip/%s(zProjName)-%s(zShortUuid).zip?uuid=%s(zUuid)">
431 @ ZIP archive</a>
432 @ | <a href="%s(g.zBaseURL)/artifact/%d(rid)">manifest</a>
433 if( g.okWrite ){
434 @ | <a href="%s(g.zBaseURL)/ci_edit?r=%d(rid)">edit</a>
@@ -736,11 +738,12 @@
736 ** * date of check-in
737 ** * Comment & user
738 */
739 static void object_description(
740 int rid, /* The artifact ID */
741 int linkToView /* Add viewer link if true */
 
742 ){
743 Stmt q;
744 int cnt = 0;
745 int nWiki = 0;
746 db_prepare(&q,
@@ -771,10 +774,13 @@
771 @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a>
772 @ uuid %s(zFuuid) part of check-in
773 hyperlink_to_uuid(zVers);
774 @ %w(zCom) by %h(zUser) on %s(zDate).
775 cnt++;
 
 
 
776 }
777 db_finalize(&q);
778 db_prepare(&q,
779 "SELECT substr(tagname, 6, 10000), datetime(event.mtime),"
780 " coalesce(event.euser, event.user), uuid"
@@ -798,10 +804,13 @@
798 }
799 @ [<a href="%s(g.zBaseURL)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
800 @ uuid %s(zUuid) by %h(zUser) on %s(zDate).
801 nWiki++;
802 cnt++;
 
 
 
803 }
804 db_finalize(&q);
805 if( nWiki==0 ){
806 db_prepare(&q,
807 "SELECT datetime(mtime), user, comment, uuid, type"
@@ -828,17 +837,23 @@
828 }else{
829 @ Control file referencing
830 }
831 hyperlink_to_uuid(zUuid);
832 @ %w(zCom) by %h(zUser) on %s(zDate).
 
 
 
833 cnt++;
834 }
835 db_finalize(&q);
836 }
837 if( cnt==0 ){
838 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
839 @ Control file %s(zUuid).
 
 
 
840 }else if( linkToView ){
841 @ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a>
842 }
843 }
844
@@ -856,15 +871,15 @@
856 login_check_credentials();
857 if( !g.okRead ){ login_needed(); return; }
858 style_header("Diff");
859 @ <h2>Differences From:</h2>
860 @ <blockquote>
861 object_description(v1, 1);
862 @ </blockquote>
863 @ <h2>To:</h2>
864 @ <blockquote>
865 object_description(v2, 1);
866 @ </blockquote>
867 @ <hr>
868 @ <blockquote><pre>
869 content_get(v1, &c1);
870 content_get(v2, &c2);
@@ -959,10 +974,11 @@
959 ** as preformatted text.
960 */
961 void hexdump_page(void){
962 int rid;
963 Blob content;
 
964
965 rid = name_to_rid(PD("name","0"));
966 login_check_credentials();
967 if( !g.okRead ){ login_needed(); return; }
968 if( rid==0 ){ cgi_redirect("/home"); }
@@ -977,11 +993,14 @@
977 }
978 }
979 style_header("Hex Artifact Content");
980 @ <h2>Hexadecimal Content Of:</h2>
981 @ <blockquote>
982 object_description(rid, 0);
 
 
 
983 @ </blockquote>
984 @ <hr>
985 content_get(rid, &content);
986 @ <blockquote><pre>
987 hexdump(&content);
@@ -998,10 +1017,11 @@
998 */
999 void artifact_page(void){
1000 int rid;
1001 Blob content;
1002 const char *zMime;
 
1003
1004 rid = name_to_rid(PD("name","0"));
1005 login_check_credentials();
1006 if( !g.okRead ){ login_needed(); return; }
1007 if( rid==0 ){ cgi_redirect("/home"); }
@@ -1016,11 +1036,14 @@
1016 }
1017 }
1018 style_header("Artifact Content");
1019 @ <h2>Content Of:</h2>
1020 @ <blockquote>
1021 object_description(rid, 0);
 
 
 
1022 @ </blockquote>
1023 @ <hr>
1024 @ <blockquote>
1025 content_get(rid, &content);
1026 zMime = mimetype_from_content(&content);
1027
--- src/info.c
+++ src/info.c
@@ -324,10 +324,11 @@
324 }
325 }
326
327
328 /*
329 ** WEBPAGE: vinfo
330 ** WEBPAGE: ci
331 ** URL: /ci?name=RID|ARTIFACTID
332 **
333 ** Return information about a baseline
334 */
@@ -425,10 +426,11 @@
426 db_finalize(&q);
427 @ </td></tr>
428 @ <tr><th>Commands:</th>
429 @ <td>
430 @ <a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a>
431 @ | <a href="%s(g.zBaseURL)/dir?ci=%s(zShortUuid)">files</a>
432 @ | <a href="%s(g.zBaseURL)/zip/%s(zProjName)-%s(zShortUuid).zip?uuid=%s(zUuid)">
433 @ ZIP archive</a>
434 @ | <a href="%s(g.zBaseURL)/artifact/%d(rid)">manifest</a>
435 if( g.okWrite ){
436 @ | <a href="%s(g.zBaseURL)/ci_edit?r=%d(rid)">edit</a>
@@ -736,11 +738,12 @@
738 ** * date of check-in
739 ** * Comment & user
740 */
741 static void object_description(
742 int rid, /* The artifact ID */
743 int linkToView, /* Add viewer link if true */
744 Blob *pDownloadName /* Fill with an appropriate download name */
745 ){
746 Stmt q;
747 int cnt = 0;
748 int nWiki = 0;
749 db_prepare(&q,
@@ -771,10 +774,13 @@
774 @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a>
775 @ uuid %s(zFuuid) part of check-in
776 hyperlink_to_uuid(zVers);
777 @ %w(zCom) by %h(zUser) on %s(zDate).
778 cnt++;
779 if( pDownloadName && blob_size(pDownloadName)==0 ){
780 blob_append(pDownloadName, zName, -1);
781 }
782 }
783 db_finalize(&q);
784 db_prepare(&q,
785 "SELECT substr(tagname, 6, 10000), datetime(event.mtime),"
786 " coalesce(event.euser, event.user), uuid"
@@ -798,10 +804,13 @@
804 }
805 @ [<a href="%s(g.zBaseURL)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
806 @ uuid %s(zUuid) by %h(zUser) on %s(zDate).
807 nWiki++;
808 cnt++;
809 if( pDownloadName && blob_size(pDownloadName)==0 ){
810 blob_append(pDownloadName, zPagename, -1);
811 }
812 }
813 db_finalize(&q);
814 if( nWiki==0 ){
815 db_prepare(&q,
816 "SELECT datetime(mtime), user, comment, uuid, type"
@@ -828,17 +837,23 @@
837 }else{
838 @ Control file referencing
839 }
840 hyperlink_to_uuid(zUuid);
841 @ %w(zCom) by %h(zUser) on %s(zDate).
842 if( pDownloadName && blob_size(pDownloadName)==0 ){
843 blob_append(pDownloadName, zUuid, -1);
844 }
845 cnt++;
846 }
847 db_finalize(&q);
848 }
849 if( cnt==0 ){
850 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
851 @ Control file %s(zUuid).
852 if( pDownloadName && blob_size(pDownloadName)==0 ){
853 blob_append(pDownloadName, zUuid, -1);
854 }
855 }else if( linkToView ){
856 @ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a>
857 }
858 }
859
@@ -856,15 +871,15 @@
871 login_check_credentials();
872 if( !g.okRead ){ login_needed(); return; }
873 style_header("Diff");
874 @ <h2>Differences From:</h2>
875 @ <blockquote>
876 object_description(v1, 1, 0);
877 @ </blockquote>
878 @ <h2>To:</h2>
879 @ <blockquote>
880 object_description(v2, 1, 0);
881 @ </blockquote>
882 @ <hr>
883 @ <blockquote><pre>
884 content_get(v1, &c1);
885 content_get(v2, &c2);
@@ -959,10 +974,11 @@
974 ** as preformatted text.
975 */
976 void hexdump_page(void){
977 int rid;
978 Blob content;
979 Blob downloadName;
980
981 rid = name_to_rid(PD("name","0"));
982 login_check_credentials();
983 if( !g.okRead ){ login_needed(); return; }
984 if( rid==0 ){ cgi_redirect("/home"); }
@@ -977,11 +993,14 @@
993 }
994 }
995 style_header("Hex Artifact Content");
996 @ <h2>Hexadecimal Content Of:</h2>
997 @ <blockquote>
998 blob_zero(&downloadName);
999 object_description(rid, 0, &downloadName);
1000 style_submenu_element("Download", "Download",
1001 "%s/raw/%T?name=%d", g.zBaseURL, blob_str(&downloadName), rid);
1002 @ </blockquote>
1003 @ <hr>
1004 content_get(rid, &content);
1005 @ <blockquote><pre>
1006 hexdump(&content);
@@ -998,10 +1017,11 @@
1017 */
1018 void artifact_page(void){
1019 int rid;
1020 Blob content;
1021 const char *zMime;
1022 Blob downloadName;
1023
1024 rid = name_to_rid(PD("name","0"));
1025 login_check_credentials();
1026 if( !g.okRead ){ login_needed(); return; }
1027 if( rid==0 ){ cgi_redirect("/home"); }
@@ -1016,11 +1036,14 @@
1036 }
1037 }
1038 style_header("Artifact Content");
1039 @ <h2>Content Of:</h2>
1040 @ <blockquote>
1041 blob_zero(&downloadName);
1042 object_description(rid, 0, &downloadName);
1043 style_submenu_element("Download", "Download",
1044 "%s/raw/%T?name=%d", g.zTop, blob_str(&downloadName), rid);
1045 @ </blockquote>
1046 @ <hr>
1047 @ <blockquote>
1048 content_get(rid, &content);
1049 zMime = mimetype_from_content(&content);
1050

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button