Fossil SCM

Continue the file browsing UX enhancements into the /tree and /fileage pages

drh 2020-05-11 22:53 trunk
Commit 92fe4a5441ee3d136e237c991911b4179da99fb23614566b40454b7626d1f498
3 files changed +14 +55 -45 +1 -7
+14
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,24 @@
1818
** This file contains code used to create new branches within a repository.
1919
*/
2020
#include "config.h"
2121
#include "branch.h"
2222
#include <assert.h>
23
+
24
+/*
25
+** Return true if zBr is the branch name associated with check-in with
26
+** blob.uuid value of zUuid
27
+*/
28
+int branch_includes_uuid(const char *zBr, const char *zUuid){
29
+ return db_exists(
30
+ "SELECT 1 FROM tagxref, blob"
31
+ " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
32
+ " AND tagxref.value=%Q AND tagxref.tagtype>0"
33
+ " AND tagxref.tagid=%d",
34
+ zUuid, zBr, TAG_BRANCH
35
+ );
36
+}
2337
2438
/*
2539
** If RID refers to a check-in, return the name of the branch for that
2640
** check-in.
2741
**
2842
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,24 @@
18 ** This file contains code used to create new branches within a repository.
19 */
20 #include "config.h"
21 #include "branch.h"
22 #include <assert.h>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
24 /*
25 ** If RID refers to a check-in, return the name of the branch for that
26 ** check-in.
27 **
28
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,24 @@
18 ** This file contains code used to create new branches within a repository.
19 */
20 #include "config.h"
21 #include "branch.h"
22 #include <assert.h>
23
24 /*
25 ** Return true if zBr is the branch name associated with check-in with
26 ** blob.uuid value of zUuid
27 */
28 int branch_includes_uuid(const char *zBr, const char *zUuid){
29 return db_exists(
30 "SELECT 1 FROM tagxref, blob"
31 " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
32 " AND tagxref.value=%Q AND tagxref.tagtype>0"
33 " AND tagxref.tagid=%d",
34 zUuid, zBr, TAG_BRANCH
35 );
36 }
37
38 /*
39 ** If RID refers to a check-in, return the name of the branch for that
40 ** check-in.
41 **
42
+55 -45
--- src/browse.c
+++ src/browse.c
@@ -103,11 +103,11 @@
103103
blob_appendf(pOut, "/%h", zPath+i);
104104
break;
105105
}
106106
}
107107
if( zCI ){
108
- char *zLink = href("%R/%s?name=%#T%s&ci=%!S", zURI, j, zPath, zREx,zCI);
108
+ char *zLink = href("%R/%s?name=%#T%s&ci=%T", zURI, j, zPath, zREx,zCI);
109109
blob_appendf(pOut, "%s%z%#h</a>",
110110
zSep, zLink, j-i, &zPath[i]);
111111
}else{
112112
char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
113113
blob_appendf(pOut, "%s%z%#h</a>",
@@ -172,17 +172,11 @@
172172
int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
173173
linkTrunk = trunkRid && rid != trunkRid;
174174
linkTip = rid != symbolic_name_to_rid("tip", "ci");
175175
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
176176
isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
177
- isBranchCI = db_exists(
178
- "SELECT 1 FROM tagxref, blob"
179
- " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
180
- " AND tagxref.value=%Q AND tagxref.tagtype>0"
181
- " AND tagxref.tagid=%d",
182
- zUuid, zCI, TAG_BRANCH
183
- );
177
+ isBranchCI = branch_includes_uuid(zCI, zUuid);
184178
}else{
185179
zCI = 0;
186180
}
187181
}
188182
@@ -231,11 +225,11 @@
231225
}else {
232226
@ of check-in %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
233227
}
234228
zSubdirLink = mprintf("%R/dir?ci=%T&name=%T", zCI, zPrefix);
235229
if( nD==0 ){
236
- style_submenu_element("File Ages", "%R/fileage?name=%!S", zUuid);
230
+ style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
237231
}
238232
}else{
239233
@ in any check-in</h2>
240234
zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
241235
}
@@ -326,11 +320,11 @@
326320
zFN++;
327321
@ <li class="dir">%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
328322
}else{
329323
const char *zLink;
330324
if( zCI ){
331
- zLink = href("%R/file?name=%T%T&ci=%!S",zPrefix,zFN,zCI);
325
+ zLink = href("%R/file?name=%T%T&ci=%T",zPrefix,zFN,zCI);
332326
}else{
333327
zLink = href("%R/finfo?name=%T%T",zPrefix,zFN);
334328
}
335329
@ <li class="%z(fileext_class(zFN))">%z(zLink)%h(zFN)</a></li>
336330
}
@@ -656,10 +650,11 @@
656650
int startExpanded; /* True to start out with the tree expanded */
657651
int showDirOnly; /* Show directories only. Omit files */
658652
int nDir = 0; /* Number of directories. Used for ID attributes */
659653
char *zProjectName = db_get("project-name", 0);
660654
int isSymbolicCI = 0; /* ci= is a symbolic name, not a hash prefix */
655
+ int isBranchCI = 0; /* ci= refers to a branch name */
661656
char *zHeader = 0;
662657
663658
if( zCI && strlen(zCI)==0 ){ zCI = 0; }
664659
if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
665660
memset(&sTree, 0, sizeof(sTree));
@@ -705,10 +700,11 @@
705700
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
706701
rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
707702
zNow = db_text("", "SELECT datetime(mtime,toLocal())"
708703
" FROM event WHERE objid=%d", rid);
709704
isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
705
+ isBranchCI = branch_includes_uuid(zCI, zUuid);
710706
}else{
711707
zCI = 0;
712708
}
713709
}
714710
if( zCI==0 ){
@@ -715,19 +711,22 @@
715711
rNow = db_double(0.0, "SELECT max(mtime) FROM event");
716712
zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
717713
}
718714
719715
assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
720
- if( isSymbolicCI ) {
721
- zHeader = mprintf("%s at %s",
722
- (zD ? zD : (showDirOnly ? "Folder Hierarchy" : "Tree-View")), zCI);
723
- }else if( zUuid && strlen(zUuid) ){
724
- zHeader = mprintf("%s at [%S]",
725
- (zD ? zD : (showDirOnly ? "Folder Hierarchy" : "Tree-View")), zUuid);
716
+ if( zD==0 ){
717
+ if( zCI ){
718
+ zHeader = mprintf("Top-level Files of %s", zCI);
719
+ }else{
720
+ zHeader = mprintf("All Top-level Files");
721
+ }
726722
}else{
727
- zHeader = mprintf("%s",
728
- (zD ? zD : (showDirOnly ?"All Folders Hierarchy":"All Files Tree-View")));
723
+ if( zCI ){
724
+ zHeader = mprintf("Files in %s/ of %s", zD, zCI);
725
+ }else{
726
+ zHeader = mprintf("All File in %s/", zD);
727
+ }
729728
}
730729
style_header("%s", zHeader);
731730
fossil_free(zHeader);
732731
733732
/* Compute the title of the page */
@@ -736,20 +735,18 @@
736735
blob_append(&dirname, "within directory ", -1);
737736
hyperlinked_path(zD, &dirname, zCI, "tree", zREx, 0);
738737
if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
739738
style_submenu_element("Top-Level", "%s",
740739
url_render(&sURI, "name", 0, 0, 0));
741
- }else{
742
- if( zRE ){
743
- blob_appendf(&dirname, "matching \"%s\"", zRE);
744
- }
740
+ }else if( zRE ){
741
+ blob_appendf(&dirname, "matching \"%s\"", zRE);
745742
}
746743
style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
747744
if( zCI ){
748745
style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
749746
if( nD==0 && !showDirOnly ){
750
- style_submenu_element("File Ages", "%R/fileage?name=%s", zUuid);
747
+ style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
751748
}
752749
}
753750
if( linkTrunk ){
754751
style_submenu_element("Trunk", "%s",
755752
url_render(&sURI, "ci", "trunk", 0, 0));
@@ -804,10 +801,11 @@
804801
tree_add_node(&sTree, zName, zUuid, mtime);
805802
nFile++;
806803
}
807804
db_finalize(&q);
808805
}
806
+ style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
809807
810808
if( showDirOnly ){
811809
for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
812810
if( p->pChild!=0 && p->nFullName>nD ) nFile++;
813811
}
@@ -814,18 +812,24 @@
814812
zObjType = "Folders";
815813
}else{
816814
zObjType = "Files";
817815
}
818816
819
- style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
820
-
821
- if( zCI ){
822
- @ <h2>%s(zObjType) at check-in
823
- if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
824
- @ "%h(zCI)"
825
- }
826
- @ [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))
817
+ if( zCI && strcmp(zCI,"tip")==0 ){
818
+ @ <h2>%s(zObjType) in the %z(href("%R/info?name=tip"))latest check-in</a>
819
+ }else if( isBranchCI ){
820
+ @ <h2>%s(zObjType) in the %z(href("%R/info?name=%T",zCI))latest check-in\
821
+ @ </a> for branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a>
822
+ if( blob_size(&dirname) ){
823
+ @ and %s(blob_str(&dirname))</h2>
824
+ }
825
+ }else if( zCI ){
826
+ @ <h2>%s(zObjType) for check-in \
827
+ @ %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
828
+ if( blob_size(&dirname) ){
829
+ @ and %s(blob_str(&dirname))</h2>
830
+ }
827831
}else{
828832
int n = db_int(0, "SELECT count(*) FROM plink");
829833
@ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
830834
}
831835
if( useMtime ){
@@ -883,11 +887,11 @@
883887
nDir++;
884888
}else if( !showDirOnly ){
885889
const char *zFileClass = fileext_class(p->zName);
886890
char *zLink;
887891
if( zCI ){
888
- zLink = href("%R/file?name=%T&ci=%!S",p->zFullName,zCI);
892
+ zLink = href("%R/file?name=%T&ci=%T",p->zFullName,zCI);
889893
}else{
890894
zLink = href("%R/finfo?name=%T",p->zFullName);
891895
}
892896
@ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
893897
@ %z(zLink)%h(p->zName)</a>
@@ -1060,10 +1064,11 @@
10601064
int rid;
10611065
const char *zName;
10621066
const char *zGlob;
10631067
const char *zUuid;
10641068
const char *zNow; /* Time of check-in */
1069
+ int isBranchCI; /* name= is a branch name */
10651070
int showId = PB("showid");
10661071
Stmt q1, q2;
10671072
double baseTime;
10681073
login_check_credentials();
10691074
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
@@ -1073,28 +1078,34 @@
10731078
rid = symbolic_name_to_rid(zName, "ci");
10741079
if( rid==0 ){
10751080
fossil_fatal("not a valid check-in: %s", zName);
10761081
}
10771082
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1083
+ isBranchCI = branch_includes_uuid(zName,zUuid);
10781084
baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
10791085
zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
10801086
" WHERE objid=%d", rid);
10811087
style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
10821088
style_header("File Ages");
10831089
zGlob = P("glob");
10841090
compute_fileage(rid,zGlob);
10851091
db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
10861092
1087
- @ <h1>Files in
1088
- @ %z(href("%R/info/%!S",zUuid))[%S(zUuid)]</a>
1093
+ if( fossil_strcmp(zName,"tip")==0 ){
1094
+ @ <h1>Files in the %z(href("%R/info?name=tip"))latest check-in</a>
1095
+ }else if( isBranchCI ){
1096
+ @ <h1>Files in the %z(href("%R/info?name=%T",zName))latest check-in</a>
1097
+ @ of branch %z(href("%R/timeline?r=%T",zName))%h(zName)</a>
1098
+ }else{
1099
+ @ <h1>Files in check-in %z(href("%R/info?name=%T",zName))%h(zName)</a>
1100
+ }
10891101
if( zGlob && zGlob[0] ){
10901102
@ that match "%h(zGlob)"
10911103
}
10921104
@ ordered by age</h1>
10931105
@
1094
- @ <p>File ages are expressed relative to the
1095
- @ %z(href("%R/ci/%!S",zUuid))[%S(zUuid)]</a> check-in time of
1106
+ @ <p>File ages are expressed relative to the check-in time of
10961107
@ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
10971108
@
10981109
@ <div class='fileage'><table>
10991110
@ <tr><th>Age</th><th>Files</th><th>Check-in</th></tr>
11001111
db_prepare(&q1,
@@ -1109,14 +1120,13 @@
11091120
" AND blob.rid=event.objid\n"
11101121
" ORDER BY event.mtime DESC;",
11111122
TAG_BRANCH
11121123
);
11131124
db_prepare(&q2,
1114
- "SELECT blob.uuid, filename.name, fileage.fid\n"
1115
- " FROM fileage, blob, filename\n"
1125
+ "SELECT filename.name, fileage.fid\n"
1126
+ " FROM fileage, filename\n"
11161127
" WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
1117
- " AND blob.rid=fileage.fid;"
11181128
);
11191129
while( db_step(&q1)==SQLITE_ROW ){
11201130
double age = baseTime - db_column_double(&q1, 0);
11211131
int mid = db_column_int(&q1, 1);
11221132
const char *zUuid = db_column_text(&q1, 2);
@@ -1126,24 +1136,24 @@
11261136
char *zAge = human_readable_age(age);
11271137
@ <tr><td>%s(zAge)</td>
11281138
@ <td>
11291139
db_bind_int(&q2, ":mid", mid);
11301140
while( db_step(&q2)==SQLITE_ROW ){
1131
- const char *zFUuid = db_column_text(&q2,0);
1132
- const char *zFile = db_column_text(&q2,1);
1133
- int fid = db_column_int(&q2,2);
1141
+ const char *zFile = db_column_text(&q2,0);
1142
+ @ %z(href("%R/file?name=%T&ci=%!S",zFile,zUuid))%h(zFile)</a> \
11341143
if( showId ){
1135
- @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a> (%d(fid))<br />
1144
+ int fid = db_column_int(&q2,1);
1145
+ @ (%d(fid))<br />
11361146
}else{
1137
- @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a><br />
1147
+ @ </a><br />
11381148
}
11391149
}
11401150
db_reset(&q2);
11411151
@ </td>
11421152
@ <td>
11431153
@ %W(zComment)
1144
- @ (check-in:&nbsp;%z(href("%R/ci/%!S",zUuid))%S(zUuid)</a>,
1154
+ @ (check-in:&nbsp;%z(href("%R/info/%!S",zUuid))%S(zUuid)</a>,
11451155
if( showId ){
11461156
@ id: %d(mid)
11471157
}
11481158
@ user:&nbsp;%z(href("%R/timeline?u=%t&c=%!S&nd",zUser,zUuid))%h(zUser)</a>,
11491159
@ branch:&nbsp;\
11501160
--- src/browse.c
+++ src/browse.c
@@ -103,11 +103,11 @@
103 blob_appendf(pOut, "/%h", zPath+i);
104 break;
105 }
106 }
107 if( zCI ){
108 char *zLink = href("%R/%s?name=%#T%s&ci=%!S", zURI, j, zPath, zREx,zCI);
109 blob_appendf(pOut, "%s%z%#h</a>",
110 zSep, zLink, j-i, &zPath[i]);
111 }else{
112 char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
113 blob_appendf(pOut, "%s%z%#h</a>",
@@ -172,17 +172,11 @@
172 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
173 linkTrunk = trunkRid && rid != trunkRid;
174 linkTip = rid != symbolic_name_to_rid("tip", "ci");
175 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
176 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
177 isBranchCI = db_exists(
178 "SELECT 1 FROM tagxref, blob"
179 " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
180 " AND tagxref.value=%Q AND tagxref.tagtype>0"
181 " AND tagxref.tagid=%d",
182 zUuid, zCI, TAG_BRANCH
183 );
184 }else{
185 zCI = 0;
186 }
187 }
188
@@ -231,11 +225,11 @@
231 }else {
232 @ of check-in %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
233 }
234 zSubdirLink = mprintf("%R/dir?ci=%T&name=%T", zCI, zPrefix);
235 if( nD==0 ){
236 style_submenu_element("File Ages", "%R/fileage?name=%!S", zUuid);
237 }
238 }else{
239 @ in any check-in</h2>
240 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
241 }
@@ -326,11 +320,11 @@
326 zFN++;
327 @ <li class="dir">%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
328 }else{
329 const char *zLink;
330 if( zCI ){
331 zLink = href("%R/file?name=%T%T&ci=%!S",zPrefix,zFN,zCI);
332 }else{
333 zLink = href("%R/finfo?name=%T%T",zPrefix,zFN);
334 }
335 @ <li class="%z(fileext_class(zFN))">%z(zLink)%h(zFN)</a></li>
336 }
@@ -656,10 +650,11 @@
656 int startExpanded; /* True to start out with the tree expanded */
657 int showDirOnly; /* Show directories only. Omit files */
658 int nDir = 0; /* Number of directories. Used for ID attributes */
659 char *zProjectName = db_get("project-name", 0);
660 int isSymbolicCI = 0; /* ci= is a symbolic name, not a hash prefix */
 
