Fossil SCM

When doing a repository list, use the first repository that has a non-zero value for the "repolist-skin" setting as the skin for the list. If the "repolist-skin" setting is 2 and if the repository list is coming from a directory scan, the omit that repository from the list. All repositories are always shown, regardless of the "repolist-skin" setting for a "fossil all ui" or "fossil all server" generated repository list.

drh 2019-07-29 18:17 trunk merge
Commit 8f5399bc7b2388a9050ae4cdf5d63d107607b77794d3a8bf8357a28de4743a88
3 files changed +7 +2 -2 +99 -38
+7
--- src/db.c
+++ src/db.c
@@ -3422,10 +3422,17 @@
34223422
** SETTING: repo-cksum boolean default=on
34233423
** Compute checksums over all files in each checkout as a double-check
34243424
** of correctness. Disable this on large repositories for a performance
34253425
** improvement.
34263426
*/
3427
+/*
3428
+** SETTING: repolist-skin width=2 default=0
3429
+** If non-zero then this repository desires to be used as the skin for
3430
+** repository lists. If 2, then use then omit this repository from the
3431
+** list for directory-scan lists. The repository is always displayed
3432
+** in lists for "fossil all ui" or "fossil all server".
3433
+*/
34273434
/*
34283435
** SETTING: self-register boolean default=off
34293436
** Allow users to register themselves through the HTTP UI.
34303437
** This is useful if you want to see other names than
34313438
** "Anonymous" in e.g. ticketing system. On the other hand
34323439
--- src/db.c
+++ src/db.c
@@ -3422,10 +3422,17 @@
3422 ** SETTING: repo-cksum boolean default=on
3423 ** Compute checksums over all files in each checkout as a double-check
3424 ** of correctness. Disable this on large repositories for a performance
3425 ** improvement.
3426 */
 
 
 
 
 
 
 
