Fossil

Check-in [bd75ea06b8]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Basic functionality for the "bisect" command is now working. Ticket [33ffff3b4d961cf6e2a0]
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: bd75ea06b8d4f74b61a94e6683eda98410f69126
User & Date: drh 2010-12-04 19:25:04.000
References
2010-12-04
22:04 New ticket [891cd78969] Error: cannot close database "unable to close due to unfinalised statements" with fossil sqlite3 command. artifact: 2c175f910e user: anonymous
Context
2010-12-07
13:31
Update the internal SQLite to the latest 3.7.4 pre-release snapshot. check-in: 0018d724b3 user: drh tags: trunk, release
2010-12-04
19:25
Basic functionality for the "bisect" command is now working. Ticket [33ffff3b4d961cf6e2a0] check-in: bd75ea06b8 user: drh tags: trunk
13:15
Simple bug-fix to get the bisect-good and bisect-bad commands working. check-in: f2dbf9017d user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/bisect.c.
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
** Find the shortest path between bad and good.
*/
static BisectNode *bisect_path(void){
  BisectNode *p;
  bisect.bad = db_lget_int("bisect-bad", 0);
  if( bisect.bad==0 ){
    bisect.bad = db_int(0, "SELECT pid FROM plink ORDER BY mtime LIMIT 1");
    db_lset_int("bisect-bad", bisect.bad);
  }
  bisect.good = db_lget_int("bisect-good", 0);
  if( bisect.good==0 ){
    bisect.good = db_int(0,"SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1");
    db_lset_int("bisect-good", bisect.good);
  }
  p = bisect_shortest_path(bisect.good, bisect.bad);
  if( p==0 ){
    char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
    char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
    fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",







|




|







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
** Find the shortest path between bad and good.
*/
static BisectNode *bisect_path(void){
  BisectNode *p;
  bisect.bad = db_lget_int("bisect-bad", 0);
  if( bisect.bad==0 ){
    bisect.bad = db_int(0, "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1");
    db_lset_int("bisect-bad", bisect.bad);
  }
  bisect.good = db_lget_int("bisect-good", 0);
  if( bisect.good==0 ){
    bisect.good = db_int(0,"SELECT pid FROM plink ORDER BY mtime LIMIT 1");
    db_lset_int("bisect-good", bisect.good);
  }
  p = bisect_shortest_path(bisect.good, bisect.bad);
  if( p==0 ){
    char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
    char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
    fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209













210
211
212
213
214
215
216
217
218


219
220
221
222
223
224
225
226
227
228
229
230
231
232


233
234
235
236
237
238
239
240
241
**     non-working versions.
**
**   fossil bisect reset
**
**     Reinitialize a bisect session.  This cancels prior bisect history
**     and allows a bisect session to start over from the beginning.
**
**   fossil bisect run SCRIPT
**
**     Automatically bisect between "bad" and "good" versions, running SCRIPT
**     at each step to determine if the version is bad or good.  SCRIPT should
**     exit with result code zero if the version is good, or non-zero if the
**     version is bad.
**
**   fossil bisect timeline
**
**     Show a timeline of all changes in between the identified "bad" and 
**     "good" versions.
**
**   fossil bisect vlist
**
**     List the versions in between "bad" and "good".
*/
void bisect_cmd(void){
  int n;
  const char *zCmd;
  db_must_be_within_tree();
  zCmd = g.argv[2];
  n = strlen(zCmd);

  if( n>=1 && memcmp(zCmd, "bad", n)==0 ){
    int ridBad;
    if( g.argc==3 ){
      ridBad = db_lget_int("checkout",0);
    }else{
      ridBad = name_to_rid(g.argv[3]);
    }
    db_lset_int("bisect-bad", ridBad);
  }else if( memcmp(zCmd, "good", n)==0 ){
    int ridGood;
    if( g.argc==3 ){
      ridGood = db_lget_int("checkout",0);
    }else{
      ridGood = name_to_rid(g.argv[3]);
    }
    db_lset_int("bisect-good", ridGood);













  }else if( n>=2 && memcmp(zCmd, "reset", n)==0 ){
    db_multi_exec(
      "REPLACE INTO vvar(name, value) "
      "  SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;"
      "REPLACE INTO vvar(name, value) "
      "  SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;"
    );
  }else if( n>=2 && memcmp(zCmd, "vlist", n)==0 ){
    BisectNode *p;


    Stmt s;
    bisect_path();
    db_prepare(&s, "SELECT substr(blob.uuid,1,20) || ' ' || "
                   "       datetime(event.mtime) FROM blob, event"
                   " WHERE blob.rid=:rid AND event.objid=:rid"
                   "   AND event.type='ci'");
    for(p=bisect.pEnd; p; p=p->pFrom){
      const char *z;
      db_bind_int(&s, ":rid", p->rid);
      if( db_step(&s)==SQLITE_ROW ){
        z = db_column_text(&s, 0);
        printf("%s", z);
        if( p->rid==bisect.good ) printf(" GOOD");
        if( p->rid==bisect.bad ) printf(" BAD");


        printf("\n");
      }
      db_reset(&s);
    }
    db_finalize(&s);
  }else{
    usage("bad|good|next|reset|run|timeline|vlist ...");
  }
}







<
<
<
<
<
<
<
<
<
<
<
<










>
|















>
>
>
>
>
>
>
>
>
>
>
>
>
|






|

>
>






|







>
>






|


165
166
167
168
169
170
171












172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
**     non-working versions.
**
**   fossil bisect reset
**
**     Reinitialize a bisect session.  This cancels prior bisect history
**     and allows a bisect session to start over from the beginning.
**












**   fossil bisect vlist
**
**     List the versions in between "bad" and "good".
*/
void bisect_cmd(void){
  int n;
  const char *zCmd;
  db_must_be_within_tree();
  zCmd = g.argv[2];
  n = strlen(zCmd);
  if( n==0 ) zCmd = "-";
  if( memcmp(zCmd, "bad", n)==0 ){
    int ridBad;
    if( g.argc==3 ){
      ridBad = db_lget_int("checkout",0);
    }else{
      ridBad = name_to_rid(g.argv[3]);
    }
    db_lset_int("bisect-bad", ridBad);
  }else if( memcmp(zCmd, "good", n)==0 ){
    int ridGood;
    if( g.argc==3 ){
      ridGood = db_lget_int("checkout",0);
    }else{
      ridGood = name_to_rid(g.argv[3]);
    }
    db_lset_int("bisect-good", ridGood);
  }else if( memcmp(zCmd, "next", n)==0 ){
    BisectNode *p;
    int n;
    bisect_path();
    if( bisect.nStep<2 ){
      fossil_fatal("bisect is done - there are no more intermediate versions");
    }
    for(p=bisect.pEnd, n=0; p && n<bisect.nStep/2; p=p->pFrom, n++){}
    g.argv[1] = "update";
    g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid);
    g.argc = 3;
    g.fNoSync = 1;
    update_cmd();
  }else if( memcmp(zCmd, "reset", n)==0 ){
    db_multi_exec(
      "REPLACE INTO vvar(name, value) "
      "  SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;"
      "REPLACE INTO vvar(name, value) "
      "  SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;"
    );
  }else if( memcmp(zCmd, "vlist", n)==0 ){
    BisectNode *p;
    int vid = db_lget_int("checkout", 0);
    int n;
    Stmt s;
    bisect_path();
    db_prepare(&s, "SELECT substr(blob.uuid,1,20) || ' ' || "
                   "       datetime(event.mtime) FROM blob, event"
                   " WHERE blob.rid=:rid AND event.objid=:rid"
                   "   AND event.type='ci'");
    for(p=bisect.pEnd, n=0; p; p=p->pFrom, n++){
      const char *z;
      db_bind_int(&s, ":rid", p->rid);
      if( db_step(&s)==SQLITE_ROW ){
        z = db_column_text(&s, 0);
        printf("%s", z);
        if( p->rid==bisect.good ) printf(" GOOD");
        if( p->rid==bisect.bad ) printf(" BAD");
        if( p->rid==vid ) printf(" CURRENT");
        if( bisect.nStep>1 && n==bisect.nStep/2 ) printf(" NEXT");
        printf("\n");
      }
      db_reset(&s);
    }
    db_finalize(&s);
  }else{
    usage("bad|good|next|reset|vlist ...");
  }
}