Fossil SCM

Replace the circumstantial "Trunk", "All" and "Tip" link the /dir|/tree|/file submenu section by 1 multi-choice element in the recent open branches + "All Checkins" and "tip" special entries.

mgagnon 2025-10-09 23:11 trunk
Commit 5a3f0386aea3b961a8e48d3636ee52bf77c12f8b5e52b21b1ee989946c467f9d
2 files changed +44 +12 -26
+44
--- src/branch.c
+++ src/branch.c
@@ -1090,5 +1090,49 @@
10901090
if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
10911091
www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, brtimeline_extra);
10921092
db_finalize(&q);
10931093
style_finish_page();
10941094
}
1095
+
1096
+/*
1097
+** Generate a multichoice submenu for the few recent active branches. zName is
1098
+** the query parameter used to select the current checkin. zCI is optional and
1099
+** represent the currently selected checkin, so if it is a checkin hash
1100
+** instead of a branch, it can be part of the multichoice menu.
1101
+*/
1102
+void generate_branch_submenu_multichoice(
1103
+ const char* zName, /* Query parameter name */
1104
+ const char* zCI /* Current checkin */
1105
+){
1106
+ Stmt q;
1107
+ const int brFlags = BRL_ORDERBY_MTIME | BRL_OPEN_ONLY;
1108
+ static const char *zBranchMenuList[32*2]; /* 2 per entries */
1109
+ const int nLimit = count(zBranchMenuList)/2;
1110
+ int i = 0;
1111
+
1112
+ if( zName == 0 ) zName = "ci";
1113
+
1114
+ branch_prepare_list_query(&q, brFlags, 0, nLimit, 0);
1115
+ zBranchMenuList[i++] = "";
1116
+ zBranchMenuList[i++] = "All Checkins";
1117
+
1118
+ if( zCI ){
1119
+ zCI = fossil_strdup(zCI);
1120
+ zBranchMenuList[i++] = zCI;
1121
+ zBranchMenuList[i++] = zCI;
1122
+ }
1123
+ /* If current checkin is not "tip", add it to the list */
1124
+ if( zCI==0 || strcmp(zCI, "tip") ){
1125
+ zBranchMenuList[i++] = "tip";
1126
+ zBranchMenuList[i++] = "tip";
1127
+ }
1128
+ while( i/2 < nLimit && db_step(&q)==SQLITE_ROW ){
1129
+ const char* zBr = fossil_strdup(db_column_text(&q, 0));
1130
+ /* zCI is already in the list, don't add it twice */
1131
+ if( zCI==0 || strcmp(zBr, zCI) ){
1132
+ zBranchMenuList[i++] = zBr;
1133
+ zBranchMenuList[i++] = zBr;
1134
+ }
1135
+ }
1136
+ db_finalize(&q);
1137
+ style_submenu_multichoice(zName, i/2, zBranchMenuList, 0);
1138
+}
10951139
--- src/branch.c
+++ src/branch.c
@@ -1090,5 +1090,49 @@
1090 if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
1091 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, brtimeline_extra);
1092 db_finalize(&q);
1093 style_finish_page();
1094 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1095
--- src/branch.c
+++ src/branch.c
@@ -1090,5 +1090,49 @@
1090 if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
1091 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, brtimeline_extra);
1092 db_finalize(&q);
1093 style_finish_page();
1094 }
1095
1096 /*
1097 ** Generate a multichoice submenu for the few recent active branches. zName is
1098 ** the query parameter used to select the current checkin. zCI is optional and
1099 ** represent the currently selected checkin, so if it is a checkin hash
1100 ** instead of a branch, it can be part of the multichoice menu.
1101 */
1102 void generate_branch_submenu_multichoice(
1103 const char* zName, /* Query parameter name */
1104 const char* zCI /* Current checkin */
1105 ){
1106 Stmt q;
1107 const int brFlags = BRL_ORDERBY_MTIME | BRL_OPEN_ONLY;
1108 static const char *zBranchMenuList[32*2]; /* 2 per entries */
1109 const int nLimit = count(zBranchMenuList)/2;
1110 int i = 0;
1111
1112 if( zName == 0 ) zName = "ci";
1113
1114 branch_prepare_list_query(&q, brFlags, 0, nLimit, 0);
1115 zBranchMenuList[i++] = "";
1116 zBranchMenuList[i++] = "All Checkins";
1117
1118 if( zCI ){
1119 zCI = fossil_strdup(zCI);
1120 zBranchMenuList[i++] = zCI;
1121 zBranchMenuList[i++] = zCI;
1122 }
1123 /* If current checkin is not "tip", add it to the list */
1124 if( zCI==0 || strcmp(zCI, "tip") ){
1125 zBranchMenuList[i++] = "tip";
1126 zBranchMenuList[i++] = "tip";
1127 }
1128 while( i/2 < nLimit && db_step(&q)==SQLITE_ROW ){
1129 const char* zBr = fossil_strdup(db_column_text(&q, 0));
1130 /* zCI is already in the list, don't add it twice */
1131 if( zCI==0 || strcmp(zBr, zCI) ){
1132 zBranchMenuList[i++] = zBr;
1133 zBranchMenuList[i++] = zBr;
1134 }
1135 }
1136 db_finalize(&q);
1137 style_submenu_multichoice(zName, i/2, zBranchMenuList, 0);
1138 }
1139
+12 -26
--- src/browse.c
+++ src/browse.c
@@ -171,12 +171,10 @@
171171
const char *zCI = P("ci");
172172
int rid = 0;
173173
char *zUuid = 0;
174174
Manifest *pM = 0;
175175
const char *zSubdirLink;
176
- int linkTrunk = 1;
177
- int linkTip = 1;
178176
HQuery sURI;
179177
int isSymbolicCI = 0; /* ci= is symbolic name, not a hash prefix */
180178
int isBranchCI = 0; /* True if ci= refers to a branch name */
181179
char *zHeader = 0;
182180
const char *zRegexp; /* The re= query parameter */
@@ -198,13 +196,10 @@
198196
*/
199197
if( bDocDir && zCI==0 ) zCI = "trunk";
200198
if( zCI ){
201199
pM = manifest_get_by_name(zCI, &rid);
202200
if( pM ){
203
- int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
204
- linkTrunk = trunkRid && rid != trunkRid;
205
- linkTip = rid != symbolic_name_to_rid("tip", "ci");
206201
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
207202
isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
208203
isBranchCI = branch_includes_uuid(zCI, zUuid);
209204
if( bDocDir ) zCI = mprintf("%S", zUuid);
210205
Th_StoreUnsafe("current_checkin", zCI);
@@ -283,25 +278,22 @@
283278
}
284279
}else{
285280
@ in any check-in</h2>
286281
zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
287282
}
288
- if( linkTrunk && !bDocDir ){
289
- style_submenu_element("Trunk", "%s",
290
- url_render(&sURI, "ci", "trunk", 0, 0));
291
- }
292
- if( linkTip && !bDocDir ){
293
- style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
294
- }
295283
if( zD && !bDocDir ){
296284
style_submenu_element("History","%R/timeline?chng=%T/*", zD);
297285
}
298286
if( !bDocDir ){
299
- style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
300287
style_submenu_element("Tree-View", "%s",
301288
url_render(&sURI, "type", "tree", 0, 0));
302289
}
290
+
291
+ if( !bDocDir ){
292
+ /* Generate the Branch list submenu */
293
+ generate_branch_submenu_multichoice("ci", zCI);
294
+ }
303295
304296
/* Compute the temporary table "localfiles" containing the names
305297
** of all files and subdirectories in the zD[] directory.
306298
**
307299
** Subdirectory names begin with "/". This causes them to sort
@@ -705,12 +697,10 @@
705697
Manifest *pM = 0;
706698
double rNow = 0;
707699
char *zNow = 0;
708700
int useMtime = atoi(PD("mtime","0"));
709701
int sortOrder = atoi(PD("sort",useMtime?"1":"0"));
710
- int linkTrunk = 1; /* include link to "trunk" */
711
- int linkTip = 1; /* include link to "tip" */
712702
const char *zRE; /* the value for the re=REGEXP query parameter */
713703
const char *zObjType; /* "files" by default or "folders" for "nofiles" */
714704
char *zREx = ""; /* Extra parameters for path hyperlinks */
715705
ReCompiled *pRE = 0; /* Compiled regular expression */
716706
FileTreeNode *p; /* One line of the tree */
@@ -762,13 +752,10 @@
762752
** files from all check-ins to be displayed.
763753
*/
764754
if( zCI ){
765755
pM = manifest_get_by_name(zCI, &rid);
766756
if( pM ){
767
- int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
768
- linkTrunk = trunkRid && rid != trunkRid;
769
- linkTip = rid != symbolic_name_to_rid("tip", "ci");
770757
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
771758
rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
772759
zNow = db_text("", "SELECT datetime(mtime,toLocal())"
773760
" FROM event WHERE objid=%d", rid);
774761
isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
@@ -781,10 +768,13 @@
781768
if( zCI==0 ){
782769
rNow = db_double(0.0, "SELECT max(mtime) FROM event");
783770
zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
784771
}
785772
773
+ /* Generate the Branch list submenu */
774
+ generate_branch_submenu_multichoice("ci", zCI);
775
+
786776
assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
787777
if( zD==0 ){
788778
if( zCI ){
789779
zHeader = mprintf("Top-level Files of %s", zCI);
790780
}else{
@@ -818,22 +808,14 @@
818808
"2", "Sort By Size"
819809
};
820810
style_submenu_multichoice("sort", 3, sort_orders, 0);
821811
}
822812
if( zCI ){
823
- style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
824813
if( nD==0 && !showDirOnly ){
825814
style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
826815
}
827816
}
828
- if( linkTrunk ){
829
- style_submenu_element("Trunk", "%s",
830
- url_render(&sURI, "ci", "trunk", 0, 0));
831
- }
832
- if( linkTip ){
833
- style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
834
- }
835817
style_submenu_element("Flat-View", "%s",
836818
url_render(&sURI, "type", "flat", 0, 0));
837819
838820
/* Compute the file hierarchy.
839821
*/
@@ -1176,10 +1158,14 @@
11761158
isBranchCI = branch_includes_uuid(zName,zUuid);
11771159
baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
11781160
zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
11791161
" WHERE objid=%d", rid);
11801162
style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
1163
+
1164
+ /* Generate the Branch list submenu */
1165
+ generate_branch_submenu_multichoice("name", zName);
1166
+
11811167
style_header("File Ages");
11821168
zGlob = P("glob");
11831169
cgi_check_for_malice();
11841170
compute_fileage(rid,zGlob);
11851171
db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
11861172
--- src/browse.c
+++ src/browse.c
@@ -171,12 +171,10 @@
171 const char *zCI = P("ci");
172 int rid = 0;
173 char *zUuid = 0;
174 Manifest *pM = 0;
175 const char *zSubdirLink;
176 int linkTrunk = 1;
177 int linkTip = 1;
178 HQuery sURI;
179 int isSymbolicCI = 0; /* ci= is symbolic name, not a hash prefix */
180 int isBranchCI = 0; /* True if ci= refers to a branch name */
181 char *zHeader = 0;
182 const char *zRegexp; /* The re= query parameter */
@@ -198,13 +196,10 @@
198 */
199 if( bDocDir && zCI==0 ) zCI = "trunk";
200 if( zCI ){
201 pM = manifest_get_by_name(zCI, &rid);
202 if( pM ){
203 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
204 linkTrunk = trunkRid && rid != trunkRid;
205 linkTip = rid != symbolic_name_to_rid("tip", "ci");
206 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
207 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
208 isBranchCI = branch_includes_uuid(zCI, zUuid);
209 if( bDocDir ) zCI = mprintf("%S", zUuid);
210 Th_StoreUnsafe("current_checkin", zCI);
@@ -283,25 +278,22 @@
283 }
284 }else{
285 @ in any check-in</h2>
286 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
287 }
288 if( linkTrunk && !bDocDir ){
289 style_submenu_element("Trunk", "%s",
290 url_render(&sURI, "ci", "trunk", 0, 0));
291 }
292 if( linkTip && !bDocDir ){
293 style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
294 }
295 if( zD && !bDocDir ){
296 style_submenu_element("History","%R/timeline?chng=%T/*", zD);
297 }
298 if( !bDocDir ){
299 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
300 style_submenu_element("Tree-View", "%s",
301 url_render(&sURI, "type", "tree", 0, 0));
302 }
 
 
 
 
 
303
304 /* Compute the temporary table "localfiles" containing the names
305 ** of all files and subdirectories in the zD[] directory.
306 **
307 ** Subdirectory names begin with "/". This causes them to sort
@@ -705,12 +697,10 @@
705 Manifest *pM = 0;
706 double rNow = 0;
707 char *zNow = 0;
708 int useMtime = atoi(PD("mtime","0"));
709 int sortOrder = atoi(PD("sort",useMtime?"1":"0"));
710 int linkTrunk = 1; /* include link to "trunk" */
711 int linkTip = 1; /* include link to "tip" */
712 const char *zRE; /* the value for the re=REGEXP query parameter */
713 const char *zObjType; /* "files" by default or "folders" for "nofiles" */
714 char *zREx = ""; /* Extra parameters for path hyperlinks */
715 ReCompiled *pRE = 0; /* Compiled regular expression */
716 FileTreeNode *p; /* One line of the tree */
@@ -762,13 +752,10 @@
762 ** files from all check-ins to be displayed.
763 */
764 if( zCI ){
765 pM = manifest_get_by_name(zCI, &rid);
766 if( pM ){
767 int trunkRid = symbolic_name_to_rid("tag:trunk", "ci");
768 linkTrunk = trunkRid && rid != trunkRid;
769 linkTip = rid != symbolic_name_to_rid("tip", "ci");
770 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
771 rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
772 zNow = db_text("", "SELECT datetime(mtime,toLocal())"
773 " FROM event WHERE objid=%d", rid);
774 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
@@ -781,10 +768,13 @@
781 if( zCI==0 ){
782 rNow = db_double(0.0, "SELECT max(mtime) FROM event");
783 zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
784 }
785
 
 
 
786 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
787 if( zD==0 ){
788 if( zCI ){
789 zHeader = mprintf("Top-level Files of %s", zCI);
790 }else{
@@ -818,22 +808,14 @@
818 "2", "Sort By Size"
819 };
820 style_submenu_multichoice("sort", 3, sort_orders, 0);
821 }
822 if( zCI ){
823 style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0));
824 if( nD==0 && !showDirOnly ){
825 style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
826 }
827 }
828 if( linkTrunk ){
829 style_submenu_element("Trunk", "%s",
830 url_render(&sURI, "ci", "trunk", 0, 0));
831 }
832 if( linkTip ){
833 style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0));
834 }
835 style_submenu_element("Flat-View", "%s",
836 url_render(&sURI, "type", "flat", 0, 0));
837
838 /* Compute the file hierarchy.
839 */
@@ -1176,10 +1158,14 @@
1176 isBranchCI = branch_includes_uuid(zName,zUuid);
1177 baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1178 zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
1179 " WHERE objid=%d", rid);
1180 style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
 
 
 
 
1181 style_header("File Ages");
1182 zGlob = P("glob");
1183 cgi_check_for_malice();
1184 compute_fileage(rid,zGlob);
1185 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1186
--- src/browse.c
+++ src/browse.c
@@ -171,12 +171,10 @@
171 const char *zCI = P("ci");
172 int rid = 0;
173 char *zUuid = 0;
174 Manifest *pM = 0;
175 const char *zSubdirLink;
 
 
176 HQuery sURI;
177 int isSymbolicCI = 0; /* ci= is symbolic name, not a hash prefix */
178 int isBranchCI = 0; /* True if ci= refers to a branch name */
179 char *zHeader = 0;
180 const char *zRegexp; /* The re= query parameter */
@@ -198,13 +196,10 @@
196 */
197 if( bDocDir && zCI==0 ) zCI = "trunk";
198 if( zCI ){
199 pM = manifest_get_by_name(zCI, &rid);
200 if( pM ){
 
 
 
201 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
202 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI))!=0);
203 isBranchCI = branch_includes_uuid(zCI, zUuid);
204 if( bDocDir ) zCI = mprintf("%S", zUuid);
205 Th_StoreUnsafe("current_checkin", zCI);
@@ -283,25 +278,22 @@
278 }
279 }else{
280 @ in any check-in</h2>
281 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
282 }
 
 
 
 
 
 
 
