Fossil SCM

Improvements to /vdiff. Provide the branch= query parameter. In the name decoder, all "merge-in:BRANCH" to mean the most recent merge-in to BRANCH from its parent. Provide "Diff" links for branches that show all changes since the most recent merge-in.

drh 2019-09-03 20:17 trunk merge
Commit e632a092a8e82bf58e3f4e3c8afe9fd5957bc5a681d9e312430675c74c94529c
--- skins/ardoise/css.txt
+++ skins/ardoise/css.txt
@@ -947,10 +947,38 @@
947947
border-radius: 5px;
948948
border: solid #ff8000;
949949
vertical-align: top;
950950
text-align: left;
951951
background: #442800
952
+}
953
+span.timelineSelected {
954
+ border-radius: 5px;
955
+ border: solid #ff8000;
956
+ vertical-align: top;
957
+ text-align: left;
958
+ background: #442800
959
+}
960
+.timelineSelected {}
961
+.timelineSecondary {}
962
+.timelineSecondary > .timelineColumnarCell,
963
+.timelineSecondary > .timelineCompactCell,
964
+.timelineSecondary > .timelineDetailCell,
965
+.timelineSecondary > .timelineModernCell,
966
+.timelineSecondary > .timelineVerboseCell {
967
+ padding: .75em;
968
+ border-radius: 5px;
969
+ border: solid #0080ff;
970
+ vertical-align: top;
971
+ text-align: left;
972
+ background: #002844
973
+}
974
+span.timelineSecondary {
975
+ border-radius: 5px;
976
+ border: solid #0080ff;
977
+ vertical-align: top;
978
+ text-align: left;
979
+ background: #002844
952980
}
953981
.timelineCurrent > .timelineColumnarCell,
954982
.timelineCurrent > .timelineCompactCell,
955983
.timelineCurrent > .timelineDetailCell,
956984
.timelineCurrent > .timelineModernCell,
957985
--- skins/ardoise/css.txt
+++ skins/ardoise/css.txt
@@ -947,10 +947,38 @@
947 border-radius: 5px;
948 border: solid #ff8000;
949 vertical-align: top;
950 text-align: left;
951 background: #442800
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
952 }
953 .timelineCurrent > .timelineColumnarCell,
954 .timelineCurrent > .timelineCompactCell,
955 .timelineCurrent > .timelineDetailCell,
956 .timelineCurrent > .timelineModernCell,
957
--- skins/ardoise/css.txt
+++ skins/ardoise/css.txt
@@ -947,10 +947,38 @@
947 border-radius: 5px;
948 border: solid #ff8000;
949 vertical-align: top;
950 text-align: left;
951 background: #442800
952 }
953 span.timelineSelected {
954 border-radius: 5px;
955 border: solid #ff8000;
956 vertical-align: top;
957 text-align: left;
958 background: #442800
959 }
960 .timelineSelected {}
961 .timelineSecondary {}
962 .timelineSecondary > .timelineColumnarCell,
963 .timelineSecondary > .timelineCompactCell,
964 .timelineSecondary > .timelineDetailCell,
965 .timelineSecondary > .timelineModernCell,
966 .timelineSecondary > .timelineVerboseCell {
967 padding: .75em;
968 border-radius: 5px;
969 border: solid #0080ff;
970 vertical-align: top;
971 text-align: left;
972 background: #002844
973 }
974 span.timelineSecondary {
975 border-radius: 5px;
976 border: solid #0080ff;
977 vertical-align: top;
978 text-align: left;
979 background: #002844
980 }
981 .timelineCurrent > .timelineColumnarCell,
982 .timelineCurrent > .timelineCompactCell,
983 .timelineCurrent > .timelineDetailCell,
984 .timelineCurrent > .timelineModernCell,
985
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -1060,16 +1060,19 @@
10601060
background-color: #ffc;
10611061
border-bottom: 1px solid #ddd;
10621062
border-right: 1px solid #ddd;
10631063
}
10641064
1065
-tr.timelineSelected {
1065
+.timelineSelected {
10661066
border-left: 2px solid orange;
10671067
background-color: #ffffe8;
10681068
border-bottom: 1px solid #ddd;
10691069
border-right: 1px solid #ddd;
10701070
}
1071
+.timelineSecondary {
1072
+ background-color: #e8ffff;
1073
+}
10711074
10721075
tr.timelineCurrent td.timelineTableCell {
10731076
}
10741077
10751078
tr.timelineBottom td {
10761079
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -1060,16 +1060,19 @@
1060 background-color: #ffc;
1061 border-bottom: 1px solid #ddd;
1062 border-right: 1px solid #ddd;
1063 }
1064
1065 tr.timelineSelected {
1066 border-left: 2px solid orange;
1067 background-color: #ffffe8;
1068 border-bottom: 1px solid #ddd;
1069 border-right: 1px solid #ddd;
1070 }
 
 
 
1071
1072 tr.timelineCurrent td.timelineTableCell {
1073 }
1074
1075 tr.timelineBottom td {
1076
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -1060,16 +1060,19 @@
1060 background-color: #ffc;
1061 border-bottom: 1px solid #ddd;
1062 border-right: 1px solid #ddd;
1063 }
1064
1065 .timelineSelected {
1066 border-left: 2px solid orange;
1067 background-color: #ffffe8;
1068 border-bottom: 1px solid #ddd;
1069 border-right: 1px solid #ddd;
1070 }
1071 .timelineSecondary {
1072 background-color: #e8ffff;
1073 }
1074
1075 tr.timelineCurrent td.timelineTableCell {
1076 }
1077
1078 tr.timelineBottom td {
1079
--- skins/eagle/css.txt
+++ skins/eagle/css.txt
@@ -168,13 +168,16 @@
168168
font-family: "courier new";
169169
border-spacing: 0px 2px;
170170
// border-collapse: collapse;
171171
}
172172
173
-tr.timelineSelected {
173
+.timelineSelected {
174174
background-color: #7EA2D9;
175175
}
176
+.timelineSecondary {
177
+ background-color: #7EA27E;
178
+}
176179
177180
/* commit node */
178181
.tl-node {
179182
width: 10px;
180183
height: 10px;
181184
--- skins/eagle/css.txt
+++ skins/eagle/css.txt
@@ -168,13 +168,16 @@
168 font-family: "courier new";
169 border-spacing: 0px 2px;
170 // border-collapse: collapse;
171 }
172
173 tr.timelineSelected {
174 background-color: #7EA2D9;
175 }
 
 
 
176
177 /* commit node */
178 .tl-node {
179 width: 10px;
180 height: 10px;
181
--- skins/eagle/css.txt
+++ skins/eagle/css.txt
@@ -168,13 +168,16 @@
168 font-family: "courier new";
169 border-spacing: 0px 2px;
170 // border-collapse: collapse;
171 }
172
173 .timelineSelected {
174 background-color: #7EA2D9;
175 }
176 .timelineSecondary {
177 background-color: #7EA27E;
178 }
179
180 /* commit node */
181 .tl-node {
182 width: 10px;
183 height: 10px;
184
--- skins/xekri/css.txt
+++ skins/xekri/css.txt
@@ -803,10 +803,12 @@
803803
.timelineTable .timelineSelected {
804804
background: #222;
805805
border: 0;
806806
box-shadow: none;
807807
}
808
+.timelineSelected {}
809
+.timelineSecondary {}
808810
809811
.timelineTable .timelineSelected .timelineTime {
810812
background: #333;
811813
border-radius: 1rem 0 0 1rem;
812814
box-shadow: 2px 2px 1px #000;
@@ -823,10 +825,17 @@
823825
.timelineTable .timelineSelected .timelineDetailCell {
824826
background: #333;
825827
border-radius: 0 1rem 1rem 0;
826828
box-shadow: 2px 2px 1px #000;
827829
}
830
+
831
+span.timelineSelected {
832
+ padding: 0 1em 0 1em;
833
+ border-radius: 1rem;
834
+ background: #333;
835
+ box-shadow: 2px 2px 1px #000;
836
+}
828837
829838
.timelineTable .timelineModernCell .timelineModernComment ,
830839
.timelineTable .timelineModernCell .timelineModernDetail ,
831840
.timelineTable .timelineCompactCell .timelineCompactComment ,
832841
.timelineTable .timelineCompactCell .timelineCompactDetail ,
833842
--- skins/xekri/css.txt
+++ skins/xekri/css.txt
@@ -803,10 +803,12 @@
803 .timelineTable .timelineSelected {
804 background: #222;
805 border: 0;
806 box-shadow: none;
807 }
 
 
808
809 .timelineTable .timelineSelected .timelineTime {
810 background: #333;
811 border-radius: 1rem 0 0 1rem;
812 box-shadow: 2px 2px 1px #000;
@@ -823,10 +825,17 @@
823 .timelineTable .timelineSelected .timelineDetailCell {
824 background: #333;
825 border-radius: 0 1rem 1rem 0;
826 box-shadow: 2px 2px 1px #000;
827 }
 
 
 
 
 
 
 
828
829 .timelineTable .timelineModernCell .timelineModernComment ,
830 .timelineTable .timelineModernCell .timelineModernDetail ,
831 .timelineTable .timelineCompactCell .timelineCompactComment ,
832 .timelineTable .timelineCompactCell .timelineCompactDetail ,
833
--- skins/xekri/css.txt
+++ skins/xekri/css.txt
@@ -803,10 +803,12 @@
803 .timelineTable .timelineSelected {
804 background: #222;
805 border: 0;
806 box-shadow: none;
807 }
808 .timelineSelected {}
809 .timelineSecondary {}
810
811 .timelineTable .timelineSelected .timelineTime {
812 background: #333;
813 border-radius: 1rem 0 0 1rem;
814 box-shadow: 2px 2px 1px #000;
@@ -823,10 +825,17 @@
825 .timelineTable .timelineSelected .timelineDetailCell {
826 background: #333;
827 border-radius: 0 1rem 1rem 0;
828 box-shadow: 2px 2px 1px #000;
829 }
830
831 span.timelineSelected {
832 padding: 0 1em 0 1em;
833 border-radius: 1rem;
834 background: #333;
835 box-shadow: 2px 2px 1px #000;
836 }
837
838 .timelineTable .timelineModernCell .timelineModernComment ,
839 .timelineTable .timelineModernCell .timelineModernDetail ,
840 .timelineTable .timelineCompactCell .timelineCompactComment ,
841 .timelineTable .timelineCompactCell .timelineCompactDetail ,
842
+28 -1
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,37 @@
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
+** If RID refers to a check-in, return the name of the branch for that
26
+** check-in.
27
+**
28
+** Space to hold the returned value is obtained from fossil_malloc()
29
+** and should be freed by the caller.
30
+*/
31
+char *branch_of_rid(int rid){
32
+ char *zBr = 0;
33
+ static Stmt q;
34
+ db_static_prepare(&q,
35
+ "SELECT value FROM tagxref"
36
+ " WHERE rid=$rid AND tagid=%d"
37
+ " AND tagtype>0", TAG_BRANCH);
38
+ db_bind_int(&q, "$rid", rid);
39
+ if( db_step(&q)==SQLITE_ROW ){
40
+ zBr = fossil_strdup(db_column_text(&q,0));
41
+ }
42
+ db_reset(&q);
43
+ if( zBr==0 ){
44
+ static char *zMain = 0;
45
+ if( zMain==0 ) zMain = db_get("main-branch","trunk");
46
+ zBr = fossil_strdup(zMain);
47
+ }
48
+ return zBr;
49
+}
2350
2451
/*
2552
** fossil branch new NAME BASIS ?OPTIONS?
2653
** argv0 argv1 argv2 argv3 argv4
2754
*/
@@ -661,9 +688,9 @@
661688
** many descenders to (off-screen) parents. */
662689
tmFlags = TIMELINE_DISJOINT | TIMELINE_NOSCROLL;
663690
if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH;
664691
if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
665692
if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
666
- www_print_timeline(&q, tmFlags, 0, 0, 0, 0, brtimeline_extra);
693
+ www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, brtimeline_extra);
667694
db_finalize(&q);
668695
style_footer();
669696
}
670697
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,37 @@
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 ** fossil branch new NAME BASIS ?OPTIONS?
26 ** argv0 argv1 argv2 argv3 argv4
27 */
@@ -661,9 +688,9 @@
661 ** many descenders to (off-screen) parents. */
662 tmFlags = TIMELINE_DISJOINT | TIMELINE_NOSCROLL;
663 if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH;
664 if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
665 if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
666 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, brtimeline_extra);
667 db_finalize(&q);
668 style_footer();
669 }
670
--- src/branch.c
+++ src/branch.c
@@ -18,10 +18,37 @@
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 ** Space to hold the returned value is obtained from fossil_malloc()
29 ** and should be freed by the caller.
30 */
31 char *branch_of_rid(int rid){
32 char *zBr = 0;
33 static Stmt q;
34 db_static_prepare(&q,
35 "SELECT value FROM tagxref"
36 " WHERE rid=$rid AND tagid=%d"
37 " AND tagtype>0", TAG_BRANCH);
38 db_bind_int(&q, "$rid", rid);
39 if( db_step(&q)==SQLITE_ROW ){
40 zBr = fossil_strdup(db_column_text(&q,0));
41 }
42 db_reset(&q);
43 if( zBr==0 ){
44 static char *zMain = 0;
45 if( zMain==0 ) zMain = db_get("main-branch","trunk");
46 zBr = fossil_strdup(zMain);
47 }
48 return zBr;
49 }
50
51 /*
52 ** fossil branch new NAME BASIS ?OPTIONS?
53 ** argv0 argv1 argv2 argv3 argv4
54 */
@@ -661,9 +688,9 @@
688 ** many descenders to (off-screen) parents. */
689 tmFlags = TIMELINE_DISJOINT | TIMELINE_NOSCROLL;
690 if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH;
691 if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
692 if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
693 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, brtimeline_extra);
694 db_finalize(&q);
695 style_footer();
696 }
697
--- src/default_css.txt
+++ src/default_css.txt
@@ -38,16 +38,19 @@
3838
tr.timelineCurrent {
3939
padding: .1em .2em;
4040
border: 1px dashed #446979;
4141
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5);
4242
}
43
-tr.timelineSelected {
43
+.timelineSelected {
4444
padding: .1em .2em;
4545
border: 2px solid lightgray;
4646
background-color: #ffc;
4747
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5);
4848
}
49
+.timelineSecondary {
50
+ background-color: #cff;
51
+}
4952
tr.timelineSelected td {
5053
border-radius: 0;
5154
border-width: 0;
5255
}
5356
tr.timelineCurrent td {
5457
--- src/default_css.txt
+++ src/default_css.txt
@@ -38,16 +38,19 @@
38 tr.timelineCurrent {
39 padding: .1em .2em;
40 border: 1px dashed #446979;
41 box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5);
42 }
43 tr.timelineSelected {
44 padding: .1em .2em;
45 border: 2px solid lightgray;
46 background-color: #ffc;
47 box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5);
48 }
 
 
 
