Fossil

Check-in [9c0d5cd8]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Initial implementation of "fossil bundle purge". Needs further testing and refinement.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | DBP-workflow
Files: files | file ages | folders
SHA1: 9c0d5cd895dcb9d4b4585873f021057cfe78c3a2
User & Date: drh 2014-11-27 14:13:04
Context
2014-11-28
14:48
Merge baseline-in-plink enhancements that allow operation with older aux-schema format without having to rebuild. check-in: 47162426 user: drh tags: DBP-workflow
2014-11-27
14:13
Initial implementation of "fossil bundle purge". Needs further testing and refinement. check-in: 9c0d5cd8 user: drh tags: DBP-workflow
12:30
Go back to using SQLite 3.8.8 after fixing the corruption bug in the b-tree balancer. check-in: eaefb180 user: drh tags: DBP-workflow
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/bundle.c.

573
574
575
576
577
578
579



























































































































580
581
582
583
584
585
586
...
587
588
589
590
591
592
593
594


595
596
597
598
599
600
601
602
603
604
605
606
607
608
609






610
611
612
613
614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630
631

632
633
634
635
636
637
638
...
645
646
647
648
649
650
651


652
653
654
655
656
657
658
659
660
661
    "   WHERE NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.uuid);"
  );
  manifest_crosslink_begin();
  bundle_import_elements(0, 0, isPriv);
  manifest_crosslink_end(0);
  db_end_transaction(0);    
}




























































































































/*
** COMMAND: bundle
**
** Usage: %fossil bundle SUBCOMMAND ARGS...
**
**   fossil bundle append BUNDLE FILE...
................................................................................
**
**      Add files named on the command line to BUNDLE.  This subcommand has
**      little practical use and is mostly intended for testing.
**
**   fossil bundle cat BUNDLE UUID...
**
**      Extract one or more artifacts from the bundle and write them
**      consecutively on standard output.


**
**   fossil bundle export BUNDLE ?OPTIONS?
**
**      Generate a new bundle, in the file named BUNDLE, that constains a
**      subset of the check-ins in the repository (usually a single branch)
**      described by the --branch, --from, --to, and/or --checkin options,
**      at least one of which is required.  If BUNDLE already exists, the
**      specified content is added to the bundle.
**
**         --branch BRANCH            Package all check-ins on BRANCH.
**         --from TAG1 --to TAG2      Package checkins between TAG1 and TAG2.
**         --checkin TAG              Package the single checkin TAG
**         --standalone               Do no use delta-encoding against
**                                      artifacts not in the bundle
**






**   fossil bundle import BUNDLE ?--publish?
**
**      Import the bundle in file BUNDLE into the repository.  By default, the
**      imported files are private and will not sync.  Use the --publish
**      option makes the import public.
**
**   fossil bundle ls BUNDLE
**
**      List the contents of BUNDLE on standard output
**
**   fossil bundle purge BUNDLE
**
**      Remove all files found in BUNDLE from the repository.  This has

**      the effect of undoing a "fossil bundle import".
**
** SUMMARY:
**   fossil bundle append BUNDLE FILE...              Add files to BUNDLE
**   fossil bundle cat BUNDLE UUID...                 Extract file from BUNDLE
**   fossil bundle export BUNDLE ?OPTIONS?            Create a new BUNDLE
**          --branch BRANCH --from TAG1 --to TAG2       Checkins to include
**          --checkin TAG                               Use only checkin TAG
**          --standalone                                Omit dependencies

**   fossil bundle import BUNDLE ?OPTIONS?            Import a bundle
**          --publish                                   Publish the import
**          --force                                     Cross-repo import
**   fossil bundle ls BUNDLE                          List content of a bundle
**   fossil bundle purge BUNDLE                       Undo an import
*/
void bundle_cmd(void){
................................................................................
  n = (int)strlen(zSubcmd);
  if( strncmp(zSubcmd, "append", n)==0 ){
    bundle_append_cmd();
  }else if( strncmp(zSubcmd, "cat", n)==0 ){
    bundle_cat_cmd();
  }else if( strncmp(zSubcmd, "export", n)==0 ){
    bundle_export_cmd();


  }else if( strncmp(zSubcmd, "import", n)==0 ){
    bundle_import_cmd();
  }else if( strncmp(zSubcmd, "ls", n)==0 ){
    bundle_ls_cmd();
  }else if( strncmp(zSubcmd, "purge", n)==0 ){
    fossil_print("Not yet implemented...\n");
  }else{
    fossil_fatal("unknown subcommand for bundle: %s", zSubcmd);
  }
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
>
>



|
|










>
>
>
>
>
>


|









|
>
|








>







 







>
>





|




573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
...
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
...
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
    "   WHERE NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.uuid);"
  );
  manifest_crosslink_begin();
  bundle_import_elements(0, 0, isPriv);
  manifest_crosslink_end(0);
  db_end_transaction(0);    
}

