Fossil SCM
Define a "leaf" as a check-in with no children in the same branch. The is_a_leaf() function does some complicated SQL to figure this out.
Commit
faf09dc7ae5417fd4a8b09cc67c7c6ef9c9793a9
Parent
042a08b564579fb…
2 files changed
+33
-14
+2
-30
+33
-14
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -346,26 +346,45 @@ | ||
| 346 | 346 | g.aCommitFile[ii-2] = 0; |
| 347 | 347 | } |
| 348 | 348 | } |
| 349 | 349 | |
| 350 | 350 | /* |
| 351 | -** Return true if the check-in with RID=rid has no child | |
| 352 | -** check-ins which are not tagged with "newbranch". In other words, | |
| 353 | -** return true if the check-in is a leaf. | |
| 351 | +** Return true if the check-in with RID=rid is a leaf. | |
| 352 | +** | |
| 353 | +** A leaf has no children in the same branch. For the purposes of | |
| 354 | +** this definition, a two check-ins are in same branch they have the | |
| 355 | +** same set of propagated symbolic tags. | |
| 354 | 356 | */ |
| 355 | 357 | int is_a_leaf(int rid){ |
| 356 | - return !db_exists( | |
| 357 | - "SELECT 1 FROM plink" | |
| 358 | - " WHERE pid=%d" | |
| 359 | - " AND NOT EXISTS(" | |
| 360 | - "SELECT 1 FROM tagxref" | |
| 361 | - " WHERE tagxref.rid=plink.cid" | |
| 362 | - " AND tagxref.tagid=%d" | |
| 363 | - " AND tagxref.tagtype=1" | |
| 364 | - ")", | |
| 365 | - rid, TAG_NEWBRANCH | |
| 366 | - ); | |
| 358 | + | |
| 359 | + /* This query selects all children in the same branch as rid */ | |
| 360 | + static const char zSql[] = | |
| 361 | + @ SELECT cid FROM plink | |
| 362 | + @ WHERE pid=:rid | |
| 363 | + @ AND (SELECT group_concat(x) FROM ( | |
| 364 | + @ SELECT tag.tagid AS x FROM tagxref, tag | |
| 365 | + @ WHERE tagxref.rid=:rid AND tagxref.tagtype=2 | |
| 366 | + @ AND tag.tagid=tagxref.tagid AND tagxref.srcid=0 | |
| 367 | + @ AND tag.tagname GLOB 'sym-*' | |
| 368 | + @ ORDER BY 1) | |
| 369 | + @ ) == | |
| 370 | + @ (SELECT group_concat(x) FROM ( | |
| 371 | + @ SELECT tag.tagid AS x FROM tagxref, tag | |
| 372 | + @ WHERE tagxref.rid=plink.cid AND tagxref.tagtype=2 | |
| 373 | + @ AND tag.tagid=tagxref.tagid | |
| 374 | + @ AND tag.tagname GLOB 'sym-*' | |
| 375 | + @ ORDER BY 1) | |
| 376 | + @ ) | |
| 377 | + ; | |
| 378 | + Stmt q; /* The prepared statement */ | |
| 379 | + int rc; /* Return code from stepping the prepared statement */ | |
| 380 | + | |
| 381 | + db_prepare(&q, zSql); | |
| 382 | + db_bind_int(&q, ":rid", rid); | |
| 383 | + rc = db_step(&q); | |
| 384 | + db_finalize(&q); | |
| 385 | + return rc==SQLITE_DONE; | |
| 367 | 386 | } |
| 368 | 387 | |
| 369 | 388 | /* |
| 370 | 389 | ** COMMAND: ci |
| 371 | 390 | ** COMMAND: commit |
| 372 | 391 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -346,26 +346,45 @@ | |
| 346 | g.aCommitFile[ii-2] = 0; |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | /* |
| 351 | ** Return true if the check-in with RID=rid has no child |
| 352 | ** check-ins which are not tagged with "newbranch". In other words, |
| 353 | ** return true if the check-in is a leaf. |
| 354 | */ |
| 355 | int is_a_leaf(int rid){ |
| 356 | return !db_exists( |
| 357 | "SELECT 1 FROM plink" |
| 358 | " WHERE pid=%d" |
| 359 | " AND NOT EXISTS(" |
| 360 | "SELECT 1 FROM tagxref" |
| 361 | " WHERE tagxref.rid=plink.cid" |
| 362 | " AND tagxref.tagid=%d" |
| 363 | " AND tagxref.tagtype=1" |
| 364 | ")", |
| 365 | rid, TAG_NEWBRANCH |
| 366 | ); |
| 367 | } |
| 368 | |
| 369 | /* |
| 370 | ** COMMAND: ci |
| 371 | ** COMMAND: commit |
| 372 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -346,26 +346,45 @@ | |
| 346 | g.aCommitFile[ii-2] = 0; |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | /* |
| 351 | ** Return true if the check-in with RID=rid is a leaf. |
| 352 | ** |
| 353 | ** A leaf has no children in the same branch. For the purposes of |
| 354 | ** this definition, a two check-ins are in same branch they have the |
| 355 | ** same set of propagated symbolic tags. |
| 356 | */ |
| 357 | int is_a_leaf(int rid){ |
| 358 | |
| 359 | /* This query selects all children in the same branch as rid */ |
| 360 | static const char zSql[] = |
| 361 | @ SELECT cid FROM plink |
| 362 | @ WHERE pid=:rid |
| 363 | @ AND (SELECT group_concat(x) FROM ( |
| 364 | @ SELECT tag.tagid AS x FROM tagxref, tag |
| 365 | @ WHERE tagxref.rid=:rid AND tagxref.tagtype=2 |
| 366 | @ AND tag.tagid=tagxref.tagid AND tagxref.srcid=0 |
| 367 | @ AND tag.tagname GLOB 'sym-*' |
| 368 | @ ORDER BY 1) |
| 369 | @ ) == |
| 370 | @ (SELECT group_concat(x) FROM ( |
| 371 | @ SELECT tag.tagid AS x FROM tagxref, tag |
| 372 | @ WHERE tagxref.rid=plink.cid AND tagxref.tagtype=2 |
| 373 | @ AND tag.tagid=tagxref.tagid |
| 374 | @ AND tag.tagname GLOB 'sym-*' |
| 375 | @ ORDER BY 1) |
| 376 | @ ) |
| 377 | ; |
| 378 | Stmt q; /* The prepared statement */ |
| 379 | int rc; /* Return code from stepping the prepared statement */ |
| 380 | |
| 381 | db_prepare(&q, zSql); |
| 382 | db_bind_int(&q, ":rid", rid); |
| 383 | rc = db_step(&q); |
| 384 | db_finalize(&q); |
| 385 | return rc==SQLITE_DONE; |
| 386 | } |
| 387 | |
| 388 | /* |
| 389 | ** COMMAND: ci |
| 390 | ** COMMAND: commit |
| 391 |
+2
-30
| --- src/descendants.c | ||
| +++ src/descendants.c | ||
| @@ -62,11 +62,10 @@ | ||
| 62 | 62 | */ |
| 63 | 63 | void compute_leaves(int iBase, int closeMode){ |
| 64 | 64 | Bag seen; /* Descendants seen */ |
| 65 | 65 | Bag pending; /* Unpropagated descendants */ |
| 66 | 66 | Stmt q1; /* Query to find children of a check-in */ |
| 67 | - Stmt q2; /* Query to detect if a merge is across branches */ | |
| 68 | 67 | Stmt isBr; /* Query to check to see if a check-in starts a new branch */ |
| 69 | 68 | Stmt ins; /* INSERT statement for a new record */ |
| 70 | 69 | |
| 71 | 70 | /* Create the LEAVES table if it does not already exist. Make sure |
| 72 | 71 | ** it is empty. |
| @@ -93,32 +92,10 @@ | ||
| 93 | 92 | bag_insert(&pending, iBase); |
| 94 | 93 | |
| 95 | 94 | /* This query returns all non-merge children of check-in :rid */ |
| 96 | 95 | db_prepare(&q1, "SELECT cid FROM plink WHERE pid=:rid AND isprim"); |
| 97 | 96 | |
| 98 | - /* This query returns all merge children of check-in :rid where | |
| 99 | - ** the child and parent are on same branch. The child and | |
| 100 | - ** parent are assumed to be on same branch if they have | |
| 101 | - ** the same set of propagated symbolic tags. | |
| 102 | - */ | |
| 103 | - db_prepare(&q2, | |
| 104 | - "SELECT cid FROM plink" | |
| 105 | - " WHERE pid=:rid AND NOT isprim" | |
| 106 | - " AND (SELECT group_concat(x) FROM (" | |
| 107 | - " SELECT tag.tagid AS x FROM tagxref, tag" | |
| 108 | - " WHERE tagxref.rid=:rid AND tagxref.tagtype=2" | |
| 109 | - " AND tag.tagid=tagxref.tagid AND tagxref.srcid=0" | |
| 110 | - " AND tag.tagname GLOB 'sym-*'" | |
| 111 | - " ORDER BY 1))" | |
| 112 | - " == (SELECT group_concat(x) FROM (" | |
| 113 | - " SELECT tag.tagid AS x FROM tagxref, tag" | |
| 114 | - " WHERE tagxref.rid=plink.cid AND tagxref.tagtype=2" | |
| 115 | - " AND tag.tagid=tagxref.tagid AND tagxref.srcid=0" | |
| 116 | - " AND tag.tagname GLOB 'sym-*'" | |
| 117 | - " ORDER BY 1))" | |
| 118 | - ); | |
| 119 | - | |
| 120 | 97 | /* This query returns a single row if check-in :rid is the first |
| 121 | 98 | ** check-in of a new branch. In other words, it returns a row if |
| 122 | 99 | ** check-in :rid has the 'newbranch' tag. |
| 123 | 100 | */ |
| 124 | 101 | db_prepare(&isBr, |
| @@ -145,26 +122,21 @@ | ||
| 145 | 122 | cnt++; |
| 146 | 123 | } |
| 147 | 124 | db_reset(&isBr); |
| 148 | 125 | } |
| 149 | 126 | db_reset(&q1); |
| 150 | - if( cnt==0 ){ | |
| 151 | - db_bind_int(&q2, ":rid", rid); | |
| 152 | - if( db_step(&q2)==SQLITE_ROW ){ | |
| 153 | - cnt++; | |
| 154 | - } | |
| 155 | - db_reset(&q2); | |
| 127 | + if( cnt==0 && !is_a_leaf(rid) ){ | |
| 128 | + cnt++; | |
| 156 | 129 | } |
| 157 | 130 | if( cnt==0 ){ |
| 158 | 131 | db_bind_int(&ins, ":rid", rid); |
| 159 | 132 | db_step(&ins); |
| 160 | 133 | db_reset(&ins); |
| 161 | 134 | } |
| 162 | 135 | } |
| 163 | 136 | db_finalize(&ins); |
| 164 | 137 | db_finalize(&isBr); |
| 165 | - db_finalize(&q2); | |
| 166 | 138 | db_finalize(&q1); |
| 167 | 139 | bag_clear(&pending); |
| 168 | 140 | bag_clear(&seen); |
| 169 | 141 | if( closeMode==1 ){ |
| 170 | 142 | db_multi_exec( |
| 171 | 143 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -62,11 +62,10 @@ | |
| 62 | */ |
| 63 | void compute_leaves(int iBase, int closeMode){ |
| 64 | Bag seen; /* Descendants seen */ |
| 65 | Bag pending; /* Unpropagated descendants */ |
| 66 | Stmt q1; /* Query to find children of a check-in */ |
| 67 | Stmt q2; /* Query to detect if a merge is across branches */ |
| 68 | Stmt isBr; /* Query to check to see if a check-in starts a new branch */ |
| 69 | Stmt ins; /* INSERT statement for a new record */ |
| 70 | |
| 71 | /* Create the LEAVES table if it does not already exist. Make sure |
| 72 | ** it is empty. |
| @@ -93,32 +92,10 @@ | |
| 93 | bag_insert(&pending, iBase); |
| 94 | |
| 95 | /* This query returns all non-merge children of check-in :rid */ |
| 96 | db_prepare(&q1, "SELECT cid FROM plink WHERE pid=:rid AND isprim"); |
| 97 | |
| 98 | /* This query returns all merge children of check-in :rid where |
| 99 | ** the child and parent are on same branch. The child and |
| 100 | ** parent are assumed to be on same branch if they have |
| 101 | ** the same set of propagated symbolic tags. |
| 102 | */ |
| 103 | db_prepare(&q2, |
| 104 | "SELECT cid FROM plink" |
| 105 | " WHERE pid=:rid AND NOT isprim" |
| 106 | " AND (SELECT group_concat(x) FROM (" |
| 107 | " SELECT tag.tagid AS x FROM tagxref, tag" |
| 108 | " WHERE tagxref.rid=:rid AND tagxref.tagtype=2" |
| 109 | " AND tag.tagid=tagxref.tagid AND tagxref.srcid=0" |
| 110 | " AND tag.tagname GLOB 'sym-*'" |
| 111 | " ORDER BY 1))" |
| 112 | " == (SELECT group_concat(x) FROM (" |
| 113 | " SELECT tag.tagid AS x FROM tagxref, tag" |
| 114 | " WHERE tagxref.rid=plink.cid AND tagxref.tagtype=2" |
| 115 | " AND tag.tagid=tagxref.tagid AND tagxref.srcid=0" |
| 116 | " AND tag.tagname GLOB 'sym-*'" |
| 117 | " ORDER BY 1))" |
| 118 | ); |
| 119 | |
| 120 | /* This query returns a single row if check-in :rid is the first |
| 121 | ** check-in of a new branch. In other words, it returns a row if |
| 122 | ** check-in :rid has the 'newbranch' tag. |
| 123 | */ |
| 124 | db_prepare(&isBr, |
| @@ -145,26 +122,21 @@ | |
| 145 | cnt++; |
| 146 | } |
| 147 | db_reset(&isBr); |
| 148 | } |
| 149 | db_reset(&q1); |
| 150 | if( cnt==0 ){ |
| 151 | db_bind_int(&q2, ":rid", rid); |
| 152 | if( db_step(&q2)==SQLITE_ROW ){ |
| 153 | cnt++; |
| 154 | } |
| 155 | db_reset(&q2); |
| 156 | } |
| 157 | if( cnt==0 ){ |
| 158 | db_bind_int(&ins, ":rid", rid); |
| 159 | db_step(&ins); |
| 160 | db_reset(&ins); |
| 161 | } |
| 162 | } |
| 163 | db_finalize(&ins); |
| 164 | db_finalize(&isBr); |
| 165 | db_finalize(&q2); |
| 166 | db_finalize(&q1); |
| 167 | bag_clear(&pending); |
| 168 | bag_clear(&seen); |
| 169 | if( closeMode==1 ){ |
| 170 | db_multi_exec( |
| 171 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -62,11 +62,10 @@ | |
| 62 | */ |
| 63 | void compute_leaves(int iBase, int closeMode){ |
| 64 | Bag seen; /* Descendants seen */ |
| 65 | Bag pending; /* Unpropagated descendants */ |
| 66 | Stmt q1; /* Query to find children of a check-in */ |
| 67 | Stmt isBr; /* Query to check to see if a check-in starts a new branch */ |
| 68 | Stmt ins; /* INSERT statement for a new record */ |
| 69 | |
| 70 | /* Create the LEAVES table if it does not already exist. Make sure |
| 71 | ** it is empty. |
| @@ -93,32 +92,10 @@ | |
| 92 | bag_insert(&pending, iBase); |
| 93 | |
| 94 | /* This query returns all non-merge children of check-in :rid */ |
| 95 | db_prepare(&q1, "SELECT cid FROM plink WHERE pid=:rid AND isprim"); |
| 96 | |
| 97 | /* This query returns a single row if check-in :rid is the first |
| 98 | ** check-in of a new branch. In other words, it returns a row if |
| 99 | ** check-in :rid has the 'newbranch' tag. |
| 100 | */ |
| 101 | db_prepare(&isBr, |
| @@ -145,26 +122,21 @@ | |
| 122 | cnt++; |
| 123 | } |
| 124 | db_reset(&isBr); |
| 125 | } |
| 126 | db_reset(&q1); |
| 127 | if( cnt==0 && !is_a_leaf(rid) ){ |
| 128 | cnt++; |
| 129 | } |
| 130 | if( cnt==0 ){ |
| 131 | db_bind_int(&ins, ":rid", rid); |
| 132 | db_step(&ins); |
| 133 | db_reset(&ins); |
| 134 | } |
| 135 | } |
| 136 | db_finalize(&ins); |
| 137 | db_finalize(&isBr); |
| 138 | db_finalize(&q1); |
| 139 | bag_clear(&pending); |
| 140 | bag_clear(&seen); |
| 141 | if( closeMode==1 ){ |
| 142 | db_multi_exec( |
| 143 |