49 tr.timelineSelected td {
50 border-radius: 0;
51 border-width: 0;
52 }
53 tr.timelineCurrent td {
54
--- src/default_css.txt
+++ src/default_css.txt
@@ -38,16 +38,19 @@
38 tr.timelineCurrent {
39 padding: .1em .2em;
40 border: 1px dashed #446979;
41 box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5);
42 }
43 .timelineSelected {
44 padding: .1em .2em;
45 border: 2px solid lightgray;
46 background-color: #ffc;
47 box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5);
48 }
49 .timelineSecondary {
50 background-color: #cff;
51 }
52 tr.timelineSelected td {
53 border-radius: 0;
54 border-width: 0;
55 }
56 tr.timelineCurrent td {
57
--- src/descendants.c
+++ src/descendants.c
@@ -183,10 +183,35 @@
183183
"INSERT INTO ok"
184184
" SELECT rid FROM ancestor;",
185185
rid, rid, directOnly ? "AND plink.isPrim" : "", N
186186
);
187187
}
188
+
189
+/*
190
+** Compute the youngest ancestor of record ID rid that is a member of
191
+** branch zBranch.
192
+*/
193
+int compute_youngest_ancestor_in_branch(int rid, const char *zBranch){
194
+ return db_int(0,
195
+ "WITH RECURSIVE "
196
+ " ancestor(rid, mtime) AS ("
197
+ " SELECT %d, mtime FROM event WHERE objid=%d "
198
+ " UNION "
199
+ " SELECT plink.pid, event.mtime"
200
+ " FROM ancestor, plink, event"
201
+ " WHERE plink.cid=ancestor.rid"
202
+ " AND event.objid=plink.pid"
203
+ " ORDER BY mtime DESC"
204
+ " )"
205
+ " SELECT ancestor.rid FROM ancestor"
206
+ " WHERE EXISTS(SELECT 1 FROM tagxref"
207
+ " WHERE tagid=%d AND tagxref.rid=ancestor.rid"
208
+ " AND value=%Q AND tagtype>0)"
209
+ " LIMIT 1",
210
+ rid, rid, TAG_BRANCH, zBranch
211
+ );
212
+}
188213
189214
/*
190215
** Compute all direct ancestors (merge ancestors do not count)
191216
** for the check-in rid and put them in a table named "ancestor".
192217
** Label each generation with consecutive integers going backwards
@@ -540,11 +565,11 @@
540565
** many descenders to (off-screen) parents. */
541566
tmFlags = TIMELINE_LEAFONLY | TIMELINE_DISJOINT | TIMELINE_NOSCROLL;
542567
if( fNg==0 ) tmFlags |= TIMELINE_GRAPH;
543568
if( fBrBg ) tmFlags |= TIMELINE_BRCOLOR;
544569
if( fUBg ) tmFlags |= TIMELINE_UCOLOR;
545
- www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0);
570
+ www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0);
546571
db_finalize(&q);
547572
@ <br />
548573
style_footer();
549574
}
550575
551576
--- src/descendants.c
+++ src/descendants.c
@@ -183,10 +183,35 @@
183 "INSERT INTO ok"
184 " SELECT rid FROM ancestor;",
185 rid, rid, directOnly ? "AND plink.isPrim" : "", N
186 );
187 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
189 /*
190 ** Compute all direct ancestors (merge ancestors do not count)
191 ** for the check-in rid and put them in a table named "ancestor".
192 ** Label each generation with consecutive integers going backwards
@@ -540,11 +565,11 @@
540 ** many descenders to (off-screen) parents. */
541 tmFlags = TIMELINE_LEAFONLY | TIMELINE_DISJOINT | TIMELINE_NOSCROLL;
542 if( fNg==0 ) tmFlags |= TIMELINE_GRAPH;
543 if( fBrBg ) tmFlags |= TIMELINE_BRCOLOR;
544 if( fUBg ) tmFlags |= TIMELINE_UCOLOR;
545 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0);
546 db_finalize(&q);
547 @ <br />
548 style_footer();
549 }
550
551
--- src/descendants.c
+++ src/descendants.c
@@ -183,10 +183,35 @@
183 "INSERT INTO ok"
184 " SELECT rid FROM ancestor;",
185 rid, rid, directOnly ? "AND plink.isPrim" : "", N
186 );
187 }
188
189 /*
190 ** Compute the youngest ancestor of record ID rid that is a member of
191 ** branch zBranch.
192 */
193 int compute_youngest_ancestor_in_branch(int rid, const char *zBranch){
194 return db_int(0,
195 "WITH RECURSIVE "
196 " ancestor(rid, mtime) AS ("
197 " SELECT %d, mtime FROM event WHERE objid=%d "
198 " UNION "
199 " SELECT plink.pid, event.mtime"
200 " FROM ancestor, plink, event"
201 " WHERE plink.cid=ancestor.rid"
202 " AND event.objid=plink.pid"
203 " ORDER BY mtime DESC"
204 " )"
205 " SELECT ancestor.rid FROM ancestor"
206 " WHERE EXISTS(SELECT 1 FROM tagxref"
207 " WHERE tagid=%d AND tagxref.rid=ancestor.rid"
208 " AND value=%Q AND tagtype>0)"
209 " LIMIT 1",
210 rid, rid, TAG_BRANCH, zBranch
211 );
212 }
213
214 /*
215 ** Compute all direct ancestors (merge ancestors do not count)
216 ** for the check-in rid and put them in a table named "ancestor".
217 ** Label each generation with consecutive integers going backwards
@@ -540,11 +565,11 @@
565 ** many descenders to (off-screen) parents. */
566 tmFlags = TIMELINE_LEAFONLY | TIMELINE_DISJOINT | TIMELINE_NOSCROLL;
567 if( fNg==0 ) tmFlags |= TIMELINE_GRAPH;
568 if( fBrBg ) tmFlags |= TIMELINE_BRCOLOR;
569 if( fUBg ) tmFlags |= TIMELINE_UCOLOR;
570 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0);
571 db_finalize(&q);
572 @ <br />
573 style_footer();
574 }
575
576
+1 -1
--- src/finfo.c
+++ src/finfo.c
@@ -780,11 +780,11 @@
780780
/* 7 */ " isaux"
781781
" FROM mlink WHERE mid=%d ORDER BY 1",
782782
mid
783783
);
784784
@ <h1>MLINK table for check-in %h(zCI)</h1>
785
- render_checkin_context(mid, 1);
785
+ render_checkin_context(mid, 0, 1);
786786
style_table_sorter();
787787
@ <hr />
788788
@ <div class='brlist'>
789789
@ <table class='sortable' data-column-types='ttxtttt' data-init-sort='1'>
790790
@ <thead><tr>
791791
--- src/finfo.c
+++ src/finfo.c
@@ -780,11 +780,11 @@
780 /* 7 */ " isaux"
781 " FROM mlink WHERE mid=%d ORDER BY 1",
782 mid
783 );
784 @ <h1>MLINK table for check-in %h(zCI)</h1>
785 render_checkin_context(mid, 1);
786 style_table_sorter();
787 @ <hr />
788 @ <div class='brlist'>
789 @ <table class='sortable' data-column-types='ttxtttt' data-init-sort='1'>
790 @ <thead><tr>
791
--- src/finfo.c
+++ src/finfo.c
@@ -780,11 +780,11 @@
780 /* 7 */ " isaux"
781 " FROM mlink WHERE mid=%d ORDER BY 1",
782 mid
783 );
784 @ <h1>MLINK table for check-in %h(zCI)</h1>
785 render_checkin_context(mid, 0, 1);
786 style_table_sorter();
787 @ <hr />
788 @ <div class='brlist'>
789 @ <table class='sortable' data-column-types='ttxtttt' data-init-sort='1'>
790 @ <thead><tr>
791
+99 -49
--- src/info.c
+++ src/info.c
@@ -252,34 +252,46 @@
252252
253253
/*
254254
** Show the context graph (immediate parents and children) for
255255
** check-in rid.
256256
*/
257
-void render_checkin_context(int rid, int parentsOnly){
257
+void render_checkin_context(int rid, int rid2, int parentsOnly){
258258
Blob sql;
259259
Stmt q;
260
+ int rx[2];
261
+ int i, n;
262
+ rx[0] = rid;
263
+ rx[1] = rid2;
264
+ n = rid2 ? 2 : 1;
260265
blob_zero(&sql);
261266
blob_append(&sql, timeline_query_for_www(), -1);
262
- db_multi_exec(
263
- "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
264
- "DELETE FROM ok;"
265
- "INSERT INTO ok VALUES(%d);"
266
- "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;",
267
- rid, rid
268
- );
269
- if( !parentsOnly ){
270
- db_multi_exec(
271
- "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rid
272
- );
273
- if( db_table_exists("repository","cherrypick") ){
274
- db_multi_exec(
275
- "INSERT OR IGNORE INTO ok "
276
- " SELECT parentid FROM cherrypick WHERE childid=%d;"
277
- "INSERT OR IGNORE INTO ok "
278
- " SELECT childid FROM cherrypick WHERE parentid=%d;",
279
- rid, rid
280
- );
267
+
268
+ db_multi_exec(
269
+ "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
270
+ "DELETE FROM ok;"
271
+ );
272
+ for(i=0; i<n; i++){
273
+ db_multi_exec(
274
+ "INSERT OR IGNORE INTO ok VALUES(%d);"
275
+ "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;",
276
+ rx[i], rx[i]
277
+ );
278
+ }
279
+ if( !parentsOnly ){
280
+ for(i=0; i<n; i++){
281
+ db_multi_exec(
282
+ "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rx[i]
283
+ );
284
+ if( db_table_exists("repository","cherrypick") ){
285
+ db_multi_exec(
286
+ "INSERT OR IGNORE INTO ok "
287
+ " SELECT parentid FROM cherrypick WHERE childid=%d;"
288
+ "INSERT OR IGNORE INTO ok "
289
+ " SELECT childid FROM cherrypick WHERE parentid=%d;",
290
+ rx[i], rx[i]
291
+ );
292
+ }
281293
}
282294
}
283295
blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
284296
db_prepare(&q, "%s", blob_sql_text(&sql));
285297
www_print_timeline(&q,
@@ -286,11 +298,11 @@
286298
TIMELINE_GRAPH
287299
|TIMELINE_FILLGAPS
288300
|TIMELINE_NOSCROLL
289301
|TIMELINE_XMERGE
290302
|TIMELINE_CHPICK,
291
- 0, 0, 0, rid, 0);
303
+ 0, 0, 0, rid, rid2, 0);
292304
db_finalize(&q);
293305
}
294306
295307
/*
296308
** Show a graph all wiki, tickets, and check-ins that refer to object zUuid.
@@ -317,11 +329,11 @@
317329
blob_zero(&sql);
318330
blob_append(&sql, timeline_query_for_www(), -1);
319331
blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
320332
db_prepare(&q, "%s", blob_sql_text(&sql));
321333
www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL,
322
- 0, 0, 0, 0, 0);
334
+ 0, 0, 0, 0, 0, 0);
323335
db_finalize(&q);
324336
}
325337
326338
/*
327339
** WEBPAGE: test-backlinks
@@ -350,11 +362,11 @@
350362
blob_zero(&sql);
351363
blob_append(&sql, timeline_query_for_www(), -1);
352364
blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
353365
db_prepare(&q, "%s", blob_sql_text(&sql));
354366
www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL,
355
- 0, 0, 0, 0, 0);
367
+ 0, 0, 0, 0, 0, 0);
356368
db_finalize(&q);
357369
style_footer();
358370
}
359371
360372
@@ -605,25 +617,27 @@
605617
" SELECT tagxref.origid"
606618
" FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
607619
" WHERE tagxref.rid=%d;",
608620
rid, rid, rid
609621
);
622
+#if 0
610623
db_multi_exec(
611624
"SELECT tag.tagid, tagname, "
612625
" (SELECT uuid FROM blob WHERE rid=tagxref.srcid AND rid!=%d),"
613626
" value, datetime(tagxref.mtime,toLocal()), tagtype,"
614627
" (SELECT uuid FROM blob WHERE rid=tagxref.origid AND rid!=%d)"
615628
" FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
616629
" WHERE tagxref.rid=%d"
617630
" ORDER BY tagname /*sort*/", rid, rid, rid
618631
);
632
+#endif
619633
blob_zero(&sql);
620634
blob_append(&sql, timeline_query_for_www(), -1);
621635
blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
622636
db_prepare(&q, "%s", blob_sql_text(&sql));
623637
www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL,
624
- 0, 0, 0, rid, 0);
638
+ 0, 0, 0, rid, 0, 0);
625639
db_finalize(&q);
626640
style_footer();
627641
}
628642
629643
/*
@@ -651,10 +665,11 @@
651665
const char *zRe; /* regex parameter */
652666
ReCompiled *pRe = 0; /* regex */
653667
const char *zW; /* URL param for ignoring whitespace */
654668
const char *zPage = "vinfo"; /* Page that shows diffs */
655669
const char *zPageHide = "ci"; /* Page that hides diffs */
670
+ const char *zBrName; /* Branch name */
656671
657672
login_check_credentials();
658673
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
659674
zName = P("name");
660675
rid = name_to_rid_www("name");
@@ -679,10 +694,11 @@
679694
" FROM blob, event"
680695
" WHERE blob.rid=%d"
681696
" AND event.objid=%d",
682697
rid, rid
683698
);
699
+ zBrName = branch_of_rid(rid);
684700
685701
cookie_link_parameter("diff","diff","2");
686702
diffType = atoi(PD("diff","2"));
687703
if( db_step(&q1)==SQLITE_ROW ){
688704
const char *zUuid = db_column_text(&q1, 0);
@@ -691,11 +707,10 @@
691707
const char *zUser;
692708
const char *zOrigUser;
693709
const char *zComment;
694710
const char *zDate;
695711
const char *zOrigDate;
696
- const char *zBrName;
697712
int okWiki = 0;
698713
Blob wiki_read_links = BLOB_INITIALIZER;
699714
Blob wiki_add_links = BLOB_INITIALIZER;
700715
701716
style_header("Check-in [%S]", zUuid);
@@ -705,13 +720,10 @@
705720
" WHERE tagid=%d AND rid=%d AND tagtype>0",
706721
TAG_USER, rid);
707722
zEComment = db_text(0,
708723
"SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
709724
TAG_COMMENT, rid);
710
- zBrName = db_text(0,
711
- "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
712
- TAG_BRANCH, rid);
713725
zOrigUser = db_column_text(&q1, 2);
714726
zUser = zEUser ? zEUser : zOrigUser;
715727
zComment = db_column_text(&q1, 3);
716728
zDate = db_column_text(&q1,1);
717729
zOrigDate = db_column_text(&q1, 4);
@@ -872,11 +884,14 @@
872884
}
873885
874886
if( g.perm.Hyperlink ){
875887
@ <tr><th>Other&nbsp;Links:</th>
876888
@ <td>
877
- @ %z(href("%R/artifact/%!S",zUuid))manifest</a>
889
+ if( fossil_strcmp(zBrName, db_get("main-branch","trunk"))!=0 ){
890
+ @ %z(href("%R/vdiff?branch=%!S", zUuid))branch diff</a> |
891
+ }
892
+ @ %z(href("%R/artifact/%!S",zUuid))manifest</a>
878893
@ | %z(href("%R/ci_tags/%!S",zUuid))tags</a>
879894
if( g.perm.Admin ){
880895
@ | %z(href("%R/mlink?ci=%!S",zUuid))mlink table</a>
881896
}
882897
if( g.anon.Write ){
@@ -896,11 +911,11 @@
896911
if( !PB("nowiki") ){
897912
wiki_render_associated("checkin", zUuid, 0);
898913
}
899914
render_backlink_graph(zUuid, "<div class=\"section\">References</div>\n");
900915
@ <div class="section">Context</div>
901
- render_checkin_context(rid, 0);
916
+ render_checkin_context(rid, 0, 0);
902917
@ <div class="section">Changes</div>
903918
@ <div class="sectionmenu">
904919
diffFlags = construct_diff_flags(diffType);
905920
zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
906921
if( diffType!=0 ){
@@ -1097,10 +1112,11 @@
10971112
return 0;
10981113
}
10991114
return manifest_get(rid, CFTYPE_MANIFEST, 0);
11001115
}
11011116
1117
+#if 0 /* not used */
11021118
/*
11031119
** Output a description of a check-in
11041120
*/
11051121
static void checkin_description(int rid){
11061122
Stmt q;
@@ -1155,10 +1171,11 @@
11551171
hyperlink_to_date(zDate, ")");
11561172
tag_private_status(rid);
11571173
}
11581174
db_finalize(&q);
11591175
}
1176
+#endif /* not used */
11601177
11611178
11621179
/*
11631180
** WEBPAGE: vdiff
11641181
** URL: /vdiff?from=TAG&to=TAG
@@ -1190,10 +1207,12 @@
11901207
const char *zFrom;
11911208
const char *zTo;
11921209
const char *zRe;
11931210
const char *zW;
11941211
const char *zGlob;
1212
+ char *zQuery;
1213
+ char *zMergeOrigin = 0;
11951214
ReCompiled *pRe = 0;
11961215
login_check_credentials();
11971216
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
11981217
login_anonymous_available();
11991218
load_control();
@@ -1201,13 +1220,18 @@
12011220
diffType = atoi(PD("diff","2"));
12021221
cookie_render();
12031222
zRe = P("regex");
12041223
if( zRe ) re_compile(&pRe, zRe, 0);
12051224
zBranch = P("branch");
1206
- if( zBranch && zBranch[0] ){
1207
- cgi_replace_parameter("from", mprintf("root:%s", zBranch));
1225
+ if( zBranch && zBranch[0]==0 ) zBranch = 0;
1226
+ if( zBranch ){
1227
+ zQuery = mprintf("branch=%T", zBranch);
1228
+ zMergeOrigin = mprintf("merge-in:%s", zBranch);
1229
+ cgi_replace_parameter("from", zMergeOrigin);
12081230
cgi_replace_parameter("to", zBranch);
1231
+ }else{
1232
+ zQuery = mprintf("from=%T&to=%T",PD("from",""),PD("to",""));
12091233
}
12101234
pTo = vdiff_parse_manifest("to", &ridTo);
12111235
if( pTo==0 ) return;
12121236
pFrom = vdiff_parse_manifest("from", &ridFrom);
12131237
if( pFrom==0 ) return;
@@ -1217,56 +1241,82 @@
12171241
if(zGlob && !*zGlob){
12181242
zGlob = NULL;
12191243
}
12201244
diffFlags = construct_diff_flags(diffType);
12211245
zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
1222
- style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1246
+ if( zBranch==0 ){
1247
+ style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1248
+ }
12231249
if( diffType!=0 ){
1224
- style_submenu_element("Hide Diff", "%R/vdiff?from=%T&to=%T&diff=0%s%T%s",
1225
- zFrom, zTo,
1250
+ style_submenu_element("Hide Diff", "%R/vdiff?%s&diff=0%s%T%s",
1251
+ zQuery,
12261252
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
12271253
}
12281254
if( diffType!=2 ){
12291255
style_submenu_element("Side-by-Side Diff",
1230
- "%R/vdiff?from=%T&to=%T&diff=2%s%T%s",
1231
- zFrom, zTo,
1256
+ "%R/vdiff?%s&diff=2%s%T%s",
1257
+ zQuery,
12321258
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
12331259
}
12341260
if( diffType!=1 ) {
12351261
style_submenu_element("Unified Diff",
1236
- "%R/vdiff?from=%T&to=%T&diff=1%s%T%s",
1237
- zFrom, zTo,
1262
+ "%R/vdiff?%s&diff=1%s%T%s",
1263
+ zQuery,
1264
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1265
+ }
1266
+ if( zBranch==0 ){
1267
+ style_submenu_element("Invert",
1268
+ "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
12381269
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
12391270
}
1240
- style_submenu_element("Invert",
1241
- "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
1242
- zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
12431271
if( zGlob ){
12441272
style_submenu_element("Clear glob",
1245
- "%R/vdiff?from=%T&to=%T&%s", zFrom, zTo, zW);
1273
+ "%R/vdiff?%s&%s", zQuery, zW);
12461274
}else{
12471275
style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
12481276
}
12491277
if( diffType!=0 ){
12501278
style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
12511279
}
1252
- style_header("Check-in Differences");
1280
+ if( zBranch ){
1281
+ style_header("Changes On Branch %h", zBranch);
1282
+ }else{
1283
+ style_header("Check-in Differences");
1284
+ }
12531285
if( P("nohdr")==0 ){
1254
- @ <h2>Difference From:</h2><blockquote>
1255
- checkin_description(ridFrom);
1256
- @ </blockquote><h2>To:</h2><blockquote>
1257
- checkin_description(ridTo);
1258
- @ </blockquote>
1286
+ if( zBranch ){
1287
+ char *zRealBranch = branch_of_rid(ridTo);
1288
+ char *zToUuid = rid_to_uuid(ridTo);
1289
+ char *zFromUuid = rid_to_uuid(ridFrom);
1290
+ @ <h2>Changes In Branch \
1291
+ @ %z(href("%R/timeline?r=%T",zRealBranch))%h(zRealBranch)</a>
1292
+ if( ridTo != symbolic_name_to_rid(zRealBranch,"ci") ){
1293
+ @ Through %z(href("%R/info/%!S",zToUuid))[%S(zToUuid)]</a>
1294
+ }
1295
+ @ Excluding Merge-Ins</h2>
1296
+ @ <p>This is equivalent to a diff from
1297
+ @ <span class='timelineSelected'>\
1298
+ @ %z(href("%R/info/%!S",zFromUuid))%S(zFromUuid)</a></span>
1299
+ @ to <span class='timelineSelected timelineSecondary'>\
1300
+ @ %z(href("%R/info/%!S",zToUuid))%S(zToUuid)</a></span></p>
1301
+ }else{
1302
+ @ <h2>Difference From <span class='timelineSelected'>\
1303
+ @ %z(href("%R/info/%h",zFrom))%h(zFrom)</a></span>
1304
+ @ To <span class='timelineSelected timelineSecondary'>\
1305
+ @ %z(href("%R/info/%h",zTo))%h(zTo)</a></span></h2>
1306
+ }
1307
+ render_checkin_context(ridFrom, ridTo, 0);
12591308
if( pRe ){
12601309
@ <p><b>Only differences that match regular expression "%h(zRe)"
12611310
@ are shown.</b></p>
12621311
}
12631312
if( zGlob ){
12641313
@ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
12651314
}
12661315
@<hr /><p>
12671316
}
1317
+ fossil_free(zQuery);
12681318
12691319
manifest_file_rewind(pFrom);
12701320
pFileFrom = manifest_file_next(pFrom, 0);
12711321
manifest_file_rewind(pTo);
12721322
pFileTo = manifest_file_next(pTo, 0);
12731323
--- src/info.c
+++ src/info.c
@@ -252,34 +252,46 @@
252
253 /*
254 ** Show the context graph (immediate parents and children) for
255 ** check-in rid.
256 */
257 void render_checkin_context(int rid, int parentsOnly){
258 Blob sql;
259 Stmt q;
 
 
 
 
 
260 blob_zero(&sql);
261 blob_append(&sql, timeline_query_for_www(), -1);
262 db_multi_exec(
263 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
264 "DELETE FROM ok;"
265 "INSERT INTO ok VALUES(%d);"
266 "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;",
267 rid, rid
268 );
269 if( !parentsOnly ){
270 db_multi_exec(
271 "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rid
272 );
273 if( db_table_exists("repository","cherrypick") ){
274 db_multi_exec(
275 "INSERT OR IGNORE INTO ok "
276 " SELECT parentid FROM cherrypick WHERE childid=%d;"
277 "INSERT OR IGNORE INTO ok "
278 " SELECT childid FROM cherrypick WHERE parentid=%d;",
279 rid, rid
280 );
 
 
 
 
 
 
 
281 }
282 }
283 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
284 db_prepare(&q, "%s", blob_sql_text(&sql));
285 www_print_timeline(&q,
@@ -286,11 +298,11 @@
286 TIMELINE_GRAPH
287 |TIMELINE_FILLGAPS
288 |TIMELINE_NOSCROLL
289 |TIMELINE_XMERGE
290 |TIMELINE_CHPICK,
291 0, 0, 0, rid, 0);
292 db_finalize(&q);
293 }
294
295 /*
296 ** Show a graph all wiki, tickets, and check-ins that refer to object zUuid.
@@ -317,11 +329,11 @@
317 blob_zero(&sql);
318 blob_append(&sql, timeline_query_for_www(), -1);
319 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
320 db_prepare(&q, "%s", blob_sql_text(&sql));
321 www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL,
322 0, 0, 0, 0, 0);
323 db_finalize(&q);
324 }
325
326 /*
327 ** WEBPAGE: test-backlinks
@@ -350,11 +362,11 @@
350 blob_zero(&sql);
351 blob_append(&sql, timeline_query_for_www(), -1);
352 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
353 db_prepare(&q, "%s", blob_sql_text(&sql));
354 www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL,
355 0, 0, 0, 0, 0);
356 db_finalize(&q);
357 style_footer();
358 }
359
360
@@ -605,25 +617,27 @@
605 " SELECT tagxref.origid"
606 " FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
607 " WHERE tagxref.rid=%d;",
608 rid, rid, rid
609 );
 
610 db_multi_exec(
611 "SELECT tag.tagid, tagname, "
612 " (SELECT uuid FROM blob WHERE rid=tagxref.srcid AND rid!=%d),"
613 " value, datetime(tagxref.mtime,toLocal()), tagtype,"
614 " (SELECT uuid FROM blob WHERE rid=tagxref.origid AND rid!=%d)"
615 " FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
616 " WHERE tagxref.rid=%d"
617 " ORDER BY tagname /*sort*/", rid, rid, rid
618 );
 