3427 /*
3428 ** SETTING: self-register boolean default=off
3429 ** Allow users to register themselves through the HTTP UI.
3430 ** This is useful if you want to see other names than
3431 ** "Anonymous" in e.g. ticketing system. On the other hand
3432
--- src/db.c
+++ src/db.c
@@ -3422,10 +3422,17 @@
3422 ** SETTING: repo-cksum boolean default=on
3423 ** Compute checksums over all files in each checkout as a double-check
3424 ** of correctness. Disable this on large repositories for a performance
3425 ** improvement.
3426 */
3427 /*
3428 ** SETTING: repolist-skin width=2 default=0
3429 ** If non-zero then this repository desires to be used as the skin for
3430 ** repository lists. If 2, then use then omit this repository from the
3431 ** list for directory-scan lists. The repository is always displayed
3432 ** in lists for "fossil all ui" or "fossil all server".
3433 */
3434 /*
3435 ** SETTING: self-register boolean default=off
3436 ** Allow users to register themselves through the HTTP UI.
3437 ** This is useful if you want to see other names than
3438 ** "Anonymous" in e.g. ticketing system. On the other hand
3439
+2 -2
--- src/main.c
+++ src/main.c
@@ -1194,11 +1194,11 @@
11941194
** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
11951195
** environment variables. However, if zAltBase is not NULL then it
11961196
** is the argument to the --baseurl option command-line option and
11971197
** g.zBaseURL and g.zTop is set from that instead.
11981198
*/
1199
-static void set_base_url(const char *zAltBase){
1199
+void set_base_url(const char *zAltBase){
12001200
int i;
12011201
const char *zHost;
12021202
const char *zMode;
12031203
const char *zCur;
12041204
@@ -2421,11 +2421,11 @@
24212421
g.fSshClient |= CGI_SSH_CLIENT;
24222422
ssh_request_loop(zIpAddr, 0);
24232423
}else{
24242424
cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
24252425
cgi_handle_http_request(0);
2426
- process_one_web_page(0, 0, 0);
2426
+ process_one_web_page(0, 0, 1);
24272427
}
24282428
}
24292429
24302430
#if !defined(_WIN32)
24312431
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
24322432
--- src/main.c
+++ src/main.c
@@ -1194,11 +1194,11 @@
1194 ** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
1195 ** environment variables. However, if zAltBase is not NULL then it
1196 ** is the argument to the --baseurl option command-line option and
1197 ** g.zBaseURL and g.zTop is set from that instead.
1198 */
1199 static void set_base_url(const char *zAltBase){
1200 int i;
1201 const char *zHost;
1202 const char *zMode;
1203 const char *zCur;
1204
@@ -2421,11 +2421,11 @@
2421 g.fSshClient |= CGI_SSH_CLIENT;
2422 ssh_request_loop(zIpAddr, 0);
2423 }else{
2424 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
2425 cgi_handle_http_request(0);
2426 process_one_web_page(0, 0, 0);
2427 }
2428 }
2429
2430 #if !defined(_WIN32)
2431 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
2432
--- src/main.c
+++ src/main.c
@@ -1194,11 +1194,11 @@
1194 ** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
1195 ** environment variables. However, if zAltBase is not NULL then it
1196 ** is the argument to the --baseurl option command-line option and
1197 ** g.zBaseURL and g.zTop is set from that instead.
1198 */
1199 void set_base_url(const char *zAltBase){
1200 int i;
1201 const char *zHost;
1202 const char *zMode;
1203 const char *zCur;
1204
@@ -2421,11 +2421,11 @@
2421 g.fSshClient |= CGI_SSH_CLIENT;
2422 ssh_request_loop(zIpAddr, 0);
2423 }else{
2424 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
2425 cgi_handle_http_request(0);
2426 process_one_web_page(0, 0, 1);
2427 }
2428 }
2429
2430 #if !defined(_WIN32)
2431 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
2432
+99 -38
--- src/repolist.c
+++ src/repolist.c
@@ -27,30 +27,44 @@
2727
** input. All other fields are outputs.
2828
*/
2929
struct RepoInfo {
3030
char *zRepoName; /* Name of the repository file */
3131
int isValid; /* True if zRepoName is a valid Fossil repository */
32
+ int isRepolistSkin; /* 1 or 2 if this repository wants to be the skin
33
+ ** for the repository list. 2 means do use this
34
+ ** repository but do not display it in the list. */
3235
char *zProjName; /* Project Name. Memory from fossil_malloc() */
3336
double rMTime; /* Last update. Julian day number */
3437
};
3538
#endif
3639
3740
/*
3841
** Discover information about the repository given by
39
-** pRepo->zRepoName.
42
+** pRepo->zRepoName. The discovered information is stored in other
43
+** fields of the RepoInfo object.
4044
*/
41
-void remote_repo_info(RepoInfo *pRepo){
45
+static void remote_repo_info(RepoInfo *pRepo){
4246
sqlite3 *db;
4347
sqlite3_stmt *pStmt;
4448
int rc;
4549
50
+ pRepo->isRepolistSkin = 0;
4651
pRepo->isValid = 0;
4752
pRepo->zProjName = 0;
4853
pRepo->rMTime = 0.0;
4954
5055
g.dbIgnoreErrors++;
5156
rc = sqlite3_open_v2(pRepo->zRepoName, &db, SQLITE_OPEN_READWRITE, 0);
57
+ if( rc ) goto finish_repo_list;
58
+ rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
59
+ " WHERE name='repolist-skin'",
60
+ -1, &pStmt, 0);
61
+ if( rc ) goto finish_repo_list;
62
+ if( sqlite3_step(pStmt)==SQLITE_ROW ){
63
+ pRepo->isRepolistSkin = sqlite3_column_int(pStmt,0);
64
+ }
65
+ sqlite3_finalize(pStmt);
5266
if( rc ) goto finish_repo_list;
5367
rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
5468
" WHERE name='project-name'",
5569
-1, &pStmt, 0);
5670
if( rc ) goto finish_repo_list;
@@ -85,15 +99,20 @@
8599
**
86100
** Or, if no repositories can be located beneath g.zRepositoryName,
87101
** return 0.
88102
*/
89103
int repo_list_page(void){
90
- Blob base;
91
- int n = 0;
92
- int allRepo;
104
+ Blob base; /* document root for all repositories */
105
+ int n = 0; /* Number of repositories found */
106
+ int allRepo; /* True if running "fossil ui all".
107
+ ** False if a directory scan of base for repos */
108
+ Blob html; /* Html for the body of the repository list */
109
+ char *zSkinRepo = 0; /* Name of the repository database used for skins */
110
+ char *zSkinUrl = 0; /* URL for the skin database */
93111
94112
assert( g.db==0 );
113
+ blob_init(&html, 0, 0);
95114
if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
96115
/* For the special case of the "repository directory" being "/",
97116
** show all of the repositories named in the ~/.fossil database.
98117
**
99118
** On unix systems, then entries are of the form "repo:/home/..."
@@ -118,28 +137,24 @@
118137
db_multi_exec("CREATE TABLE vfile(pathname);");
119138
vfile_scan(&base, blob_size(&base), 0, 0, 0);
120139
db_multi_exec("DELETE FROM sfile WHERE pathname NOT GLOB '*[^/].fossil'");
121140
allRepo = 0;
122141
}
123
- @ <html>
124
- @ <head>
125
- @ <base href="%s(g.zBaseURL)/" />
126
- @ <meta name="viewport" content="width=device-width, initial-scale=1.0">
127
- @ <title>Repository List</title>
128
- @ </head>
129
- @ <body>
130142
n = db_int(0, "SELECT count(*) FROM sfile");
131
- if( n>0 ){
143
+ if( n==0 ){
144
+ sqlite3_close(g.db);
145
+ return 0;
146
+ }else{
132147
Stmt q;
133148
double rNow;
134
- @ <h1 align="center">Fossil Repositories</h1>
135
- @ <table border="0" class="sortable" data-init-sort="1" \
136
- @ data-column-types="tntnk"><thead>
137
- @ <tr><th>Filename<th width="20">\
138
- @ <th>Project Name<th width="20">\
139
- @ <th>Last Modified</tr>
140
- @ </thead><tbody>
149
+ blob_append_sql(&html,
150
+ "<table border='0' class='sortable' data-init-sort='1'"
151
+ " data-column-types='txtxk'><thead>\n"
152
+ "<tr><th>Filename<th width='20'>"
153
+ "<th>Project Name<th width='20'>"
154
+ "<th>Last Modified</tr>\n"
155
+ "</thead><tbody>\n");
141156
db_prepare(&q, "SELECT pathname"
142157
" FROM sfile ORDER BY pathname COLLATE nocase;");
143158
rNow = db_double(0, "SELECT julianday('now')");
144159
while( db_step(&q)==SQLITE_ROW ){
145160
const char *zName = db_column_text(&q, 0);
@@ -162,51 +177,97 @@
162177
}else{
163178
zFull = mprintf("%s/%s", g.zRepositoryName, zName);
164179
}
165180
x.zRepoName = zFull;
166181
remote_repo_info(&x);
182
+ if( x.isRepolistSkin ){
183
+ if( zSkinRepo==0 ){
184
+ zSkinRepo = mprintf("%s", x.zRepoName);
185
+ zSkinUrl = mprintf("%s", zUrl);
186
+ }
187
+ }
167188
fossil_free(zFull);
168189
if( !x.isValid ){
169190
continue;
191
+ }
192
+ if( x.isRepolistSkin==2 && !allRepo ){
193
+ /* Repositories with repolist-skin==2 are omitted from directory
194
+ ** scan lists, but included in "fossil all ui" lists */
195
+ continue;
170196
}
171197
iAge = (rNow - x.rMTime)*86400;
172198
if( iAge<0 ) x.rMTime = rNow;
173199
zAge = human_readable_age(rNow - x.rMTime);
174
- @ <tr><td valign="top">\
200
+ blob_append_sql(&html, "<tr><td valign='top'>");
175201
if( sqlite3_strglob("*.fossil", zName)!=0 ){
176202
/* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands
177203
** do not work for repositories whose names do not end in ".fossil".
178204
** So do not hyperlink those cases. */
179
- @ %h(zName)
205
+ blob_append_sql(&html,"%h",zName);
180206
} else if( sqlite3_strglob("*/.*", zName)==0 ){
181
- /* Do not show hidden repos */
182
- @ %h(zName) (hidden)
207
+ /* Do not show hyperlinks for hidden repos */
208
+ blob_append_sql(&html, "%h (hidden)", zName);
183209
} else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){
184
- @ <a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a>
210
+ blob_append_sql(&html,
211
+ "<a href='/%T/home' target='_blank'>/%h</a>\n",
212
+ zUrl, zName);
185213
}else{
186
- @ <a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a>
214
+ blob_append_sql(&html,
215
+ "<a href='/%T/home' target='_blank'>%h</a>\n",
216
+ zUrl, zName);
187217
}
188218
if( x.zProjName ){
189
- @ <td></td><td>%h(x.zProjName)</td>
219
+ blob_append_sql(&html, "<td></td><td>%h</td>\n", x.zProjName);
190220
fossil_free(x.zProjName);
191221
}else{
192
- @ <td></td><td></td>
222
+ blob_append_sql(&html, "<td></td><td></td>\n");
193223
}
194
- @ <td></td><td data-sortkey='%08x(iAge)'>%h(zAge)</tr>
224
+ blob_append_sql(&html,
225
+ "<td></td><td data-sortkey='%08x'>%h</tr>\n",
226
+ iAge, zAge);
195227
fossil_free(zAge);
196228
sqlite3_free(zUrl);
197229
}
198
- @ </tbody></table>
230
+ db_finalize(&q);
231
+ blob_append_sql(&html,"</tbody></table>\n");
232
+ }
233
+ if( zSkinRepo ){
234
+ char *zNewBase = mprintf("%s/%s", g.zBaseURL, zSkinUrl);
235
+ g.zBaseURL = 0;
236
+ set_base_url(zNewBase);
237
+ db_open_repository(zSkinRepo);
238
+ fossil_free(zSkinRepo);
239
+ fossil_free(zSkinUrl);
240
+ }
241
+ if( g.repositoryOpen ){
242
+ /* This case runs if remote_repository_info() found a repository
243
+ ** that has the "repolist_skin" property set to non-zero and left
244
+ ** that repository open in g.db. Use the skin of that repository
245
+ ** for display. */
246
+ login_check_credentials();
247
+ style_header("Repository List");
248
+ @ %s(blob_str(&html))
249
+ style_table_sorter();
250
+ style_footer();
199251
}else{
200
- @ <h1>No Repositories Found</h1>
201
- }
202
- @ <script>%s(builtin_text("sorttable.js"))</script>
203
- @ </body>
204
- @ </html>
205
- cgi_reply();
206
- sqlite3_close(g.db);
207
- g.db = 0;
252
+ /* If no repositories were found that had the "repolist_skin"
253
+ ** property set, then use a default skin */
254
+ @ <html>
255
+ @ <head>
256
+ @ <base href="%s(g.zBaseURL)/" />
257
+ @ <meta name="viewport" content="width=device-width, initial-scale=1.0">
258
+ @ <title>Repository List</title>
259
+ @ </head>
260
+ @ <body>
261
+ @ <h1 align="center">Fossil Repositories</h1>
262
+ @ %s(blob_str(&html))
263
+ @ <script>%s(builtin_text("sorttable.js"))</script>
264
+ @ </body>
265
+ @ </html>
266
+ }
267
+ blob_reset(&html);
268
+ cgi_reply();
208269
return n;
209270
}
210271
211272
/*
212273
** COMMAND: test-list-page
213274
--- src/repolist.c
+++ src/repolist.c
@@ -27,30 +27,44 @@
27 ** input. All other fields are outputs.
28 */
29 struct RepoInfo {
30 char *zRepoName; /* Name of the repository file */
31 int isValid; /* True if zRepoName is a valid Fossil repository */
 
 
 
32 char *zProjName; /* Project Name. Memory from fossil_malloc() */
33 double rMTime; /* Last update. Julian day number */
34 };
35 #endif
36
37 /*
38 ** Discover information about the repository given by
39 ** pRepo->zRepoName.
 
40 */
41 void remote_repo_info(RepoInfo *pRepo){
42 sqlite3 *db;
43 sqlite3_stmt *pStmt;
44 int rc;
45
 
46 pRepo->isValid = 0;
47 pRepo->zProjName = 0;
48 pRepo->rMTime = 0.0;
49
50 g.dbIgnoreErrors++;
51 rc = sqlite3_open_v2(pRepo->zRepoName, &db, SQLITE_OPEN_READWRITE, 0);
 
 
 
 
 
 
 
 
 
52 if( rc ) goto finish_repo_list;
53 rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
54 " WHERE name='project-name'",
55 -1, &pStmt, 0);
56 if( rc ) goto finish_repo_list;
@@ -85,15 +99,20 @@
85 **
86 ** Or, if no repositories can be located beneath g.zRepositoryName,
87 ** return 0.
88 */
89 int repo_list_page(void){
90 Blob base;
91 int n = 0;
92 int allRepo;
 
 
 
 
93
94 assert( g.db==0 );
 
95 if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
96 /* For the special case of the "repository directory" being "/",
97 ** show all of the repositories named in the ~/.fossil database.
98 **
99 ** On unix systems, then entries are of the form "repo:/home/..."
@@ -118,28 +137,24 @@
118 db_multi_exec("CREATE TABLE vfile(pathname);");
119 vfile_scan(&base, blob_size(&base), 0, 0, 0);
120 db_multi_exec("DELETE FROM sfile WHERE pathname NOT GLOB '*[^/].fossil'");
121 allRepo = 0;
122 }
123 @ <html>
124 @ <head>
125 @ <base href="%s(g.zBaseURL)/" />
126 @ <meta name="viewport" content="width=device-width, initial-scale=1.0">
127 @ <title>Repository List</title>
128 @ </head>
129 @ <body>
130 n = db_int(0, "SELECT count(*) FROM sfile");
131 if( n>0 ){
 
 
 
132 Stmt q;
133 double rNow;
134 @ <h1 align="center">Fossil Repositories</h1>
135 @ <table border="0" class="sortable" data-init-sort="1" \
136 @ data-column-types="tntnk"><thead>
137 @ <tr><th>Filename<th width="20">\
138 @ <th>Project Name<th width="20">\
139 @ <th>Last Modified</tr>
140 @ </thead><tbody>
141 db_prepare(&q, "SELECT pathname"
142 " FROM sfile ORDER BY pathname COLLATE nocase;");
143 rNow = db_double(0, "SELECT julianday('now')");
144 while( db_step(&q)==SQLITE_ROW ){
145 const char *zName = db_column_text(&q, 0);
@@ -162,51 +177,97 @@
162 }else{
163 zFull = mprintf("%s/%s", g.zRepositoryName, zName);
164 }
165 x.zRepoName = zFull;
166 remote_repo_info(&x);
 
 
 
 
 
 
167 fossil_free(zFull);
168 if( !x.isValid ){
169 continue;
 
 
 
 
 
170 }
171 iAge = (rNow - x.rMTime)*86400;
172 if( iAge<0 ) x.rMTime = rNow;
173 zAge = human_readable_age(rNow - x.rMTime);
174 @ <tr><td valign="top">\
175 if( sqlite3_strglob("*.fossil", zName)!=0 ){
176 /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands
177 ** do not work for repositories whose names do not end in ".fossil".
178 ** So do not hyperlink those cases. */
179 @ %h(zName)
180 } else if( sqlite3_strglob("*/.*", zName)==0 ){
181 /* Do not show hidden repos */
182 @ %h(zName) (hidden)
183 } else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){
184 @ <a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a>
 
 
185 }else{
186 @ <a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a>
 
 
187 }
188 if( x.zProjName ){
189 @ <td></td><td>%h(x.zProjName)</td>
190 fossil_free(x.zProjName);
191 }else{
192 @ <td></td><td></td>
193 }
194 @ <td></td><td data-sortkey='%08x(iAge)'>%h(zAge)</tr>
 
 
195 fossil_free(zAge);
196 sqlite3_free(zUrl);
197 }
198 @ </tbody></table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199 }else{
200 @ <h1>No Repositories Found</h1>
201 }
202 @ <script>%s(builtin_text("sorttable.js"))</script>
203 @ </body>
204 @ </html>
205 cgi_reply();
206 sqlite3_close(g.db);
207 g.db = 0;
 
 
 
 
 
 
 
 
 
