Fossil SCM
Basic functionality for the "bisect" command is now working. Ticket [33ffff3b4d961cf6e2a0]
Commit
bd75ea06b8d4f74b61a94e6683eda98410f69126
Parent
f2dbf9017d9bb1a…
1 file changed
+25
-19
+25
-19
| --- src/bisect.c | ||
| +++ src/bisect.c | ||
| @@ -120,16 +120,16 @@ | ||
| 120 | 120 | */ |
| 121 | 121 | static BisectNode *bisect_path(void){ |
| 122 | 122 | BisectNode *p; |
| 123 | 123 | bisect.bad = db_lget_int("bisect-bad", 0); |
| 124 | 124 | if( bisect.bad==0 ){ |
| 125 | - bisect.bad = db_int(0, "SELECT pid FROM plink ORDER BY mtime LIMIT 1"); | |
| 125 | + bisect.bad = db_int(0, "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1"); | |
| 126 | 126 | db_lset_int("bisect-bad", bisect.bad); |
| 127 | 127 | } |
| 128 | 128 | bisect.good = db_lget_int("bisect-good", 0); |
| 129 | 129 | if( bisect.good==0 ){ |
| 130 | - bisect.good = db_int(0,"SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1"); | |
| 130 | + bisect.good = db_int(0,"SELECT pid FROM plink ORDER BY mtime LIMIT 1"); | |
| 131 | 131 | db_lset_int("bisect-good", bisect.good); |
| 132 | 132 | } |
| 133 | 133 | p = bisect_shortest_path(bisect.good, bisect.bad); |
| 134 | 134 | if( p==0 ){ |
| 135 | 135 | char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad); |
| @@ -167,22 +167,10 @@ | ||
| 167 | 167 | ** fossil bisect reset |
| 168 | 168 | ** |
| 169 | 169 | ** Reinitialize a bisect session. This cancels prior bisect history |
| 170 | 170 | ** and allows a bisect session to start over from the beginning. |
| 171 | 171 | ** |
| 172 | -** fossil bisect run SCRIPT | |
| 173 | -** | |
| 174 | -** Automatically bisect between "bad" and "good" versions, running SCRIPT | |
| 175 | -** at each step to determine if the version is bad or good. SCRIPT should | |
| 176 | -** exit with result code zero if the version is good, or non-zero if the | |
| 177 | -** version is bad. | |
| 178 | -** | |
| 179 | -** fossil bisect timeline | |
| 180 | -** | |
| 181 | -** Show a timeline of all changes in between the identified "bad" and | |
| 182 | -** "good" versions. | |
| 183 | -** | |
| 184 | 172 | ** fossil bisect vlist |
| 185 | 173 | ** |
| 186 | 174 | ** List the versions in between "bad" and "good". |
| 187 | 175 | */ |
| 188 | 176 | void bisect_cmd(void){ |
| @@ -189,11 +177,12 @@ | ||
| 189 | 177 | int n; |
| 190 | 178 | const char *zCmd; |
| 191 | 179 | db_must_be_within_tree(); |
| 192 | 180 | zCmd = g.argv[2]; |
| 193 | 181 | n = strlen(zCmd); |
| 194 | - if( n>=1 && memcmp(zCmd, "bad", n)==0 ){ | |
| 182 | + if( n==0 ) zCmd = "-"; | |
| 183 | + if( memcmp(zCmd, "bad", n)==0 ){ | |
| 195 | 184 | int ridBad; |
| 196 | 185 | if( g.argc==3 ){ |
| 197 | 186 | ridBad = db_lget_int("checkout",0); |
| 198 | 187 | }else{ |
| 199 | 188 | ridBad = name_to_rid(g.argv[3]); |
| @@ -205,37 +194,54 @@ | ||
| 205 | 194 | ridGood = db_lget_int("checkout",0); |
| 206 | 195 | }else{ |
| 207 | 196 | ridGood = name_to_rid(g.argv[3]); |
| 208 | 197 | } |
| 209 | 198 | db_lset_int("bisect-good", ridGood); |
| 210 | - }else if( n>=2 && memcmp(zCmd, "reset", n)==0 ){ | |
| 199 | + }else if( memcmp(zCmd, "next", n)==0 ){ | |
| 200 | + BisectNode *p; | |
| 201 | + int n; | |
| 202 | + bisect_path(); | |
| 203 | + if( bisect.nStep<2 ){ | |
| 204 | + fossil_fatal("bisect is done - there are no more intermediate versions"); | |
| 205 | + } | |
| 206 | + for(p=bisect.pEnd, n=0; p && n<bisect.nStep/2; p=p->pFrom, n++){} | |
| 207 | + g.argv[1] = "update"; | |
| 208 | + g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid); | |
| 209 | + g.argc = 3; | |
| 210 | + g.fNoSync = 1; | |
| 211 | + update_cmd(); | |
| 212 | + }else if( memcmp(zCmd, "reset", n)==0 ){ | |
| 211 | 213 | db_multi_exec( |
| 212 | 214 | "REPLACE INTO vvar(name, value) " |
| 213 | 215 | " SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;" |
| 214 | 216 | "REPLACE INTO vvar(name, value) " |
| 215 | 217 | " SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;" |
| 216 | 218 | ); |
| 217 | - }else if( n>=2 && memcmp(zCmd, "vlist", n)==0 ){ | |
| 219 | + }else if( memcmp(zCmd, "vlist", n)==0 ){ | |
| 218 | 220 | BisectNode *p; |
| 221 | + int vid = db_lget_int("checkout", 0); | |
| 222 | + int n; | |
| 219 | 223 | Stmt s; |
| 220 | 224 | bisect_path(); |
| 221 | 225 | db_prepare(&s, "SELECT substr(blob.uuid,1,20) || ' ' || " |
| 222 | 226 | " datetime(event.mtime) FROM blob, event" |
| 223 | 227 | " WHERE blob.rid=:rid AND event.objid=:rid" |
| 224 | 228 | " AND event.type='ci'"); |
| 225 | - for(p=bisect.pEnd; p; p=p->pFrom){ | |
| 229 | + for(p=bisect.pEnd, n=0; p; p=p->pFrom, n++){ | |
| 226 | 230 | const char *z; |
| 227 | 231 | db_bind_int(&s, ":rid", p->rid); |
| 228 | 232 | if( db_step(&s)==SQLITE_ROW ){ |
| 229 | 233 | z = db_column_text(&s, 0); |
| 230 | 234 | printf("%s", z); |
| 231 | 235 | if( p->rid==bisect.good ) printf(" GOOD"); |
| 232 | 236 | if( p->rid==bisect.bad ) printf(" BAD"); |
| 237 | + if( p->rid==vid ) printf(" CURRENT"); | |
| 238 | + if( bisect.nStep>1 && n==bisect.nStep/2 ) printf(" NEXT"); | |
| 233 | 239 | printf("\n"); |
| 234 | 240 | } |
| 235 | 241 | db_reset(&s); |
| 236 | 242 | } |
| 237 | 243 | db_finalize(&s); |
| 238 | 244 | }else{ |
| 239 | - usage("bad|good|next|reset|run|timeline|vlist ..."); | |
| 245 | + usage("bad|good|next|reset|vlist ..."); | |
| 240 | 246 | } |
| 241 | 247 | } |
| 242 | 248 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -120,16 +120,16 @@ | |
| 120 | */ |
| 121 | static BisectNode *bisect_path(void){ |
| 122 | BisectNode *p; |
| 123 | bisect.bad = db_lget_int("bisect-bad", 0); |
| 124 | if( bisect.bad==0 ){ |
| 125 | bisect.bad = db_int(0, "SELECT pid FROM plink ORDER BY mtime LIMIT 1"); |
| 126 | db_lset_int("bisect-bad", bisect.bad); |
| 127 | } |
| 128 | bisect.good = db_lget_int("bisect-good", 0); |
| 129 | if( bisect.good==0 ){ |
| 130 | bisect.good = db_int(0,"SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1"); |
| 131 | db_lset_int("bisect-good", bisect.good); |
| 132 | } |
| 133 | p = bisect_shortest_path(bisect.good, bisect.bad); |
| 134 | if( p==0 ){ |
| 135 | char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad); |
| @@ -167,22 +167,10 @@ | |
| 167 | ** fossil bisect reset |
| 168 | ** |
| 169 | ** Reinitialize a bisect session. This cancels prior bisect history |
| 170 | ** and allows a bisect session to start over from the beginning. |
| 171 | ** |
| 172 | ** fossil bisect run SCRIPT |
| 173 | ** |
| 174 | ** Automatically bisect between "bad" and "good" versions, running SCRIPT |
| 175 | ** at each step to determine if the version is bad or good. SCRIPT should |
| 176 | ** exit with result code zero if the version is good, or non-zero if the |
| 177 | ** version is bad. |
| 178 | ** |
| 179 | ** fossil bisect timeline |
| 180 | ** |
| 181 | ** Show a timeline of all changes in between the identified "bad" and |
| 182 | ** "good" versions. |
| 183 | ** |
| 184 | ** fossil bisect vlist |
| 185 | ** |
| 186 | ** List the versions in between "bad" and "good". |
| 187 | */ |
| 188 | void bisect_cmd(void){ |
| @@ -189,11 +177,12 @@ | |
| 189 | int n; |
| 190 | const char *zCmd; |
| 191 | db_must_be_within_tree(); |
| 192 | zCmd = g.argv[2]; |
| 193 | n = strlen(zCmd); |
| 194 | if( n>=1 && memcmp(zCmd, "bad", n)==0 ){ |
| 195 | int ridBad; |
| 196 | if( g.argc==3 ){ |
| 197 | ridBad = db_lget_int("checkout",0); |
| 198 | }else{ |
| 199 | ridBad = name_to_rid(g.argv[3]); |
| @@ -205,37 +194,54 @@ | |
| 205 | ridGood = db_lget_int("checkout",0); |
| 206 | }else{ |
| 207 | ridGood = name_to_rid(g.argv[3]); |
| 208 | } |
| 209 | db_lset_int("bisect-good", ridGood); |
| 210 | }else if( n>=2 && memcmp(zCmd, "reset", n)==0 ){ |
| 211 | db_multi_exec( |
| 212 | "REPLACE INTO vvar(name, value) " |
| 213 | " SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;" |
| 214 | "REPLACE INTO vvar(name, value) " |
| 215 | " SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;" |
| 216 | ); |
| 217 | }else if( n>=2 && memcmp(zCmd, "vlist", n)==0 ){ |
| 218 | BisectNode *p; |
| 219 | Stmt s; |
| 220 | bisect_path(); |
| 221 | db_prepare(&s, "SELECT substr(blob.uuid,1,20) || ' ' || " |
| 222 | " datetime(event.mtime) FROM blob, event" |
| 223 | " WHERE blob.rid=:rid AND event.objid=:rid" |
| 224 | " AND event.type='ci'"); |
| 225 | for(p=bisect.pEnd; p; p=p->pFrom){ |
| 226 | const char *z; |
| 227 | db_bind_int(&s, ":rid", p->rid); |
| 228 | if( db_step(&s)==SQLITE_ROW ){ |
| 229 | z = db_column_text(&s, 0); |
| 230 | printf("%s", z); |
| 231 | if( p->rid==bisect.good ) printf(" GOOD"); |
| 232 | if( p->rid==bisect.bad ) printf(" BAD"); |
| 233 | printf("\n"); |
| 234 | } |
| 235 | db_reset(&s); |
| 236 | } |
| 237 | db_finalize(&s); |
| 238 | }else{ |
| 239 | usage("bad|good|next|reset|run|timeline|vlist ..."); |
| 240 | } |
| 241 | } |
| 242 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -120,16 +120,16 @@ | |
| 120 | */ |
| 121 | static BisectNode *bisect_path(void){ |
| 122 | BisectNode *p; |
| 123 | bisect.bad = db_lget_int("bisect-bad", 0); |
| 124 | if( bisect.bad==0 ){ |
| 125 | bisect.bad = db_int(0, "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1"); |
| 126 | db_lset_int("bisect-bad", bisect.bad); |
| 127 | } |
| 128 | bisect.good = db_lget_int("bisect-good", 0); |
| 129 | if( bisect.good==0 ){ |
| 130 | bisect.good = db_int(0,"SELECT pid FROM plink ORDER BY mtime LIMIT 1"); |
| 131 | db_lset_int("bisect-good", bisect.good); |
| 132 | } |
| 133 | p = bisect_shortest_path(bisect.good, bisect.bad); |
| 134 | if( p==0 ){ |
| 135 | char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad); |
| @@ -167,22 +167,10 @@ | |
| 167 | ** fossil bisect reset |
| 168 | ** |
| 169 | ** Reinitialize a bisect session. This cancels prior bisect history |
| 170 | ** and allows a bisect session to start over from the beginning. |
| 171 | ** |
| 172 | ** fossil bisect vlist |
| 173 | ** |
| 174 | ** List the versions in between "bad" and "good". |
| 175 | */ |
| 176 | void bisect_cmd(void){ |
| @@ -189,11 +177,12 @@ | |
| 177 | int n; |
| 178 | const char *zCmd; |
| 179 | db_must_be_within_tree(); |
| 180 | zCmd = g.argv[2]; |
| 181 | n = strlen(zCmd); |
| 182 | if( n==0 ) zCmd = "-"; |
| 183 | if( memcmp(zCmd, "bad", n)==0 ){ |
| 184 | int ridBad; |
| 185 | if( g.argc==3 ){ |
| 186 | ridBad = db_lget_int("checkout",0); |
| 187 | }else{ |
| 188 | ridBad = name_to_rid(g.argv[3]); |
| @@ -205,37 +194,54 @@ | |
| 194 | ridGood = db_lget_int("checkout",0); |
| 195 | }else{ |
| 196 | ridGood = name_to_rid(g.argv[3]); |
| 197 | } |
| 198 | db_lset_int("bisect-good", ridGood); |
| 199 | }else if( memcmp(zCmd, "next", n)==0 ){ |
| 200 | BisectNode *p; |
| 201 | int n; |
| 202 | bisect_path(); |
| 203 | if( bisect.nStep<2 ){ |
| 204 | fossil_fatal("bisect is done - there are no more intermediate versions"); |
| 205 | } |
| 206 | for(p=bisect.pEnd, n=0; p && n<bisect.nStep/2; p=p->pFrom, n++){} |
| 207 | g.argv[1] = "update"; |
| 208 | g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid); |
| 209 | g.argc = 3; |
| 210 | g.fNoSync = 1; |
| 211 | update_cmd(); |
| 212 | }else if( memcmp(zCmd, "reset", n)==0 ){ |
| 213 | db_multi_exec( |
| 214 | "REPLACE INTO vvar(name, value) " |
| 215 | " SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;" |
| 216 | "REPLACE INTO vvar(name, value) " |
| 217 | " SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;" |
| 218 | ); |
| 219 | }else if( memcmp(zCmd, "vlist", n)==0 ){ |
| 220 | BisectNode *p; |
| 221 | int vid = db_lget_int("checkout", 0); |
| 222 | int n; |
| 223 | Stmt s; |
| 224 | bisect_path(); |
| 225 | db_prepare(&s, "SELECT substr(blob.uuid,1,20) || ' ' || " |
| 226 | " datetime(event.mtime) FROM blob, event" |
| 227 | " WHERE blob.rid=:rid AND event.objid=:rid" |
| 228 | " AND event.type='ci'"); |
| 229 | for(p=bisect.pEnd, n=0; p; p=p->pFrom, n++){ |
| 230 | const char *z; |
| 231 | db_bind_int(&s, ":rid", p->rid); |
| 232 | if( db_step(&s)==SQLITE_ROW ){ |
| 233 | z = db_column_text(&s, 0); |
| 234 | printf("%s", z); |
| 235 | if( p->rid==bisect.good ) printf(" GOOD"); |
| 236 | if( p->rid==bisect.bad ) printf(" BAD"); |
| 237 | if( p->rid==vid ) printf(" CURRENT"); |
| 238 | if( bisect.nStep>1 && n==bisect.nStep/2 ) printf(" NEXT"); |
| 239 | printf("\n"); |
| 240 | } |
| 241 | db_reset(&s); |
| 242 | } |
| 243 | db_finalize(&s); |
| 244 | }else{ |
| 245 | usage("bad|good|next|reset|vlist ..."); |
| 246 | } |
| 247 | } |
| 248 |