619 blob_zero(&sql);
620 blob_append(&sql, timeline_query_for_www(), -1);
621 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
622 db_prepare(&q, "%s", blob_sql_text(&sql));
623 www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL,
624 0, 0, 0, rid, 0);
625 db_finalize(&q);
626 style_footer();
627 }
628
629 /*
@@ -651,10 +665,11 @@
651 const char *zRe; /* regex parameter */
652 ReCompiled *pRe = 0; /* regex */
653 const char *zW; /* URL param for ignoring whitespace */
654 const char *zPage = "vinfo"; /* Page that shows diffs */
655 const char *zPageHide = "ci"; /* Page that hides diffs */
 
656
657 login_check_credentials();
658 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
659 zName = P("name");
660 rid = name_to_rid_www("name");
@@ -679,10 +694,11 @@
679 " FROM blob, event"
680 " WHERE blob.rid=%d"
681 " AND event.objid=%d",
682 rid, rid
683 );
 
684
685 cookie_link_parameter("diff","diff","2");
686 diffType = atoi(PD("diff","2"));
687 if( db_step(&q1)==SQLITE_ROW ){
688 const char *zUuid = db_column_text(&q1, 0);
@@ -691,11 +707,10 @@
691 const char *zUser;
692 const char *zOrigUser;
693 const char *zComment;
694 const char *zDate;
695 const char *zOrigDate;
696 const char *zBrName;
697 int okWiki = 0;
698 Blob wiki_read_links = BLOB_INITIALIZER;
699 Blob wiki_add_links = BLOB_INITIALIZER;
700
701 style_header("Check-in [%S]", zUuid);
@@ -705,13 +720,10 @@
705 " WHERE tagid=%d AND rid=%d AND tagtype>0",
706 TAG_USER, rid);
707 zEComment = db_text(0,
708 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
709 TAG_COMMENT, rid);
710 zBrName = db_text(0,
711 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
712 TAG_BRANCH, rid);
713 zOrigUser = db_column_text(&q1, 2);
714 zUser = zEUser ? zEUser : zOrigUser;
715 zComment = db_column_text(&q1, 3);
716 zDate = db_column_text(&q1,1);
717 zOrigDate = db_column_text(&q1, 4);
@@ -872,11 +884,14 @@
872 }
873
874 if( g.perm.Hyperlink ){
875 @ <tr><th>Other&nbsp;Links:</th>
876 @ <td>
877 @ %z(href("%R/artifact/%!S",zUuid))manifest</a>
 
 
 
878 @ | %z(href("%R/ci_tags/%!S",zUuid))tags</a>
879 if( g.perm.Admin ){
880 @ | %z(href("%R/mlink?ci=%!S",zUuid))mlink table</a>
881 }
882 if( g.anon.Write ){
@@ -896,11 +911,11 @@
896 if( !PB("nowiki") ){
897 wiki_render_associated("checkin", zUuid, 0);
898 }
899 render_backlink_graph(zUuid, "<div class=\"section\">References</div>\n");
900 @ <div class="section">Context</div>
901 render_checkin_context(rid, 0);
902 @ <div class="section">Changes</div>
903 @ <div class="sectionmenu">
904 diffFlags = construct_diff_flags(diffType);
905 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
906 if( diffType!=0 ){
@@ -1097,10 +1112,11 @@
1097 return 0;
1098 }
1099 return manifest_get(rid, CFTYPE_MANIFEST, 0);
1100 }
1101
 
1102 /*
1103 ** Output a description of a check-in
1104 */
1105 static void checkin_description(int rid){
1106 Stmt q;
@@ -1155,10 +1171,11 @@
1155 hyperlink_to_date(zDate, ")");
1156 tag_private_status(rid);
1157 }
1158 db_finalize(&q);
1159 }
 
