Fossil SCM
Allow patches to be sent and received via standard input and standard output.
Commit
9180106327c3863cc4cc1b18b41508193639234ce4bbd95938ecb1b298d11de2
Parent
f5629790cc79116…
1 file changed
+87
-25
+87
-25
| --- src/patch.c | ||
| +++ src/patch.c | ||
| @@ -116,20 +116,20 @@ | ||
| 116 | 116 | ** named zOut. |
| 117 | 117 | */ |
| 118 | 118 | void patch_create(const char *zOut){ |
| 119 | 119 | int vid; |
| 120 | 120 | |
| 121 | - if( file_isdir(zOut, ExtFILE)!=0 ){ | |
| 121 | + if( zOut && file_isdir(zOut, ExtFILE)!=0 ){ | |
| 122 | 122 | fossil_fatal("patch file already exists: %s", zOut); |
| 123 | 123 | } |
| 124 | 124 | add_content_sql_commands(g.db); |
| 125 | 125 | deltafunc_init(g.db); |
| 126 | 126 | sqlite3_create_function(g.db, "read_co_file", 1, SQLITE_UTF8, 0, |
| 127 | 127 | readfileFunc, 0, 0); |
| 128 | 128 | sqlite3_create_function(g.db, "mkdelta", 2, SQLITE_UTF8, 0, |
| 129 | 129 | mkdeltaFunc, 0, 0); |
| 130 | - db_multi_exec("ATTACH %Q AS patch;", zOut); | |
| 130 | + db_multi_exec("ATTACH %Q AS patch;", zOut ? zOut : ":memory:"); | |
| 131 | 131 | db_multi_exec( |
| 132 | 132 | "PRAGMA patch.journal_mode=OFF;\n" |
| 133 | 133 | "PRAGMA patch.page_size=512;\n" |
| 134 | 134 | "CREATE TABLE patch.chng(\n" |
| 135 | 135 | " pathname TEXT,\n" /* Filename */ |
| @@ -189,25 +189,67 @@ | ||
| 189 | 189 | "INSERT INTO patch.patchmerge(type,mhash)" |
| 190 | 190 | " SELECT tmap.type,vmerge.mhash FROM vmerge, tmap" |
| 191 | 191 | " WHERE tmap.id=vmerge.id;" |
| 192 | 192 | ); |
| 193 | 193 | } |
| 194 | + | |
| 195 | + /* Write the database to standard output if zOut==0 */ | |
| 196 | + if( zOut==0 ){ | |
| 197 | + sqlite3_int64 sz; | |
| 198 | + unsigned char *pData; | |
| 199 | + pData = sqlite3_serialize(g.db, "patch", &sz, 0); | |
| 200 | + if( pData==0 ){ | |
| 201 | + fossil_fatal("out of memory"); | |
| 202 | + } | |
| 203 | + fossil_print("%025lld\n", sz); | |
| 204 | + fwrite(pData, sz, 1, stdout); | |
| 205 | + sqlite3_free(pData); | |
| 206 | + fflush(stdout); | |
| 207 | + } | |
| 194 | 208 | } |
| 195 | 209 | |
| 196 | 210 | /* |
| 197 | 211 | ** Attempt to load and validate a patchfile identified by the first |
| 198 | 212 | ** argument. |
| 199 | 213 | */ |
| 200 | 214 | void patch_attach(const char *zIn){ |
| 201 | 215 | Stmt q; |
| 202 | - if( !file_isfile(zIn, ExtFILE) ){ | |
| 203 | - fossil_fatal("no such file: %s", zIn); | |
| 204 | - } | |
| 205 | 216 | if( g.db==0 ){ |
| 206 | 217 | sqlite3_open(":memory:", &g.db); |
| 207 | 218 | } |
| 208 | - db_multi_exec("ATTACH %Q AS patch", zIn); | |
| 219 | + if( zIn==0 ){ | |
| 220 | + char zBuf[26]; | |
| 221 | + size_t n; | |
| 222 | + sqlite3_int64 sz; | |
| 223 | + unsigned char *aIn; | |
| 224 | + | |
| 225 | + n = fread(zBuf, sizeof(zBuf), 1, stdin); | |
| 226 | + if( n!=1 ){ | |
| 227 | + fossil_fatal("unable to read size of input\n"); | |
| 228 | + } | |
| 229 | + zBuf[sizeof(zBuf)-1] = 0; | |
| 230 | + sz = atoll(zBuf); | |
| 231 | + if( sz<512 || (sz%512)!=0 ){ | |
| 232 | + fossil_fatal("bad size for input: %lld", sz); | |
| 233 | + } | |
| 234 | + aIn = sqlite3_malloc64( sz ); | |
| 235 | + if( aIn==0 ){ | |
| 236 | + fossil_fatal("out of memory"); | |
| 237 | + } | |
| 238 | + n = fread(aIn, 1, sz, stdin); | |
| 239 | + if( n!=sz ){ | |
| 240 | + fossil_fatal("got only %lld of %lld input bytes", | |
| 241 | + (sqlite3_int64)n, sz); | |
| 242 | + } | |
| 243 | + db_multi_exec("ATTACH ':memory:' AS patch"); | |
| 244 | + sqlite3_deserialize(g.db, "patch", aIn, sz, sz, | |
| 245 | + SQLITE_DESERIALIZE_FREEONCLOSE); | |
| 246 | + }else if( !file_isfile(zIn, ExtFILE) ){ | |
| 247 | + fossil_fatal("no such file: %s", zIn); | |
| 248 | + }else{ | |
| 249 | + db_multi_exec("ATTACH %Q AS patch", zIn); | |
| 250 | + } | |
| 209 | 251 | db_prepare(&q, "PRAGMA patch.quick_check"); |
| 210 | 252 | while( db_step(&q)==SQLITE_ROW ){ |
| 211 | 253 | if( fossil_strcmp(db_column_text(&q,0),"ok")!=0 ){ |
| 212 | 254 | fossil_fatal("file %s is not a well-formed Fossil patchfile", zIn); |
| 213 | 255 | } |
| @@ -472,29 +514,31 @@ | ||
| 472 | 514 | ** This command is used to creates, view, and apply Fossil binary patches. |
| 473 | 515 | ** A Fossil binary patch is a single (binary) file that captures all of the |
| 474 | 516 | ** uncommitted changes of a check-out. Use Fossil binary patches to transfer |
| 475 | 517 | ** proposed or incomplete changes between machines for testing or analysis. |
| 476 | 518 | ** |
| 477 | -** > fossil patch create FILENAME | |
| 519 | +** > fossil patch create [DIRECTORY] FILENAME | |
| 478 | 520 | ** |
| 479 | 521 | ** Create a new binary patch in FILENAME that captures all uncommitted |
| 480 | -** changes in the current check-out. | |
| 522 | +** changes in the check-out at DIRECTORY, or the current directory if | |
| 523 | +** DIRECTORY is omitted. | |
| 524 | +** | |
| 525 | +** If FILENAME is "-" then the binary patch is written to standard | |
| 526 | +** output, preceeded by 26 bytes of header that is an ASCII | |
| 527 | +** representation of the number of bytes in the patch followed by a | |
| 528 | +** newline. | |
| 481 | 529 | ** |
| 482 | -** > fossil patch apply FILENAME | |
| 530 | +** > fossil patch apply [DIRECTORY] FILENAME | |
| 483 | 531 | ** |
| 484 | -** Apply the changes in FILENAME to the current check-out. Options: | |
| 532 | +** Apply the changes in FILENAME to the check-out a DIRECTORY, or | |
| 533 | +** in the current directory if DIRECTORY is omitted. Options: | |
| 485 | 534 | ** |
| 486 | 535 | ** -f|--force Apply the patch even though there are unsaved |
| 487 | 536 | ** changes in the current check-out. |
| 488 | 537 | ** -n|--dryrun Do nothing, but print what would have happened. |
| 489 | 538 | ** -v|--verbose Extra output explaining what happens. |
| 490 | 539 | ** |
| 491 | -** > fossil patch diff [DIFF-FLAGS] FILENAME | |
| 492 | -** | |
| 493 | -** View the changes specified by the binary patch FILENAME in a | |
| 494 | -** human-readable format. The usual diff flags apply. | |
| 495 | -** | |
| 496 | 540 | ** > fossil patch push REMOTE-CHECKOUT |
| 497 | 541 | ** |
| 498 | 542 | ** Create a patch for the current check-out, transfer that patch to |
| 499 | 543 | ** a remote machine (using ssh) and apply the patch there. |
| 500 | 544 | ** |
| @@ -518,30 +562,46 @@ | ||
| 518 | 562 | zCmd = g.argv[2]; |
| 519 | 563 | n = strlen(zCmd); |
| 520 | 564 | if( strncmp(zCmd, "apply", n)==0 ){ |
| 521 | 565 | int forceFlag = find_option("force","f",0)!=0; |
| 522 | 566 | unsigned flags = 0; |
| 567 | + const char *zIn; | |
| 523 | 568 | if( find_option("dryrun","n",0) ) flags |= PATCH_DRYRUN; |
| 524 | 569 | if( find_option("verbose","v",0) ) flags |= PATCH_VERBOSE; |
| 525 | - db_must_be_within_tree(); | |
| 526 | 570 | verify_all_options(); |
| 527 | - if( g.argc!=4 ){ | |
| 528 | - usage("apply FILENAME"); | |
| 571 | + if( g.argc!=4 && g.argc!=5 ){ | |
| 572 | + usage("apply [DIRECTORY] FILENAME"); | |
| 573 | + } | |
| 574 | + if( g.argc==5 ){ | |
| 575 | + file_chdir(g.argv[3], 0); | |
| 576 | + zIn = g.argv[4]; | |
| 577 | + }else{ | |
| 578 | + zIn = g.argv[3]; | |
| 529 | 579 | } |
| 580 | + db_must_be_within_tree(); | |
| 530 | 581 | if( !forceFlag && unsaved_changes(0) ){ |
| 531 | 582 | fossil_fatal("there are unsaved changes in the current checkout"); |
| 532 | 583 | } |
| 533 | - patch_attach(g.argv[3]); | |
| 584 | + if( fossil_strcmp(zIn,"-")==0 ) zIn = 0; | |
| 585 | + patch_attach(zIn); | |
| 534 | 586 | patch_apply(flags); |
| 535 | 587 | }else |
| 536 | 588 | if( strncmp(zCmd, "create", n)==0 ){ |
| 537 | - db_must_be_within_tree(); | |
| 589 | + const char *zOut; | |
| 538 | 590 | verify_all_options(); |
| 539 | - if( g.argc!=4 ){ | |
| 540 | - usage("create FILENAME"); | |
| 591 | + if( g.argc!=4 && g.argc!=5 ){ | |
| 592 | + usage("create [DIRECTORY] FILENAME"); | |
| 593 | + } | |
| 594 | + if( g.argc==5 ){ | |
| 595 | + file_chdir(g.argv[3], 0); | |
| 596 | + zOut = g.argv[4]; | |
| 597 | + }else{ | |
| 598 | + zOut = g.argv[3]; | |
| 541 | 599 | } |
| 542 | - patch_create(g.argv[3]); | |
| 600 | + if( fossil_strcmp(zOut, "-")==0 ) zOut = 0; | |
| 601 | + db_must_be_within_tree(); | |
| 602 | + patch_create(zOut); | |
| 543 | 603 | }else |
| 544 | 604 | if( strncmp(zCmd, "pull", n)==0 ){ |
| 545 | 605 | db_must_be_within_tree(); |
| 546 | 606 | verify_all_options(); |
| 547 | 607 | if( g.argc!=4 ){ |
| @@ -556,17 +616,19 @@ | ||
| 556 | 616 | usage("push REMOTE-CHECKOUT"); |
| 557 | 617 | } |
| 558 | 618 | fossil_print("TBD...\n"); |
| 559 | 619 | }else |
| 560 | 620 | if( strncmp(zCmd, "view", n)==0 ){ |
| 561 | - /* u64 diffFlags = diff_options(); */ | |
| 621 | + const char *zIn; | |
| 562 | 622 | verify_all_options(); |
| 563 | 623 | if( g.argc!=4 ){ |
| 564 | 624 | usage("view FILENAME"); |
| 565 | 625 | } |
| 566 | - patch_attach(g.argv[3]); | |
| 626 | + zIn = g.argv[3]; | |
| 627 | + if( fossil_strcmp(zIn, "-")==0 ) zIn = 0; | |
| 628 | + patch_attach(zIn); | |
| 567 | 629 | patch_view(); |
| 568 | 630 | }else |
| 569 | 631 | { |
| 570 | 632 | goto patch_usage; |
| 571 | 633 | } |
| 572 | 634 | } |
| 573 | 635 |
| --- src/patch.c | |
| +++ src/patch.c | |
| @@ -116,20 +116,20 @@ | |
| 116 | ** named zOut. |
| 117 | */ |
| 118 | void patch_create(const char *zOut){ |
| 119 | int vid; |
| 120 | |
| 121 | if( file_isdir(zOut, ExtFILE)!=0 ){ |
| 122 | fossil_fatal("patch file already exists: %s", zOut); |
| 123 | } |
| 124 | add_content_sql_commands(g.db); |
| 125 | deltafunc_init(g.db); |
| 126 | sqlite3_create_function(g.db, "read_co_file", 1, SQLITE_UTF8, 0, |
| 127 | readfileFunc, 0, 0); |
| 128 | sqlite3_create_function(g.db, "mkdelta", 2, SQLITE_UTF8, 0, |
| 129 | mkdeltaFunc, 0, 0); |
| 130 | db_multi_exec("ATTACH %Q AS patch;", zOut); |
| 131 | db_multi_exec( |
| 132 | "PRAGMA patch.journal_mode=OFF;\n" |
| 133 | "PRAGMA patch.page_size=512;\n" |
| 134 | "CREATE TABLE patch.chng(\n" |
| 135 | " pathname TEXT,\n" /* Filename */ |
| @@ -189,25 +189,67 @@ | |
| 189 | "INSERT INTO patch.patchmerge(type,mhash)" |
| 190 | " SELECT tmap.type,vmerge.mhash FROM vmerge, tmap" |
| 191 | " WHERE tmap.id=vmerge.id;" |
| 192 | ); |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | /* |
| 197 | ** Attempt to load and validate a patchfile identified by the first |
| 198 | ** argument. |
| 199 | */ |
| 200 | void patch_attach(const char *zIn){ |
| 201 | Stmt q; |
| 202 | if( !file_isfile(zIn, ExtFILE) ){ |
| 203 | fossil_fatal("no such file: %s", zIn); |
| 204 | } |
| 205 | if( g.db==0 ){ |
| 206 | sqlite3_open(":memory:", &g.db); |
| 207 | } |
| 208 | db_multi_exec("ATTACH %Q AS patch", zIn); |
| 209 | db_prepare(&q, "PRAGMA patch.quick_check"); |
| 210 | while( db_step(&q)==SQLITE_ROW ){ |
| 211 | if( fossil_strcmp(db_column_text(&q,0),"ok")!=0 ){ |
| 212 | fossil_fatal("file %s is not a well-formed Fossil patchfile", zIn); |
| 213 | } |
| @@ -472,29 +514,31 @@ | |
| 472 | ** This command is used to creates, view, and apply Fossil binary patches. |
| 473 | ** A Fossil binary patch is a single (binary) file that captures all of the |
| 474 | ** uncommitted changes of a check-out. Use Fossil binary patches to transfer |
| 475 | ** proposed or incomplete changes between machines for testing or analysis. |
| 476 | ** |
| 477 | ** > fossil patch create FILENAME |
| 478 | ** |
| 479 | ** Create a new binary patch in FILENAME that captures all uncommitted |
| 480 | ** changes in the current check-out. |
| 481 | ** |
| 482 | ** > fossil patch apply FILENAME |
| 483 | ** |
| 484 | ** Apply the changes in FILENAME to the current check-out. Options: |
| 485 | ** |
| 486 | ** -f|--force Apply the patch even though there are unsaved |
| 487 | ** changes in the current check-out. |
| 488 | ** -n|--dryrun Do nothing, but print what would have happened. |
| 489 | ** -v|--verbose Extra output explaining what happens. |
| 490 | ** |
| 491 | ** > fossil patch diff [DIFF-FLAGS] FILENAME |
| 492 | ** |
| 493 | ** View the changes specified by the binary patch FILENAME in a |
| 494 | ** human-readable format. The usual diff flags apply. |
| 495 | ** |
| 496 | ** > fossil patch push REMOTE-CHECKOUT |
| 497 | ** |
| 498 | ** Create a patch for the current check-out, transfer that patch to |
| 499 | ** a remote machine (using ssh) and apply the patch there. |
| 500 | ** |
| @@ -518,30 +562,46 @@ | |
| 518 | zCmd = g.argv[2]; |
| 519 | n = strlen(zCmd); |
| 520 | if( strncmp(zCmd, "apply", n)==0 ){ |
| 521 | int forceFlag = find_option("force","f",0)!=0; |
| 522 | unsigned flags = 0; |
| 523 | if( find_option("dryrun","n",0) ) flags |= PATCH_DRYRUN; |
| 524 | if( find_option("verbose","v",0) ) flags |= PATCH_VERBOSE; |
| 525 | db_must_be_within_tree(); |
| 526 | verify_all_options(); |
| 527 | if( g.argc!=4 ){ |
| 528 | usage("apply FILENAME"); |
| 529 | } |
| 530 | if( !forceFlag && unsaved_changes(0) ){ |
| 531 | fossil_fatal("there are unsaved changes in the current checkout"); |
| 532 | } |
| 533 | patch_attach(g.argv[3]); |
| 534 | patch_apply(flags); |
| 535 | }else |
| 536 | if( strncmp(zCmd, "create", n)==0 ){ |
| 537 | db_must_be_within_tree(); |
| 538 | verify_all_options(); |
| 539 | if( g.argc!=4 ){ |
| 540 | usage("create FILENAME"); |
| 541 | } |
| 542 | patch_create(g.argv[3]); |
| 543 | }else |
| 544 | if( strncmp(zCmd, "pull", n)==0 ){ |
| 545 | db_must_be_within_tree(); |
| 546 | verify_all_options(); |
| 547 | if( g.argc!=4 ){ |
| @@ -556,17 +616,19 @@ | |
| 556 | usage("push REMOTE-CHECKOUT"); |
| 557 | } |
| 558 | fossil_print("TBD...\n"); |
| 559 | }else |
| 560 | if( strncmp(zCmd, "view", n)==0 ){ |
| 561 | /* u64 diffFlags = diff_options(); */ |
| 562 | verify_all_options(); |
| 563 | if( g.argc!=4 ){ |
| 564 | usage("view FILENAME"); |
| 565 | } |
| 566 | patch_attach(g.argv[3]); |
| 567 | patch_view(); |
| 568 | }else |
| 569 | { |
| 570 | goto patch_usage; |
| 571 | } |
| 572 | } |
| 573 |
| --- src/patch.c | |
| +++ src/patch.c | |
| @@ -116,20 +116,20 @@ | |
| 116 | ** named zOut. |
| 117 | */ |
| 118 | void patch_create(const char *zOut){ |
| 119 | int vid; |
| 120 | |
| 121 | if( zOut && file_isdir(zOut, ExtFILE)!=0 ){ |
| 122 | fossil_fatal("patch file already exists: %s", zOut); |
| 123 | } |
| 124 | add_content_sql_commands(g.db); |
| 125 | deltafunc_init(g.db); |
| 126 | sqlite3_create_function(g.db, "read_co_file", 1, SQLITE_UTF8, 0, |
| 127 | readfileFunc, 0, 0); |
| 128 | sqlite3_create_function(g.db, "mkdelta", 2, SQLITE_UTF8, 0, |
| 129 | mkdeltaFunc, 0, 0); |
| 130 | db_multi_exec("ATTACH %Q AS patch;", zOut ? zOut : ":memory:"); |
| 131 | db_multi_exec( |
| 132 | "PRAGMA patch.journal_mode=OFF;\n" |
| 133 | "PRAGMA patch.page_size=512;\n" |
| 134 | "CREATE TABLE patch.chng(\n" |
| 135 | " pathname TEXT,\n" /* Filename */ |
| @@ -189,25 +189,67 @@ | |
| 189 | "INSERT INTO patch.patchmerge(type,mhash)" |
| 190 | " SELECT tmap.type,vmerge.mhash FROM vmerge, tmap" |
| 191 | " WHERE tmap.id=vmerge.id;" |
| 192 | ); |
| 193 | } |
| 194 | |
| 195 | /* Write the database to standard output if zOut==0 */ |
| 196 | if( zOut==0 ){ |
| 197 | sqlite3_int64 sz; |
| 198 | unsigned char *pData; |
| 199 | pData = sqlite3_serialize(g.db, "patch", &sz, 0); |
| 200 | if( pData==0 ){ |
| 201 | fossil_fatal("out of memory"); |
| 202 | } |
| 203 | fossil_print("%025lld\n", sz); |
| 204 | fwrite(pData, sz, 1, stdout); |
| 205 | sqlite3_free(pData); |
| 206 | fflush(stdout); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | /* |
| 211 | ** Attempt to load and validate a patchfile identified by the first |
| 212 | ** argument. |
| 213 | */ |
| 214 | void patch_attach(const char *zIn){ |
| 215 | Stmt q; |
| 216 | if( g.db==0 ){ |
| 217 | sqlite3_open(":memory:", &g.db); |
| 218 | } |
| 219 | if( zIn==0 ){ |
| 220 | char zBuf[26]; |
| 221 | size_t n; |
| 222 | sqlite3_int64 sz; |
| 223 | unsigned char *aIn; |
| 224 | |
| 225 | n = fread(zBuf, sizeof(zBuf), 1, stdin); |
| 226 | if( n!=1 ){ |
| 227 | fossil_fatal("unable to read size of input\n"); |
| 228 | } |
| 229 | zBuf[sizeof(zBuf)-1] = 0; |
| 230 | sz = atoll(zBuf); |
| 231 | if( sz<512 || (sz%512)!=0 ){ |
| 232 | fossil_fatal("bad size for input: %lld", sz); |
| 233 | } |
| 234 | aIn = sqlite3_malloc64( sz ); |
| 235 | if( aIn==0 ){ |
| 236 | fossil_fatal("out of memory"); |
| 237 | } |
| 238 | n = fread(aIn, 1, sz, stdin); |
| 239 | if( n!=sz ){ |
| 240 | fossil_fatal("got only %lld of %lld input bytes", |
| 241 | (sqlite3_int64)n, sz); |
| 242 | } |
| 243 | db_multi_exec("ATTACH ':memory:' AS patch"); |
| 244 | sqlite3_deserialize(g.db, "patch", aIn, sz, sz, |
| 245 | SQLITE_DESERIALIZE_FREEONCLOSE); |
| 246 | }else if( !file_isfile(zIn, ExtFILE) ){ |
| 247 | fossil_fatal("no such file: %s", zIn); |
| 248 | }else{ |
| 249 | db_multi_exec("ATTACH %Q AS patch", zIn); |
| 250 | } |
| 251 | db_prepare(&q, "PRAGMA patch.quick_check"); |
| 252 | while( db_step(&q)==SQLITE_ROW ){ |
| 253 | if( fossil_strcmp(db_column_text(&q,0),"ok")!=0 ){ |
| 254 | fossil_fatal("file %s is not a well-formed Fossil patchfile", zIn); |
| 255 | } |
| @@ -472,29 +514,31 @@ | |
| 514 | ** This command is used to creates, view, and apply Fossil binary patches. |
| 515 | ** A Fossil binary patch is a single (binary) file that captures all of the |
| 516 | ** uncommitted changes of a check-out. Use Fossil binary patches to transfer |
| 517 | ** proposed or incomplete changes between machines for testing or analysis. |
| 518 | ** |
| 519 | ** > fossil patch create [DIRECTORY] FILENAME |
| 520 | ** |
| 521 | ** Create a new binary patch in FILENAME that captures all uncommitted |
| 522 | ** changes in the check-out at DIRECTORY, or the current directory if |
| 523 | ** DIRECTORY is omitted. |
| 524 | ** |
| 525 | ** If FILENAME is "-" then the binary patch is written to standard |
| 526 | ** output, preceeded by 26 bytes of header that is an ASCII |
| 527 | ** representation of the number of bytes in the patch followed by a |
| 528 | ** newline. |
| 529 | ** |
| 530 | ** > fossil patch apply [DIRECTORY] FILENAME |
| 531 | ** |
| 532 | ** Apply the changes in FILENAME to the check-out a DIRECTORY, or |
| 533 | ** in the current directory if DIRECTORY is omitted. Options: |
| 534 | ** |
| 535 | ** -f|--force Apply the patch even though there are unsaved |
| 536 | ** changes in the current check-out. |
| 537 | ** -n|--dryrun Do nothing, but print what would have happened. |
| 538 | ** -v|--verbose Extra output explaining what happens. |
| 539 | ** |
| 540 | ** > fossil patch push REMOTE-CHECKOUT |
| 541 | ** |
| 542 | ** Create a patch for the current check-out, transfer that patch to |
| 543 | ** a remote machine (using ssh) and apply the patch there. |
| 544 | ** |
| @@ -518,30 +562,46 @@ | |
| 562 | zCmd = g.argv[2]; |
| 563 | n = strlen(zCmd); |
| 564 | if( strncmp(zCmd, "apply", n)==0 ){ |
| 565 | int forceFlag = find_option("force","f",0)!=0; |
| 566 | unsigned flags = 0; |
| 567 | const char *zIn; |
| 568 | if( find_option("dryrun","n",0) ) flags |= PATCH_DRYRUN; |
| 569 | if( find_option("verbose","v",0) ) flags |= PATCH_VERBOSE; |
| 570 | verify_all_options(); |
| 571 | if( g.argc!=4 && g.argc!=5 ){ |
| 572 | usage("apply [DIRECTORY] FILENAME"); |
| 573 | } |
| 574 | if( g.argc==5 ){ |
| 575 | file_chdir(g.argv[3], 0); |
| 576 | zIn = g.argv[4]; |
| 577 | }else{ |
| 578 | zIn = g.argv[3]; |
| 579 | } |
| 580 | db_must_be_within_tree(); |
| 581 | if( !forceFlag && unsaved_changes(0) ){ |
| 582 | fossil_fatal("there are unsaved changes in the current checkout"); |
| 583 | } |
| 584 | if( fossil_strcmp(zIn,"-")==0 ) zIn = 0; |
| 585 | patch_attach(zIn); |
| 586 | patch_apply(flags); |
| 587 | }else |
| 588 | if( strncmp(zCmd, "create", n)==0 ){ |
| 589 | const char *zOut; |
| 590 | verify_all_options(); |
| 591 | if( g.argc!=4 && g.argc!=5 ){ |
| 592 | usage("create [DIRECTORY] FILENAME"); |
| 593 | } |
| 594 | if( g.argc==5 ){ |
| 595 | file_chdir(g.argv[3], 0); |
| 596 | zOut = g.argv[4]; |
| 597 | }else{ |
| 598 | zOut = g.argv[3]; |
| 599 | } |
| 600 | if( fossil_strcmp(zOut, "-")==0 ) zOut = 0; |
| 601 | db_must_be_within_tree(); |
| 602 | patch_create(zOut); |
| 603 | }else |
| 604 | if( strncmp(zCmd, "pull", n)==0 ){ |
| 605 | db_must_be_within_tree(); |
| 606 | verify_all_options(); |
| 607 | if( g.argc!=4 ){ |
| @@ -556,17 +616,19 @@ | |
| 616 | usage("push REMOTE-CHECKOUT"); |
| 617 | } |
| 618 | fossil_print("TBD...\n"); |
| 619 | }else |
| 620 | if( strncmp(zCmd, "view", n)==0 ){ |
| 621 | const char *zIn; |
| 622 | verify_all_options(); |
| 623 | if( g.argc!=4 ){ |
| 624 | usage("view FILENAME"); |
| 625 | } |
| 626 | zIn = g.argv[3]; |
| 627 | if( fossil_strcmp(zIn, "-")==0 ) zIn = 0; |
| 628 | patch_attach(zIn); |
| 629 | patch_view(); |
| 630 | }else |
| 631 | { |
| 632 | goto patch_usage; |
| 633 | } |
| 634 | } |
| 635 |