/* fossil bundle purge BUNDLE
**
** Try to undo a prior "bundle import BUNDLE".
**
** If the --force option is omitted, then this will only work if
** there have been no checkins or tags added that use the import.
**
** This routine never removes content that is not already in the bundle
** so the bundle serves as a backup.  The purge can be undone using
** "fossil bundle import BUNDLE".
*/
static void bundle_purge_cmd(void){
  int bForce = find_option("force",0,0)!=0;
  int bTest = find_option("test",0,0)!=0;  /* Undocumented --test option */
  const char *zFile = g.argv[3];
  verify_all_options();
  bundle_attach_file(zFile, "b1", 0);
  db_begin_transaction();

  /* Find all checkins of the bundle */
  db_multi_exec(
    "CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY);"
    "INSERT INTO ok SELECT blob.rid FROM bblob, blob, plink"
    " WHERE bblob.uuid=blob.uuid"
    "   AND plink.cid=blob.rid;"
  );

  /* Check to see if new checkins have been committed to checkins in
  ** the bundle.  Do not allow the purge if that is true and if --force
  ** is omitted.
  */
  if( !bForce ){
    Stmt q;
    int n = 0;
    db_prepare(&q,
      "SELECT cid FROM plink WHERE pid IN ok AND cid NOT IN ok"
    );
    while( db_step(&q)==SQLITE_ROW ){
      whatis_rid(db_column_int(&q,0),0);
      fossil_print("%.78c\n", '-');
      n++;
    }
    db_finalize(&q);
    if( n>0 ){
      fossil_fatal("checkins above are derived from checkins in the bundle.");
    }
  }

  /* Find all files associated with those check-ins that are used
  ** nowhere else. */
  find_checkin_associates("ok", 1);

  /* Check to see if any associated files are not in the bundle.  Issue
  ** an error if there are any, unless --force is used.
  */
  if( !bForce ){
    Stmt q;
    int n = 0;
    db_prepare(&q,
       "SELECT rid FROM ok, blob"
       " WHERE blob.rid=ok.rid"
       "   AND blob.uuid NOT IN (SELECT uuid FROM bblob)"
    );
    while( db_step(&q)==SQLITE_OK ){
      whatis_rid(db_column_int(&q,0),0);
      fossil_print("%.78c\n", '-');
      n++;
    }
    if( n>0 ){
      fossil_fatal("artifacts above associated with bundle checkins "
                   " are not in the bundle");
    }
  }

  if( bTest ){
    const char *zBanner = "Artifacts purged that are found in %s:\n";
    Stmt q;
    db_prepare(&q,"SELECT blob.uuid FROM ok, blob, bblob"
                  " WHERE blob.rid=ok.rid AND blob.uuid=bblob.uuid"
                  " ORDER BY 1"
    );
    while( db_step(&q)==SQLITE_ROW ){
      if( zBanner ){
        fossil_print(zBanner/*works-like:"%s"*/,zFile);
        zBanner = 0;
      }
      fossil_print("    %s\n", db_column_text(&q,0));
    }
    db_finalize(&q);
    zBanner = "Artifacts purged that are NOT found in %s:\n";
    db_prepare(&q,"SELECT blob.uuid FROM ok, blob"
                  " WHERE blob.rid=ok.rid"
                  "   AND blob.uuid NOT IN (SELECT uuid FROM bblob)"
                  " ORDER BY 1"
    );
    while( db_step(&q)==SQLITE_ROW ){
      if( zBanner ){
        fossil_print(zBanner/*works-like:"%s"*/,zFile);
        zBanner = 0;
      }
      fossil_print("    %s\n", db_column_text(&q,0));
    }
    db_finalize(&q);
    zBanner = "Artifacts in %s that are not purged:\n";
    db_prepare(&q,"SELECT bblob.uuid FROM bblob, blob"
                  " WHERE blob.uuid=bblob.uuid"
                  "   AND blob.rid NOT IN ok"
                  " ORDER BY 1"
    );
    while( db_step(&q)==SQLITE_ROW ){
      if( zBanner ){
        fossil_print(zBanner/*works-like:"%s"*/,zFile);
        zBanner = 0;
      }
      fossil_print("    %s\n", db_column_text(&q,0));
    }
    db_finalize(&q);
  }else{
    purge_artifact_list("ok",0,0);
  }
  db_end_transaction(0);
}