1160
1161
1162 /*
1163 ** WEBPAGE: vdiff
1164 ** URL: /vdiff?from=TAG&to=TAG
@@ -1190,10 +1207,12 @@
1190 const char *zFrom;
1191 const char *zTo;
1192 const char *zRe;
1193 const char *zW;
1194 const char *zGlob;
 
 
1195 ReCompiled *pRe = 0;
1196 login_check_credentials();
1197 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1198 login_anonymous_available();
1199 load_control();
@@ -1201,13 +1220,18 @@
1201 diffType = atoi(PD("diff","2"));
1202 cookie_render();
1203 zRe = P("regex");
1204 if( zRe ) re_compile(&pRe, zRe, 0);
1205 zBranch = P("branch");
1206 if( zBranch && zBranch[0] ){
1207 cgi_replace_parameter("from", mprintf("root:%s", zBranch));
 
 
 
1208 cgi_replace_parameter("to", zBranch);
 
 
1209 }
1210 pTo = vdiff_parse_manifest("to", &ridTo);
1211 if( pTo==0 ) return;
1212 pFrom = vdiff_parse_manifest("from", &ridFrom);
1213 if( pFrom==0 ) return;
@@ -1217,56 +1241,82 @@
1217 if(zGlob && !*zGlob){
1218 zGlob = NULL;
1219 }
1220 diffFlags = construct_diff_flags(diffType);
1221 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
1222 style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
 
 
1223 if( diffType!=0 ){
1224 style_submenu_element("Hide Diff", "%R/vdiff?from=%T&to=%T&diff=0%s%T%s",
1225 zFrom, zTo,
1226 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1227 }
1228 if( diffType!=2 ){
1229 style_submenu_element("Side-by-Side Diff",
1230 "%R/vdiff?from=%T&to=%T&diff=2%s%T%s",
1231 zFrom, zTo,
1232 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1233 }
1234 if( diffType!=1 ) {
1235 style_submenu_element("Unified Diff",
1236 "%R/vdiff?from=%T&to=%T&diff=1%s%T%s",
1237 zFrom, zTo,
 
 
 
 
 
1238 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1239 }
1240 style_submenu_element("Invert",
1241 "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
1242 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1243 if( zGlob ){
1244 style_submenu_element("Clear glob",
1245 "%R/vdiff?from=%T&to=%T&%s", zFrom, zTo, zW);
1246 }else{
1247 style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
1248 }
1249 if( diffType!=0 ){
1250 style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
1251 }
1252 style_header("Check-in Differences");
 
 
 
 
1253 if( P("nohdr")==0 ){
1254 @ <h2>Difference From:</h2><blockquote>
1255 checkin_description(ridFrom);
1256 @ </blockquote><h2>To:</h2><blockquote>
1257 checkin_description(ridTo);
1258 @ </blockquote>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1259 if( pRe ){
1260 @ <p><b>Only differences that match regular expression "%h(zRe)"
1261 @ are shown.</b></p>
1262 }
1263 if( zGlob ){
1264 @ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
1265 }
1266 @<hr /><p>
1267 }
 
1268
1269 manifest_file_rewind(pFrom);
1270 pFileFrom = manifest_file_next(pFrom, 0);
1271 manifest_file_rewind(pTo);
1272 pFileTo = manifest_file_next(pTo, 0);
1273
--- src/info.c
+++ src/info.c
@@ -252,34 +252,46 @@
252
253 /*
254 ** Show the context graph (immediate parents and children) for
255 ** check-in rid.
256 */
257 void render_checkin_context(int rid, int rid2, int parentsOnly){
258 Blob sql;
259 Stmt q;
260 int rx[2];
261 int i, n;
262 rx[0] = rid;
263 rx[1] = rid2;
264 n = rid2 ? 2 : 1;
265 blob_zero(&sql);
266 blob_append(&sql, timeline_query_for_www(), -1);
267
268 db_multi_exec(
269 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
270 "DELETE FROM ok;"
271 );
272 for(i=0; i<n; i++){
273 db_multi_exec(
274 "INSERT OR IGNORE INTO ok VALUES(%d);"
275 "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;",
276 rx[i], rx[i]
277 );
278 }
279 if( !parentsOnly ){
280 for(i=0; i<n; i++){
281 db_multi_exec(
282 "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rx[i]
283 );
284 if( db_table_exists("repository","cherrypick") ){
285 db_multi_exec(
286 "INSERT OR IGNORE INTO ok "
287 " SELECT parentid FROM cherrypick WHERE childid=%d;"
288 "INSERT OR IGNORE INTO ok "
289 " SELECT childid FROM cherrypick WHERE parentid=%d;",
290 rx[i], rx[i]
291 );
292 }
293 }
294 }
295 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
296 db_prepare(&q, "%s", blob_sql_text(&sql));
297 www_print_timeline(&q,
@@ -286,11 +298,11 @@
298 TIMELINE_GRAPH
299 |TIMELINE_FILLGAPS
300 |TIMELINE_NOSCROLL
301 |TIMELINE_XMERGE
302 |TIMELINE_CHPICK,
303 0, 0, 0, rid, rid2, 0);
304 db_finalize(&q);
305 }
306
307 /*
308 ** Show a graph all wiki, tickets, and check-ins that refer to object zUuid.
@@ -317,11 +329,11 @@
329 blob_zero(&sql);
330 blob_append(&sql, timeline_query_for_www(), -1);
331 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
332 db_prepare(&q, "%s", blob_sql_text(&sql));
333 www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL,
334 0, 0, 0, 0, 0, 0);
335 db_finalize(&q);
336 }
337
338 /*
339 ** WEBPAGE: test-backlinks
@@ -350,11 +362,11 @@
362 blob_zero(&sql);
363 blob_append(&sql, timeline_query_for_www(), -1);
364 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
365 db_prepare(&q, "%s", blob_sql_text(&sql));
366 www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL,
367 0, 0, 0, 0, 0, 0);
368 db_finalize(&q);
369 style_footer();
370 }
371
372
@@ -605,25 +617,27 @@
617 " SELECT tagxref.origid"
618 " FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
619 " WHERE tagxref.rid=%d;",
620 rid, rid, rid
621 );
622 #if 0
623 db_multi_exec(
624 "SELECT tag.tagid, tagname, "
625 " (SELECT uuid FROM blob WHERE rid=tagxref.srcid AND rid!=%d),"
626 " value, datetime(tagxref.mtime,toLocal()), tagtype,"
627 " (SELECT uuid FROM blob WHERE rid=tagxref.origid AND rid!=%d)"
628 " FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
629 " WHERE tagxref.rid=%d"
630 " ORDER BY tagname /*sort*/", rid, rid, rid
631 );
632 #endif
633 blob_zero(&sql);
634 blob_append(&sql, timeline_query_for_www(), -1);
635 blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC");
636 db_prepare(&q, "%s", blob_sql_text(&sql));
637 www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL,
638 0, 0, 0, rid, 0, 0);
639 db_finalize(&q);
640 style_footer();
641 }
642
643 /*
@@ -651,10 +665,11 @@
665 const char *zRe; /* regex parameter */
666 ReCompiled *pRe = 0; /* regex */
667 const char *zW; /* URL param for ignoring whitespace */
668 const char *zPage = "vinfo"; /* Page that shows diffs */
669 const char *zPageHide = "ci"; /* Page that hides diffs */
670 const char *zBrName; /* Branch name */
671
672 login_check_credentials();
673 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
674 zName = P("name");
675 rid = name_to_rid_www("name");
@@ -679,10 +694,11 @@
694 " FROM blob, event"
695 " WHERE blob.rid=%d"
696 " AND event.objid=%d",
697 rid, rid
698 );
699 zBrName = branch_of_rid(rid);
700
701 cookie_link_parameter("diff","diff","2");
702 diffType = atoi(PD("diff","2"));
703 if( db_step(&q1)==SQLITE_ROW ){
704 const char *zUuid = db_column_text(&q1, 0);
@@ -691,11 +707,10 @@
707 const char *zUser;
708 const char *zOrigUser;
709 const char *zComment;
710 const char *zDate;
711 const char *zOrigDate;
 
712 int okWiki = 0;
713 Blob wiki_read_links = BLOB_INITIALIZER;
714 Blob wiki_add_links = BLOB_INITIALIZER;
715
716 style_header("Check-in [%S]", zUuid);
@@ -705,13 +720,10 @@
720 " WHERE tagid=%d AND rid=%d AND tagtype>0",
721 TAG_USER, rid);
722 zEComment = db_text(0,
723 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
724 TAG_COMMENT, rid);
 
 
 
