Fossil SCM
Improvements to the "stash" command: (1) Stash all files, not just those below the working directory. (2) Add the --detail option to "list". (3) Confirm before "drop --all". (4) Add the "help" subcommand.
Commit
966ae9a942d3c840f2a3aad6b80f592991864394
Parent
b2581e1553df477…
1 file changed
+56
-26
+56
-26
| --- src/stash.c | ||
| +++ src/stash.c | ||
| @@ -170,11 +170,11 @@ | ||
| 170 | 170 | int i; |
| 171 | 171 | for(i=3; i<g.argc; i++){ |
| 172 | 172 | stash_add_file_or_dir(stashid, vid, g.argv[i]); |
| 173 | 173 | } |
| 174 | 174 | }else{ |
| 175 | - stash_add_file_or_dir(stashid, vid, "."); | |
| 175 | + stash_add_file_or_dir(stashid, vid, g.zLocalRoot); | |
| 176 | 176 | } |
| 177 | 177 | return stashid; |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | 180 | /* |
| @@ -258,12 +258,13 @@ | ||
| 258 | 258 | file_delete(zOPath); |
| 259 | 259 | } |
| 260 | 260 | } |
| 261 | 261 | db_finalize(&q); |
| 262 | 262 | if( nConflict ){ |
| 263 | - fossil_print("WARNING: %d merge conflicts - see messages above for details.\n", | |
| 264 | - nConflict); | |
| 263 | + fossil_print( | |
| 264 | + "WARNING: %d merge conflicts - see messages above for details.\n", | |
| 265 | + nConflict); | |
| 265 | 266 | } |
| 266 | 267 | } |
| 267 | 268 | |
| 268 | 269 | /* |
| 269 | 270 | ** Show the diffs associate with a single stash. |
| @@ -363,35 +364,32 @@ | ||
| 363 | 364 | ** |
| 364 | 365 | ** Usage: %fossil stash SUBCOMMAND ARGS... |
| 365 | 366 | ** |
| 366 | 367 | ** fossil stash |
| 367 | 368 | ** fossil stash save ?-m COMMENT? ?FILES...? |
| 369 | +** fossil stash snapshot ?-m COMMENT? ?FILES...? | |
| 368 | 370 | ** |
| 369 | 371 | ** Save the current changes in the working tree as a new stash. |
| 370 | 372 | ** Then revert the changes back to the last check-in. If FILES |
| 371 | 373 | ** are listed, then only stash and revert the named files. The |
| 372 | 374 | ** "save" verb can be omitted if and only if there are no other |
| 373 | -** arguments. | |
| 375 | +** arguments. The "snapshot" verb works the same as "save" but | |
| 376 | +** omits the revert, keeping the check-out unchanged. | |
| 374 | 377 | ** |
| 375 | -** fossil stash list | |
| 376 | -** fossil stash ls | |
| 378 | +** fossil stash list ?--detail? | |
| 379 | +** fossil stash ls ?-l? | |
| 377 | 380 | ** |
| 378 | -** List all changes sets currently stashed. | |
| 381 | +** List all changes sets currently stashed. Show information about | |
| 382 | +** individual files in each changeset if --detail or -l is used. | |
| 379 | 383 | ** |
| 380 | 384 | ** fossil stash pop |
| 381 | -** | |
| 382 | -** Apply the most recently create stash to the current working | |
| 383 | -** check-out. Then delete that stash. This is equivalent to | |
| 384 | -** doing an "apply" and a "drop" against the most recent stash. | |
| 385 | -** This command is undoable. | |
| 386 | -** | |
| 387 | 385 | ** fossil stash apply ?STASHID? |
| 388 | 386 | ** |
| 389 | -** Apply the identified stash to the current working check-out. | |
| 390 | -** If no STASHID is specified, use the most recent stash. Unlike | |
| 391 | -** the "pop" command, the stash is retained so that it can be used | |
| 392 | -** again. This command is undoable. | |
| 387 | +** Apply STASHID or the most recently create stash to the current | |
| 388 | +** working check-out. The "pop" command deletes that changeset from | |
| 389 | +** the stash after applying it but the "apply" command retains the | |
| 390 | +** changeset. | |
| 393 | 391 | ** |
| 394 | 392 | ** fossil stash goto ?STASHID? |
| 395 | 393 | ** |
| 396 | 394 | ** Update to the baseline checkout for STASHID then apply the |
| 397 | 395 | ** changes of STASHID. Keep STASHID so that it can be reused |
| @@ -401,15 +399,10 @@ | ||
| 401 | 399 | ** fossil stash rm ?STASHID? ?--all? |
| 402 | 400 | ** |
| 403 | 401 | ** Forget everything about STASHID. Forget the whole stash if the |
| 404 | 402 | ** --all flag is used. Individual drops are undoable but --all is not. |
| 405 | 403 | ** |
| 406 | -** fossil stash snapshot ?-m COMMENT? ?FILES...? | |
| 407 | -** | |
| 408 | -** Save the current changes in the working tree as a new stash | |
| 409 | -** but, unlike "save", do not revert those changes. | |
| 410 | -** | |
| 411 | 404 | ** fossil stash diff ?STASHID? |
| 412 | 405 | ** fossil stash gdiff ?STASHID? |
| 413 | 406 | ** |
| 414 | 407 | ** Show diffs of the current working directory and what that |
| 415 | 408 | ** directory would be if STASHID were applied. |
| @@ -455,40 +448,71 @@ | ||
| 455 | 448 | }else |
| 456 | 449 | if( memcmp(zCmd, "snapshot", nCmd)==0 ){ |
| 457 | 450 | stash_create(); |
| 458 | 451 | }else |
| 459 | 452 | if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){ |
| 460 | - Stmt q; | |
| 453 | + Stmt q, q2; | |
| 461 | 454 | int n = 0; |
| 455 | + int fDetail = find_option("detail","l",0)!=0; | |
| 462 | 456 | verify_all_options(); |
| 463 | 457 | db_prepare(&q, |
| 464 | 458 | "SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid)," |
| 465 | 459 | " comment, datetime(ctime) FROM stash" |
| 466 | 460 | " ORDER BY ctime DESC" |
| 467 | 461 | ); |
| 462 | + if( fDetail ){ | |
| 463 | + db_prepare(&q2, "SELECT isAdded, isRemoved, origname, newname" | |
| 464 | + " FROM stashfile WHERE stashid=$id"); | |
| 465 | + } | |
| 468 | 466 | while( db_step(&q)==SQLITE_ROW ){ |
| 467 | + int stashid = db_column_int(&q, 0); | |
| 469 | 468 | const char *zCom; |
| 470 | 469 | n++; |
| 471 | 470 | fossil_print("%5d: [%.14s] on %s\n", |
| 472 | - db_column_int(&q, 0), | |
| 471 | + stashid, | |
| 473 | 472 | db_column_text(&q, 1), |
| 474 | 473 | db_column_text(&q, 3) |
| 475 | 474 | ); |
| 476 | 475 | zCom = db_column_text(&q, 2); |
| 477 | 476 | if( zCom && zCom[0] ){ |
| 478 | 477 | fossil_print(" "); |
| 479 | 478 | comment_print(zCom, 7, 79); |
| 480 | 479 | } |
| 480 | + if( fDetail ){ | |
| 481 | + db_bind_int(&q2, "$id", stashid); | |
| 482 | + while( db_step(&q2)==SQLITE_ROW ){ | |
| 483 | + int isAdded = db_column_int(&q2, 0); | |
| 484 | + int isRemoved = db_column_int(&q2, 1); | |
| 485 | + const char *zOrig = db_column_text(&q2, 2); | |
| 486 | + const char *zNew = db_column_text(&q2, 3); | |
| 487 | + if( isAdded ){ | |
| 488 | + fossil_print(" ADD %s\n", zNew); | |
| 489 | + }else if( isRemoved ){ | |
| 490 | + fossil_print(" REMOVE %s\n", zOrig); | |
| 491 | + }else if( fossil_strcmp(zOrig,zNew)!=0 ){ | |
| 492 | + fossil_print(" RENAME %s -> %s\n", zOrig, zNew); | |
| 493 | + }else{ | |
| 494 | + fossil_print(" EDIT %s\n", zOrig); | |
| 495 | + } | |
| 496 | + } | |
| 497 | + db_reset(&q2); | |
| 498 | + } | |
| 481 | 499 | } |
| 482 | 500 | db_finalize(&q); |
| 501 | + if( fDetail ) db_finalize(&q2); | |
| 483 | 502 | if( n==0 ) fossil_print("empty stash\n"); |
| 484 | 503 | }else |
| 485 | 504 | if( memcmp(zCmd, "drop", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){ |
| 486 | 505 | int allFlag = find_option("all", 0, 0)!=0; |
| 487 | - if( g.argc>4 ) usage("apply STASHID"); | |
| 506 | + if( g.argc>4 ) usage("drop STASHID"); | |
| 488 | 507 | if( allFlag ){ |
| 489 | - db_multi_exec("DELETE FROM stash; DELETE FROM stashfile;"); | |
| 508 | + Blob ans; | |
| 509 | + blob_zero(&ans); | |
| 510 | + prompt_user("This action is not undoable. Continue (y/N)? ", &ans); | |
| 511 | + if( blob_str(&ans)[0]=='y' ){ | |
| 512 | + db_multi_exec("DELETE FROM stash; DELETE FROM stashfile;"); | |
| 513 | + } | |
| 490 | 514 | }else{ |
| 491 | 515 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 492 | 516 | undo_begin(); |
| 493 | 517 | undo_save_stash(stashid); |
| 494 | 518 | stash_drop(stashid); |
| @@ -537,11 +561,17 @@ | ||
| 537 | 561 | const char *zDiffCmd = db_get("gdiff-command", 0); |
| 538 | 562 | int diffFlags = diff_options(); |
| 539 | 563 | if( g.argc>4 ) usage("diff STASHID"); |
| 540 | 564 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 541 | 565 | stash_diff(stashid, zDiffCmd, diffFlags); |
| 566 | + }else | |
| 567 | + if( memcmp(zCmd, "help", nCmd)==0 ){ | |
| 568 | + g.argv[1] = "help"; | |
| 569 | + g.argv[2] = "stash"; | |
| 570 | + g.argc = 3; | |
| 571 | + help_cmd(); | |
| 542 | 572 | }else |
| 543 | 573 | { |
| 544 | 574 | usage("SUBCOMMAND ARGS..."); |
| 545 | 575 | } |
| 546 | 576 | db_end_transaction(0); |
| 547 | 577 | } |
| 548 | 578 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -170,11 +170,11 @@ | |
| 170 | int i; |
| 171 | for(i=3; i<g.argc; i++){ |
| 172 | stash_add_file_or_dir(stashid, vid, g.argv[i]); |
| 173 | } |
| 174 | }else{ |
| 175 | stash_add_file_or_dir(stashid, vid, "."); |
| 176 | } |
| 177 | return stashid; |
| 178 | } |
| 179 | |
| 180 | /* |
| @@ -258,12 +258,13 @@ | |
| 258 | file_delete(zOPath); |
| 259 | } |
| 260 | } |
| 261 | db_finalize(&q); |
| 262 | if( nConflict ){ |
| 263 | fossil_print("WARNING: %d merge conflicts - see messages above for details.\n", |
| 264 | nConflict); |
| 265 | } |
| 266 | } |
| 267 | |
| 268 | /* |
| 269 | ** Show the diffs associate with a single stash. |
| @@ -363,35 +364,32 @@ | |
| 363 | ** |
| 364 | ** Usage: %fossil stash SUBCOMMAND ARGS... |
| 365 | ** |
| 366 | ** fossil stash |
| 367 | ** fossil stash save ?-m COMMENT? ?FILES...? |
| 368 | ** |
| 369 | ** Save the current changes in the working tree as a new stash. |
| 370 | ** Then revert the changes back to the last check-in. If FILES |
| 371 | ** are listed, then only stash and revert the named files. The |
| 372 | ** "save" verb can be omitted if and only if there are no other |
| 373 | ** arguments. |
| 374 | ** |
| 375 | ** fossil stash list |
| 376 | ** fossil stash ls |
| 377 | ** |
| 378 | ** List all changes sets currently stashed. |
| 379 | ** |
| 380 | ** fossil stash pop |
| 381 | ** |
| 382 | ** Apply the most recently create stash to the current working |
| 383 | ** check-out. Then delete that stash. This is equivalent to |
| 384 | ** doing an "apply" and a "drop" against the most recent stash. |
| 385 | ** This command is undoable. |
| 386 | ** |
| 387 | ** fossil stash apply ?STASHID? |
| 388 | ** |
| 389 | ** Apply the identified stash to the current working check-out. |
| 390 | ** If no STASHID is specified, use the most recent stash. Unlike |
| 391 | ** the "pop" command, the stash is retained so that it can be used |
| 392 | ** again. This command is undoable. |
| 393 | ** |
| 394 | ** fossil stash goto ?STASHID? |
| 395 | ** |
| 396 | ** Update to the baseline checkout for STASHID then apply the |
| 397 | ** changes of STASHID. Keep STASHID so that it can be reused |
| @@ -401,15 +399,10 @@ | |
| 401 | ** fossil stash rm ?STASHID? ?--all? |
| 402 | ** |
| 403 | ** Forget everything about STASHID. Forget the whole stash if the |
| 404 | ** --all flag is used. Individual drops are undoable but --all is not. |
| 405 | ** |
| 406 | ** fossil stash snapshot ?-m COMMENT? ?FILES...? |
| 407 | ** |
| 408 | ** Save the current changes in the working tree as a new stash |
| 409 | ** but, unlike "save", do not revert those changes. |
| 410 | ** |
| 411 | ** fossil stash diff ?STASHID? |
| 412 | ** fossil stash gdiff ?STASHID? |
| 413 | ** |
| 414 | ** Show diffs of the current working directory and what that |
| 415 | ** directory would be if STASHID were applied. |
| @@ -455,40 +448,71 @@ | |
| 455 | }else |
| 456 | if( memcmp(zCmd, "snapshot", nCmd)==0 ){ |
| 457 | stash_create(); |
| 458 | }else |
| 459 | if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){ |
| 460 | Stmt q; |
| 461 | int n = 0; |
| 462 | verify_all_options(); |
| 463 | db_prepare(&q, |
| 464 | "SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid)," |
| 465 | " comment, datetime(ctime) FROM stash" |
| 466 | " ORDER BY ctime DESC" |
| 467 | ); |
| 468 | while( db_step(&q)==SQLITE_ROW ){ |
| 469 | const char *zCom; |
| 470 | n++; |
| 471 | fossil_print("%5d: [%.14s] on %s\n", |
| 472 | db_column_int(&q, 0), |
| 473 | db_column_text(&q, 1), |
| 474 | db_column_text(&q, 3) |
| 475 | ); |
| 476 | zCom = db_column_text(&q, 2); |
| 477 | if( zCom && zCom[0] ){ |
| 478 | fossil_print(" "); |
| 479 | comment_print(zCom, 7, 79); |
| 480 | } |
| 481 | } |
| 482 | db_finalize(&q); |
| 483 | if( n==0 ) fossil_print("empty stash\n"); |
| 484 | }else |
| 485 | if( memcmp(zCmd, "drop", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){ |
| 486 | int allFlag = find_option("all", 0, 0)!=0; |
| 487 | if( g.argc>4 ) usage("apply STASHID"); |
| 488 | if( allFlag ){ |
| 489 | db_multi_exec("DELETE FROM stash; DELETE FROM stashfile;"); |
| 490 | }else{ |
| 491 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 492 | undo_begin(); |
| 493 | undo_save_stash(stashid); |
| 494 | stash_drop(stashid); |
| @@ -537,11 +561,17 @@ | |
| 537 | const char *zDiffCmd = db_get("gdiff-command", 0); |
| 538 | int diffFlags = diff_options(); |
| 539 | if( g.argc>4 ) usage("diff STASHID"); |
| 540 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 541 | stash_diff(stashid, zDiffCmd, diffFlags); |
| 542 | }else |
| 543 | { |
| 544 | usage("SUBCOMMAND ARGS..."); |
| 545 | } |
| 546 | db_end_transaction(0); |
| 547 | } |
| 548 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -170,11 +170,11 @@ | |
| 170 | int i; |
| 171 | for(i=3; i<g.argc; i++){ |
| 172 | stash_add_file_or_dir(stashid, vid, g.argv[i]); |
| 173 | } |
| 174 | }else{ |
| 175 | stash_add_file_or_dir(stashid, vid, g.zLocalRoot); |
| 176 | } |
| 177 | return stashid; |
| 178 | } |
| 179 | |
| 180 | /* |
| @@ -258,12 +258,13 @@ | |
| 258 | file_delete(zOPath); |
| 259 | } |
| 260 | } |
| 261 | db_finalize(&q); |
| 262 | if( nConflict ){ |
| 263 | fossil_print( |
| 264 | "WARNING: %d merge conflicts - see messages above for details.\n", |
| 265 | nConflict); |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | /* |
| 270 | ** Show the diffs associate with a single stash. |
| @@ -363,35 +364,32 @@ | |
| 364 | ** |
| 365 | ** Usage: %fossil stash SUBCOMMAND ARGS... |
| 366 | ** |
| 367 | ** fossil stash |
| 368 | ** fossil stash save ?-m COMMENT? ?FILES...? |
| 369 | ** fossil stash snapshot ?-m COMMENT? ?FILES...? |
| 370 | ** |
| 371 | ** Save the current changes in the working tree as a new stash. |
| 372 | ** Then revert the changes back to the last check-in. If FILES |
| 373 | ** are listed, then only stash and revert the named files. The |
| 374 | ** "save" verb can be omitted if and only if there are no other |
| 375 | ** arguments. The "snapshot" verb works the same as "save" but |
| 376 | ** omits the revert, keeping the check-out unchanged. |
| 377 | ** |
| 378 | ** fossil stash list ?--detail? |
| 379 | ** fossil stash ls ?-l? |
| 380 | ** |
| 381 | ** List all changes sets currently stashed. Show information about |
| 382 | ** individual files in each changeset if --detail or -l is used. |
| 383 | ** |
| 384 | ** fossil stash pop |
| 385 | ** fossil stash apply ?STASHID? |
| 386 | ** |
| 387 | ** Apply STASHID or the most recently create stash to the current |
| 388 | ** working check-out. The "pop" command deletes that changeset from |
| 389 | ** the stash after applying it but the "apply" command retains the |
| 390 | ** changeset. |
| 391 | ** |
| 392 | ** fossil stash goto ?STASHID? |
| 393 | ** |
| 394 | ** Update to the baseline checkout for STASHID then apply the |
| 395 | ** changes of STASHID. Keep STASHID so that it can be reused |
| @@ -401,15 +399,10 @@ | |
| 399 | ** fossil stash rm ?STASHID? ?--all? |
| 400 | ** |
| 401 | ** Forget everything about STASHID. Forget the whole stash if the |
| 402 | ** --all flag is used. Individual drops are undoable but --all is not. |
| 403 | ** |
| 404 | ** fossil stash diff ?STASHID? |
| 405 | ** fossil stash gdiff ?STASHID? |
| 406 | ** |
| 407 | ** Show diffs of the current working directory and what that |
| 408 | ** directory would be if STASHID were applied. |
| @@ -455,40 +448,71 @@ | |
| 448 | }else |
| 449 | if( memcmp(zCmd, "snapshot", nCmd)==0 ){ |
| 450 | stash_create(); |
| 451 | }else |
| 452 | if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){ |
| 453 | Stmt q, q2; |
| 454 | int n = 0; |
| 455 | int fDetail = find_option("detail","l",0)!=0; |
| 456 | verify_all_options(); |
| 457 | db_prepare(&q, |
| 458 | "SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid)," |
| 459 | " comment, datetime(ctime) FROM stash" |
| 460 | " ORDER BY ctime DESC" |
| 461 | ); |
| 462 | if( fDetail ){ |
| 463 | db_prepare(&q2, "SELECT isAdded, isRemoved, origname, newname" |
| 464 | " FROM stashfile WHERE stashid=$id"); |
| 465 | } |
| 466 | while( db_step(&q)==SQLITE_ROW ){ |
| 467 | int stashid = db_column_int(&q, 0); |
| 468 | const char *zCom; |
| 469 | n++; |
| 470 | fossil_print("%5d: [%.14s] on %s\n", |
| 471 | stashid, |
| 472 | db_column_text(&q, 1), |
| 473 | db_column_text(&q, 3) |
| 474 | ); |
| 475 | zCom = db_column_text(&q, 2); |
| 476 | if( zCom && zCom[0] ){ |
| 477 | fossil_print(" "); |
| 478 | comment_print(zCom, 7, 79); |
| 479 | } |
| 480 | if( fDetail ){ |
| 481 | db_bind_int(&q2, "$id", stashid); |
| 482 | while( db_step(&q2)==SQLITE_ROW ){ |
| 483 | int isAdded = db_column_int(&q2, 0); |
| 484 | int isRemoved = db_column_int(&q2, 1); |
| 485 | const char *zOrig = db_column_text(&q2, 2); |
| 486 | const char *zNew = db_column_text(&q2, 3); |
| 487 | if( isAdded ){ |
| 488 | fossil_print(" ADD %s\n", zNew); |
| 489 | }else if( isRemoved ){ |
| 490 | fossil_print(" REMOVE %s\n", zOrig); |
| 491 | }else if( fossil_strcmp(zOrig,zNew)!=0 ){ |
| 492 | fossil_print(" RENAME %s -> %s\n", zOrig, zNew); |
| 493 | }else{ |
| 494 | fossil_print(" EDIT %s\n", zOrig); |
| 495 | } |
| 496 | } |
| 497 | db_reset(&q2); |
| 498 | } |
| 499 | } |
| 500 | db_finalize(&q); |
| 501 | if( fDetail ) db_finalize(&q2); |
| 502 | if( n==0 ) fossil_print("empty stash\n"); |
| 503 | }else |
| 504 | if( memcmp(zCmd, "drop", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){ |
| 505 | int allFlag = find_option("all", 0, 0)!=0; |
| 506 | if( g.argc>4 ) usage("drop STASHID"); |
| 507 | if( allFlag ){ |
| 508 | Blob ans; |
| 509 | blob_zero(&ans); |
| 510 | prompt_user("This action is not undoable. Continue (y/N)? ", &ans); |
| 511 | if( blob_str(&ans)[0]=='y' ){ |
| 512 | db_multi_exec("DELETE FROM stash; DELETE FROM stashfile;"); |
| 513 | } |
| 514 | }else{ |
| 515 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 516 | undo_begin(); |
| 517 | undo_save_stash(stashid); |
| 518 | stash_drop(stashid); |
| @@ -537,11 +561,17 @@ | |
| 561 | const char *zDiffCmd = db_get("gdiff-command", 0); |
| 562 | int diffFlags = diff_options(); |
| 563 | if( g.argc>4 ) usage("diff STASHID"); |
| 564 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 565 | stash_diff(stashid, zDiffCmd, diffFlags); |
| 566 | }else |
| 567 | if( memcmp(zCmd, "help", nCmd)==0 ){ |
| 568 | g.argv[1] = "help"; |
| 569 | g.argv[2] = "stash"; |
| 570 | g.argc = 3; |
| 571 | help_cmd(); |
| 572 | }else |
| 573 | { |
| 574 | usage("SUBCOMMAND ARGS..."); |
| 575 | } |
| 576 | db_end_transaction(0); |
| 577 | } |
| 578 |