283 if( zD && !bDocDir ){
284 style_submenu_element("History","%R/timeline?chng=%T/*", zD);
285 }
286 if( !bDocDir ){
 
287 style_submenu_element("Tree-View", "%s",
288 url_render(&sURI, "type", "tree", 0, 0));
289 }
290
291 if( !bDocDir ){
292 /* Generate the Branch list submenu */
293 generate_branch_submenu_multichoice("ci", zCI);
294 }
295
296 /* Compute the temporary table "localfiles" containing the names
297 ** of all files and subdirectories in the zD[] directory.
298 **
299 ** Subdirectory names begin with "/". This causes them to sort
@@ -705,12 +697,10 @@
697 Manifest *pM = 0;
698 double rNow = 0;
699 char *zNow = 0;
700 int useMtime = atoi(PD("mtime","0"));
701 int sortOrder = atoi(PD("sort",useMtime?"1":"0"));
 
 
702 const char *zRE; /* the value for the re=REGEXP query parameter */
703 const char *zObjType; /* "files" by default or "folders" for "nofiles" */
704 char *zREx = ""; /* Extra parameters for path hyperlinks */
705 ReCompiled *pRE = 0; /* Compiled regular expression */
706 FileTreeNode *p; /* One line of the tree */
@@ -762,13 +752,10 @@
752 ** files from all check-ins to be displayed.
753 */
754 if( zCI ){
755 pM = manifest_get_by_name(zCI, &rid);
756 if( pM ){
 
 
 
757 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
758 rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
759 zNow = db_text("", "SELECT datetime(mtime,toLocal())"
760 " FROM event WHERE objid=%d", rid);
761 isSymbolicCI = (sqlite3_strnicmp(zUuid, zCI, strlen(zCI)) != 0);
@@ -781,10 +768,13 @@
768 if( zCI==0 ){
769 rNow = db_double(0.0, "SELECT max(mtime) FROM event");
770 zNow = db_text("", "SELECT datetime(max(mtime),toLocal()) FROM event");
771 }
772
773 /* Generate the Branch list submenu */
774 generate_branch_submenu_multichoice("ci", zCI);
775
776 assert( isSymbolicCI==0 || (zCI!=0 && zCI[0]!=0) );
777 if( zD==0 ){
778 if( zCI ){
779 zHeader = mprintf("Top-level Files of %s", zCI);
780 }else{
@@ -818,22 +808,14 @@
808 "2", "Sort By Size"
809 };
810 style_submenu_multichoice("sort", 3, sort_orders, 0);
811 }
812 if( zCI ){
 
813 if( nD==0 && !showDirOnly ){
814 style_submenu_element("File Ages", "%R/fileage?name=%T", zCI);
815 }
816 }
 
 
 
 
 
 
 
817 style_submenu_element("Flat-View", "%s",
818 url_render(&sURI, "type", "flat", 0, 0));
819
820 /* Compute the file hierarchy.
821 */
@@ -1176,10 +1158,14 @@
1158 isBranchCI = branch_includes_uuid(zName,zUuid);
1159 baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
1160 zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
1161 " WHERE objid=%d", rid);
1162 style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName);
1163
1164 /* Generate the Branch list submenu */
1165 generate_branch_submenu_multichoice("name", zName);
1166
1167 style_header("File Ages");
1168 zGlob = P("glob");
1169 cgi_check_for_malice();
1170 compute_fileage(rid,zGlob);
1171 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1172

Keyboard Shortcuts

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