/*
** COMMAND: bundle
**
** Usage: %fossil bundle SUBCOMMAND ARGS...
**
**   fossil bundle append BUNDLE FILE...
................................................................................
**
**      Add files named on the command line to BUNDLE.  This subcommand has
**      little practical use and is mostly intended for testing.
**
**   fossil bundle cat BUNDLE UUID...
**
**      Extract one or more artifacts from the bundle and write them
**      consecutively on standard output.  This subcommand was designed
**      for testing and introspection of bundles and is not something
**      commonly used.
**
**   fossil bundle export BUNDLE ?OPTIONS?
**
**      Generate a new bundle, in the file named BUNDLE, that contains a
**      subset of the checkins in the repository (usually a single branch)
**      described by the --branch, --from, --to, and/or --checkin options,
**      at least one of which is required.  If BUNDLE already exists, the
**      specified content is added to the bundle.
**
**         --branch BRANCH            Package all check-ins on BRANCH.
**         --from TAG1 --to TAG2      Package checkins between TAG1 and TAG2.
**         --checkin TAG              Package the single checkin TAG
**         --standalone               Do no use delta-encoding against
**                                      artifacts not in the bundle
**
**   fossil bundle extend BUNDLE
**
**      The BUNDLE must already exist.  This subcommand adds to the bundle
**      any checkins that are descendants of checkins already in the bundle,
**      and any tags that apply to artifacts in the bundle.
**
**   fossil bundle import BUNDLE ?--publish?
**
**      Import all content from BUNDLE into the repository.  By default, the
**      imported files are private and will not sync.  Use the --publish
**      option makes the import public.
**
**   fossil bundle ls BUNDLE
**
**      List the contents of BUNDLE on standard output
**
**   fossil bundle purge BUNDLE
**
**      Remove from the repository all files that are used exclusively 
**      by checkins in BUNDLE.  This has the effect of undoing a
**      "fossil bundle import".
**
** SUMMARY:
**   fossil bundle append BUNDLE FILE...              Add files to BUNDLE
**   fossil bundle cat BUNDLE UUID...                 Extract file from BUNDLE
**   fossil bundle export BUNDLE ?OPTIONS?            Create a new BUNDLE
**          --branch BRANCH --from TAG1 --to TAG2       Checkins to include
**          --checkin TAG                               Use only checkin TAG
**          --standalone                                Omit dependencies
**   fossil bundle extend BUNDLE                      Update with newer content
**   fossil bundle import BUNDLE ?OPTIONS?            Import a bundle
**          --publish                                   Publish the import
**          --force                                     Cross-repo import
**   fossil bundle ls BUNDLE                          List content of a bundle
**   fossil bundle purge BUNDLE                       Undo an import
*/
void bundle_cmd(void){
................................................................................
  n = (int)strlen(zSubcmd);
  if( strncmp(zSubcmd, "append", n)==0 ){
    bundle_append_cmd();
  }else if( strncmp(zSubcmd, "cat", n)==0 ){
    bundle_cat_cmd();
  }else if( strncmp(zSubcmd, "export", n)==0 ){
    bundle_export_cmd();
  }else if( strncmp(zSubcmd, "extend", n)==0 ){
    fossil_fatal("not yet implemented");
  }else if( strncmp(zSubcmd, "import", n)==0 ){
    bundle_import_cmd();
  }else if( strncmp(zSubcmd, "ls", n)==0 ){
    bundle_ls_cmd();
  }else if( strncmp(zSubcmd, "purge", n)==0 ){
    bundle_purge_cmd();
  }else{
    fossil_fatal("unknown subcommand for bundle: %s", zSubcmd);
  }
}