725 zOrigUser = db_column_text(&q1, 2);
726 zUser = zEUser ? zEUser : zOrigUser;
727 zComment = db_column_text(&q1, 3);
728 zDate = db_column_text(&q1,1);
729 zOrigDate = db_column_text(&q1, 4);
@@ -872,11 +884,14 @@
884 }
885
886 if( g.perm.Hyperlink ){
887 @ <tr><th>Other&nbsp;Links:</th>
888 @ <td>
889 if( fossil_strcmp(zBrName, db_get("main-branch","trunk"))!=0 ){
890 @ %z(href("%R/vdiff?branch=%!S", zUuid))branch diff</a> |
891 }
892 @ %z(href("%R/artifact/%!S",zUuid))manifest</a>
893 @ | %z(href("%R/ci_tags/%!S",zUuid))tags</a>
894 if( g.perm.Admin ){
895 @ | %z(href("%R/mlink?ci=%!S",zUuid))mlink table</a>
896 }
897 if( g.anon.Write ){
@@ -896,11 +911,11 @@
911 if( !PB("nowiki") ){
912 wiki_render_associated("checkin", zUuid, 0);
913 }
914 render_backlink_graph(zUuid, "<div class=\"section\">References</div>\n");
915 @ <div class="section">Context</div>
916 render_checkin_context(rid, 0, 0);
917 @ <div class="section">Changes</div>
918 @ <div class="sectionmenu">
919 diffFlags = construct_diff_flags(diffType);
920 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
921 if( diffType!=0 ){
@@ -1097,10 +1112,11 @@
1112 return 0;
1113 }
1114 return manifest_get(rid, CFTYPE_MANIFEST, 0);
1115 }
1116
1117 #if 0 /* not used */
1118 /*
1119 ** Output a description of a check-in
1120 */
1121 static void checkin_description(int rid){
1122 Stmt q;
@@ -1155,10 +1171,11 @@
1171 hyperlink_to_date(zDate, ")");
1172 tag_private_status(rid);
1173 }
1174 db_finalize(&q);
1175 }
1176 #endif /* not used */
1177
1178
1179 /*
1180 ** WEBPAGE: vdiff
1181 ** URL: /vdiff?from=TAG&to=TAG
@@ -1190,10 +1207,12 @@
1207 const char *zFrom;
1208 const char *zTo;
1209 const char *zRe;
1210 const char *zW;
1211 const char *zGlob;
1212 char *zQuery;
1213 char *zMergeOrigin = 0;
1214 ReCompiled *pRe = 0;
1215 login_check_credentials();
1216 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1217 login_anonymous_available();
1218 load_control();
@@ -1201,13 +1220,18 @@
1220 diffType = atoi(PD("diff","2"));
1221 cookie_render();
1222 zRe = P("regex");
1223 if( zRe ) re_compile(&pRe, zRe, 0);
1224 zBranch = P("branch");
1225 if( zBranch && zBranch[0]==0 ) zBranch = 0;
1226 if( zBranch ){
1227 zQuery = mprintf("branch=%T", zBranch);
1228 zMergeOrigin = mprintf("merge-in:%s", zBranch);
1229 cgi_replace_parameter("from", zMergeOrigin);
1230 cgi_replace_parameter("to", zBranch);
1231 }else{
1232 zQuery = mprintf("from=%T&to=%T",PD("from",""),PD("to",""));
1233 }
1234 pTo = vdiff_parse_manifest("to", &ridTo);
1235 if( pTo==0 ) return;
1236 pFrom = vdiff_parse_manifest("from", &ridFrom);
1237 if( pFrom==0 ) return;
@@ -1217,56 +1241,82 @@
1241 if(zGlob && !*zGlob){
1242 zGlob = NULL;
1243 }
1244 diffFlags = construct_diff_flags(diffType);
1245 zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
1246 if( zBranch==0 ){
1247 style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1248 }
1249 if( diffType!=0 ){
1250 style_submenu_element("Hide Diff", "%R/vdiff?%s&diff=0%s%T%s",
1251 zQuery,
1252 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1253 }
1254 if( diffType!=2 ){
1255 style_submenu_element("Side-by-Side Diff",
1256 "%R/vdiff?%s&diff=2%s%T%s",
1257 zQuery,
1258 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1259 }
1260 if( diffType!=1 ) {
1261 style_submenu_element("Unified Diff",
1262 "%R/vdiff?%s&diff=1%s%T%s",
1263 zQuery,
1264 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1265 }
1266 if( zBranch==0 ){
1267 style_submenu_element("Invert",
1268 "%R/vdiff?from=%T&to=%T&%s%T%s", zTo, zFrom,
1269 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1270 }
 
 
 
1271 if( zGlob ){
1272 style_submenu_element("Clear glob",
1273 "%R/vdiff?%s&%s", zQuery, zW);
1274 }else{
1275 style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
1276 }
1277 if( diffType!=0 ){
1278 style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
1279 }
1280 if( zBranch ){
1281 style_header("Changes On Branch %h", zBranch);
1282 }else{
1283 style_header("Check-in Differences");
1284 }
1285 if( P("nohdr")==0 ){
1286 if( zBranch ){
1287 char *zRealBranch = branch_of_rid(ridTo);
1288 char *zToUuid = rid_to_uuid(ridTo);
1289 char *zFromUuid = rid_to_uuid(ridFrom);
1290 @ <h2>Changes In Branch \
1291 @ %z(href("%R/timeline?r=%T",zRealBranch))%h(zRealBranch)</a>
1292 if( ridTo != symbolic_name_to_rid(zRealBranch,"ci") ){
1293 @ Through %z(href("%R/info/%!S",zToUuid))[%S(zToUuid)]</a>
1294 }
1295 @ Excluding Merge-Ins</h2>
1296 @ <p>This is equivalent to a diff from
1297 @ <span class='timelineSelected'>\
1298 @ %z(href("%R/info/%!S",zFromUuid))%S(zFromUuid)</a></span>
1299 @ to <span class='timelineSelected timelineSecondary'>\
1300 @ %z(href("%R/info/%!S",zToUuid))%S(zToUuid)</a></span></p>
1301 }else{
1302 @ <h2>Difference From <span class='timelineSelected'>\
1303 @ %z(href("%R/info/%h",zFrom))%h(zFrom)</a></span>
1304 @ To <span class='timelineSelected timelineSecondary'>\
1305 @ %z(href("%R/info/%h",zTo))%h(zTo)</a></span></h2>
1306 }
1307 render_checkin_context(ridFrom, ridTo, 0);
1308 if( pRe ){
1309 @ <p><b>Only differences that match regular expression "%h(zRe)"
1310 @ are shown.</b></p>
1311 }
1312 if( zGlob ){
1313 @ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
1314 }
1315 @<hr /><p>
1316 }
1317 fossil_free(zQuery);
1318
1319 manifest_file_rewind(pFrom);
1320 pFileFrom = manifest_file_next(pFrom, 0);
1321 manifest_file_rewind(pTo);
1322 pFileTo = manifest_file_next(pTo, 0);
1323
+1 -1
--- src/moderate.c
+++ src/moderate.c
@@ -184,11 +184,11 @@
184184
blob_append_sql(&sql,
185185
" AND event.objid IN (SELECT objid FROM modreq)"
186186
" ORDER BY event.mtime DESC"
187187
);
188188
db_prepare(&q, "%s", blob_sql_text(&sql));
189
- www_print_timeline(&q, 0, 0, 0, 0, 0, 0);
189
+ www_print_timeline(&q, 0, 0, 0, 0, 0, 0, 0);
190190
db_finalize(&q);
191191
}
192192
style_footer();
193193
}
194194
195195
--- src/moderate.c
+++ src/moderate.c
@@ -184,11 +184,11 @@
184 blob_append_sql(&sql,
185 " AND event.objid IN (SELECT objid FROM modreq)"
186 " ORDER BY event.mtime DESC"
187 );
188 db_prepare(&q, "%s", blob_sql_text(&sql));
189 www_print_timeline(&q, 0, 0, 0, 0, 0, 0);
190 db_finalize(&q);
191 }
192 style_footer();
193 }
194
195
--- src/moderate.c
+++ src/moderate.c
@@ -184,11 +184,11 @@
184 blob_append_sql(&sql,
185 " AND event.objid IN (SELECT objid FROM modreq)"
186 " ORDER BY event.mtime DESC"
187 );
188 db_prepare(&q, "%s", blob_sql_text(&sql));
189 www_print_timeline(&q, 0, 0, 0, 0, 0, 0, 0);
190 db_finalize(&q);
191 }
192 style_footer();
193 }
194
195
+51 -25
--- src/name.c
+++ src/name.c
@@ -108,21 +108,25 @@
108108
return zEDate;
109109
}
110110
111111
/*
112112
** Return the RID that is the "root" of the branch that contains
113
-** check-in "rid" if inBranch==0 or the first check-in in the branch
114
-** if inBranch==1.
113
+** check-in "rid". Details depending on eType:
114
+**
115
+** eType==0 The check-in of the parent branch off of which
116
+** the branch containing RID originally diverged.
117
+**
118
+** eType==1 The first check-in of the branch that contains RID.
119
+**
120
+** eType==2 The youngest ancestor of RID that is on the branch
121
+** from which the branch containing RID diverged.
115122
*/
116
-int start_of_branch(int rid, int inBranch){
123
+int start_of_branch(int rid, int eType){
117124
Stmt q;
118125
int rc;
119
- char *zBr;
120
- zBr = db_text("trunk","SELECT value FROM tagxref"
121
- " WHERE rid=%d AND tagid=%d"
122
- " AND tagtype>0",
123
- rid, TAG_BRANCH);
126
+ int ans = rid;
127
+ char *zBr = branch_of_rid(rid);
124128
db_prepare(&q,
125129
"SELECT pid, EXISTS(SELECT 1 FROM tagxref"
126130
" WHERE tagid=%d AND tagtype>0"
127131
" AND value=%Q AND rid=plink.pid)"
128132
" FROM plink"
@@ -130,18 +134,23 @@
130134
TAG_BRANCH, zBr
131135
);
132136
fossil_free(zBr);
133137
do{
134138
db_reset(&q);
135
- db_bind_int(&q, ":cid", rid);
139
+ db_bind_int(&q, ":cid", ans);
136140
rc = db_step(&q);
137141
if( rc!=SQLITE_ROW ) break;
138
- if( inBranch && db_column_int(&q,1)==0 ) break;
139
- rid = db_column_int(&q, 0);
140
- }while( db_column_int(&q, 1)==1 && rid>0 );
142
+ if( eType==1 && db_column_int(&q,1)==0 ) break;
143
+ ans = db_column_int(&q, 0);
144
+ }while( db_column_int(&q, 1)==1 && ans>0 );
141145
db_finalize(&q);
142
- return rid;
146
+ if( eType==2 && ans>0 ){
147
+ zBr = branch_of_rid(ans);
148
+ ans = compute_youngest_ancestor_in_branch(rid, zBr);
149
+ fossil_free(zBr);
150
+ }
151
+ return ans;
143152
}
144153
145154
/*
146155
** Convert a symbolic name into a RID. Acceptable forms:
147156
**
@@ -165,10 +174,11 @@
165174
**
166175
** The zType parameter specifies the type of artifact: ci, t, w, e, g, f.
167176
** If zType is NULL or "" or "*" then any type of artifact will serve.
168177
** If zType is "br" then find the first check-in of the named branch
169178
** rather than the last.
179
+**
170180
** zType is "ci" in most use cases since we are usually searching for
171181
** a check-in.
172182
**
173183
** Note that the input zTag for types "t" and "e" is the artifact hash of
174184
** the ticket-change or technote-change artifact, not the randomly generated
@@ -270,14 +280,19 @@
270280
);
271281
if( startOfBranch ) rid = start_of_branch(rid,1);
272282
return rid;
273283
}
274284
275
- /* root:TAG -> The origin of the branch */
276
- if( memcmp(zTag, "root:", 5)==0 ){
285
+ /* root:BR -> The origin of the branch named BR */
286
+ if( strncmp(zTag, "root:", 5)==0 ){
277287
rid = symbolic_name_to_rid(zTag+5, zType);
278288
return start_of_branch(rid, 0);
289
+ }
290
+ /* rootx:BR -> Most recent merge-in for the branch name BR */
291
+ if( strncmp(zTag, "merge-in:", 9)==0 ){
292
+ rid = symbolic_name_to_rid(zTag+9, zType);
293
+ return start_of_branch(rid, 2);
279294
}
280295
281296
/* symbolic-name ":" date-time */
282297
nTag = strlen(zTag);
283298
for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
@@ -465,26 +480,37 @@
465480
}
466481
467482
/*
468483
** COMMAND: test-name-to-id
469484
**
470
-** Convert a name to a full artifact ID.
485
+** Usage: %fossil test-name-to-id [--count N] NAME
486
+**
487
+** Convert a NAME to a full artifact ID. Repeat the conversion N
488
+** times (for timing purposes) if the --count option is given.
471489
*/
472490
void test_name_to_id(void){
473491
int i;
492
+ int n = 0;
474493
Blob name;
475494
db_must_be_within_tree();
476495
for(i=2; i<g.argc; i++){
477
- blob_init(&name, g.argv[i], -1);
478
- fossil_print("%s -> ", g.argv[i]);
479
- if( name_to_uuid(&name, 1, "*") ){
480
- fossil_print("ERROR: %s\n", g.zErrMsg);
481
- fossil_error_reset();
482
- }else{
483
- fossil_print("%s\n", blob_buffer(&name));
484
- }
485
- blob_reset(&name);
496
+ if( strcmp(g.argv[i],"--count")==0 && i+1<g.argc ){
497
+ i++;
498
+ n = atoi(g.argv[i]);
499
+ continue;
500
+ }
501
+ do{
502
+ blob_init(&name, g.argv[i], -1);
503
+ fossil_print("%s -> ", g.argv[i]);
504
+ if( name_to_uuid(&name, 1, "*") ){
505
+ fossil_print("ERROR: %s\n", g.zErrMsg);
506
+ fossil_error_reset();
507
+ }else{
508
+ fossil_print("%s\n", blob_buffer(&name));
509
+ }
510
+ blob_reset(&name);
511
+ }while( n-- > 0 );
486512
}
487513
}
488514
489515
/*
490516
** Convert a name to a rid. If the name can be any of the various forms
491517
--- src/name.c
+++ src/name.c
@@ -108,21 +108,25 @@
108 return zEDate;
109 }
110
111 /*
112 ** Return the RID that is the "root" of the branch that contains
113 ** check-in "rid" if inBranch==0 or the first check-in in the branch
114 ** if inBranch==1.
 
 
 
 
 
 
 
115 */
116 int start_of_branch(int rid, int inBranch){
117 Stmt q;
118 int rc;
119 char *zBr;
120 zBr = db_text("trunk","SELECT value FROM tagxref"
121 " WHERE rid=%d AND tagid=%d"
122 " AND tagtype>0",
123 rid, TAG_BRANCH);
124 db_prepare(&q,
125 "SELECT pid, EXISTS(SELECT 1 FROM tagxref"
126 " WHERE tagid=%d AND tagtype>0"
127 " AND value=%Q AND rid=plink.pid)"
128 " FROM plink"
@@ -130,18 +134,23 @@
130 TAG_BRANCH, zBr
131 );
132 fossil_free(zBr);
133 do{
134 db_reset(&q);
135 db_bind_int(&q, ":cid", rid);
136 rc = db_step(&q);
137 if( rc!=SQLITE_ROW ) break;
138 if( inBranch && db_column_int(&q,1)==0 ) break;
139 rid = db_column_int(&q, 0);
140 }while( db_column_int(&q, 1)==1 && rid>0 );
141 db_finalize(&q);
142 return rid;
 
 
 
 
 
143 }
144
145 /*
146 ** Convert a symbolic name into a RID. Acceptable forms:
147 **
@@ -165,10 +174,11 @@
165 **
166 ** The zType parameter specifies the type of artifact: ci, t, w, e, g, f.
167 ** If zType is NULL or "" or "*" then any type of artifact will serve.
168 ** If zType is "br" then find the first check-in of the named branch
169 ** rather than the last.
 
170 ** zType is "ci" in most use cases since we are usually searching for
171 ** a check-in.
172 **
173 ** Note that the input zTag for types "t" and "e" is the artifact hash of
174 ** the ticket-change or technote-change artifact, not the randomly generated
@@ -270,14 +280,19 @@
270 );
271 if( startOfBranch ) rid = start_of_branch(rid,1);
272 return rid;
273 }
274
275 /* root:TAG -> The origin of the branch */
276 if( memcmp(zTag, "root:", 5)==0 ){
277 rid = symbolic_name_to_rid(zTag+5, zType);
278 return start_of_branch(rid, 0);
 
 
 
 
 
279 }
280
281 /* symbolic-name ":" date-time */
282 nTag = strlen(zTag);
283 for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
@@ -465,26 +480,37 @@
465 }
466
467 /*
468 ** COMMAND: test-name-to-id
469 **
470 ** Convert a name to a full artifact ID.
 
 
 
471 */
472 void test_name_to_id(void){
473 int i;
 
474 Blob name;
475 db_must_be_within_tree();
476 for(i=2; i<g.argc; i++){
477 blob_init(&name, g.argv[i], -1);
478 fossil_print("%s -> ", g.argv[i]);
479 if( name_to_uuid(&name, 1, "*") ){
480 fossil_print("ERROR: %s\n", g.zErrMsg);
481 fossil_error_reset();
482 }else{
483 fossil_print("%s\n", blob_buffer(&name));
484 }
485 blob_reset(&name);
 
 
 
 
 
 
 
486 }
487 }
488
489 /*
490 ** Convert a name to a rid. If the name can be any of the various forms
491
--- src/name.c
+++ src/name.c
@@ -108,21 +108,25 @@
108 return zEDate;
109 }
110
111 /*
112 ** Return the RID that is the "root" of the branch that contains
113 ** check-in "rid". Details depending on eType:
114 **
115 ** eType==0 The check-in of the parent branch off of which
116 ** the branch containing RID originally diverged.
117 **
118 ** eType==1 The first check-in of the branch that contains RID.
119 **
120 ** eType==2 The youngest ancestor of RID that is on the branch
121 ** from which the branch containing RID diverged.
122 */
123 int start_of_branch(int rid, int eType){
124 Stmt q;
125 int rc;
126 int ans = rid;
127 char *zBr = branch_of_rid(rid);
 
 
 
128 db_prepare(&q,
129 "SELECT pid, EXISTS(SELECT 1 FROM tagxref"
130 " WHERE tagid=%d AND tagtype>0"
131 " AND value=%Q AND rid=plink.pid)"
132 " FROM plink"
@@ -130,18 +134,23 @@
134 TAG_BRANCH, zBr
135 );
136 fossil_free(zBr);
137 do{
138 db_reset(&q);
139 db_bind_int(&q, ":cid", ans);
140 rc = db_step(&q);
141 if( rc!=SQLITE_ROW ) break;
142 if( eType==1 && db_column_int(&q,1)==0 ) break;
143 ans = db_column_int(&q, 0);
144 }while( db_column_int(&q, 1)==1 && ans>0 );
145 db_finalize(&q);
146 if( eType==2 && ans>0 ){
147 zBr = branch_of_rid(ans);
148 ans = compute_youngest_ancestor_in_branch(rid, zBr);
149 fossil_free(zBr);
150 }
151 return ans;
152 }
153
154 /*
155 ** Convert a symbolic name into a RID. Acceptable forms:
156 **
@@ -165,10 +174,11 @@
174 **
175 ** The zType parameter specifies the type of artifact: ci, t, w, e, g, f.
176 ** If zType is NULL or "" or "*" then any type of artifact will serve.
177 ** If zType is "br" then find the first check-in of the named branch
178 ** rather than the last.
179 **
180 ** zType is "ci" in most use cases since we are usually searching for
181 ** a check-in.
182 **
183 ** Note that the input zTag for types "t" and "e" is the artifact hash of
184 ** the ticket-change or technote-change artifact, not the randomly generated
@@ -270,14 +280,19 @@
280 );
281 if( startOfBranch ) rid = start_of_branch(rid,1);
282 return rid;
283 }
284
285 /* root:BR -> The origin of the branch named BR */
286 if( strncmp(zTag, "root:", 5)==0 ){
287 rid = symbolic_name_to_rid(zTag+5, zType);
288 return start_of_branch(rid, 0);
289 }
290 /* rootx:BR -> Most recent merge-in for the branch name BR */
291 if( strncmp(zTag, "merge-in:", 9)==0 ){
292 rid = symbolic_name_to_rid(zTag+9, zType);
293 return start_of_branch(rid, 2);
294 }
295
296 /* symbolic-name ":" date-time */
297 nTag = strlen(zTag);
298 for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
@@ -465,26 +480,37 @@
480 }
481
482 /*
483 ** COMMAND: test-name-to-id
484 **
485 ** Usage: %fossil test-name-to-id [--count N] NAME
486 **
487 ** Convert a NAME to a full artifact ID. Repeat the conversion N
488 ** times (for timing purposes) if the --count option is given.
489 */
490 void test_name_to_id(void){
491 int i;
492 int n = 0;
493 Blob name;
494 db_must_be_within_tree();
495 for(i=2; i<g.argc; i++){
496 if( strcmp(g.argv[i],"--count")==0 && i+1<g.argc ){
497 i++;
498 n = atoi(g.argv[i]);
499 continue;
500 }
501 do{
502 blob_init(&name, g.argv[i], -1);
503 fossil_print("%s -> ", g.argv[i]);
504 if( name_to_uuid(&name, 1, "*") ){
505 fossil_print("ERROR: %s\n", g.zErrMsg);
506 fossil_error_reset();
507 }else{
508 fossil_print("%s\n", blob_buffer(&name));
509 }
510 blob_reset(&name);
511 }while( n-- > 0 );
512 }
513 }
514
515 /*
516 ** Convert a name to a rid. If the name can be any of the various forms
517
+1 -1
--- src/tag.c
+++ src/tag.c
@@ -776,10 +776,10 @@
776776
** many descenders to (off-screen) parents. */
777777
tmFlags = TIMELINE_XMERGE | TIMELINE_FILLGAPS | TIMELINE_NOSCROLL;
778778
if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH;
779779
if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
780780
if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
781
- www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0);
781
+ www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0);
782782
db_finalize(&q);
783783
@ <br />
784784
style_footer();
785785
}
786786
--- src/tag.c
+++ src/tag.c
@@ -776,10 +776,10 @@
776 ** many descenders to (off-screen) parents. */
777 tmFlags = TIMELINE_XMERGE | TIMELINE_FILLGAPS | TIMELINE_NOSCROLL;
778 if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH;
779 if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
780 if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
781 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0);
782 db_finalize(&q);
783 @ <br />
784 style_footer();
785 }
786
--- src/tag.c
+++ src/tag.c
@@ -776,10 +776,10 @@
776 ** many descenders to (off-screen) parents. */
777 tmFlags = TIMELINE_XMERGE | TIMELINE_FILLGAPS | TIMELINE_NOSCROLL;
778 if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH;
779 if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR;
780 if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR;
781 www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0);
782 db_finalize(&q);
783 @ <br />
784 style_footer();
785 }
786
+18 -9
--- src/timeline.c
+++ src/timeline.c
@@ -243,11 +243,12 @@
243243
Stmt *pQuery, /* Query to implement the timeline */
244244
int tmFlags, /* Flags controlling display behavior */
245245
const char *zThisUser, /* Suppress links to this user */
246246
const char *zThisTag, /* Suppress links to this tag */
247247
const char *zLeftBranch, /* Strive to put this branch on the left margin */
248
- int selectedRid, /* Highlight the line with this RID value */
248
+ int selectedRid, /* Highlight the line with this RID value or zero */
249
+ int secondRid, /* Secondary highlight (or zero) */
249250
void (*xExtra)(int) /* Routine to call on each line of display */
250251
){
251252
int mxWikiLen;
252253
Blob comment;
253254
int prevTagid = 0;
@@ -395,10 +396,13 @@
395396
}
396397
pendingEndTr = 1;
397398
if( rid==selectedRid ){
398399
@ <tr class="timelineSelected">
399400
isSelectedOrCurrent = 1;
401
+ }else if( rid==secondRid ){
402
+ @ <tr class="timelineSelected timelineSecondary">
403
+ isSelectedOrCurrent = 1;
400404
}else if( rid==vid ){
401405
@ <tr class="timelineCurrent">
402406
isSelectedOrCurrent = 1;
403407
}else {
404408
@ <tr>
@@ -1601,11 +1605,12 @@
16011605
int pd_rid;
16021606
double rBefore, rAfter, rCirca; /* Boundary times */
16031607
const char *z;
16041608
char *zOlderButton = 0; /* URL for Older button at the bottom */
16051609
char *zNewerButton = 0; /* URL for Newer button at the top */
1606
- int selectedRid = -9999999; /* Show a highlight on this RID */
1610
+ int selectedRid = 0; /* Show a highlight on this RID */
1611
+ int secondaryRid = 0; /* Show secondary highlight */
16071612
int disableY = 0; /* Disable type selector on submenu */
16081613
int advancedMenu = 0; /* Use the advanced menu design */
16091614
char *zPlural; /* Ending for plural forms */
16101615
int showCherrypicks = 1; /* True to show cherrypick merges */
16111616
@@ -1625,10 +1630,12 @@
16251630
}
16261631
}else{
16271632
z = "50";
16281633
nEntry = 50;
16291634
}
1635
+ secondaryRid = name_to_typed_rid(P("sel2"),"ci");
1636
+ selectedRid = name_to_typed_rid(P("sel1"),"ci");
16301637
cgi_replace_query_parameter("n",z);
16311638
cookie_write_parameter("n","n",0);
16321639
tmFlags |= timeline_ss_submenu();
16331640
cookie_link_parameter("advm","advm","0");
16341641
advancedMenu = atoi(PD("advm","0"));
@@ -2387,15 +2394,17 @@
23872394
blob_zero(&sql);
23882395
db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
23892396
if( fossil_islower(desc.aData[0]) ){
23902397
desc.aData[0] = fossil_toupper(desc.aData[0]);
23912398
}
2392
- if( zBrName
2393
- && !PB("nowiki")
2394
- && wiki_render_associated("branch", zBrName, WIKIASSOC_ALL)
2395
- ){
2396
- @ <div class="section">%b(&desc)</div>
2399
+ if( zBrName ){
2400
+ if( !PB("nowiki")
2401
+ && wiki_render_associated("branch", zBrName, WIKIASSOC_ALL)
2402
+ ){
2403
+ @ <div class="section">%b(&desc)</div>
2404
+ }
2405
+ style_submenu_element("Diff", "%R/vdiff?branch=%T", zBrName);
23972406
}else
23982407
if( zTagName
23992408
&& matchStyle==MS_EXACT
24002409
&& zBrName==0
24012410
&& !PB("nowiki")
@@ -2414,11 +2423,11 @@
24142423
24152424
if( zNewerButton ){
24162425
@ %z(chref("button","%z",zNewerButton))More&nbsp;&uarr;</a>
24172426
}
24182427
www_print_timeline(&q, tmFlags, zThisUser, zThisTag, zBrName,
2419
- selectedRid, 0);
2428
+ selectedRid, secondaryRid, 0);
24202429
db_finalize(&q);
24212430
if( zOlderButton ){
24222431
@ %z(chref("button","%z",zOlderButton))More&nbsp;&darr;</a>
24232432
}
24242433
style_footer();
@@ -2907,11 +2916,11 @@
29072916
zId = db_text(0, "SELECT timestamp FROM timeline"
29082917
" ORDER BY sortby DESC LIMIT 1");
29092918
@ <h2>%d(iAgo) Year%s(iAgo>1?"s":"") Ago
29102919
@ <small>%z(href("%R/timeline?c=%t",zId))(more context)</a>\
29112920
@ </small></h2>
2912
- www_print_timeline(&q, TIMELINE_GRAPH, 0, 0, 0, 0, 0);
2921
+ www_print_timeline(&q, TIMELINE_GRAPH, 0, 0, 0, 0, 0, 0);
29132922
}
29142923
db_finalize(&q);
29152924
style_footer();
29162925
}
29172926
29182927
--- src/timeline.c
+++ src/timeline.c
@@ -243,11 +243,12 @@
243 Stmt *pQuery, /* Query to implement the timeline */
244 int tmFlags, /* Flags controlling display behavior */
245 const char *zThisUser, /* Suppress links to this user */
246 const char *zThisTag, /* Suppress links to this tag */
247 const char *zLeftBranch, /* Strive to put this branch on the left margin */
248 int selectedRid, /* Highlight the line with this RID value */
 