661 char *zHeader = 0;
662
663 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
664 if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
665 memset(&sTree, 0, sizeof(sTree));
@@ -705,10 +700,11 @@
705 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
706 rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
707 zNow = db_text("", "SELECT datetime(mtime,toLocal())"
708 " FROM event WHERE objid=%d", rid);
709 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
 
710 }else{
711 zCI = 0;
712 }
713 }
714 if( zCI==0 ){
@@ -715,19 +711,22 @@
715 rNow = db_double(0.0, "SELECT max(mtime) FROM event");
716 zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
717 }
718
719 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
720 if( isSymbolicCI ) {
721 zHeader = mprintf("%s at %s",
722 (zD ? zD : (showDirOnly ? "Folder Hierarchy" : "Tree-View")), zCI);
723 }else if( zUuid && strlen(zUuid) ){
724 zHeader = mprintf("%s at [%S]",
725 (zD ? zD : (showDirOnly ? "Folder Hierarchy" : "Tree-View")), zUuid);
726 }else{
727 zHeader = mprintf("%s",
728 (zD ? zD : (showDirOnly ?"All Folders Hierarchy":"All Files Tree-View")));
 
 
 
729 }
730 style_header("%s", zHeader);
731 fossil_free(zHeader);
732
733 /* Compute the title of the page */
@@ -736,20 +735,18 @@
736 blob_append(&dirname, "within directory ", -1);
737 hyperlinked_path(zD, &dirname, zCI, "tree", zREx, 0);
738 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
739 style_submenu_element("Top-Level", "%s",
740 url_render(&sURI, "name", 0, 0, 0));
741 }else{
742 if( zRE ){
743 blob_appendf(&dirname, "matching \"%s\"", zRE);
744 }
745 }
746 style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
747 if( zCI ){
748 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
749 if( nD==0 && !showDirOnly ){
750 style_submenu_element("File Ages", "%R/fileage?name=%s", zUuid);
751 }
752 }
753 if( linkTrunk ){
754 style_submenu_element("Trunk", "%s",
755 url_render(&sURI, "ci", "trunk", 0, 0));
@@ -804,10 +801,11 @@
804 tree_add_node(&sTree, zName, zUuid, mtime);
805 nFile++;
806 }
807 db_finalize(&q);
808 }
 
