| | @@ -180,5 +180,92 @@ |
| 180 | 180 | for(rid=bag_first(&needToCheck); rid; rid=bag_next(&needToCheck,rid)){ |
| 181 | 181 | leaf_check(rid); |
| 182 | 182 | } |
| 183 | 183 | bag_clear(&needToCheck); |
| 184 | 184 | } |
| 185 | + |
| 186 | +/* |
| 187 | +** If check-in rid is an open-leaf and there exists another |
| 188 | +** open leaf on the same branch, then return 1. |
| 189 | +** |
| 190 | +** If check-in rid is not an open leaf, or if it is the only open leaf |
| 191 | +** on its branch, then return 0. |
| 192 | +*/ |
| 193 | +int leaf_ambiguity(int rid){ |
| 194 | + int rc; /* Result */ |
| 195 | + char zVal[30]; |
| 196 | + if( !is_a_leaf(rid) ) return 0; |
| 197 | + sqlite3_snprintf(sizeof(zVal), zVal, "%d", rid); |
| 198 | + rc = db_exists( |
| 199 | + "SELECT 1 FROM leaf" |
| 200 | + " WHERE NOT %z" |
| 201 | + " AND rid<>%d" |
| 202 | + " AND (SELECT value FROM tagxref WHERE tagid=%d AND rid=leaf.rid)=" |
| 203 | + " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d)" |
| 204 | + " AND NOT %z", |
| 205 | + leaf_is_closed_sql(zVal), rid, TAG_BRANCH, TAG_BRANCH, rid, |
| 206 | + leaf_is_closed_sql("leaf.rid")); |
| 207 | + return rc; |
| 208 | +} |
| 209 | + |
| 210 | +/* |
| 211 | +** If check-in rid is an open-leaf and there exists another open leaf |
| 212 | +** on the same branch, then print a detailed warning showing all open |
| 213 | +** leaves on that branch. |
| 214 | +*/ |
| 215 | +int leaf_ambiguity_warning(int rid, int currentCkout){ |
| 216 | + char *zBr; |
| 217 | + Stmt q; |
| 218 | + int n = 0; |
| 219 | + Blob msg; |
| 220 | + if( leaf_ambiguity(rid)==0 ) return 0; |
| 221 | + zBr = db_text(0, "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d", |
| 222 | + TAG_BRANCH, rid); |
| 223 | + if( zBr==0 ) zBr = fossil_strdup("trunk"); |
| 224 | + blob_init(&msg, 0, 0); |
| 225 | + blob_appendf(&msg, "WARNING: multiple open leaves on %s:", zBr); |
| 226 | + db_prepare(&q, |
| 227 | + "SELECT" |
| 228 | + " (SELECT uuid FROM blob WHERE rid=leaf.rid)," |
| 229 | + " (SELECT datetime(mtime%s) FROM event WHERE objid=leaf.rid)," |
| 230 | + " leaf.rid" |
| 231 | + " FROM leaf" |
| 232 | + " WHERE (SELECT value FROM tagxref WHERE tagid=%d AND rid=leaf.rid)=%Q" |
| 233 | + " AND NOT %z" |
| 234 | + " ORDER BY 2 DESC", |
| 235 | + timeline_utc(), TAG_BRANCH, zBr, leaf_is_closed_sql("leaf.rid") |
| 236 | + ); |
| 237 | + while( db_step(&q)==SQLITE_ROW ){ |
| 238 | + blob_appendf(&msg, "\n (%d) %s [%S]%s", |
| 239 | + ++n, db_column_text(&q,1), db_column_text(&q,0), |
| 240 | + db_column_int(&q,2)==currentCkout ? " (current)" : ""); |
| 241 | + } |
| 242 | + db_finalize(&q); |
| 243 | + fossil_warning("%s",blob_str(&msg)); |
| 244 | + blob_reset(&msg); |
| 245 | + return 1; |
| 246 | +} |
| 247 | + |
| 248 | +/* |
| 249 | +** COMMAND: test-leaf-ambiguity |
| 250 | +** |
| 251 | +** Usage: %fossil NAME ... |
| 252 | +** |
| 253 | +** Resolve each name on the command line and call leaf_ambiguity_warning() |
| 254 | +** for each resulting RID. |
| 255 | +*/ |
| 256 | +void leaf_ambiguity_warning_test(void){ |
| 257 | + int i; |
| 258 | + int rid; |
| 259 | + int rc; |
| 260 | + db_find_and_open_repository(0,0); |
| 261 | + verify_all_options(); |
| 262 | + for(i=2; i<g.argc; i++){ |
| 263 | + char *zUuid; |
| 264 | + rid = name_to_typed_rid(g.argv[i], "ci"); |
| 265 | + zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 266 | + fossil_print("%s (rid=%d) %S ", g.argv[i], rid, zUuid ? zUuid : "(none)"); |
| 267 | + fossil_free(zUuid); |
| 268 | + rc = leaf_ambiguity_warning(rid, rid); |
| 269 | + if( rc==0 ) fossil_print(" ok\n"); |
| 270 | + } |
| 271 | +} |
| 185 | 272 | |