249 void (*xExtra)(int) /* Routine to call on each line of display */
250 ){
251 int mxWikiLen;
252 Blob comment;
253 int prevTagid = 0;
@@ -395,10 +396,13 @@
395 }
396 pendingEndTr = 1;
397 if( rid==selectedRid ){
398 @ <tr class="timelineSelected">
399 isSelectedOrCurrent = 1;
 
 
 
400 }else if( rid==vid ){
401 @ <tr class="timelineCurrent">
402 isSelectedOrCurrent = 1;
403 }else {
404 @ <tr>
@@ -1601,11 +1605,12 @@
1601 int pd_rid;
1602 double rBefore, rAfter, rCirca; /* Boundary times */
1603 const char *z;
1604 char *zOlderButton = 0; /* URL for Older button at the bottom */
1605 char *zNewerButton = 0; /* URL for Newer button at the top */
1606 int selectedRid = -9999999; /* Show a highlight on this RID */
 
1607 int disableY = 0; /* Disable type selector on submenu */
1608 int advancedMenu = 0; /* Use the advanced menu design */
1609 char *zPlural; /* Ending for plural forms */
1610 int showCherrypicks = 1; /* True to show cherrypick merges */
1611
@@ -1625,10 +1630,12 @@
1625 }
1626 }else{
1627 z = "50";
1628 nEntry = 50;
1629 }
 
 
1630 cgi_replace_query_parameter("n",z);
1631 cookie_write_parameter("n","n",0);
1632 tmFlags |= timeline_ss_submenu();
1633 cookie_link_parameter("advm","advm","0");
1634 advancedMenu = atoi(PD("advm","0"));
@@ -2387,15 +2394,17 @@
2387 blob_zero(&sql);
2388 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
2389 if( fossil_islower(desc.aData[0]) ){
2390 desc.aData[0] = fossil_toupper(desc.aData[0]);
2391 }
2392 if( zBrName
2393 && !PB("nowiki")
2394 && wiki_render_associated("branch", zBrName, WIKIASSOC_ALL)
2395 ){
2396 @ <div class="section">%b(&desc)</div>
 
 
2397 }else
2398 if( zTagName
2399 && matchStyle==MS_EXACT
2400 && zBrName==0
2401 && !PB("nowiki")
@@ -2414,11 +2423,11 @@
2414
2415 if( zNewerButton ){
2416 @ %z(chref("button","%z",zNewerButton))More&nbsp;&uarr;</a>
2417 }
2418 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, zBrName,
2419 selectedRid, 0);
2420 db_finalize(&q);
2421 if( zOlderButton ){
2422 @ %z(chref("button","%z",zOlderButton))More&nbsp;&darr;</a>
2423 }
2424 style_footer();
@@ -2907,11 +2916,11 @@
2907 zId = db_text(0, "SELECT timestamp FROM timeline"
2908 " ORDER BY sortby DESC LIMIT 1");
2909 @ <h2>%d(iAgo) Year%s(iAgo>1?"s":"") Ago
2910 @ <small>%z(href("%R/timeline?c=%t",zId))(more context)</a>\
2911 @ </small></h2>
2912 www_print_timeline(&q, TIMELINE_GRAPH, 0, 0, 0, 0, 0);
2913 }
2914 db_finalize(&q);
2915 style_footer();
2916 }
2917
2918
--- src/timeline.c
+++ src/timeline.c
@@ -243,11 +243,12 @@
243 Stmt *pQuery, /* Query to implement the timeline */
244 int tmFlags, /* Flags controlling display behavior */
245 const char *zThisUser, /* Suppress links to this user */
246 const char *zThisTag, /* Suppress links to this tag */
247 const char *zLeftBranch, /* Strive to put this branch on the left margin */
248 int selectedRid, /* Highlight the line with this RID value or zero */
249 int secondRid, /* Secondary highlight (or zero) */
250 void (*xExtra)(int) /* Routine to call on each line of display */
251 ){
252 int mxWikiLen;
253 Blob comment;
254 int prevTagid = 0;
@@ -395,10 +396,13 @@
396 }
397 pendingEndTr = 1;
398 if( rid==selectedRid ){
399 @ <tr class="timelineSelected">
400 isSelectedOrCurrent = 1;
401 }else if( rid==secondRid ){
402 @ <tr class="timelineSelected timelineSecondary">
403 isSelectedOrCurrent = 1;
404 }else if( rid==vid ){
405 @ <tr class="timelineCurrent">
406 isSelectedOrCurrent = 1;
407 }else {
408 @ <tr>
@@ -1601,11 +1605,12 @@
1605 int pd_rid;
1606 double rBefore, rAfter, rCirca; /* Boundary times */
1607 const char *z;
1608 char *zOlderButton = 0; /* URL for Older button at the bottom */
1609 char *zNewerButton = 0; /* URL for Newer button at the top */
1610 int selectedRid = 0; /* Show a highlight on this RID */
1611 int secondaryRid = 0; /* Show secondary highlight */
1612 int disableY = 0; /* Disable type selector on submenu */
1613 int advancedMenu = 0; /* Use the advanced menu design */
1614 char *zPlural; /* Ending for plural forms */
1615 int showCherrypicks = 1; /* True to show cherrypick merges */
1616
@@ -1625,10 +1630,12 @@
1630 }
1631 }else{
1632 z = "50";
1633 nEntry = 50;
1634 }
1635 secondaryRid = name_to_typed_rid(P("sel2"),"ci");
1636 selectedRid = name_to_typed_rid(P("sel1"),"ci");
1637 cgi_replace_query_parameter("n",z);
1638 cookie_write_parameter("n","n",0);
1639 tmFlags |= timeline_ss_submenu();
1640 cookie_link_parameter("advm","advm","0");
1641 advancedMenu = atoi(PD("advm","0"));
@@ -2387,15 +2394,17 @@
2394 blob_zero(&sql);
2395 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
2396 if( fossil_islower(desc.aData[0]) ){
2397 desc.aData[0] = fossil_toupper(desc.aData[0]);
2398 }
2399 if( zBrName ){
2400 if( !PB("nowiki")
2401 && wiki_render_associated("branch", zBrName, WIKIASSOC_ALL)
2402 ){
2403 @ <div class="section">%b(&desc)</div>
2404 }
2405 style_submenu_element("Diff", "%R/vdiff?branch=%T", zBrName);
2406 }else
2407 if( zTagName
2408 && matchStyle==MS_EXACT
2409 && zBrName==0
2410 && !PB("nowiki")
@@ -2414,11 +2423,11 @@
2423
2424 if( zNewerButton ){
2425 @ %z(chref("button","%z",zNewerButton))More&nbsp;&uarr;</a>
2426 }
2427 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, zBrName,
2428 selectedRid, secondaryRid, 0);
2429 db_finalize(&q);
2430 if( zOlderButton ){
2431 @ %z(chref("button","%z",zOlderButton))More&nbsp;&darr;</a>
2432 }
2433 style_footer();
@@ -2907,11 +2916,11 @@
2916 zId = db_text(0, "SELECT timestamp FROM timeline"
2917 " ORDER BY sortby DESC LIMIT 1");
2918 @ <h2>%d(iAgo) Year%s(iAgo>1?"s":"") Ago
2919 @ <small>%z(href("%R/timeline?c=%t",zId))(more context)</a>\
2920 @ </small></h2>
2921 www_print_timeline(&q, TIMELINE_GRAPH, 0, 0, 0, 0, 0, 0);
2922 }
2923 db_finalize(&q);
2924 style_footer();
2925 }
2926
2927
+1 -1
--- src/tkt.c
+++ src/tkt.c
@@ -896,11 +896,11 @@
896896
timeline_query_for_www(), tagid, zFullUuid, zFullUuid, zFullUuid
897897
);
898898
}
899899
db_prepare(&q, "%z", zSQL/*safe-for-%s*/);
900900
www_print_timeline(&q, TIMELINE_ARTID|TIMELINE_DISJOINT|TIMELINE_GRAPH,
901
- 0, 0, 0, 0, 0);
901
+ 0, 0, 0, 0, 0, 0);
902902
db_finalize(&q);
903903
style_footer();
904904
}
905905
906906
/*
907907
--- src/tkt.c
+++ src/tkt.c
@@ -896,11 +896,11 @@
896 timeline_query_for_www(), tagid, zFullUuid, zFullUuid, zFullUuid
897 );
898 }
899 db_prepare(&q, "%z", zSQL/*safe-for-%s*/);
900 www_print_timeline(&q, TIMELINE_ARTID|TIMELINE_DISJOINT|TIMELINE_GRAPH,
901 0, 0, 0, 0, 0);
902 db_finalize(&q);
903 style_footer();
904 }
905
906 /*
907
--- src/tkt.c
+++ src/tkt.c
@@ -896,11 +896,11 @@
896 timeline_query_for_www(), tagid, zFullUuid, zFullUuid, zFullUuid
897 );
898 }
899 db_prepare(&q, "%z", zSQL/*safe-for-%s*/);
900 www_print_timeline(&q, TIMELINE_ARTID|TIMELINE_DISJOINT|TIMELINE_GRAPH,
901 0, 0, 0, 0, 0, 0);
902 db_finalize(&q);
903 style_footer();
904 }
905
906 /*
907

Keyboard Shortcuts

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