809
810 if( showDirOnly ){
811 for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
812 if( p->pChild!=0 && p->nFullName>nD ) nFile++;
813 }
@@ -814,18 +812,24 @@
814 zObjType = "Folders";
815 }else{
816 zObjType = "Files";
817 }
818
819 style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
820
821 if( zCI ){
822 @ <h2>%s(zObjType) at check-in
823 if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
824 @ "%h(zCI)"
825 }
826 @ [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))
 
 
 
 
 
 
827 }else{
828 int n = db_int(0, "SELECT count(*) FROM plink");
829 @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
830 }
831 if( useMtime ){
@@ -883,11 +887,11 @@
883 nDir++;
884 }else if( !showDirOnly ){
885 const char *zFileClass = fileext_class(p->zName);
886 char *zLink;
887 if( zCI ){
888 zLink = href("%R/file?name=%T&ci=%!S",p->zFullName,zCI);
889 }else{
890 zLink = href("%R/finfo?name=%T",p->zFullName);
891 }
892 @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
893 @ %z(zLink)%h(p->zName)</a>
@@ -1060,10 +1064,11 @@
1060 int rid;
1061 const char *zName;
1062 const char *zGlob;
1063 const char *zUuid;
1064 const char *zNow; /* Time of check-in */
 
1065 int showId = PB("showid");
1066 Stmt q1, q2;
1067 double baseTime;
1068 login_check_credentials();
1069 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
@@ -1073,28 +1078,34 @@
1073 rid = symbolic_name_to_rid(zName, "ci");
1074 if( rid==0 ){
1075 fossil_fatal("not a valid check-in: %s", zName);
1076 }
1077 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
 
1078 baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1079 zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
1080 " WHERE objid=%d", rid);
1081 style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
1082 style_header("File Ages");
1083 zGlob = P("glob");
1084 compute_fileage(rid,zGlob);
1085 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1086
1087 @ <h1>Files in
1088 @ %z(href("%R/info/%!S",zUuid))[%S(zUuid)]</a>
 
 
 
 
 
 
1089 if( zGlob && zGlob[0] ){
1090 @ that match "%h(zGlob)"
1091 }
1092 @ ordered by age</h1>
1093 @
1094 @ <p>File ages are expressed relative to the
1095 @ %z(href("%R/ci/%!S",zUuid))[%S(zUuid)]</a> check-in time of
1096 @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
1097 @
1098 @ <div class='fileage'><table>
1099 @ <tr><th>Age</th><th>Files</th><th>Check-in</th></tr>
1100 db_prepare(&q1,
@@ -1109,14 +1120,13 @@
1109 " AND blob.rid=event.objid\n"
1110 " ORDER BY event.mtime DESC;",
1111 TAG_BRANCH
1112 );
1113 db_prepare(&q2,
1114 "SELECT blob.uuid, filename.name, fileage.fid\n"
1115 " FROM fileage, blob, filename\n"
1116 " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
1117 " AND blob.rid=fileage.fid;"
1118 );
1119 while( db_step(&q1)==SQLITE_ROW ){
1120 double age = baseTime - db_column_double(&q1, 0);
1121 int mid = db_column_int(&q1, 1);
1122 const char *zUuid = db_column_text(&q1, 2);
@@ -1126,24 +1136,24 @@
1126 char *zAge = human_readable_age(age);
1127 @ <tr><td>%s(zAge)</td>
1128 @ <td>
1129 db_bind_int(&q2, ":mid", mid);
1130 while( db_step(&q2)==SQLITE_ROW ){
1131 const char *zFUuid = db_column_text(&q2,0);
1132 const char *zFile = db_column_text(&q2,1);
1133 int fid = db_column_int(&q2,2);
1134 if( showId ){
1135 @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a> (%d(fid))<br />
 
1136 }else{
1137 @ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a><br />
1138 }
1139 }
1140 db_reset(&q2);
1141 @ </td>
1142 @ <td>
1143 @ %W(zComment)
1144 @ (check-in:&nbsp;%z(href("%R/ci/%!S",zUuid))%S(zUuid)</a>,
1145 if( showId ){
1146 @ id: %d(mid)
1147 }
1148 @ user:&nbsp;%z(href("%R/timeline?u=%t&c=%!S&nd",zUser,zUuid))%h(zUser)</a>,
1149 @ branch:&nbsp;\
1150
--- src/browse.c
+++ src/browse.c
@@ -103,11 +103,11 @@
103 blob_appendf(pOut, "/%h", zPath+i);
104 break;
105 }
106 }
107 if( zCI ){
108 char *zLink = href("%R/%s?name=%#T%s&ci=%T", zURI, j, zPath, zREx,zCI);
109 blob_appendf(pOut, "%s%z%#h</a>",
110 zSep, zLink, j-i, &zPath[i]);
111 }else{
112 char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
113 blob_appendf(pOut, "%s%z%#h</a>",
@@ -172,17 +172,11 @@
172 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
173 linkTrunk = trunkRid && rid != trunkRid;
174 linkTip = rid != symbolic_name_to_rid("tip", "ci");
175 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
176 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
177 isBranchCI = branch_includes_uuid(zCI, zUuid);
 
 
 
 
 
 
178 }else{
179 zCI = 0;
180 }
181 }
182
@@ -231,11 +225,11 @@
225 }else {
226 @ of check-in %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
227 }
228 zSubdirLink = mprintf("%R/dir?ci=%T&name=%T", zCI, zPrefix);
229 if( nD==0 ){
230 style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
231 }
232 }else{
233 @ in any check-in</h2>
234 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
235 }
@@ -326,11 +320,11 @@
320 zFN++;
321 @ <li class="dir">%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
322 }else{
323 const char *zLink;
324 if( zCI ){
325 zLink = href("%R/file?name=%T%T&ci=%T",zPrefix,zFN,zCI);
326 }else{
327 zLink = href("%R/finfo?name=%T%T",zPrefix,zFN);
328 }
329 @ <li class="%z(fileext_class(zFN))">%z(zLink)%h(zFN)</a></li>
330 }
@@ -656,10 +650,11 @@
650 int startExpanded; /* True to start out with the tree expanded */
651 int showDirOnly; /* Show directories only. Omit files */
652 int nDir = 0; /* Number of directories. Used for ID attributes */
653 char *zProjectName = db_get("project-name", 0);
654 int isSymbolicCI = 0; /* ci= is a symbolic name, not a hash prefix */
655 int isBranchCI = 0; /* ci= refers to a branch name */
656 char *zHeader = 0;
657
658 if( zCI && strlen(zCI)==0 ){ zCI = 0; }
659 if( strcmp(PD("type","flat"),"flat")==0 ){ page_dir(); return; }
660 memset(&sTree, 0, sizeof(sTree));
@@ -705,10 +700,11 @@
700 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
701 rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
702 zNow = db_text("", "SELECT datetime(mtime,toLocal())"
703 " FROM event WHERE objid=%d", rid);
704 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
705 isBranchCI = branch_includes_uuid(zCI, zUuid);
706 }else{
707 zCI = 0;
708 }
709 }
710 if( zCI==0 ){
@@ -715,19 +711,22 @@
711 rNow = db_double(0.0, "SELECT max(mtime) FROM event");
712 zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
713 }
714
715 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
716 if( zD==0 ){
717 if( zCI ){
718 zHeader = mprintf("Top-level Files of %s", zCI);
719 }else{
720 zHeader = mprintf("All Top-level Files");
721 }
722 }else{
723 if( zCI ){
724 zHeader = mprintf("Files in %s/ of %s", zD, zCI);
725 }else{
726 zHeader = mprintf("All File in %s/", zD);
727 }
728 }
729 style_header("%s", zHeader);
730 fossil_free(zHeader);
731
732 /* Compute the title of the page */
@@ -736,20 +735,18 @@
735 blob_append(&dirname, "within directory ", -1);
736 hyperlinked_path(zD, &dirname, zCI, "tree", zREx, 0);
737 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
738 style_submenu_element("Top-Level", "%s",
739 url_render(&sURI, "name", 0, 0, 0));
740 }else if( zRE ){
741 blob_appendf(&dirname, "matching \"%s\"", zRE);
 
 
742 }
743 style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
744 if( zCI ){
745 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
746 if( nD==0 && !showDirOnly ){
747 style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
748 }
749 }
750 if( linkTrunk ){
751 style_submenu_element("Trunk", "%s",
752 url_render(&sURI, "ci", "trunk", 0, 0));
@@ -804,10 +801,11 @@
801 tree_add_node(&sTree, zName, zUuid, mtime);
802 nFile++;
803 }
804 db_finalize(&q);
805 }
806 style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
807
808 if( showDirOnly ){
809 for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
810 if( p->pChild!=0 && p->nFullName>nD ) nFile++;
811 }
@@ -814,18 +812,24 @@
812 zObjType = "Folders";
813 }else{
814 zObjType = "Files";
815 }
816
817 if( zCI && strcmp(zCI,"tip")==0 ){
818 @ <h2>%s(zObjType) in the %z(href("%R/info?name=tip"))latest check-in</a>
819 }else if( isBranchCI ){
820 @ <h2>%s(zObjType) in the %z(href("%R/info?name=%T",zCI))latest check-in\
821 @ </a> for branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a>
822 if( blob_size(&dirname) ){
823 @ and %s(blob_str(&dirname))</h2>
824 }
825 }else if( zCI ){
826 @ <h2>%s(zObjType) for check-in \
827 @ %z(href("%R/info?name=%T",zCI))%h(zCI)</a></h2>
828 if( blob_size(&dirname) ){
829 @ and %s(blob_str(&dirname))</h2>
830 }
831 }else{
832 int n = db_int(0, "SELECT count(*) FROM plink");
833 @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname))
834 }
835 if( useMtime ){
@@ -883,11 +887,11 @@
887 nDir++;
888 }else if( !showDirOnly ){
889 const char *zFileClass = fileext_class(p->zName);
890 char *zLink;
891 if( zCI ){
892 zLink = href("%R/file?name=%T&ci=%T",p->zFullName,zCI);
893 }else{
894 zLink = href("%R/finfo?name=%T",p->zFullName);
895 }
896 @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline">
897 @ %z(zLink)%h(p->zName)</a>
@@ -1060,10 +1064,11 @@
1064 int rid;
1065 const char *zName;
1066 const char *zGlob;
1067 const char *zUuid;
1068 const char *zNow; /* Time of check-in */
1069 int isBranchCI; /* name= is a branch name */
1070 int showId = PB("showid");
1071 Stmt q1, q2;
1072 double baseTime;
1073 login_check_credentials();
1074 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
@@ -1073,28 +1078,34 @@
1078 rid = symbolic_name_to_rid(zName, "ci");
1079 if( rid==0 ){
1080 fossil_fatal("not a valid check-in: %s", zName);
1081 }
1082 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1083 isBranchCI = branch_includes_uuid(zName,zUuid);
1084 baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1085 zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
1086 " WHERE objid=%d", rid);
1087 style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
1088 style_header("File Ages");
1089 zGlob = P("glob");
1090 compute_fileage(rid,zGlob);
1091 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1092
1093 if( fossil_strcmp(zName,"tip")==0 ){
1094 @ <h1>Files in the %z(href("%R/info?name=tip"))latest check-in</a>
1095 }else if( isBranchCI ){
1096 @ <h1>Files in the %z(href("%R/info?name=%T",zName))latest check-in</a>
1097 @ of branch %z(href("%R/timeline?r=%T",zName))%h(zName)</a>
1098 }else{
1099 @ <h1>Files in check-in %z(href("%R/info?name=%T",zName))%h(zName)</a>
1100 }
1101 if( zGlob && zGlob[0] ){
1102 @ that match "%h(zGlob)"
1103 }
1104 @ ordered by age</h1>
1105 @
1106 @ <p>File ages are expressed relative to the check-in time of
 
