Fossil SCM
Add the --list option to the "tarball", "zip", and "sqlar" commands. Also rig those commands so that if the output filename is an empty string or "/dev/null" then they do not actually form the output archive.
Commit
c88880fa8af0ed5664d984a5593d106509d0581c589823ed75e1403f056745bc
Parent
487776dc454b2bb…
2 files changed
+56
-24
+61
-24
+56
-24
| --- src/tar.c | ||
| +++ src/tar.c | ||
| @@ -474,11 +474,12 @@ | ||
| 474 | 474 | void tarball_of_checkin( |
| 475 | 475 | int rid, /* The RID of the checkin from which to form a tarball */ |
| 476 | 476 | Blob *pTar, /* Write the tarball into this blob */ |
| 477 | 477 | const char *zDir, /* Directory prefix for all file added to tarball */ |
| 478 | 478 | Glob *pInclude, /* Only add files matching this pattern */ |
| 479 | - Glob *pExclude /* Exclude files matching this pattern */ | |
| 479 | + Glob *pExclude, /* Exclude files matching this pattern */ | |
| 480 | + int listFlag /* Show filenames on stdout */ | |
| 480 | 481 | ){ |
| 481 | 482 | Blob mfile, hash, file; |
| 482 | 483 | Manifest *pManifest; |
| 483 | 484 | ManifestFile *pFile; |
| 484 | 485 | Blob filename; |
| @@ -501,11 +502,11 @@ | ||
| 501 | 502 | |
| 502 | 503 | pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 503 | 504 | if( pManifest ){ |
| 504 | 505 | int flg, eflg = 0; |
| 505 | 506 | mTime = (pManifest->rDate - 2440587.5)*86400.0; |
| 506 | - tar_begin(mTime); | |
| 507 | + if( pTar ) tar_begin(mTime); | |
| 507 | 508 | flg = db_get_manifest_setting(); |
| 508 | 509 | if( flg ){ |
| 509 | 510 | /* eflg is the effective flags, taking include/exclude into account */ |
| 510 | 511 | if( (pInclude==0 || glob_match(pInclude, "manifest")) |
| 511 | 512 | && !glob_match(pExclude, "manifest") |
| @@ -525,62 +526,75 @@ | ||
| 525 | 526 | |
| 526 | 527 | if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 527 | 528 | if( eflg & MFESTFLG_RAW ){ |
| 528 | 529 | blob_append(&filename, "manifest", -1); |
| 529 | 530 | zName = blob_str(&filename); |
| 530 | - } | |
| 531 | - if( eflg & MFESTFLG_RAW ) { | |
| 532 | - sterilize_manifest(&mfile, CFTYPE_MANIFEST); | |
| 533 | - tar_add_file(zName, &mfile, 0, mTime); | |
| 531 | + if( listFlag ) fossil_print("%s\n", zName); | |
| 532 | + if( pTar ){ | |
| 533 | + sterilize_manifest(&mfile, CFTYPE_MANIFEST); | |
| 534 | + tar_add_file(zName, &mfile, 0, mTime); | |
| 535 | + } | |
| 534 | 536 | } |
| 535 | 537 | } |
| 536 | 538 | blob_reset(&mfile); |
| 537 | 539 | if( eflg & MFESTFLG_UUID ){ |
| 538 | - blob_append(&hash, "\n", 1); | |
| 539 | 540 | blob_resize(&filename, nPrefix); |
| 540 | 541 | blob_append(&filename, "manifest.uuid", -1); |
| 541 | 542 | zName = blob_str(&filename); |
| 542 | - tar_add_file(zName, &hash, 0, mTime); | |
| 543 | + if( listFlag ) fossil_print("%s\n", zName); | |
| 544 | + if( pTar ){ | |
| 545 | + blob_append(&hash, "\n", 1); | |
| 546 | + tar_add_file(zName, &hash, 0, mTime); | |
| 547 | + } | |
| 543 | 548 | } |
| 544 | 549 | if( eflg & MFESTFLG_TAGS ){ |
| 545 | - Blob tagslist; | |
| 546 | - blob_zero(&tagslist); | |
| 547 | - get_checkin_taglist(rid, &tagslist); | |
| 548 | 550 | blob_resize(&filename, nPrefix); |
| 549 | 551 | blob_append(&filename, "manifest.tags", -1); |
| 550 | 552 | zName = blob_str(&filename); |
| 551 | - tar_add_file(zName, &tagslist, 0, mTime); | |
| 552 | - blob_reset(&tagslist); | |
| 553 | + if( listFlag ) fossil_print("%s\n", zName); | |
| 554 | + if( pTar ){ | |
| 555 | + Blob tagslist; | |
| 556 | + blob_zero(&tagslist); | |
| 557 | + get_checkin_taglist(rid, &tagslist); | |
| 558 | + tar_add_file(zName, &tagslist, 0, mTime); | |
| 559 | + blob_reset(&tagslist); | |
| 560 | + } | |
| 553 | 561 | } |
| 554 | 562 | } |
| 555 | 563 | manifest_file_rewind(pManifest); |
| 556 | 564 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 557 | 565 | int fid; |
| 558 | 566 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 559 | 567 | if( glob_match(pExclude, pFile->zName) ) continue; |
| 560 | 568 | fid = uuid_to_rid(pFile->zUuid, 0); |
| 561 | 569 | if( fid ){ |
| 562 | - content_get(fid, &file); | |
| 563 | 570 | blob_resize(&filename, nPrefix); |
| 564 | 571 | blob_append(&filename, pFile->zName, -1); |
| 565 | 572 | zName = blob_str(&filename); |
| 566 | - tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime); | |
| 567 | - blob_reset(&file); | |
| 573 | + if( listFlag ) fossil_print("%s\n", zName); | |
| 574 | + if( pTar ){ | |
| 575 | + content_get(fid, &file); | |
| 576 | + tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime); | |
| 577 | + blob_reset(&file); | |
| 578 | + } | |
| 568 | 579 | } |
| 569 | 580 | } |
| 570 | 581 | }else{ |
| 571 | 582 | blob_append(&filename, blob_str(&hash), 16); |
| 572 | 583 | zName = blob_str(&filename); |
| 573 | - mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;"); | |
| 574 | - tar_begin(mTime); | |
| 575 | - tar_add_file(zName, &mfile, 0, mTime); | |
| 584 | + if( listFlag ) fossil_print("%s\n", zName); | |
| 585 | + if( pTar ){ | |
| 586 | + mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;"); | |
| 587 | + tar_begin(mTime); | |
| 588 | + tar_add_file(zName, &mfile, 0, mTime); | |
| 589 | + } | |
| 576 | 590 | } |
| 577 | 591 | manifest_destroy(pManifest); |
| 578 | 592 | blob_reset(&mfile); |
| 579 | 593 | blob_reset(&hash); |
| 580 | 594 | blob_reset(&filename); |
| 581 | - tar_finish(pTar); | |
| 595 | + if( pTar ) tar_finish(pTar); | |
| 582 | 596 | } |
| 583 | 597 | |
| 584 | 598 | /* |
| 585 | 599 | ** COMMAND: tarball* |
| 586 | 600 | ** |
| @@ -595,13 +609,20 @@ | ||
| 595 | 609 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 596 | 610 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 597 | 611 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| 598 | 612 | ** --include and --exclude then it is excluded. |
| 599 | 613 | ** |
| 614 | +** If OUTPUTFILE is an empty string or "/dev/null" then no tarball is | |
| 615 | +** actually generated. This feature can be used in combination with | |
| 616 | +** the --list option to get a list of the filename that would be in the | |
| 617 | +** tarball had it actually been generated. Note that --list shows only | |
| 618 | +** filenames. "tar tzf" shows both filesnames and subdirectory names. | |
| 619 | +** | |
| 600 | 620 | ** Options: |
| 601 | 621 | ** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude |
| 602 | 622 | ** --include GLOBLIST Comma-separated list of GLOBs of files to include |
| 623 | +** -l|--list Show archive content on stdout | |
| 603 | 624 | ** --name DIRECTORYNAME The name of the top-level directory in the archive |
| 604 | 625 | ** -R REPOSITORY Specify a Fossil repository |
| 605 | 626 | */ |
| 606 | 627 | void tarball_cmd(void){ |
| 607 | 628 | int rid; |
| @@ -609,16 +630,19 @@ | ||
| 609 | 630 | const char *zName; |
| 610 | 631 | Glob *pInclude = 0; |
| 611 | 632 | Glob *pExclude = 0; |
| 612 | 633 | const char *zInclude; |
| 613 | 634 | const char *zExclude; |
| 635 | + int listFlag = 0; | |
| 636 | + const char *zOut; | |
| 614 | 637 | zName = find_option("name", 0, 1); |
| 615 | 638 | zExclude = find_option("exclude", "X", 1); |
| 616 | 639 | if( zExclude ) pExclude = glob_create(zExclude); |
| 617 | 640 | zInclude = find_option("include", 0, 1); |
| 618 | 641 | if( zInclude ) pInclude = glob_create(zInclude); |
| 619 | 642 | db_find_and_open_repository(0, 0); |
| 643 | + listFlag = find_option("list","l",0)!=0; | |
| 620 | 644 | |
| 621 | 645 | /* We should be done with options.. */ |
| 622 | 646 | verify_all_options(); |
| 623 | 647 | |
| 624 | 648 | if( g.argc!=4 ){ |
| @@ -628,10 +652,14 @@ | ||
| 628 | 652 | rid = name_to_typed_rid(g.argv[2], "ci"); |
| 629 | 653 | if( rid==0 ){ |
| 630 | 654 | fossil_fatal("Check-in not found: %s", g.argv[2]); |
| 631 | 655 | return; |
| 632 | 656 | } |
| 657 | + zOut = g.argv[3]; | |
| 658 | + if( fossil_strcmp("/dev/null",zOut)==0 || fossil_strcmp("",zOut)==0 ){ | |
| 659 | + zOut = 0; | |
| 660 | + } | |
| 633 | 661 | |
| 634 | 662 | if( zName==0 ){ |
| 635 | 663 | zName = db_text("default-name", |
| 636 | 664 | "SELECT replace(%Q,' ','_') " |
| 637 | 665 | " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| @@ -640,15 +668,19 @@ | ||
| 640 | 668 | " WHERE event.objid=%d" |
| 641 | 669 | " AND blob.rid=%d", |
| 642 | 670 | db_get("project-name", "unnamed"), rid, rid |
| 643 | 671 | ); |
| 644 | 672 | } |
| 645 | - tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude); | |
| 673 | + tarball_of_checkin(rid, zOut ? &tarball : 0, | |
| 674 | + zName, pInclude, pExclude, listFlag); | |
| 646 | 675 | glob_free(pInclude); |
| 647 | 676 | glob_free(pExclude); |
| 648 | - blob_write_to_file(&tarball, g.argv[3]); | |
| 649 | - blob_reset(&tarball); | |
| 677 | + if( listFlag ) fflush(stdout); | |
| 678 | + if( zOut ){ | |
| 679 | + blob_write_to_file(&tarball, zOut); | |
| 680 | + blob_reset(&tarball); | |
| 681 | + } | |
| 650 | 682 | } |
| 651 | 683 | |
| 652 | 684 | /* |
| 653 | 685 | ** Check to see if the input string is of the form: |
| 654 | 686 | ** |
| @@ -801,11 +833,11 @@ | ||
| 801 | 833 | style_finish_page(); |
| 802 | 834 | return; |
| 803 | 835 | } |
| 804 | 836 | blob_zero(&tarball); |
| 805 | 837 | if( cache_read(&tarball, zKey)==0 ){ |
| 806 | - tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude); | |
| 838 | + tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude, 0); | |
| 807 | 839 | cache_write(&tarball, zKey); |
| 808 | 840 | } |
| 809 | 841 | glob_free(pInclude); |
| 810 | 842 | glob_free(pExclude); |
| 811 | 843 | fossil_free(zName); |
| 812 | 844 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -474,11 +474,12 @@ | |
| 474 | void tarball_of_checkin( |
| 475 | int rid, /* The RID of the checkin from which to form a tarball */ |
| 476 | Blob *pTar, /* Write the tarball into this blob */ |
| 477 | const char *zDir, /* Directory prefix for all file added to tarball */ |
| 478 | Glob *pInclude, /* Only add files matching this pattern */ |
| 479 | Glob *pExclude /* Exclude files matching this pattern */ |
| 480 | ){ |
| 481 | Blob mfile, hash, file; |
| 482 | Manifest *pManifest; |
| 483 | ManifestFile *pFile; |
| 484 | Blob filename; |
| @@ -501,11 +502,11 @@ | |
| 501 | |
| 502 | pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 503 | if( pManifest ){ |
| 504 | int flg, eflg = 0; |
| 505 | mTime = (pManifest->rDate - 2440587.5)*86400.0; |
| 506 | tar_begin(mTime); |
| 507 | flg = db_get_manifest_setting(); |
| 508 | if( flg ){ |
| 509 | /* eflg is the effective flags, taking include/exclude into account */ |
| 510 | if( (pInclude==0 || glob_match(pInclude, "manifest")) |
| 511 | && !glob_match(pExclude, "manifest") |
| @@ -525,62 +526,75 @@ | |
| 525 | |
| 526 | if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 527 | if( eflg & MFESTFLG_RAW ){ |
| 528 | blob_append(&filename, "manifest", -1); |
| 529 | zName = blob_str(&filename); |
| 530 | } |
| 531 | if( eflg & MFESTFLG_RAW ) { |
| 532 | sterilize_manifest(&mfile, CFTYPE_MANIFEST); |
| 533 | tar_add_file(zName, &mfile, 0, mTime); |
| 534 | } |
| 535 | } |
| 536 | blob_reset(&mfile); |
| 537 | if( eflg & MFESTFLG_UUID ){ |
| 538 | blob_append(&hash, "\n", 1); |
| 539 | blob_resize(&filename, nPrefix); |
| 540 | blob_append(&filename, "manifest.uuid", -1); |
| 541 | zName = blob_str(&filename); |
| 542 | tar_add_file(zName, &hash, 0, mTime); |
| 543 | } |
| 544 | if( eflg & MFESTFLG_TAGS ){ |
| 545 | Blob tagslist; |
| 546 | blob_zero(&tagslist); |
| 547 | get_checkin_taglist(rid, &tagslist); |
| 548 | blob_resize(&filename, nPrefix); |
| 549 | blob_append(&filename, "manifest.tags", -1); |
| 550 | zName = blob_str(&filename); |
| 551 | tar_add_file(zName, &tagslist, 0, mTime); |
| 552 | blob_reset(&tagslist); |
| 553 | } |
| 554 | } |
| 555 | manifest_file_rewind(pManifest); |
| 556 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 557 | int fid; |
| 558 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 559 | if( glob_match(pExclude, pFile->zName) ) continue; |
| 560 | fid = uuid_to_rid(pFile->zUuid, 0); |
| 561 | if( fid ){ |
| 562 | content_get(fid, &file); |
| 563 | blob_resize(&filename, nPrefix); |
| 564 | blob_append(&filename, pFile->zName, -1); |
| 565 | zName = blob_str(&filename); |
| 566 | tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime); |
| 567 | blob_reset(&file); |
| 568 | } |
| 569 | } |
| 570 | }else{ |
| 571 | blob_append(&filename, blob_str(&hash), 16); |
| 572 | zName = blob_str(&filename); |
| 573 | mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;"); |
| 574 | tar_begin(mTime); |
| 575 | tar_add_file(zName, &mfile, 0, mTime); |
| 576 | } |
| 577 | manifest_destroy(pManifest); |
| 578 | blob_reset(&mfile); |
| 579 | blob_reset(&hash); |
| 580 | blob_reset(&filename); |
| 581 | tar_finish(pTar); |
| 582 | } |
| 583 | |
| 584 | /* |
| 585 | ** COMMAND: tarball* |
| 586 | ** |
| @@ -595,13 +609,20 @@ | |
| 595 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 596 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 597 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| 598 | ** --include and --exclude then it is excluded. |
| 599 | ** |
| 600 | ** Options: |
| 601 | ** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude |
| 602 | ** --include GLOBLIST Comma-separated list of GLOBs of files to include |
| 603 | ** --name DIRECTORYNAME The name of the top-level directory in the archive |
| 604 | ** -R REPOSITORY Specify a Fossil repository |
| 605 | */ |
| 606 | void tarball_cmd(void){ |
| 607 | int rid; |
| @@ -609,16 +630,19 @@ | |
| 609 | const char *zName; |
| 610 | Glob *pInclude = 0; |
| 611 | Glob *pExclude = 0; |
| 612 | const char *zInclude; |
| 613 | const char *zExclude; |
| 614 | zName = find_option("name", 0, 1); |
| 615 | zExclude = find_option("exclude", "X", 1); |
| 616 | if( zExclude ) pExclude = glob_create(zExclude); |
| 617 | zInclude = find_option("include", 0, 1); |
| 618 | if( zInclude ) pInclude = glob_create(zInclude); |
| 619 | db_find_and_open_repository(0, 0); |
| 620 | |
| 621 | /* We should be done with options.. */ |
| 622 | verify_all_options(); |
| 623 | |
| 624 | if( g.argc!=4 ){ |
| @@ -628,10 +652,14 @@ | |
| 628 | rid = name_to_typed_rid(g.argv[2], "ci"); |
| 629 | if( rid==0 ){ |
| 630 | fossil_fatal("Check-in not found: %s", g.argv[2]); |
| 631 | return; |
| 632 | } |
| 633 | |
| 634 | if( zName==0 ){ |
| 635 | zName = db_text("default-name", |
| 636 | "SELECT replace(%Q,' ','_') " |
| 637 | " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| @@ -640,15 +668,19 @@ | |
| 640 | " WHERE event.objid=%d" |
| 641 | " AND blob.rid=%d", |
| 642 | db_get("project-name", "unnamed"), rid, rid |
| 643 | ); |
| 644 | } |
| 645 | tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude); |
| 646 | glob_free(pInclude); |
| 647 | glob_free(pExclude); |
| 648 | blob_write_to_file(&tarball, g.argv[3]); |
| 649 | blob_reset(&tarball); |
| 650 | } |
| 651 | |
| 652 | /* |
| 653 | ** Check to see if the input string is of the form: |
| 654 | ** |
| @@ -801,11 +833,11 @@ | |
| 801 | style_finish_page(); |
| 802 | return; |
| 803 | } |
| 804 | blob_zero(&tarball); |
| 805 | if( cache_read(&tarball, zKey)==0 ){ |
| 806 | tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude); |
| 807 | cache_write(&tarball, zKey); |
| 808 | } |
| 809 | glob_free(pInclude); |
| 810 | glob_free(pExclude); |
| 811 | fossil_free(zName); |
| 812 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -474,11 +474,12 @@ | |
| 474 | void tarball_of_checkin( |
| 475 | int rid, /* The RID of the checkin from which to form a tarball */ |
| 476 | Blob *pTar, /* Write the tarball into this blob */ |
| 477 | const char *zDir, /* Directory prefix for all file added to tarball */ |
| 478 | Glob *pInclude, /* Only add files matching this pattern */ |
| 479 | Glob *pExclude, /* Exclude files matching this pattern */ |
| 480 | int listFlag /* Show filenames on stdout */ |
| 481 | ){ |
| 482 | Blob mfile, hash, file; |
| 483 | Manifest *pManifest; |
| 484 | ManifestFile *pFile; |
| 485 | Blob filename; |
| @@ -501,11 +502,11 @@ | |
| 502 | |
| 503 | pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 504 | if( pManifest ){ |
| 505 | int flg, eflg = 0; |
| 506 | mTime = (pManifest->rDate - 2440587.5)*86400.0; |
| 507 | if( pTar ) tar_begin(mTime); |
| 508 | flg = db_get_manifest_setting(); |
| 509 | if( flg ){ |
| 510 | /* eflg is the effective flags, taking include/exclude into account */ |
| 511 | if( (pInclude==0 || glob_match(pInclude, "manifest")) |
| 512 | && !glob_match(pExclude, "manifest") |
| @@ -525,62 +526,75 @@ | |
| 526 | |
| 527 | if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 528 | if( eflg & MFESTFLG_RAW ){ |
| 529 | blob_append(&filename, "manifest", -1); |
| 530 | zName = blob_str(&filename); |
| 531 | if( listFlag ) fossil_print("%s\n", zName); |
| 532 | if( pTar ){ |
| 533 | sterilize_manifest(&mfile, CFTYPE_MANIFEST); |
| 534 | tar_add_file(zName, &mfile, 0, mTime); |
| 535 | } |
| 536 | } |
| 537 | } |
| 538 | blob_reset(&mfile); |
| 539 | if( eflg & MFESTFLG_UUID ){ |
| 540 | blob_resize(&filename, nPrefix); |
| 541 | blob_append(&filename, "manifest.uuid", -1); |
| 542 | zName = blob_str(&filename); |
| 543 | if( listFlag ) fossil_print("%s\n", zName); |
| 544 | if( pTar ){ |
| 545 | blob_append(&hash, "\n", 1); |
| 546 | tar_add_file(zName, &hash, 0, mTime); |
| 547 | } |
| 548 | } |
| 549 | if( eflg & MFESTFLG_TAGS ){ |
| 550 | blob_resize(&filename, nPrefix); |
| 551 | blob_append(&filename, "manifest.tags", -1); |
| 552 | zName = blob_str(&filename); |
| 553 | if( listFlag ) fossil_print("%s\n", zName); |
| 554 | if( pTar ){ |
| 555 | Blob tagslist; |
| 556 | blob_zero(&tagslist); |
| 557 | get_checkin_taglist(rid, &tagslist); |
| 558 | tar_add_file(zName, &tagslist, 0, mTime); |
| 559 | blob_reset(&tagslist); |
| 560 | } |
| 561 | } |
| 562 | } |
| 563 | manifest_file_rewind(pManifest); |
| 564 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 565 | int fid; |
| 566 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 567 | if( glob_match(pExclude, pFile->zName) ) continue; |
| 568 | fid = uuid_to_rid(pFile->zUuid, 0); |
| 569 | if( fid ){ |
| 570 | blob_resize(&filename, nPrefix); |
| 571 | blob_append(&filename, pFile->zName, -1); |
| 572 | zName = blob_str(&filename); |
| 573 | if( listFlag ) fossil_print("%s\n", zName); |
| 574 | if( pTar ){ |
| 575 | content_get(fid, &file); |
| 576 | tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime); |
| 577 | blob_reset(&file); |
| 578 | } |
| 579 | } |
| 580 | } |
| 581 | }else{ |
| 582 | blob_append(&filename, blob_str(&hash), 16); |
| 583 | zName = blob_str(&filename); |
| 584 | if( listFlag ) fossil_print("%s\n", zName); |
| 585 | if( pTar ){ |
| 586 | mTime = db_int64(0, "SELECT (julianday('now') - 2440587.5)*86400.0;"); |
| 587 | tar_begin(mTime); |
| 588 | tar_add_file(zName, &mfile, 0, mTime); |
| 589 | } |
| 590 | } |
| 591 | manifest_destroy(pManifest); |
| 592 | blob_reset(&mfile); |
| 593 | blob_reset(&hash); |
| 594 | blob_reset(&filename); |
| 595 | if( pTar ) tar_finish(pTar); |
| 596 | } |
| 597 | |
| 598 | /* |
| 599 | ** COMMAND: tarball* |
| 600 | ** |
| @@ -595,13 +609,20 @@ | |
| 609 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 610 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 611 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| 612 | ** --include and --exclude then it is excluded. |
| 613 | ** |
| 614 | ** If OUTPUTFILE is an empty string or "/dev/null" then no tarball is |
| 615 | ** actually generated. This feature can be used in combination with |
| 616 | ** the --list option to get a list of the filename that would be in the |
| 617 | ** tarball had it actually been generated. Note that --list shows only |
| 618 | ** filenames. "tar tzf" shows both filesnames and subdirectory names. |
| 619 | ** |
| 620 | ** Options: |
| 621 | ** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude |
| 622 | ** --include GLOBLIST Comma-separated list of GLOBs of files to include |
| 623 | ** -l|--list Show archive content on stdout |
| 624 | ** --name DIRECTORYNAME The name of the top-level directory in the archive |
| 625 | ** -R REPOSITORY Specify a Fossil repository |
| 626 | */ |
| 627 | void tarball_cmd(void){ |
| 628 | int rid; |
| @@ -609,16 +630,19 @@ | |
| 630 | const char *zName; |
| 631 | Glob *pInclude = 0; |
| 632 | Glob *pExclude = 0; |
| 633 | const char *zInclude; |
| 634 | const char *zExclude; |
| 635 | int listFlag = 0; |
| 636 | const char *zOut; |
| 637 | zName = find_option("name", 0, 1); |
| 638 | zExclude = find_option("exclude", "X", 1); |
| 639 | if( zExclude ) pExclude = glob_create(zExclude); |
| 640 | zInclude = find_option("include", 0, 1); |
| 641 | if( zInclude ) pInclude = glob_create(zInclude); |
| 642 | db_find_and_open_repository(0, 0); |
| 643 | listFlag = find_option("list","l",0)!=0; |
| 644 | |
| 645 | /* We should be done with options.. */ |
| 646 | verify_all_options(); |
| 647 | |
| 648 | if( g.argc!=4 ){ |
| @@ -628,10 +652,14 @@ | |
| 652 | rid = name_to_typed_rid(g.argv[2], "ci"); |
| 653 | if( rid==0 ){ |
| 654 | fossil_fatal("Check-in not found: %s", g.argv[2]); |
| 655 | return; |
| 656 | } |
| 657 | zOut = g.argv[3]; |
| 658 | if( fossil_strcmp("/dev/null",zOut)==0 || fossil_strcmp("",zOut)==0 ){ |
| 659 | zOut = 0; |
| 660 | } |
| 661 | |
| 662 | if( zName==0 ){ |
| 663 | zName = db_text("default-name", |
| 664 | "SELECT replace(%Q,' ','_') " |
| 665 | " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| @@ -640,15 +668,19 @@ | |
| 668 | " WHERE event.objid=%d" |
| 669 | " AND blob.rid=%d", |
| 670 | db_get("project-name", "unnamed"), rid, rid |
| 671 | ); |
| 672 | } |
| 673 | tarball_of_checkin(rid, zOut ? &tarball : 0, |
| 674 | zName, pInclude, pExclude, listFlag); |
| 675 | glob_free(pInclude); |
| 676 | glob_free(pExclude); |
| 677 | if( listFlag ) fflush(stdout); |
| 678 | if( zOut ){ |
| 679 | blob_write_to_file(&tarball, zOut); |
| 680 | blob_reset(&tarball); |
| 681 | } |
| 682 | } |
| 683 | |
| 684 | /* |
| 685 | ** Check to see if the input string is of the form: |
| 686 | ** |
| @@ -801,11 +833,11 @@ | |
| 833 | style_finish_page(); |
| 834 | return; |
| 835 | } |
| 836 | blob_zero(&tarball); |
| 837 | if( cache_read(&tarball, zKey)==0 ){ |
| 838 | tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude, 0); |
| 839 | cache_write(&tarball, zKey); |
| 840 | } |
| 841 | glob_free(pInclude); |
| 842 | glob_free(pExclude); |
| 843 | fossil_free(zName); |
| 844 |
+61
-24
| --- src/zip.c | ||
| +++ src/zip.c | ||
| @@ -623,11 +623,12 @@ | ||
| 623 | 623 | int eType, /* Type of archive (ZIP or SQLAR) */ |
| 624 | 624 | int rid, /* The RID of the checkin to build the archive from */ |
| 625 | 625 | Blob *pZip, /* Write the archive content into this blob */ |
| 626 | 626 | const char *zDir, /* Top-level directory of the archive */ |
| 627 | 627 | Glob *pInclude, /* Only include files that match this pattern */ |
| 628 | - Glob *pExclude /* Exclude files that match this pattern */ | |
| 628 | + Glob *pExclude, /* Exclude files that match this pattern */ | |
| 629 | + int listFlag /* Print each file on stdout */ | |
| 629 | 630 | ){ |
| 630 | 631 | Blob mfile, hash, file; |
| 631 | 632 | Manifest *pManifest; |
| 632 | 633 | ManifestFile *pFile; |
| 633 | 634 | Blob filename; |
| @@ -636,19 +637,19 @@ | ||
| 636 | 637 | Archive sArchive; |
| 637 | 638 | memset(&sArchive, 0, sizeof(Archive)); |
| 638 | 639 | sArchive.eType = eType; |
| 639 | 640 | sArchive.pBlob = pZip; |
| 640 | 641 | blob_zero(&sArchive.tmp); |
| 641 | - blob_zero(pZip); | |
| 642 | + if( pZip ) blob_zero(pZip); | |
| 642 | 643 | |
| 643 | 644 | content_get(rid, &mfile); |
| 644 | 645 | if( blob_size(&mfile)==0 ){ |
| 645 | 646 | return; |
| 646 | 647 | } |
| 647 | 648 | blob_set_dynamic(&hash, rid_to_uuid(rid)); |
| 648 | 649 | blob_zero(&filename); |
| 649 | - zip_open(); | |
| 650 | + if( pZip ) zip_open(); | |
| 650 | 651 | |
| 651 | 652 | if( zDir && zDir[0] ){ |
| 652 | 653 | blob_appendf(&filename, "%s/", zDir); |
| 653 | 654 | } |
| 654 | 655 | nPrefix = blob_size(&filename); |
| @@ -678,57 +679,71 @@ | ||
| 678 | 679 | } |
| 679 | 680 | |
| 680 | 681 | if( eflg & MFESTFLG_RAW ){ |
| 681 | 682 | blob_append(&filename, "manifest", -1); |
| 682 | 683 | zName = blob_str(&filename); |
| 683 | - zip_add_folders(&sArchive, zName); | |
| 684 | - sterilize_manifest(&mfile, CFTYPE_MANIFEST); | |
| 685 | - zip_add_file(&sArchive, zName, &mfile, 0); | |
| 684 | + if( listFlag ) fossil_print("%s\n", zName); | |
| 685 | + if( pZip ){ | |
| 686 | + zip_add_folders(&sArchive, zName); | |
| 687 | + sterilize_manifest(&mfile, CFTYPE_MANIFEST); | |
| 688 | + zip_add_file(&sArchive, zName, &mfile, 0); | |
| 689 | + } | |
| 686 | 690 | } |
| 687 | 691 | if( eflg & MFESTFLG_UUID ){ |
| 688 | 692 | blob_append(&hash, "\n", 1); |
| 689 | 693 | blob_resize(&filename, nPrefix); |
| 690 | 694 | blob_append(&filename, "manifest.uuid", -1); |
| 691 | 695 | zName = blob_str(&filename); |
| 692 | - zip_add_folders(&sArchive, zName); | |
| 693 | - zip_add_file(&sArchive, zName, &hash, 0); | |
| 696 | + if( listFlag ) fossil_print("%s\n", zName); | |
| 697 | + if( pZip ){ | |
| 698 | + zip_add_folders(&sArchive, zName); | |
| 699 | + zip_add_file(&sArchive, zName, &hash, 0); | |
| 700 | + } | |
| 694 | 701 | } |
| 695 | 702 | if( eflg & MFESTFLG_TAGS ){ |
| 696 | - Blob tagslist; | |
| 697 | - blob_zero(&tagslist); | |
| 698 | - get_checkin_taglist(rid, &tagslist); | |
| 699 | 703 | blob_resize(&filename, nPrefix); |
| 700 | 704 | blob_append(&filename, "manifest.tags", -1); |
| 701 | 705 | zName = blob_str(&filename); |
| 702 | - zip_add_folders(&sArchive, zName); | |
| 703 | - zip_add_file(&sArchive, zName, &tagslist, 0); | |
| 704 | - blob_reset(&tagslist); | |
| 706 | + if( listFlag ) fossil_print("%s\n", zName); | |
| 707 | + if( pZip ){ | |
| 708 | + Blob tagslist; | |
| 709 | + blob_zero(&tagslist); | |
| 710 | + get_checkin_taglist(rid, &tagslist); | |
| 711 | + zip_add_folders(&sArchive, zName); | |
| 712 | + zip_add_file(&sArchive, zName, &tagslist, 0); | |
| 713 | + blob_reset(&tagslist); | |
| 714 | + } | |
| 705 | 715 | } |
| 706 | 716 | } |
| 707 | 717 | manifest_file_rewind(pManifest); |
| 708 | - zip_add_file(&sArchive, "", 0, 0); | |
| 718 | + if( pZip ) zip_add_file(&sArchive, "", 0, 0); | |
| 709 | 719 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 710 | 720 | int fid; |
| 711 | 721 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 712 | 722 | if( glob_match(pExclude, pFile->zName) ) continue; |
| 713 | 723 | fid = uuid_to_rid(pFile->zUuid, 0); |
| 714 | 724 | if( fid ){ |
| 715 | - content_get(fid, &file); | |
| 716 | 725 | blob_resize(&filename, nPrefix); |
| 717 | 726 | blob_append(&filename, pFile->zName, -1); |
| 718 | 727 | zName = blob_str(&filename); |
| 719 | - zip_add_folders(&sArchive, zName); | |
| 720 | - zip_add_file(&sArchive, zName, &file, manifest_file_mperm(pFile)); | |
| 721 | - blob_reset(&file); | |
| 728 | + if( listFlag ) fossil_print("%s\n", zName); | |
| 729 | + if( pZip ){ | |
| 730 | + content_get(fid, &file); | |
| 731 | + zip_add_folders(&sArchive, zName); | |
| 732 | + zip_add_file(&sArchive, zName, &file, manifest_file_mperm(pFile)); | |
| 733 | + blob_reset(&file); | |
| 734 | + } | |
| 722 | 735 | } |
| 723 | 736 | } |
| 724 | 737 | } |
| 725 | 738 | blob_reset(&mfile); |
| 726 | 739 | manifest_destroy(pManifest); |
| 727 | 740 | blob_reset(&filename); |
| 728 | 741 | blob_reset(&hash); |
| 729 | - zip_close(&sArchive); | |
| 742 | + if( pZip ){ | |
| 743 | + zip_close(&sArchive); | |
| 744 | + } | |
| 730 | 745 | } |
| 731 | 746 | |
| 732 | 747 | /* |
| 733 | 748 | ** Implementation of zip_cmd and sqlar_cmd. |
| 734 | 749 | */ |
| @@ -738,16 +753,19 @@ | ||
| 738 | 753 | const char *zName; |
| 739 | 754 | Glob *pInclude = 0; |
| 740 | 755 | Glob *pExclude = 0; |
| 741 | 756 | const char *zInclude; |
| 742 | 757 | const char *zExclude; |
| 758 | + int listFlag = 0; | |
| 759 | + const char *zOut; | |
| 743 | 760 | |
| 744 | 761 | zName = find_option("name", 0, 1); |
| 745 | 762 | zExclude = find_option("exclude", "X", 1); |
| 746 | 763 | if( zExclude ) pExclude = glob_create(zExclude); |
| 747 | 764 | zInclude = find_option("include", 0, 1); |
| 748 | 765 | if( zInclude ) pInclude = glob_create(zInclude); |
| 766 | + listFlag = find_option("list","l",0)!=0; | |
| 749 | 767 | db_find_and_open_repository(0, 0); |
| 750 | 768 | |
| 751 | 769 | /* We should be done with options.. */ |
| 752 | 770 | verify_all_options(); |
| 753 | 771 | |
| @@ -758,10 +776,14 @@ | ||
| 758 | 776 | rid = name_to_typed_rid(g.argv[2], "ci"); |
| 759 | 777 | if( rid==0 ){ |
| 760 | 778 | fossil_fatal("Check-in not found: %s", g.argv[2]); |
| 761 | 779 | return; |
| 762 | 780 | } |
| 781 | + zOut = g.argv[3]; | |
| 782 | + if( fossil_strcmp(zOut,"")==0 || fossil_strcmp(zOut,"/dev/null")==0 ){ | |
| 783 | + zOut = 0; | |
| 784 | + } | |
| 763 | 785 | |
| 764 | 786 | if( zName==0 ){ |
| 765 | 787 | zName = db_text("default-name", |
| 766 | 788 | "SELECT replace(%Q,' ','_') " |
| 767 | 789 | " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| @@ -770,15 +792,18 @@ | ||
| 770 | 792 | " WHERE event.objid=%d" |
| 771 | 793 | " AND blob.rid=%d", |
| 772 | 794 | db_get("project-name", "unnamed"), rid, rid |
| 773 | 795 | ); |
| 774 | 796 | } |
| 775 | - zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude); | |
| 797 | + zip_of_checkin(eType, rid, zOut ? &zip : 0, | |
| 798 | + zName, pInclude, pExclude, listFlag); | |
| 776 | 799 | glob_free(pInclude); |
| 777 | 800 | glob_free(pExclude); |
| 778 | - blob_write_to_file(&zip, g.argv[3]); | |
| 779 | - blob_reset(&zip); | |
| 801 | + if( zOut ){ | |
| 802 | + blob_write_to_file(&zip, zOut); | |
| 803 | + blob_reset(&zip); | |
| 804 | + } | |
| 780 | 805 | } |
| 781 | 806 | |
| 782 | 807 | /* |
| 783 | 808 | ** COMMAND: zip* |
| 784 | 809 | ** |
| @@ -793,13 +818,19 @@ | ||
| 793 | 818 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 794 | 819 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 795 | 820 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| 796 | 821 | ** --include and --exclude then it is excluded. |
| 797 | 822 | ** |
| 823 | +** If OUTPUTFILE is an empty string or "/dev/null" then no ZIP archive is | |
| 824 | +** actually generated. This feature can be used in combination with | |
| 825 | +** the --list option to get a list of the filename that would be in the | |
| 826 | +** ZIP archive had it actually been generated. | |
| 827 | +** | |
| 798 | 828 | ** Options: |
| 799 | 829 | ** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude |
| 800 | 830 | ** --include GLOBLIST Comma-separated list of GLOBs of files to include |
| 831 | +** -l|--list Show archive content on stdout | |
| 801 | 832 | ** --name DIRECTORYNAME The name of the top-level directory in the archive |
| 802 | 833 | ** -R REPOSITORY Specify a Fossil repository |
| 803 | 834 | */ |
| 804 | 835 | void zip_cmd(void){ |
| 805 | 836 | archive_cmd(ARCHIVE_ZIP); |
| @@ -819,13 +850,19 @@ | ||
| 819 | 850 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 820 | 851 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 821 | 852 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| 822 | 853 | ** --include and --exclude then it is excluded. |
| 823 | 854 | ** |
| 855 | +** If OUTPUTFILE is an empty string or "/dev/null" then no SQLAR archive is | |
| 856 | +** actually generated. This feature can be used in combination with | |
| 857 | +** the --list option to get a list of the filename that would be in the | |
| 858 | +** SQLAR archive had it actually been generated. | |
| 859 | +** | |
| 824 | 860 | ** Options: |
| 825 | 861 | ** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude |
| 826 | 862 | ** --include GLOBLIST Comma-separated list of GLOBs of files to include |
| 863 | +** -l|--list Show archive content on stdout | |
| 827 | 864 | ** --name DIRECTORYNAME The name of the top-level directory in the archive |
| 828 | 865 | ** -R REPOSITORY Specify a Fossil repository |
| 829 | 866 | */ |
| 830 | 867 | void sqlar_cmd(void){ |
| 831 | 868 | archive_cmd(ARCHIVE_SQLAR); |
| @@ -972,11 +1009,11 @@ | ||
| 972 | 1009 | style_finish_page(); |
| 973 | 1010 | return; |
| 974 | 1011 | } |
| 975 | 1012 | blob_zero(&zip); |
| 976 | 1013 | if( cache_read(&zip, zKey)==0 ){ |
| 977 | - zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude); | |
| 1014 | + zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude, 0); | |
| 978 | 1015 | cache_write(&zip, zKey); |
| 979 | 1016 | } |
| 980 | 1017 | glob_free(pInclude); |
| 981 | 1018 | glob_free(pExclude); |
| 982 | 1019 | fossil_free(zName); |
| 983 | 1020 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -623,11 +623,12 @@ | |
| 623 | int eType, /* Type of archive (ZIP or SQLAR) */ |
| 624 | int rid, /* The RID of the checkin to build the archive from */ |
| 625 | Blob *pZip, /* Write the archive content into this blob */ |
| 626 | const char *zDir, /* Top-level directory of the archive */ |
| 627 | Glob *pInclude, /* Only include files that match this pattern */ |
| 628 | Glob *pExclude /* Exclude files that match this pattern */ |
| 629 | ){ |
| 630 | Blob mfile, hash, file; |
| 631 | Manifest *pManifest; |
| 632 | ManifestFile *pFile; |
| 633 | Blob filename; |
| @@ -636,19 +637,19 @@ | |
| 636 | Archive sArchive; |
| 637 | memset(&sArchive, 0, sizeof(Archive)); |
| 638 | sArchive.eType = eType; |
| 639 | sArchive.pBlob = pZip; |
| 640 | blob_zero(&sArchive.tmp); |
| 641 | blob_zero(pZip); |
| 642 | |
| 643 | content_get(rid, &mfile); |
| 644 | if( blob_size(&mfile)==0 ){ |
| 645 | return; |
| 646 | } |
| 647 | blob_set_dynamic(&hash, rid_to_uuid(rid)); |
| 648 | blob_zero(&filename); |
| 649 | zip_open(); |
| 650 | |
| 651 | if( zDir && zDir[0] ){ |
| 652 | blob_appendf(&filename, "%s/", zDir); |
| 653 | } |
| 654 | nPrefix = blob_size(&filename); |
| @@ -678,57 +679,71 @@ | |
| 678 | } |
| 679 | |
| 680 | if( eflg & MFESTFLG_RAW ){ |
| 681 | blob_append(&filename, "manifest", -1); |
| 682 | zName = blob_str(&filename); |
| 683 | zip_add_folders(&sArchive, zName); |
| 684 | sterilize_manifest(&mfile, CFTYPE_MANIFEST); |
| 685 | zip_add_file(&sArchive, zName, &mfile, 0); |
| 686 | } |
| 687 | if( eflg & MFESTFLG_UUID ){ |
| 688 | blob_append(&hash, "\n", 1); |
| 689 | blob_resize(&filename, nPrefix); |
| 690 | blob_append(&filename, "manifest.uuid", -1); |
| 691 | zName = blob_str(&filename); |
| 692 | zip_add_folders(&sArchive, zName); |
| 693 | zip_add_file(&sArchive, zName, &hash, 0); |
| 694 | } |
| 695 | if( eflg & MFESTFLG_TAGS ){ |
| 696 | Blob tagslist; |
| 697 | blob_zero(&tagslist); |
| 698 | get_checkin_taglist(rid, &tagslist); |
| 699 | blob_resize(&filename, nPrefix); |
| 700 | blob_append(&filename, "manifest.tags", -1); |
| 701 | zName = blob_str(&filename); |
| 702 | zip_add_folders(&sArchive, zName); |
| 703 | zip_add_file(&sArchive, zName, &tagslist, 0); |
| 704 | blob_reset(&tagslist); |
| 705 | } |
| 706 | } |
| 707 | manifest_file_rewind(pManifest); |
| 708 | zip_add_file(&sArchive, "", 0, 0); |
| 709 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 710 | int fid; |
| 711 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 712 | if( glob_match(pExclude, pFile->zName) ) continue; |
| 713 | fid = uuid_to_rid(pFile->zUuid, 0); |
| 714 | if( fid ){ |
| 715 | content_get(fid, &file); |
| 716 | blob_resize(&filename, nPrefix); |
| 717 | blob_append(&filename, pFile->zName, -1); |
| 718 | zName = blob_str(&filename); |
| 719 | zip_add_folders(&sArchive, zName); |
| 720 | zip_add_file(&sArchive, zName, &file, manifest_file_mperm(pFile)); |
| 721 | blob_reset(&file); |
| 722 | } |
| 723 | } |
| 724 | } |
| 725 | blob_reset(&mfile); |
| 726 | manifest_destroy(pManifest); |
| 727 | blob_reset(&filename); |
| 728 | blob_reset(&hash); |
| 729 | zip_close(&sArchive); |
| 730 | } |
| 731 | |
| 732 | /* |
| 733 | ** Implementation of zip_cmd and sqlar_cmd. |
| 734 | */ |
| @@ -738,16 +753,19 @@ | |
| 738 | const char *zName; |
| 739 | Glob *pInclude = 0; |
| 740 | Glob *pExclude = 0; |
| 741 | const char *zInclude; |
| 742 | const char *zExclude; |
| 743 | |
| 744 | zName = find_option("name", 0, 1); |
| 745 | zExclude = find_option("exclude", "X", 1); |
| 746 | if( zExclude ) pExclude = glob_create(zExclude); |
| 747 | zInclude = find_option("include", 0, 1); |
| 748 | if( zInclude ) pInclude = glob_create(zInclude); |
| 749 | db_find_and_open_repository(0, 0); |
| 750 | |
| 751 | /* We should be done with options.. */ |
| 752 | verify_all_options(); |
| 753 | |
| @@ -758,10 +776,14 @@ | |
| 758 | rid = name_to_typed_rid(g.argv[2], "ci"); |
| 759 | if( rid==0 ){ |
| 760 | fossil_fatal("Check-in not found: %s", g.argv[2]); |
| 761 | return; |
| 762 | } |
| 763 | |
| 764 | if( zName==0 ){ |
| 765 | zName = db_text("default-name", |
| 766 | "SELECT replace(%Q,' ','_') " |
| 767 | " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| @@ -770,15 +792,18 @@ | |
| 770 | " WHERE event.objid=%d" |
| 771 | " AND blob.rid=%d", |
| 772 | db_get("project-name", "unnamed"), rid, rid |
| 773 | ); |
| 774 | } |
| 775 | zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude); |
| 776 | glob_free(pInclude); |
| 777 | glob_free(pExclude); |
| 778 | blob_write_to_file(&zip, g.argv[3]); |
| 779 | blob_reset(&zip); |
| 780 | } |
| 781 | |
| 782 | /* |
| 783 | ** COMMAND: zip* |
| 784 | ** |
| @@ -793,13 +818,19 @@ | |
| 793 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 794 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 795 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| 796 | ** --include and --exclude then it is excluded. |
| 797 | ** |
| 798 | ** Options: |
| 799 | ** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude |
| 800 | ** --include GLOBLIST Comma-separated list of GLOBs of files to include |
| 801 | ** --name DIRECTORYNAME The name of the top-level directory in the archive |
| 802 | ** -R REPOSITORY Specify a Fossil repository |
| 803 | */ |
| 804 | void zip_cmd(void){ |
| 805 | archive_cmd(ARCHIVE_ZIP); |
| @@ -819,13 +850,19 @@ | |
| 819 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 820 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 821 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| 822 | ** --include and --exclude then it is excluded. |
| 823 | ** |
| 824 | ** Options: |
| 825 | ** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude |
| 826 | ** --include GLOBLIST Comma-separated list of GLOBs of files to include |
| 827 | ** --name DIRECTORYNAME The name of the top-level directory in the archive |
| 828 | ** -R REPOSITORY Specify a Fossil repository |
| 829 | */ |
| 830 | void sqlar_cmd(void){ |
| 831 | archive_cmd(ARCHIVE_SQLAR); |
| @@ -972,11 +1009,11 @@ | |
| 972 | style_finish_page(); |
| 973 | return; |
| 974 | } |
| 975 | blob_zero(&zip); |
| 976 | if( cache_read(&zip, zKey)==0 ){ |
| 977 | zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude); |
| 978 | cache_write(&zip, zKey); |
| 979 | } |
| 980 | glob_free(pInclude); |
| 981 | glob_free(pExclude); |
| 982 | fossil_free(zName); |
| 983 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -623,11 +623,12 @@ | |
| 623 | int eType, /* Type of archive (ZIP or SQLAR) */ |
| 624 | int rid, /* The RID of the checkin to build the archive from */ |
| 625 | Blob *pZip, /* Write the archive content into this blob */ |
| 626 | const char *zDir, /* Top-level directory of the archive */ |
| 627 | Glob *pInclude, /* Only include files that match this pattern */ |
| 628 | Glob *pExclude, /* Exclude files that match this pattern */ |
| 629 | int listFlag /* Print each file on stdout */ |
| 630 | ){ |
| 631 | Blob mfile, hash, file; |
| 632 | Manifest *pManifest; |
| 633 | ManifestFile *pFile; |
| 634 | Blob filename; |
| @@ -636,19 +637,19 @@ | |
| 637 | Archive sArchive; |
| 638 | memset(&sArchive, 0, sizeof(Archive)); |
| 639 | sArchive.eType = eType; |
| 640 | sArchive.pBlob = pZip; |
| 641 | blob_zero(&sArchive.tmp); |
| 642 | if( pZip ) blob_zero(pZip); |
| 643 | |
| 644 | content_get(rid, &mfile); |
| 645 | if( blob_size(&mfile)==0 ){ |
| 646 | return; |
| 647 | } |
| 648 | blob_set_dynamic(&hash, rid_to_uuid(rid)); |
| 649 | blob_zero(&filename); |
| 650 | if( pZip ) zip_open(); |
| 651 | |
| 652 | if( zDir && zDir[0] ){ |
| 653 | blob_appendf(&filename, "%s/", zDir); |
| 654 | } |
| 655 | nPrefix = blob_size(&filename); |
| @@ -678,57 +679,71 @@ | |
| 679 | } |
| 680 | |
| 681 | if( eflg & MFESTFLG_RAW ){ |
| 682 | blob_append(&filename, "manifest", -1); |
| 683 | zName = blob_str(&filename); |
| 684 | if( listFlag ) fossil_print("%s\n", zName); |
| 685 | if( pZip ){ |
| 686 | zip_add_folders(&sArchive, zName); |
| 687 | sterilize_manifest(&mfile, CFTYPE_MANIFEST); |
| 688 | zip_add_file(&sArchive, zName, &mfile, 0); |
| 689 | } |
| 690 | } |
| 691 | if( eflg & MFESTFLG_UUID ){ |
| 692 | blob_append(&hash, "\n", 1); |
| 693 | blob_resize(&filename, nPrefix); |
| 694 | blob_append(&filename, "manifest.uuid", -1); |
| 695 | zName = blob_str(&filename); |
| 696 | if( listFlag ) fossil_print("%s\n", zName); |
| 697 | if( pZip ){ |
| 698 | zip_add_folders(&sArchive, zName); |
| 699 | zip_add_file(&sArchive, zName, &hash, 0); |
| 700 | } |
| 701 | } |
| 702 | if( eflg & MFESTFLG_TAGS ){ |
| 703 | blob_resize(&filename, nPrefix); |
| 704 | blob_append(&filename, "manifest.tags", -1); |
| 705 | zName = blob_str(&filename); |
| 706 | if( listFlag ) fossil_print("%s\n", zName); |
| 707 | if( pZip ){ |
| 708 | Blob tagslist; |
| 709 | blob_zero(&tagslist); |
| 710 | get_checkin_taglist(rid, &tagslist); |
| 711 | zip_add_folders(&sArchive, zName); |
| 712 | zip_add_file(&sArchive, zName, &tagslist, 0); |
| 713 | blob_reset(&tagslist); |
| 714 | } |
| 715 | } |
| 716 | } |
| 717 | manifest_file_rewind(pManifest); |
| 718 | if( pZip ) zip_add_file(&sArchive, "", 0, 0); |
| 719 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 720 | int fid; |
| 721 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 722 | if( glob_match(pExclude, pFile->zName) ) continue; |
| 723 | fid = uuid_to_rid(pFile->zUuid, 0); |
| 724 | if( fid ){ |
| 725 | blob_resize(&filename, nPrefix); |
| 726 | blob_append(&filename, pFile->zName, -1); |
| 727 | zName = blob_str(&filename); |
| 728 | if( listFlag ) fossil_print("%s\n", zName); |
| 729 | if( pZip ){ |
| 730 | content_get(fid, &file); |
| 731 | zip_add_folders(&sArchive, zName); |
| 732 | zip_add_file(&sArchive, zName, &file, manifest_file_mperm(pFile)); |
| 733 | blob_reset(&file); |
| 734 | } |
| 735 | } |
| 736 | } |
| 737 | } |
| 738 | blob_reset(&mfile); |
| 739 | manifest_destroy(pManifest); |
| 740 | blob_reset(&filename); |
| 741 | blob_reset(&hash); |
| 742 | if( pZip ){ |
| 743 | zip_close(&sArchive); |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | /* |
| 748 | ** Implementation of zip_cmd and sqlar_cmd. |
| 749 | */ |
| @@ -738,16 +753,19 @@ | |
| 753 | const char *zName; |
| 754 | Glob *pInclude = 0; |
| 755 | Glob *pExclude = 0; |
| 756 | const char *zInclude; |
| 757 | const char *zExclude; |
| 758 | int listFlag = 0; |
| 759 | const char *zOut; |
| 760 | |
| 761 | zName = find_option("name", 0, 1); |
| 762 | zExclude = find_option("exclude", "X", 1); |
| 763 | if( zExclude ) pExclude = glob_create(zExclude); |
| 764 | zInclude = find_option("include", 0, 1); |
| 765 | if( zInclude ) pInclude = glob_create(zInclude); |
| 766 | listFlag = find_option("list","l",0)!=0; |
| 767 | db_find_and_open_repository(0, 0); |
| 768 | |
| 769 | /* We should be done with options.. */ |
| 770 | verify_all_options(); |
| 771 | |
| @@ -758,10 +776,14 @@ | |
| 776 | rid = name_to_typed_rid(g.argv[2], "ci"); |
| 777 | if( rid==0 ){ |
| 778 | fossil_fatal("Check-in not found: %s", g.argv[2]); |
| 779 | return; |
| 780 | } |
| 781 | zOut = g.argv[3]; |
| 782 | if( fossil_strcmp(zOut,"")==0 || fossil_strcmp(zOut,"/dev/null")==0 ){ |
| 783 | zOut = 0; |
| 784 | } |
| 785 | |
| 786 | if( zName==0 ){ |
| 787 | zName = db_text("default-name", |
| 788 | "SELECT replace(%Q,' ','_') " |
| 789 | " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| @@ -770,15 +792,18 @@ | |
| 792 | " WHERE event.objid=%d" |
| 793 | " AND blob.rid=%d", |
| 794 | db_get("project-name", "unnamed"), rid, rid |
| 795 | ); |
| 796 | } |
| 797 | zip_of_checkin(eType, rid, zOut ? &zip : 0, |
| 798 | zName, pInclude, pExclude, listFlag); |
| 799 | glob_free(pInclude); |
| 800 | glob_free(pExclude); |
| 801 | if( zOut ){ |
| 802 | blob_write_to_file(&zip, zOut); |
| 803 | blob_reset(&zip); |
| 804 | } |
| 805 | } |
| 806 | |
| 807 | /* |
| 808 | ** COMMAND: zip* |
| 809 | ** |
| @@ -793,13 +818,19 @@ | |
| 818 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 819 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 820 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| 821 | ** --include and --exclude then it is excluded. |
| 822 | ** |
| 823 | ** If OUTPUTFILE is an empty string or "/dev/null" then no ZIP archive is |
| 824 | ** actually generated. This feature can be used in combination with |
| 825 | ** the --list option to get a list of the filename that would be in the |
| 826 | ** ZIP archive had it actually been generated. |
| 827 | ** |
| 828 | ** Options: |
| 829 | ** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude |
| 830 | ** --include GLOBLIST Comma-separated list of GLOBs of files to include |
| 831 | ** -l|--list Show archive content on stdout |
| 832 | ** --name DIRECTORYNAME The name of the top-level directory in the archive |
| 833 | ** -R REPOSITORY Specify a Fossil repository |
| 834 | */ |
| 835 | void zip_cmd(void){ |
| 836 | archive_cmd(ARCHIVE_ZIP); |
| @@ -819,13 +850,19 @@ | |
| 850 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 851 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 852 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| 853 | ** --include and --exclude then it is excluded. |
| 854 | ** |
| 855 | ** If OUTPUTFILE is an empty string or "/dev/null" then no SQLAR archive is |
| 856 | ** actually generated. This feature can be used in combination with |
| 857 | ** the --list option to get a list of the filename that would be in the |
| 858 | ** SQLAR archive had it actually been generated. |
| 859 | ** |
| 860 | ** Options: |
| 861 | ** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude |
| 862 | ** --include GLOBLIST Comma-separated list of GLOBs of files to include |
| 863 | ** -l|--list Show archive content on stdout |
| 864 | ** --name DIRECTORYNAME The name of the top-level directory in the archive |
| 865 | ** -R REPOSITORY Specify a Fossil repository |
| 866 | */ |
| 867 | void sqlar_cmd(void){ |
| 868 | archive_cmd(ARCHIVE_SQLAR); |
| @@ -972,11 +1009,11 @@ | |
| 1009 | style_finish_page(); |
| 1010 | return; |
| 1011 | } |
| 1012 | blob_zero(&zip); |
| 1013 | if( cache_read(&zip, zKey)==0 ){ |
| 1014 | zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude, 0); |
| 1015 | cache_write(&zip, zKey); |
| 1016 | } |
| 1017 | glob_free(pInclude); |
| 1018 | glob_free(pExclude); |
| 1019 | fossil_free(zName); |
| 1020 |