Fossil SCM
Internal refactoring of (branch close) subcommand in prep for pending addition of similar (branch hide/unhide) feature.
Commit
9baa9768f6ae5a68d4d2ddacddc701edd90ab1069a1e5ae284bf10a16814db4e
Parent
94764e962c098ee…
1 file changed
+98
-55
+98
-55
| --- src/branch.c | ||
| +++ src/branch.c | ||
| @@ -345,70 +345,76 @@ | ||
| 345 | 345 | TAG_BRANCH, zBrName, TAG_CLOSED |
| 346 | 346 | ); |
| 347 | 347 | } |
| 348 | 348 | |
| 349 | 349 | /* |
| 350 | -** Implementation of (branch close) subcommand. nStartAtArg is the | |
| 351 | -** g.argv index to start reading branch names. Fails fatally on error. | |
| 350 | +** Internal helper for branch_cmd_close() and friends. Adds a row to | |
| 351 | +** the to the brcmdtag TEMP table, initializing that table if needed, | |
| 352 | +** holding a pending tag for the given blob.rid (which is assumed to | |
| 353 | +** be valid). zTag must be a fully-formed tag name, including the | |
| 354 | +** (+,-,*) prefix character. | |
| 355 | +** | |
| 356 | +*/ | |
| 357 | +static void branch_cmd_tag_add(int rid, const char *zTag){ | |
| 358 | + static int once = 0; | |
| 359 | + assert(zTag && ('+'==zTag[0] || '-'==zTag[0] || '*'==zTag[0])); | |
| 360 | + if(0==once++){ | |
| 361 | + db_multi_exec("CREATE TEMP TABLE brcmdtag(" | |
| 362 | + "rid INTEGER UNIQUE ON CONFLICT IGNORE," | |
| 363 | + "tag TEXT NOT NULL" | |
| 364 | + ")"); | |
| 365 | + } | |
| 366 | + db_multi_exec("INSERT INTO brcmdtag(rid,tag) VALUES(%d,%Q)", | |
| 367 | + rid, zTag); | |
| 368 | +} | |
| 369 | + | |
| 370 | +/* | |
| 371 | +** Internal helper for branch_cmd_close() and friends. Creates and | |
| 372 | +** saves a control artifact of tag changes stored via | |
| 373 | +** branch_cmd_tag_add(). Fails fatally on error, returns 0 if it saves | |
| 374 | +** an artifact, and a negative value if it does not save anything | |
| 375 | +** because no tags were queued up. A positive return value is reserved | |
| 376 | +** for potential future semantics. | |
| 377 | +** | |
| 378 | +** This function asserts that a transaction is underway and it ends | |
| 379 | +** the transaction, committing or rolling back, as appropriate. | |
| 352 | 380 | */ |
| 353 | -static void branch_cmd_close(int nStartAtArg){ | |
| 354 | - int argPos = nStartAtArg; /* g.argv pos with first branch name */ | |
| 355 | - Blob manifest = empty_blob; /* Control artifact */ | |
| 381 | +static int branch_cmd_tag_finalize(int fDryRun /* roll back if true */, | |
| 382 | + int fVerbose /* output extra info */, | |
| 383 | + const char *zDateOvrd /* --date-override */, | |
| 384 | + const char *zUserOvrd /* --user-override */){ | |
| 385 | + int nTags = 0; | |
| 356 | 386 | Stmt q = empty_Stmt; |
| 357 | - int nQueued = 0; /* # of branches queued for closing */ | |
| 358 | - char * zUuid = 0; /* Resolved branch UUID. */ | |
| 359 | - const int fVerbose = find_option("verbose","v",0)!=0; | |
| 360 | - const int fDryRun = find_option("dry-run","n",0)!=0; | |
| 361 | - const char *zDateOvrd = find_option("date-override",0,1); | |
| 362 | - const char *zUserOvrd = find_option("user-override",0,1); | |
| 363 | - int doRollback = fDryRun!=0; /* Roll back transaction if true */ | |
| 364 | - | |
| 365 | - verify_all_options(); | |
| 366 | - db_begin_transaction(); | |
| 367 | - db_multi_exec("CREATE TEMP TABLE brclose(" | |
| 368 | - "rid INTEGER UNIQUE ON CONFLICT IGNORE" | |
| 369 | - ")"); | |
| 370 | - db_prepare(&q, "INSERT INTO brclose(rid) VALUES(:rid)"); | |
| 371 | - for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){ | |
| 372 | - const char * zBranch = g.argv[argPos]; | |
| 373 | - const int rid = name_to_uuid2(zBranch, "ci", &zUuid); | |
| 374 | - if(0==rid){ | |
| 375 | - fossil_fatal("Cannot resolve branch name: %s", zBranch); | |
| 376 | - }else if(rid<0){ | |
| 377 | - fossil_fatal("Ambiguous branch name: %s", zBranch); | |
| 378 | - }else if(!is_a_leaf(rid)){ | |
| 379 | - fossil_warning("Skipping non-leaf [%s] %s", zBranch, zUuid); | |
| 380 | - continue; | |
| 381 | - }else if(leaf_is_closed(rid)){ | |
| 382 | - fossil_warning("Skipping closed [%s] %s", zBranch, zUuid); | |
| 383 | - continue; | |
| 384 | - } | |
| 385 | - ++nQueued; | |
| 386 | - db_bind_int(&q, ":rid", rid); | |
| 387 | - db_step(&q); | |
| 388 | - db_reset(&q); | |
| 389 | - if(fVerbose!=0){ | |
| 390 | - fossil_print("Closing branch [%s] %s\n", zBranch, zUuid); | |
| 391 | - } | |
| 392 | - } | |
| 393 | - db_finalize(&q); | |
| 394 | - if(!nQueued){ | |
| 395 | - fossil_warning("No branches queued for closing. Nothing to do."); | |
| 396 | - doRollback = 1; | |
| 397 | - goto br_close_end; | |
| 398 | - } | |
| 387 | + Blob manifest = empty_blob; | |
| 388 | + int doRollback = fDryRun!=0; | |
| 389 | + | |
| 390 | + assert(db_transaction_nesting_depth() > 0); | |
| 391 | + if(!db_table_exists("temp","brcmdtag")){ | |
| 392 | + fossil_warning("No tags added - nothing to do."); | |
| 393 | + db_end_transaction(1); | |
| 394 | + return -1; | |
| 395 | + } | |
| 396 | + db_prepare(&q, "SELECT b.uuid, t.tag " | |
| 397 | + "FROM blob b, brcmdtag t " | |
| 398 | + "WHERE b.rid=t.rid " | |
| 399 | + "ORDER BY t.tag, b.uuid"); | |
| 399 | 400 | blob_appendf(&manifest, "D %z\n", |
| 400 | 401 | date_in_standard_format( zDateOvrd ? zDateOvrd : "now")); |
| 401 | - db_prepare(&q, "SELECT uuid FROM blob WHERE rid IN brclose"); | |
| 402 | 402 | while(SQLITE_ROW==db_step(&q)){ |
| 403 | 403 | const char * zHash = db_column_text(&q, 0); |
| 404 | - blob_appendf(&manifest, "T +closed %s\n", zHash); | |
| 404 | + const char * zTag = db_column_text(&q, 1); | |
| 405 | + blob_appendf(&manifest, "T %s %s\n", zTag, zHash); | |
| 406 | + ++nTags; | |
| 405 | 407 | } |
| 406 | - db_finalize(&q); | |
| 408 | + if(!nTags){ | |
| 409 | + fossil_warning("No tags added - nothing to do."); | |
| 410 | + db_end_transaction(1); | |
| 411 | + blob_reset(&manifest); | |
| 412 | + return -1; | |
| 413 | + } | |
| 407 | 414 | user_select(); |
| 408 | - blob_appendf(&manifest, "U %F\n", | |
| 409 | - zUserOvrd ? zUserOvrd : login_name()); | |
| 415 | + blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name()); | |
| 410 | 416 | { /* Z-card and save artifact */ |
| 411 | 417 | int newRid; |
| 412 | 418 | Blob cksum = empty_blob; |
| 413 | 419 | md5sum_blob(&manifest, &cksum); |
| 414 | 420 | blob_appendf(&manifest, "Z %b\n", &cksum); |
| @@ -427,19 +433,56 @@ | ||
| 427 | 433 | }else if(manifest_crosslink(newRid, &manifest, 0)==0){ |
| 428 | 434 | fossil_fatal("Crosslinking error: %s", g.zErrMsg); |
| 429 | 435 | } |
| 430 | 436 | fossil_print("Saved new control artifact %z (RID %d).\n", |
| 431 | 437 | rid_to_uuid(newRid), newRid); |
| 438 | + db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", newRid); | |
| 432 | 439 | if(fDryRun){ |
| 433 | 440 | fossil_print("Dry-run mode: rolling back new artifact.\n"); |
| 434 | - assert(doRollback!=0); | |
| 441 | + assert(0!=doRollback); | |
| 435 | 442 | } |
| 436 | 443 | } |
| 444 | + db_multi_exec("DROP TABLE brcmdtag"); | |
| 437 | 445 | blob_reset(&manifest); |
| 438 | - br_close_end: | |
| 439 | - db_multi_exec("DROP TABLE brclose"); | |
| 440 | 446 | db_end_transaction(doRollback); |
| 447 | + return 0; | |
| 448 | +} | |
| 449 | + | |
| 450 | +/* | |
| 451 | +** Implementation of (branch close) subcommand. nStartAtArg is the | |
| 452 | +** g.argv index to start reading branch names. Fails fatally on error. | |
| 453 | +*/ | |
| 454 | +static void branch_cmd_close(int nStartAtArg){ | |
| 455 | + int argPos = nStartAtArg; /* g.argv pos with first branch name */ | |
| 456 | + char * zUuid = 0; /* Resolved branch UUID. */ | |
| 457 | + const int fVerbose = find_option("verbose","v",0)!=0; | |
| 458 | + const int fDryRun = find_option("dry-run","n",0)!=0; | |
| 459 | + const char *zDateOvrd = find_option("date-override",0,1); | |
| 460 | + const char *zUserOvrd = find_option("user-override",0,1); | |
| 461 | + | |
| 462 | + verify_all_options(); | |
| 463 | + db_begin_transaction(); | |
| 464 | + for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){ | |
| 465 | + const char * zBranch = g.argv[argPos]; | |
| 466 | + const int rid = name_to_uuid2(zBranch, "ci", &zUuid); | |
| 467 | + if(0==rid){ | |
| 468 | + fossil_fatal("Cannot resolve branch name: %s", zBranch); | |
| 469 | + }else if(rid<0){ | |
| 470 | + fossil_fatal("Ambiguous branch name: %s", zBranch); | |
| 471 | + }else if(!is_a_leaf(rid)){ | |
| 472 | + fossil_warning("Skipping non-leaf [%s] %s", zBranch, zUuid); | |
| 473 | + continue; | |
| 474 | + }else if(leaf_is_closed(rid)){ | |
| 475 | + fossil_warning("Skipping closed [%s] %s", zBranch, zUuid); | |
| 476 | + continue; | |
| 477 | + } | |
| 478 | + branch_cmd_tag_add(rid, "+closed"); | |
| 479 | + if(fVerbose!=0){ | |
| 480 | + fossil_print("Closing branch [%s] %s\n", zBranch, zUuid); | |
| 481 | + } | |
| 482 | + } | |
| 483 | + branch_cmd_tag_finalize(fDryRun, fVerbose, zDateOvrd, zUserOvrd); | |
| 441 | 484 | } |
| 442 | 485 | |
| 443 | 486 | /* |
| 444 | 487 | ** COMMAND: branch |
| 445 | 488 | ** |
| 446 | 489 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -345,70 +345,76 @@ | |
| 345 | TAG_BRANCH, zBrName, TAG_CLOSED |
| 346 | ); |
| 347 | } |
| 348 | |
| 349 | /* |
| 350 | ** Implementation of (branch close) subcommand. nStartAtArg is the |
| 351 | ** g.argv index to start reading branch names. Fails fatally on error. |
| 352 | */ |
| 353 | static void branch_cmd_close(int nStartAtArg){ |
| 354 | int argPos = nStartAtArg; /* g.argv pos with first branch name */ |
| 355 | Blob manifest = empty_blob; /* Control artifact */ |
| 356 | Stmt q = empty_Stmt; |
| 357 | int nQueued = 0; /* # of branches queued for closing */ |
| 358 | char * zUuid = 0; /* Resolved branch UUID. */ |
| 359 | const int fVerbose = find_option("verbose","v",0)!=0; |
| 360 | const int fDryRun = find_option("dry-run","n",0)!=0; |
| 361 | const char *zDateOvrd = find_option("date-override",0,1); |
| 362 | const char *zUserOvrd = find_option("user-override",0,1); |
| 363 | int doRollback = fDryRun!=0; /* Roll back transaction if true */ |
| 364 | |
| 365 | verify_all_options(); |
| 366 | db_begin_transaction(); |
| 367 | db_multi_exec("CREATE TEMP TABLE brclose(" |
| 368 | "rid INTEGER UNIQUE ON CONFLICT IGNORE" |
| 369 | ")"); |
| 370 | db_prepare(&q, "INSERT INTO brclose(rid) VALUES(:rid)"); |
| 371 | for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){ |
| 372 | const char * zBranch = g.argv[argPos]; |
| 373 | const int rid = name_to_uuid2(zBranch, "ci", &zUuid); |
| 374 | if(0==rid){ |
| 375 | fossil_fatal("Cannot resolve branch name: %s", zBranch); |
| 376 | }else if(rid<0){ |
| 377 | fossil_fatal("Ambiguous branch name: %s", zBranch); |
| 378 | }else if(!is_a_leaf(rid)){ |
| 379 | fossil_warning("Skipping non-leaf [%s] %s", zBranch, zUuid); |
| 380 | continue; |
| 381 | }else if(leaf_is_closed(rid)){ |
| 382 | fossil_warning("Skipping closed [%s] %s", zBranch, zUuid); |
| 383 | continue; |
| 384 | } |
| 385 | ++nQueued; |
| 386 | db_bind_int(&q, ":rid", rid); |
| 387 | db_step(&q); |
| 388 | db_reset(&q); |
| 389 | if(fVerbose!=0){ |
| 390 | fossil_print("Closing branch [%s] %s\n", zBranch, zUuid); |
| 391 | } |
| 392 | } |
| 393 | db_finalize(&q); |
| 394 | if(!nQueued){ |
| 395 | fossil_warning("No branches queued for closing. Nothing to do."); |
| 396 | doRollback = 1; |
| 397 | goto br_close_end; |
| 398 | } |
| 399 | blob_appendf(&manifest, "D %z\n", |
| 400 | date_in_standard_format( zDateOvrd ? zDateOvrd : "now")); |
| 401 | db_prepare(&q, "SELECT uuid FROM blob WHERE rid IN brclose"); |
| 402 | while(SQLITE_ROW==db_step(&q)){ |
| 403 | const char * zHash = db_column_text(&q, 0); |
| 404 | blob_appendf(&manifest, "T +closed %s\n", zHash); |
| 405 | } |
| 406 | db_finalize(&q); |
| 407 | user_select(); |
| 408 | blob_appendf(&manifest, "U %F\n", |
| 409 | zUserOvrd ? zUserOvrd : login_name()); |
| 410 | { /* Z-card and save artifact */ |
| 411 | int newRid; |
| 412 | Blob cksum = empty_blob; |
| 413 | md5sum_blob(&manifest, &cksum); |
| 414 | blob_appendf(&manifest, "Z %b\n", &cksum); |
| @@ -427,19 +433,56 @@ | |
| 427 | }else if(manifest_crosslink(newRid, &manifest, 0)==0){ |
| 428 | fossil_fatal("Crosslinking error: %s", g.zErrMsg); |
| 429 | } |
| 430 | fossil_print("Saved new control artifact %z (RID %d).\n", |
| 431 | rid_to_uuid(newRid), newRid); |
| 432 | if(fDryRun){ |
| 433 | fossil_print("Dry-run mode: rolling back new artifact.\n"); |
| 434 | assert(doRollback!=0); |
| 435 | } |
| 436 | } |
| 437 | blob_reset(&manifest); |
| 438 | br_close_end: |
| 439 | db_multi_exec("DROP TABLE brclose"); |
| 440 | db_end_transaction(doRollback); |
| 441 | } |
| 442 | |
| 443 | /* |
| 444 | ** COMMAND: branch |
| 445 | ** |
| 446 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -345,70 +345,76 @@ | |
| 345 | TAG_BRANCH, zBrName, TAG_CLOSED |
| 346 | ); |
| 347 | } |
| 348 | |
| 349 | /* |
| 350 | ** Internal helper for branch_cmd_close() and friends. Adds a row to |
| 351 | ** the to the brcmdtag TEMP table, initializing that table if needed, |
| 352 | ** holding a pending tag for the given blob.rid (which is assumed to |
| 353 | ** be valid). zTag must be a fully-formed tag name, including the |
| 354 | ** (+,-,*) prefix character. |
| 355 | ** |
| 356 | */ |
| 357 | static void branch_cmd_tag_add(int rid, const char *zTag){ |
| 358 | static int once = 0; |
| 359 | assert(zTag && ('+'==zTag[0] || '-'==zTag[0] || '*'==zTag[0])); |
| 360 | if(0==once++){ |
| 361 | db_multi_exec("CREATE TEMP TABLE brcmdtag(" |
| 362 | "rid INTEGER UNIQUE ON CONFLICT IGNORE," |
| 363 | "tag TEXT NOT NULL" |
| 364 | ")"); |
| 365 | } |
| 366 | db_multi_exec("INSERT INTO brcmdtag(rid,tag) VALUES(%d,%Q)", |
| 367 | rid, zTag); |
| 368 | } |
| 369 | |
| 370 | /* |
| 371 | ** Internal helper for branch_cmd_close() and friends. Creates and |
| 372 | ** saves a control artifact of tag changes stored via |
| 373 | ** branch_cmd_tag_add(). Fails fatally on error, returns 0 if it saves |
| 374 | ** an artifact, and a negative value if it does not save anything |
| 375 | ** because no tags were queued up. A positive return value is reserved |
| 376 | ** for potential future semantics. |
| 377 | ** |
| 378 | ** This function asserts that a transaction is underway and it ends |
| 379 | ** the transaction, committing or rolling back, as appropriate. |
| 380 | */ |
| 381 | static int branch_cmd_tag_finalize(int fDryRun /* roll back if true */, |
| 382 | int fVerbose /* output extra info */, |
| 383 | const char *zDateOvrd /* --date-override */, |
| 384 | const char *zUserOvrd /* --user-override */){ |
| 385 | int nTags = 0; |
| 386 | Stmt q = empty_Stmt; |
| 387 | Blob manifest = empty_blob; |
| 388 | int doRollback = fDryRun!=0; |
| 389 | |
| 390 | assert(db_transaction_nesting_depth() > 0); |
| 391 | if(!db_table_exists("temp","brcmdtag")){ |
| 392 | fossil_warning("No tags added - nothing to do."); |
| 393 | db_end_transaction(1); |
| 394 | return -1; |
| 395 | } |
| 396 | db_prepare(&q, "SELECT b.uuid, t.tag " |
| 397 | "FROM blob b, brcmdtag t " |
| 398 | "WHERE b.rid=t.rid " |
| 399 | "ORDER BY t.tag, b.uuid"); |
| 400 | blob_appendf(&manifest, "D %z\n", |
| 401 | date_in_standard_format( zDateOvrd ? zDateOvrd : "now")); |
| 402 | while(SQLITE_ROW==db_step(&q)){ |
| 403 | const char * zHash = db_column_text(&q, 0); |
| 404 | const char * zTag = db_column_text(&q, 1); |
| 405 | blob_appendf(&manifest, "T %s %s\n", zTag, zHash); |
| 406 | ++nTags; |
| 407 | } |
| 408 | if(!nTags){ |
| 409 | fossil_warning("No tags added - nothing to do."); |
| 410 | db_end_transaction(1); |
| 411 | blob_reset(&manifest); |
| 412 | return -1; |
| 413 | } |
| 414 | user_select(); |
| 415 | blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name()); |
| 416 | { /* Z-card and save artifact */ |
| 417 | int newRid; |
| 418 | Blob cksum = empty_blob; |
| 419 | md5sum_blob(&manifest, &cksum); |
| 420 | blob_appendf(&manifest, "Z %b\n", &cksum); |
| @@ -427,19 +433,56 @@ | |
| 433 | }else if(manifest_crosslink(newRid, &manifest, 0)==0){ |
| 434 | fossil_fatal("Crosslinking error: %s", g.zErrMsg); |
| 435 | } |
| 436 | fossil_print("Saved new control artifact %z (RID %d).\n", |
| 437 | rid_to_uuid(newRid), newRid); |
| 438 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", newRid); |
| 439 | if(fDryRun){ |
| 440 | fossil_print("Dry-run mode: rolling back new artifact.\n"); |
| 441 | assert(0!=doRollback); |
| 442 | } |
| 443 | } |
| 444 | db_multi_exec("DROP TABLE brcmdtag"); |
| 445 | blob_reset(&manifest); |
| 446 | db_end_transaction(doRollback); |
| 447 | return 0; |
| 448 | } |
| 449 | |
| 450 | /* |
| 451 | ** Implementation of (branch close) subcommand. nStartAtArg is the |
| 452 | ** g.argv index to start reading branch names. Fails fatally on error. |
| 453 | */ |
| 454 | static void branch_cmd_close(int nStartAtArg){ |
| 455 | int argPos = nStartAtArg; /* g.argv pos with first branch name */ |
| 456 | char * zUuid = 0; /* Resolved branch UUID. */ |
| 457 | const int fVerbose = find_option("verbose","v",0)!=0; |
| 458 | const int fDryRun = find_option("dry-run","n",0)!=0; |
| 459 | const char *zDateOvrd = find_option("date-override",0,1); |
| 460 | const char *zUserOvrd = find_option("user-override",0,1); |
| 461 | |
| 462 | verify_all_options(); |
| 463 | db_begin_transaction(); |
| 464 | for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){ |
| 465 | const char * zBranch = g.argv[argPos]; |
| 466 | const int rid = name_to_uuid2(zBranch, "ci", &zUuid); |
| 467 | if(0==rid){ |
| 468 | fossil_fatal("Cannot resolve branch name: %s", zBranch); |
| 469 | }else if(rid<0){ |
| 470 | fossil_fatal("Ambiguous branch name: %s", zBranch); |
| 471 | }else if(!is_a_leaf(rid)){ |
| 472 | fossil_warning("Skipping non-leaf [%s] %s", zBranch, zUuid); |
| 473 | continue; |
| 474 | }else if(leaf_is_closed(rid)){ |
| 475 | fossil_warning("Skipping closed [%s] %s", zBranch, zUuid); |
| 476 | continue; |
| 477 | } |
| 478 | branch_cmd_tag_add(rid, "+closed"); |
| 479 | if(fVerbose!=0){ |
| 480 | fossil_print("Closing branch [%s] %s\n", zBranch, zUuid); |
| 481 | } |
| 482 | } |
| 483 | branch_cmd_tag_finalize(fDryRun, fVerbose, zDateOvrd, zUserOvrd); |
| 484 | } |
| 485 | |
| 486 | /* |
| 487 | ** COMMAND: branch |
| 488 | ** |
| 489 |