208 return n;
209 }
210
211 /*
212 ** COMMAND: test-list-page
213
--- src/repolist.c
+++ src/repolist.c
@@ -27,30 +27,44 @@
27 ** input. All other fields are outputs.
28 */
29 struct RepoInfo {
30 char *zRepoName; /* Name of the repository file */
31 int isValid; /* True if zRepoName is a valid Fossil repository */
32 int isRepolistSkin; /* 1 or 2 if this repository wants to be the skin
33 ** for the repository list. 2 means do use this
34 ** repository but do not display it in the list. */
35 char *zProjName; /* Project Name. Memory from fossil_malloc() */
36 double rMTime; /* Last update. Julian day number */
37 };
38 #endif
39
40 /*
41 ** Discover information about the repository given by
42 ** pRepo->zRepoName. The discovered information is stored in other
43 ** fields of the RepoInfo object.
44 */
45 static void remote_repo_info(RepoInfo *pRepo){
46 sqlite3 *db;
47 sqlite3_stmt *pStmt;
48 int rc;
49
50 pRepo->isRepolistSkin = 0;
51 pRepo->isValid = 0;
52 pRepo->zProjName = 0;
53 pRepo->rMTime = 0.0;
54
55 g.dbIgnoreErrors++;
56 rc = sqlite3_open_v2(pRepo->zRepoName, &db, SQLITE_OPEN_READWRITE, 0);
57 if( rc ) goto finish_repo_list;
58 rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
59 " WHERE name='repolist-skin'",
60 -1, &pStmt, 0);
61 if( rc ) goto finish_repo_list;
62 if( sqlite3_step(pStmt)==SQLITE_ROW ){
63 pRepo->isRepolistSkin = sqlite3_column_int(pStmt,0);
64 }
65 sqlite3_finalize(pStmt);
66 if( rc ) goto finish_repo_list;
67 rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
68 " WHERE name='project-name'",
69 -1, &pStmt, 0);
70 if( rc ) goto finish_repo_list;
@@ -85,15 +99,20 @@
99 **
100 ** Or, if no repositories can be located beneath g.zRepositoryName,
101 ** return 0.
102 */
103 int repo_list_page(void){
104 Blob base; /* document root for all repositories */
105 int n = 0; /* Number of repositories found */
106 int allRepo; /* True if running "fossil ui all".
107 ** False if a directory scan of base for repos */
108 Blob html; /* Html for the body of the repository list */
109 char *zSkinRepo = 0; /* Name of the repository database used for skins */
110 char *zSkinUrl = 0; /* URL for the skin database */
111
112 assert( g.db==0 );
113 blob_init(&html, 0, 0);
114 if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
115 /* For the special case of the "repository directory" being "/",
116 ** show all of the repositories named in the ~/.fossil database.
117 **
118 ** On unix systems, then entries are of the form "repo:/home/..."
@@ -118,28 +137,24 @@
137 db_multi_exec("CREATE TABLE vfile(pathname);");
138 vfile_scan(&base, blob_size(&base), 0, 0, 0);
139 db_multi_exec("DELETE FROM sfile WHERE pathname NOT GLOB '*[^/].fossil'");
140 allRepo = 0;
141 }
 
 
 
 
 
 
 
142 n = db_int(0, "SELECT count(*) FROM sfile");
143 if( n==0 ){
144 sqlite3_close(g.db);
145 return 0;
146 }else{
147 Stmt q;
148 double rNow;
149 blob_append_sql(&html,
150 "<table border='0' class='sortable' data-init-sort='1'"
151 " data-column-types='txtxk'><thead>\n"
152 "<tr><th>Filename<th width='20'>"
153 "<th>Project Name<th width='20'>"
154 "<th>Last Modified</tr>\n"
155 "</thead><tbody>\n");
156 db_prepare(&q, "SELECT pathname"
157 " FROM sfile ORDER BY pathname COLLATE nocase;");
158 rNow = db_double(0, "SELECT julianday('now')");
159 while( db_step(&q)==SQLITE_ROW ){
160 const char *zName = db_column_text(&q, 0);
@@ -162,51 +177,97 @@
177 }else{
178 zFull = mprintf("%s/%s", g.zRepositoryName, zName);
179 }
180 x.zRepoName = zFull;
181 remote_repo_info(&x);
182 if( x.isRepolistSkin ){
183 if( zSkinRepo==0 ){
184 zSkinRepo = mprintf("%s", x.zRepoName);
185 zSkinUrl = mprintf("%s", zUrl);
186 }
187 }
188 fossil_free(zFull);
189 if( !x.isValid ){
190 continue;
191 }
192 if( x.isRepolistSkin==2 && !allRepo ){
193 /* Repositories with repolist-skin==2 are omitted from directory
194 ** scan lists, but included in "fossil all ui" lists */
195 continue;
196 }
197 iAge = (rNow - x.rMTime)*86400;
198 if( iAge<0 ) x.rMTime = rNow;
199 zAge = human_readable_age(rNow - x.rMTime);
200 blob_append_sql(&html, "<tr><td valign='top'>");
201 if( sqlite3_strglob("*.fossil", zName)!=0 ){
202 /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands
203 ** do not work for repositories whose names do not end in ".fossil".
204 ** So do not hyperlink those cases. */
205 blob_append_sql(&html,"%h",zName);
206 } else if( sqlite3_strglob("*/.*", zName)==0 ){
207 /* Do not show hyperlinks for hidden repos */
208 blob_append_sql(&html, "%h (hidden)", zName);
209 } else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){
210 blob_append_sql(&html,
211 "<a href='/%T/home' target='_blank'>/%h</a>\n",
212 zUrl, zName);
213 }else{
214 blob_append_sql(&html,
215 "<a href='/%T/home' target='_blank'>%h</a>\n",
216 zUrl, zName);
217 }
218 if( x.zProjName ){
219 blob_append_sql(&html, "<td></td><td>%h</td>\n", x.zProjName);
220 fossil_free(x.zProjName);
221 }else{
222 blob_append_sql(&html, "<td></td><td></td>\n");
223 }
224 blob_append_sql(&html,
225 "<td></td><td data-sortkey='%08x'>%h</tr>\n",
226 iAge, zAge);
227 fossil_free(zAge);
228 sqlite3_free(zUrl);
229 }
230 db_finalize(&q);
231 blob_append_sql(&html,"</tbody></table>\n");
232 }
233 if( zSkinRepo ){
234 char *zNewBase = mprintf("%s/%s", g.zBaseURL, zSkinUrl);
235 g.zBaseURL = 0;
236 set_base_url(zNewBase);
237 db_open_repository(zSkinRepo);
238 fossil_free(zSkinRepo);
239 fossil_free(zSkinUrl);
240 }
241 if( g.repositoryOpen ){
242 /* This case runs if remote_repository_info() found a repository
243 ** that has the "repolist_skin" property set to non-zero and left
244 ** that repository open in g.db. Use the skin of that repository
245 ** for display. */
246 login_check_credentials();
247 style_header("Repository List");
248 @ %s(blob_str(&html))
249 style_table_sorter();
250 style_footer();
251 }else{
252 /* If no repositories were found that had the "repolist_skin"
253 ** property set, then use a default skin */
254 @ <html>
255 @ <head>
256 @ <base href="%s(g.zBaseURL)/" />
257 @ <meta name="viewport" content="width=device-width, initial-scale=1.0">
258 @ <title>Repository List</title>
259 @ </head>
260 @ <body>
261 @ <h1 align="center">Fossil Repositories</h1>
262 @ %s(blob_str(&html))
263 @ <script>%s(builtin_text("sorttable.js"))</script>
264 @ </body>
265 @ </html>
266 }
267 blob_reset(&html);
268 cgi_reply();
269 return n;
270 }
271
272 /*
273 ** COMMAND: test-list-page
274

Keyboard Shortcuts

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