1107 @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p>
1108 @
1109 @ <div class='fileage'><table>
1110 @ <tr><th>Age</th><th>Files</th><th>Check-in</th></tr>
1111 db_prepare(&q1,
@@ -1109,14 +1120,13 @@
1120 " AND blob.rid=event.objid\n"
1121 " ORDER BY event.mtime DESC;",
1122 TAG_BRANCH
1123 );
1124 db_prepare(&q2,
1125 "SELECT filename.name, fileage.fid\n"
1126 " FROM fileage, filename\n"
1127 " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid"
 
1128 );
1129 while( db_step(&q1)==SQLITE_ROW ){
1130 double age = baseTime - db_column_double(&q1, 0);
1131 int mid = db_column_int(&q1, 1);
1132 const char *zUuid = db_column_text(&q1, 2);
@@ -1126,24 +1136,24 @@
1136 char *zAge = human_readable_age(age);
1137 @ <tr><td>%s(zAge)</td>
1138 @ <td>
1139 db_bind_int(&q2, ":mid", mid);
1140 while( db_step(&q2)==SQLITE_ROW ){
1141 const char *zFile = db_column_text(&q2,0);
1142 @ %z(href("%R/file?name=%T&ci=%!S",zFile,zUuid))%h(zFile)</a> \
 
1143 if( showId ){
1144 int fid = db_column_int(&q2,1);
1145 @ (%d(fid))<br />
1146 }else{
1147 @ </a><br />
1148 }
1149 }
1150 db_reset(&q2);
1151 @ </td>
1152 @ <td>
1153 @ %W(zComment)
1154 @ (check-in:&nbsp;%z(href("%R/info/%!S",zUuid))%S(zUuid)</a>,
1155 if( showId ){
1156 @ id: %d(mid)
1157 }
1158 @ user:&nbsp;%z(href("%R/timeline?u=%t&c=%!S&nd",zUser,zUuid))%h(zUser)</a>,
1159 @ branch:&nbsp;\
1160
+1 -7
--- src/info.c
+++ src/info.c
@@ -2150,17 +2150,11 @@
21502150
if( zCI
21512151
&& name_to_uuid2(zCI, "ci", &zCIUuid)
21522152
&& sqlite3_strnicmp(zCIUuid, zCI, strlen(zCI))!=0
21532153
){
21542154
isSymbolicCI = 1;
2155
- isBranchCI = db_exists(
2156
- "SELECT 1 FROM tagxref, blob"
2157
- " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
2158
- " AND tagxref.value=%Q AND tagxref.tagtype>0"
2159
- " AND tagxref.tagid=%d",
2160
- zCIUuid, zCI, TAG_BRANCH
2161
- );
2155
+ isBranchCI = branch_includes_uuid(zCI, zCIUuid);
21622156
}
21632157
21642158
/* The name= query parameter (or at least one of its alternative
21652159
** spellings) is required. Except for /file, show a top-level
21662160
** directory listing if name= is omitted.
21672161
--- src/info.c
+++ src/info.c
@@ -2150,17 +2150,11 @@
2150 if( zCI
2151 && name_to_uuid2(zCI, "ci", &zCIUuid)
2152 && sqlite3_strnicmp(zCIUuid, zCI, strlen(zCI))!=0
2153 ){
2154 isSymbolicCI = 1;
2155 isBranchCI = db_exists(
2156 "SELECT 1 FROM tagxref, blob"
2157 " WHERE blob.uuid=%Q AND tagxref.rid=blob.rid"
2158 " AND tagxref.value=%Q AND tagxref.tagtype>0"
2159 " AND tagxref.tagid=%d",
2160 zCIUuid, zCI, TAG_BRANCH
2161 );
2162 }
2163
2164 /* The name= query parameter (or at least one of its alternative
2165 ** spellings) is required. Except for /file, show a top-level
2166 ** directory listing if name= is omitted.
2167
--- src/info.c
+++ src/info.c
@@ -2150,17 +2150,11 @@
2150 if( zCI
2151 && name_to_uuid2(zCI, "ci", &zCIUuid)
2152 && sqlite3_strnicmp(zCIUuid, zCI, strlen(zCI))!=0
2153 ){
2154 isSymbolicCI = 1;
2155 isBranchCI = branch_includes_uuid(zCI, zCIUuid);
 
 
 
 
 
 
2156 }
2157
2158 /* The name= query parameter (or at least one of its alternative
2159 ** spellings) is required. Except for /file, show a top-level
2160 ** directory listing if name= is omitted.
2161

Keyboard Shortcuts

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