Fossil SCM

Initial implementation of "fossil bundle purge". Needs further testing and refinement.

drh 2014-11-27 14:13 UTC DBP-workflow
Commit 9c0d5cd895dcb9d4b4585873f021057cfe78c3a2
1 file changed +142 -7
+142 -7
--- src/bundle.c
+++ src/bundle.c
@@ -575,10 +575,133 @@
575575
manifest_crosslink_begin();
576576
bundle_import_elements(0, 0, isPriv);
577577
manifest_crosslink_end(0);
578578
db_end_transaction(0);
579579
}
580
+
581
+/* fossil bundle purge BUNDLE
582
+**
583
+** Try to undo a prior "bundle import BUNDLE".
584
+**
585
+** If the --force option is omitted, then this will only work if
586
+** there have been no checkins or tags added that use the import.
587
+**
588
+** This routine never removes content that is not already in the bundle
589
+** so the bundle serves as a backup. The purge can be undone using
590
+** "fossil bundle import BUNDLE".
591
+*/
592
+static void bundle_purge_cmd(void){
593
+ int bForce = find_option("force",0,0)!=0;
594
+ int bTest = find_option("test",0,0)!=0; /* Undocumented --test option */
595
+ const char *zFile = g.argv[3];
596
+ verify_all_options();
597
+ bundle_attach_file(zFile, "b1", 0);
598
+ db_begin_transaction();
599
+
600
+ /* Find all checkins of the bundle */
601
+ db_multi_exec(
602
+ "CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY);"
603
+ "INSERT INTO ok SELECT blob.rid FROM bblob, blob, plink"
604
+ " WHERE bblob.uuid=blob.uuid"
605
+ " AND plink.cid=blob.rid;"
606
+ );
607
+
608
+ /* Check to see if new checkins have been committed to checkins in
609
+ ** the bundle. Do not allow the purge if that is true and if --force
610
+ ** is omitted.
611
+ */
612
+ if( !bForce ){
613
+ Stmt q;
614
+ int n = 0;
615
+ db_prepare(&q,
616
+ "SELECT cid FROM plink WHERE pid IN ok AND cid NOT IN ok"
617
+ );
618
+ while( db_step(&q)==SQLITE_ROW ){
619
+ whatis_rid(db_column_int(&q,0),0);
620
+ fossil_print("%.78c\n", '-');
621
+ n++;
622
+ }
623
+ db_finalize(&q);
624
+ if( n>0 ){
625
+ fossil_fatal("checkins above are derived from checkins in the bundle.");
626
+ }
627
+ }
628
+
629
+ /* Find all files associated with those check-ins that are used
630
+ ** nowhere else. */
631
+ find_checkin_associates("ok", 1);
632
+
633
+ /* Check to see if any associated files are not in the bundle. Issue
634
+ ** an error if there are any, unless --force is used.
635
+ */
636
+ if( !bForce ){
637
+ Stmt q;
638
+ int n = 0;
639
+ db_prepare(&q,
640
+ "SELECT rid FROM ok, blob"
641
+ " WHERE blob.rid=ok.rid"
642
+ " AND blob.uuid NOT IN (SELECT uuid FROM bblob)"
643
+ );
644
+ while( db_step(&q)==SQLITE_OK ){
645
+ whatis_rid(db_column_int(&q,0),0);
646
+ fossil_print("%.78c\n", '-');
647
+ n++;
648
+ }
649
+ if( n>0 ){
650
+ fossil_fatal("artifacts above associated with bundle checkins "
651
+ " are not in the bundle");
652
+ }
653
+ }
654
+
655
+ if( bTest ){
656
+ const char *zBanner = "Artifacts purged that are found in %s:\n";
657
+ Stmt q;
658
+ db_prepare(&q,"SELECT blob.uuid FROM ok, blob, bblob"
659
+ " WHERE blob.rid=ok.rid AND blob.uuid=bblob.uuid"
660
+ " ORDER BY 1"
661
+ );
662
+ while( db_step(&q)==SQLITE_ROW ){
663
+ if( zBanner ){
664
+ fossil_print(zBanner/*works-like:"%s"*/,zFile);
665
+ zBanner = 0;
666
+ }
667
+ fossil_print(" %s\n", db_column_text(&q,0));
668
+ }
669
+ db_finalize(&q);
670
+ zBanner = "Artifacts purged that are NOT found in %s:\n";
671
+ db_prepare(&q,"SELECT blob.uuid FROM ok, blob"
672
+ " WHERE blob.rid=ok.rid"
673
+ " AND blob.uuid NOT IN (SELECT uuid FROM bblob)"
674
+ " ORDER BY 1"
675
+ );
676
+ while( db_step(&q)==SQLITE_ROW ){
677
+ if( zBanner ){
678
+ fossil_print(zBanner/*works-like:"%s"*/,zFile);
679
+ zBanner = 0;
680
+ }
681
+ fossil_print(" %s\n", db_column_text(&q,0));
682
+ }
683
+ db_finalize(&q);
684
+ zBanner = "Artifacts in %s that are not purged:\n";
685
+ db_prepare(&q,"SELECT bblob.uuid FROM bblob, blob"
686
+ " WHERE blob.uuid=bblob.uuid"
687
+ " AND blob.rid NOT IN ok"
688
+ " ORDER BY 1"
689
+ );
690
+ while( db_step(&q)==SQLITE_ROW ){
691
+ if( zBanner ){
692
+ fossil_print(zBanner/*works-like:"%s"*/,zFile);
693
+ zBanner = 0;
694
+ }
695
+ fossil_print(" %s\n", db_column_text(&q,0));
696
+ }
697
+ db_finalize(&q);
698
+ }else{
699
+ purge_artifact_list("ok",0,0);
700
+ }
701
+ db_end_transaction(0);
702
+}
580703
581704
/*
582705
** COMMAND: bundle
583706
**
584707
** Usage: %fossil bundle SUBCOMMAND ARGS...
@@ -589,16 +712,18 @@
589712
** little practical use and is mostly intended for testing.
590713
**
591714
** fossil bundle cat BUNDLE UUID...
592715
**
593716
** Extract one or more artifacts from the bundle and write them
594
-** consecutively on standard output.
717
+** consecutively on standard output. This subcommand was designed
718
+** for testing and introspection of bundles and is not something
719
+** commonly used.
595720
**
596721
** fossil bundle export BUNDLE ?OPTIONS?
597722
**
598
-** Generate a new bundle, in the file named BUNDLE, that constains a
599
-** subset of the check-ins in the repository (usually a single branch)
723
+** Generate a new bundle, in the file named BUNDLE, that contains a
724
+** subset of the checkins in the repository (usually a single branch)
600725
** described by the --branch, --from, --to, and/or --checkin options,
601726
** at least one of which is required. If BUNDLE already exists, the
602727
** specified content is added to the bundle.
603728
**
604729
** --branch BRANCH Package all check-ins on BRANCH.
@@ -605,32 +730,40 @@
605730
** --from TAG1 --to TAG2 Package checkins between TAG1 and TAG2.
606731
** --checkin TAG Package the single checkin TAG
607732
** --standalone Do no use delta-encoding against
608733
** artifacts not in the bundle
609734
**
735
+** fossil bundle extend BUNDLE
736
+**
737
+** The BUNDLE must already exist. This subcommand adds to the bundle
738
+** any checkins that are descendants of checkins already in the bundle,
739
+** and any tags that apply to artifacts in the bundle.
740
+**
610741
** fossil bundle import BUNDLE ?--publish?
611742
**
612
-** Import the bundle in file BUNDLE into the repository. By default, the
743
+** Import all content from BUNDLE into the repository. By default, the
613744
** imported files are private and will not sync. Use the --publish
614745
** option makes the import public.
615746
**
616747
** fossil bundle ls BUNDLE
617748
**
618749
** List the contents of BUNDLE on standard output
619750
**
620751
** fossil bundle purge BUNDLE
621752
**
622
-** Remove all files found in BUNDLE from the repository. This has
623
-** the effect of undoing a "fossil bundle import".
753
+** Remove from the repository all files that are used exclusively
754
+** by checkins in BUNDLE. This has the effect of undoing a
755
+** "fossil bundle import".
624756
**
625757
** SUMMARY:
626758
** fossil bundle append BUNDLE FILE... Add files to BUNDLE
627759
** fossil bundle cat BUNDLE UUID... Extract file from BUNDLE
628760
** fossil bundle export BUNDLE ?OPTIONS? Create a new BUNDLE
629761
** --branch BRANCH --from TAG1 --to TAG2 Checkins to include
630762
** --checkin TAG Use only checkin TAG
631763
** --standalone Omit dependencies
764
+** fossil bundle extend BUNDLE Update with newer content
632765
** fossil bundle import BUNDLE ?OPTIONS? Import a bundle
633766
** --publish Publish the import
634767
** --force Cross-repo import
635768
** fossil bundle ls BUNDLE List content of a bundle
636769
** fossil bundle purge BUNDLE Undo an import
@@ -647,15 +780,17 @@
647780
bundle_append_cmd();
648781
}else if( strncmp(zSubcmd, "cat", n)==0 ){
649782
bundle_cat_cmd();
650783
}else if( strncmp(zSubcmd, "export", n)==0 ){
651784
bundle_export_cmd();
785
+ }else if( strncmp(zSubcmd, "extend", n)==0 ){
786
+ fossil_fatal("not yet implemented");
652787
}else if( strncmp(zSubcmd, "import", n)==0 ){
653788
bundle_import_cmd();
654789
}else if( strncmp(zSubcmd, "ls", n)==0 ){
655790
bundle_ls_cmd();
656791
}else if( strncmp(zSubcmd, "purge", n)==0 ){
657
- fossil_print("Not yet implemented...\n");
792
+ bundle_purge_cmd();
658793
}else{
659794
fossil_fatal("unknown subcommand for bundle: %s", zSubcmd);
660795
}
661796
}
662797
--- src/bundle.c
+++ src/bundle.c
@@ -575,10 +575,133 @@
575 manifest_crosslink_begin();
576 bundle_import_elements(0, 0, isPriv);
577 manifest_crosslink_end(0);
578 db_end_transaction(0);
579 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
581 /*
582 ** COMMAND: bundle
583 **
584 ** Usage: %fossil bundle SUBCOMMAND ARGS...
@@ -589,16 +712,18 @@
589 ** little practical use and is mostly intended for testing.
590 **
591 ** fossil bundle cat BUNDLE UUID...
592 **
593 ** Extract one or more artifacts from the bundle and write them
594 ** consecutively on standard output.
 
 
595 **
596 ** fossil bundle export BUNDLE ?OPTIONS?
597 **
598 ** Generate a new bundle, in the file named BUNDLE, that constains a
599 ** subset of the check-ins in the repository (usually a single branch)
600 ** described by the --branch, --from, --to, and/or --checkin options,
601 ** at least one of which is required. If BUNDLE already exists, the
602 ** specified content is added to the bundle.
603 **
604 ** --branch BRANCH Package all check-ins on BRANCH.
@@ -605,32 +730,40 @@
605 ** --from TAG1 --to TAG2 Package checkins between TAG1 and TAG2.
606 ** --checkin TAG Package the single checkin TAG
607 ** --standalone Do no use delta-encoding against
608 ** artifacts not in the bundle
609 **
 
 
 
 
 
 
610 ** fossil bundle import BUNDLE ?--publish?
611 **
612 ** Import the bundle in file BUNDLE into the repository. By default, the
613 ** imported files are private and will not sync. Use the --publish
614 ** option makes the import public.
615 **
616 ** fossil bundle ls BUNDLE
617 **
618 ** List the contents of BUNDLE on standard output
619 **
620 ** fossil bundle purge BUNDLE
621 **
622 ** Remove all files found in BUNDLE from the repository. This has
623 ** the effect of undoing a "fossil bundle import".
 
624 **
625 ** SUMMARY:
626 ** fossil bundle append BUNDLE FILE... Add files to BUNDLE
627 ** fossil bundle cat BUNDLE UUID... Extract file from BUNDLE
628 ** fossil bundle export BUNDLE ?OPTIONS? Create a new BUNDLE
629 ** --branch BRANCH --from TAG1 --to TAG2 Checkins to include
630 ** --checkin TAG Use only checkin TAG
631 ** --standalone Omit dependencies
 
632 ** fossil bundle import BUNDLE ?OPTIONS? Import a bundle
633 ** --publish Publish the import
634 ** --force Cross-repo import
635 ** fossil bundle ls BUNDLE List content of a bundle
636 ** fossil bundle purge BUNDLE Undo an import
@@ -647,15 +780,17 @@
647 bundle_append_cmd();
648 }else if( strncmp(zSubcmd, "cat", n)==0 ){
649 bundle_cat_cmd();
650 }else if( strncmp(zSubcmd, "export", n)==0 ){
651 bundle_export_cmd();
 
 
652 }else if( strncmp(zSubcmd, "import", n)==0 ){
653 bundle_import_cmd();
654 }else if( strncmp(zSubcmd, "ls", n)==0 ){
655 bundle_ls_cmd();
656 }else if( strncmp(zSubcmd, "purge", n)==0 ){
657 fossil_print("Not yet implemented...\n");
658 }else{
659 fossil_fatal("unknown subcommand for bundle: %s", zSubcmd);
660 }
661 }
662
--- src/bundle.c
+++ src/bundle.c
@@ -575,10 +575,133 @@
575 manifest_crosslink_begin();
576 bundle_import_elements(0, 0, isPriv);
577 manifest_crosslink_end(0);
578 db_end_transaction(0);
579 }
580
581 /* fossil bundle purge BUNDLE
582 **
583 ** Try to undo a prior "bundle import BUNDLE".
584 **
585 ** If the --force option is omitted, then this will only work if
586 ** there have been no checkins or tags added that use the import.
587 **
588 ** This routine never removes content that is not already in the bundle
589 ** so the bundle serves as a backup. The purge can be undone using
590 ** "fossil bundle import BUNDLE".
591 */
592 static void bundle_purge_cmd(void){
593 int bForce = find_option("force",0,0)!=0;
594 int bTest = find_option("test",0,0)!=0; /* Undocumented --test option */
595 const char *zFile = g.argv[3];
596 verify_all_options();
597 bundle_attach_file(zFile, "b1", 0);
598 db_begin_transaction();
599
600 /* Find all checkins of the bundle */
601 db_multi_exec(
602 "CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY);"
603 "INSERT INTO ok SELECT blob.rid FROM bblob, blob, plink"
604 " WHERE bblob.uuid=blob.uuid"
605 " AND plink.cid=blob.rid;"
606 );
607
608 /* Check to see if new checkins have been committed to checkins in
609 ** the bundle. Do not allow the purge if that is true and if --force
610 ** is omitted.
611 */
612 if( !bForce ){
613 Stmt q;
614 int n = 0;
615 db_prepare(&q,
616 "SELECT cid FROM plink WHERE pid IN ok AND cid NOT IN ok"
617 );
618 while( db_step(&q)==SQLITE_ROW ){
619 whatis_rid(db_column_int(&q,0),0);
620 fossil_print("%.78c\n", '-');
621 n++;
622 }
623 db_finalize(&q);
624 if( n>0 ){
625 fossil_fatal("checkins above are derived from checkins in the bundle.");
626 }
627 }
628
629 /* Find all files associated with those check-ins that are used
630 ** nowhere else. */
631 find_checkin_associates("ok", 1);
632
633 /* Check to see if any associated files are not in the bundle. Issue
634 ** an error if there are any, unless --force is used.
635 */
636 if( !bForce ){
637 Stmt q;
638 int n = 0;
639 db_prepare(&q,
640 "SELECT rid FROM ok, blob"
641 " WHERE blob.rid=ok.rid"
642 " AND blob.uuid NOT IN (SELECT uuid FROM bblob)"
643 );
644 while( db_step(&q)==SQLITE_OK ){
645 whatis_rid(db_column_int(&q,0),0);
646 fossil_print("%.78c\n", '-');
647 n++;
648 }
649 if( n>0 ){
650 fossil_fatal("artifacts above associated with bundle checkins "
651 " are not in the bundle");
652 }
653 }
654
655 if( bTest ){
656 const char *zBanner = "Artifacts purged that are found in %s:\n";
657 Stmt q;
658 db_prepare(&q,"SELECT blob.uuid FROM ok, blob, bblob"
659 " WHERE blob.rid=ok.rid AND blob.uuid=bblob.uuid"
660 " ORDER BY 1"
661 );
662 while( db_step(&q)==SQLITE_ROW ){
663 if( zBanner ){
664 fossil_print(zBanner/*works-like:"%s"*/,zFile);
665 zBanner = 0;
666 }
667 fossil_print(" %s\n", db_column_text(&q,0));
668 }
669 db_finalize(&q);
670 zBanner = "Artifacts purged that are NOT found in %s:\n";
671 db_prepare(&q,"SELECT blob.uuid FROM ok, blob"
672 " WHERE blob.rid=ok.rid"
673 " AND blob.uuid NOT IN (SELECT uuid FROM bblob)"
674 " ORDER BY 1"
675 );
676 while( db_step(&q)==SQLITE_ROW ){
677 if( zBanner ){
678 fossil_print(zBanner/*works-like:"%s"*/,zFile);
679 zBanner = 0;
680 }
681 fossil_print(" %s\n", db_column_text(&q,0));
682 }
683 db_finalize(&q);
684 zBanner = "Artifacts in %s that are not purged:\n";
685 db_prepare(&q,"SELECT bblob.uuid FROM bblob, blob"
686 " WHERE blob.uuid=bblob.uuid"
687 " AND blob.rid NOT IN ok"
688 " ORDER BY 1"
689 );
690 while( db_step(&q)==SQLITE_ROW ){
691 if( zBanner ){
692 fossil_print(zBanner/*works-like:"%s"*/,zFile);
693 zBanner = 0;
694 }
695 fossil_print(" %s\n", db_column_text(&q,0));
696 }
697 db_finalize(&q);
698 }else{
699 purge_artifact_list("ok",0,0);
700 }
701 db_end_transaction(0);
702 }
703
704 /*
705 ** COMMAND: bundle
706 **
707 ** Usage: %fossil bundle SUBCOMMAND ARGS...
@@ -589,16 +712,18 @@
712 ** little practical use and is mostly intended for testing.
713 **
714 ** fossil bundle cat BUNDLE UUID...
715 **
716 ** Extract one or more artifacts from the bundle and write them
717 ** consecutively on standard output. This subcommand was designed
718 ** for testing and introspection of bundles and is not something
719 ** commonly used.
720 **
721 ** fossil bundle export BUNDLE ?OPTIONS?
722 **
723 ** Generate a new bundle, in the file named BUNDLE, that contains a
724 ** subset of the checkins in the repository (usually a single branch)
725 ** described by the --branch, --from, --to, and/or --checkin options,
726 ** at least one of which is required. If BUNDLE already exists, the
727 ** specified content is added to the bundle.
728 **
729 ** --branch BRANCH Package all check-ins on BRANCH.
@@ -605,32 +730,40 @@
730 ** --from TAG1 --to TAG2 Package checkins between TAG1 and TAG2.
731 ** --checkin TAG Package the single checkin TAG
732 ** --standalone Do no use delta-encoding against
733 ** artifacts not in the bundle
734 **
735 ** fossil bundle extend BUNDLE
736 **
737 ** The BUNDLE must already exist. This subcommand adds to the bundle
738 ** any checkins that are descendants of checkins already in the bundle,
739 ** and any tags that apply to artifacts in the bundle.
740 **
741 ** fossil bundle import BUNDLE ?--publish?
742 **
743 ** Import all content from BUNDLE into the repository. By default, the
744 ** imported files are private and will not sync. Use the --publish
745 ** option makes the import public.
746 **
747 ** fossil bundle ls BUNDLE
748 **
749 ** List the contents of BUNDLE on standard output
750 **
751 ** fossil bundle purge BUNDLE
752 **
753 ** Remove from the repository all files that are used exclusively
754 ** by checkins in BUNDLE. This has the effect of undoing a
755 ** "fossil bundle import".
756 **
757 ** SUMMARY:
758 ** fossil bundle append BUNDLE FILE... Add files to BUNDLE
759 ** fossil bundle cat BUNDLE UUID... Extract file from BUNDLE
760 ** fossil bundle export BUNDLE ?OPTIONS? Create a new BUNDLE
761 ** --branch BRANCH --from TAG1 --to TAG2 Checkins to include
762 ** --checkin TAG Use only checkin TAG
763 ** --standalone Omit dependencies
764 ** fossil bundle extend BUNDLE Update with newer content
765 ** fossil bundle import BUNDLE ?OPTIONS? Import a bundle
766 ** --publish Publish the import
767 ** --force Cross-repo import
768 ** fossil bundle ls BUNDLE List content of a bundle
769 ** fossil bundle purge BUNDLE Undo an import
@@ -647,15 +780,17 @@
780 bundle_append_cmd();
781 }else if( strncmp(zSubcmd, "cat", n)==0 ){
782 bundle_cat_cmd();
783 }else if( strncmp(zSubcmd, "export", n)==0 ){
784 bundle_export_cmd();
785 }else if( strncmp(zSubcmd, "extend", n)==0 ){
786 fossil_fatal("not yet implemented");
787 }else if( strncmp(zSubcmd, "import", n)==0 ){
788 bundle_import_cmd();
789 }else if( strncmp(zSubcmd, "ls", n)==0 ){
790 bundle_ls_cmd();
791 }else if( strncmp(zSubcmd, "purge", n)==0 ){
792 bundle_purge_cmd();
793 }else{
794 fossil_fatal("unknown subcommand for bundle: %s", zSubcmd);
795 }
796 }
797

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button