Fossil SCM

Add the "fossil bisect options" command. Make the auto-next and direct-only options default to on since that seems to generate a more useful bisect in a heavily branched tree.

drh 2011-04-01 01:22 trunk
Commit fa81575c8d8d2121852c0c9cb1ad500262d25e8a
1 file changed +94 -10
+94 -10
--- src/bisect.c
+++ src/bisect.c
@@ -36,26 +36,59 @@
3636
*/
3737
void bisect_path(void){
3838
PathNode *p;
3939
bisect.bad = db_lget_int("bisect-bad", 0);
4040
if( bisect.bad==0 ){
41
- bisect.bad = db_int(0, "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1");
42
- db_lset_int("bisect-bad", bisect.bad);
41
+ fossil_fatal("no \"bad\" version has been identified");
4342
}
4443
bisect.good = db_lget_int("bisect-good", 0);
4544
if( bisect.good==0 ){
46
- bisect.good = db_int(0,"SELECT pid FROM plink ORDER BY mtime LIMIT 1");
47
- db_lset_int("bisect-good", bisect.good);
45
+ fossil_fatal("no \"good\" version has been identified");
4846
}
49
- p = path_shortest(bisect.good, bisect.bad, 0);
47
+ p = path_shortest(bisect.good, bisect.bad, bisect_option("direct-only"));
5048
if( p==0 ){
5149
char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
5250
char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
5351
fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
5452
zGood, zBad);
5553
}
5654
}
55
+
56
+/*
57
+** The set of all bisect options.
58
+*/
59
+static const struct {
60
+ const char *zName;
61
+ const char *zDefault;
62
+ const char *zDesc;
63
+} aBisectOption[] = {
64
+ { "auto-next", "on", "Automatically run \"bisect next\" after each "
65
+ "\"bisect good\" or \"bisect bad\"" },
66
+ { "direct-only", "on", "Follow only primary parent-child links, not "
67
+ "merges\n" },
68
+};
69
+
70
+/*
71
+** Return the value of a boolean bisect option.
72
+*/
73
+int bisect_option(const char *zName){
74
+ unsigned int i;
75
+ int r = -1;
76
+ for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
77
+ if( strcmp(zName, aBisectOption[i].zName)==0 ){
78
+ char *zLabel = mprintf("bisect-%s", zName);
79
+ char *z = db_lget(zLabel, (char*)aBisectOption[i].zDefault);
80
+ if( is_truth(z) ) r = 1;
81
+ if( is_false(z) ) r = 0;
82
+ if( r<0 ) r = is_truth(aBisectOption[i].zDefault);
83
+ free(zLabel);
84
+ break;
85
+ }
86
+ }
87
+ assert( r>=0 );
88
+ return r;
89
+}
5790
5891
/*
5992
** COMMAND: bisect
6093
**
6194
** Usage: %fossil bisect SUBCOMMAND ...
@@ -74,10 +107,15 @@
74107
**
75108
** fossil bisect next
76109
**
77110
** Update to the next version that is halfway between the working and
78111
** non-working versions.
112
+**
113
+** fossil bisect options ?NAME? ?VALUE?
114
+**
115
+** List all bisect options, or the value of a single option, or set the
116
+** value of a bisect option.
79117
**
80118
** fossil bisect reset
81119
**
82120
** Reinitialize a bisect session. This cancels prior bisect history
83121
** and allows a bisect session to start over from the beginning.
@@ -102,19 +140,38 @@
102140
ridBad = db_lget_int("checkout",0);
103141
}else{
104142
ridBad = name_to_rid(g.argv[3]);
105143
}
106144
db_lset_int("bisect-bad", ridBad);
145
+ if( ridBad>0
146
+ && bisect_option("auto-next")
147
+ && db_lget_int("bisect-good",0)>0
148
+ ){
149
+ zCmd = "next";
150
+ n = 4;
151
+ }else{
152
+ return;
153
+ }
107154
}else if( memcmp(zCmd, "good", n)==0 ){
108155
int ridGood;
109156
if( g.argc==3 ){
110157
ridGood = db_lget_int("checkout",0);
111158
}else{
112159
ridGood = name_to_rid(g.argv[3]);
113160
}
114161
db_lset_int("bisect-good", ridGood);
115
- }else if( memcmp(zCmd, "next", n)==0 ){
162
+ if( ridGood>0
163
+ && bisect_option("auto-next")
164
+ && db_lget_int("bisect-bad",0)>0
165
+ ){
166
+ zCmd = "next";
167
+ n = 4;
168
+ }else{
169
+ return;
170
+ }
171
+ }
172
+ if( memcmp(zCmd, "next", n)==0 ){
116173
PathNode *pMid;
117174
bisect_path();
118175
pMid = path_midpoint();
119176
if( pMid==0 ){
120177
fossil_fatal("bisect is done - there are no more intermediate versions");
@@ -122,16 +179,43 @@
122179
g.argv[1] = "update";
123180
g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
124181
g.argc = 3;
125182
g.fNoSync = 1;
126183
update_cmd();
184
+ }else if( memcmp(zCmd, "options", n)==0 ){
185
+ if( g.argc==3 ){
186
+ unsigned int i;
187
+ for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
188
+ char *z = mprintf("bisect-%s", aBisectOption[i].zName);
189
+ printf(" %-15s %-6s ", aBisectOption[i].zName,
190
+ db_lget(z, (char*)aBisectOption[i].zDefault));
191
+ fossil_free(z);
192
+ comment_print(aBisectOption[i].zDesc, 27, 79);
193
+ }
194
+ }else if( g.argc==4 || g.argc==5 ){
195
+ unsigned int i;
196
+ n = strlen(g.argv[3]);
197
+ for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
198
+ if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
199
+ char *z = mprintf("bisect-%s", aBisectOption[i].zName);
200
+ if( g.argc==5 ){
201
+ db_lset(z, g.argv[4]);
202
+ }
203
+ printf("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
204
+ fossil_free(z);
205
+ break;
206
+ }
207
+ }
208
+ if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
209
+ fossil_fatal("no such bisect option: %s", g.argv[3]);
210
+ }
211
+ }else{
212
+ usage("bisect option ?NAME? ?VALUE?");
213
+ }
127214
}else if( memcmp(zCmd, "reset", n)==0 ){
128215
db_multi_exec(
129
- "REPLACE INTO vvar(name, value) "
130
- " SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;"
131
- "REPLACE INTO vvar(name, value) "
132
- " SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;"
216
+ "DELETE FROM vvar WHERE name IN ('bisect-good', 'bisect-bad');"
133217
);
134218
}else if( memcmp(zCmd, "vlist", n)==0 ){
135219
PathNode *p;
136220
int vid = db_lget_int("checkout", 0);
137221
int n;
138222
--- src/bisect.c
+++ src/bisect.c
@@ -36,26 +36,59 @@
36 */
37 void bisect_path(void){
38 PathNode *p;
39 bisect.bad = db_lget_int("bisect-bad", 0);
40 if( bisect.bad==0 ){
41 bisect.bad = db_int(0, "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1");
42 db_lset_int("bisect-bad", bisect.bad);
43 }
44 bisect.good = db_lget_int("bisect-good", 0);
45 if( bisect.good==0 ){
46 bisect.good = db_int(0,"SELECT pid FROM plink ORDER BY mtime LIMIT 1");
47 db_lset_int("bisect-good", bisect.good);
48 }
49 p = path_shortest(bisect.good, bisect.bad, 0);
50 if( p==0 ){
51 char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
52 char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
53 fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
54 zGood, zBad);
55 }
56 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
58 /*
59 ** COMMAND: bisect
60 **
61 ** Usage: %fossil bisect SUBCOMMAND ...
@@ -74,10 +107,15 @@
74 **
75 ** fossil bisect next
76 **
77 ** Update to the next version that is halfway between the working and
78 ** non-working versions.
 
 
 
 
 
79 **
80 ** fossil bisect reset
81 **
82 ** Reinitialize a bisect session. This cancels prior bisect history
83 ** and allows a bisect session to start over from the beginning.
@@ -102,19 +140,38 @@
102 ridBad = db_lget_int("checkout",0);
103 }else{
104 ridBad = name_to_rid(g.argv[3]);
105 }
106 db_lset_int("bisect-bad", ridBad);
 
 
 
 
 
 
 
 
 
107 }else if( memcmp(zCmd, "good", n)==0 ){
108 int ridGood;
109 if( g.argc==3 ){
110 ridGood = db_lget_int("checkout",0);
111 }else{
112 ridGood = name_to_rid(g.argv[3]);
113 }
114 db_lset_int("bisect-good", ridGood);
115 }else if( memcmp(zCmd, "next", n)==0 ){
 
 
 
 
 
 
 
 
 
 
116 PathNode *pMid;
117 bisect_path();
118 pMid = path_midpoint();
119 if( pMid==0 ){
120 fossil_fatal("bisect is done - there are no more intermediate versions");
@@ -122,16 +179,43 @@
122 g.argv[1] = "update";
123 g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
124 g.argc = 3;
125 g.fNoSync = 1;
126 update_cmd();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127 }else if( memcmp(zCmd, "reset", n)==0 ){
128 db_multi_exec(
129 "REPLACE INTO vvar(name, value) "
130 " SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;"
131 "REPLACE INTO vvar(name, value) "
132 " SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;"
133 );
134 }else if( memcmp(zCmd, "vlist", n)==0 ){
135 PathNode *p;
136 int vid = db_lget_int("checkout", 0);
137 int n;
138
--- src/bisect.c
+++ src/bisect.c
@@ -36,26 +36,59 @@
36 */
37 void bisect_path(void){
38 PathNode *p;
39 bisect.bad = db_lget_int("bisect-bad", 0);
40 if( bisect.bad==0 ){
41 fossil_fatal("no \"bad\" version has been identified");
 
42 }
43 bisect.good = db_lget_int("bisect-good", 0);
44 if( bisect.good==0 ){
45 fossil_fatal("no \"good\" version has been identified");
 
46 }
47 p = path_shortest(bisect.good, bisect.bad, bisect_option("direct-only"));
48 if( p==0 ){
49 char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
50 char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
51 fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
52 zGood, zBad);
53 }
54 }
55
56 /*
57 ** The set of all bisect options.
58 */
59 static const struct {
60 const char *zName;
61 const char *zDefault;
62 const char *zDesc;
63 } aBisectOption[] = {
64 { "auto-next", "on", "Automatically run \"bisect next\" after each "
65 "\"bisect good\" or \"bisect bad\"" },
66 { "direct-only", "on", "Follow only primary parent-child links, not "
67 "merges\n" },
68 };
69
70 /*
71 ** Return the value of a boolean bisect option.
72 */
73 int bisect_option(const char *zName){
74 unsigned int i;
75 int r = -1;
76 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
77 if( strcmp(zName, aBisectOption[i].zName)==0 ){
78 char *zLabel = mprintf("bisect-%s", zName);
79 char *z = db_lget(zLabel, (char*)aBisectOption[i].zDefault);
80 if( is_truth(z) ) r = 1;
81 if( is_false(z) ) r = 0;
82 if( r<0 ) r = is_truth(aBisectOption[i].zDefault);
83 free(zLabel);
84 break;
85 }
86 }
87 assert( r>=0 );
88 return r;
89 }
90
91 /*
92 ** COMMAND: bisect
93 **
94 ** Usage: %fossil bisect SUBCOMMAND ...
@@ -74,10 +107,15 @@
107 **
108 ** fossil bisect next
109 **
110 ** Update to the next version that is halfway between the working and
111 ** non-working versions.
112 **
113 ** fossil bisect options ?NAME? ?VALUE?
114 **
115 ** List all bisect options, or the value of a single option, or set the
116 ** value of a bisect option.
117 **
118 ** fossil bisect reset
119 **
120 ** Reinitialize a bisect session. This cancels prior bisect history
121 ** and allows a bisect session to start over from the beginning.
@@ -102,19 +140,38 @@
140 ridBad = db_lget_int("checkout",0);
141 }else{
142 ridBad = name_to_rid(g.argv[3]);
143 }
144 db_lset_int("bisect-bad", ridBad);
145 if( ridBad>0
146 && bisect_option("auto-next")
147 && db_lget_int("bisect-good",0)>0
148 ){
149 zCmd = "next";
150 n = 4;
151 }else{
152 return;
153 }
154 }else if( memcmp(zCmd, "good", n)==0 ){
155 int ridGood;
156 if( g.argc==3 ){
157 ridGood = db_lget_int("checkout",0);
158 }else{
159 ridGood = name_to_rid(g.argv[3]);
160 }
161 db_lset_int("bisect-good", ridGood);
162 if( ridGood>0
163 && bisect_option("auto-next")
164 && db_lget_int("bisect-bad",0)>0
165 ){
166 zCmd = "next";
167 n = 4;
168 }else{
169 return;
170 }
171 }
172 if( memcmp(zCmd, "next", n)==0 ){
173 PathNode *pMid;
174 bisect_path();
175 pMid = path_midpoint();
176 if( pMid==0 ){
177 fossil_fatal("bisect is done - there are no more intermediate versions");
@@ -122,16 +179,43 @@
179 g.argv[1] = "update";
180 g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
181 g.argc = 3;
182 g.fNoSync = 1;
183 update_cmd();
184 }else if( memcmp(zCmd, "options", n)==0 ){
185 if( g.argc==3 ){
186 unsigned int i;
187 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
188 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
189 printf(" %-15s %-6s ", aBisectOption[i].zName,
190 db_lget(z, (char*)aBisectOption[i].zDefault));
191 fossil_free(z);
192 comment_print(aBisectOption[i].zDesc, 27, 79);
193 }
194 }else if( g.argc==4 || g.argc==5 ){
195 unsigned int i;
196 n = strlen(g.argv[3]);
197 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
198 if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
199 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
200 if( g.argc==5 ){
201 db_lset(z, g.argv[4]);
202 }
203 printf("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
204 fossil_free(z);
205 break;
206 }
207 }
208 if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
209 fossil_fatal("no such bisect option: %s", g.argv[3]);
210 }
211 }else{
212 usage("bisect option ?NAME? ?VALUE?");
213 }
214 }else if( memcmp(zCmd, "reset", n)==0 ){
215 db_multi_exec(
216 "DELETE FROM vvar WHERE name IN ('bisect-good', 'bisect-bad');"
 
 
 
217 );
218 }else if( memcmp(zCmd, "vlist", n)==0 ){
219 PathNode *p;
220 int vid = db_lget_int("checkout", 0);
221 int n;
222

Keyboard Shortcuts

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