File Annotation
Not logged in
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Copyright (c) 2007 D. Richard Hipp
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is free software; you can redistribute it and/or
dbda8d6ce9 2007-07-21       drh: ** modify it under the terms of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License version 2 as published by the Free Software Foundation.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is distributed in the hope that it will be useful,
dbda8d6ce9 2007-07-21       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
dbda8d6ce9 2007-07-21       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dbda8d6ce9 2007-07-21       drh: ** General Public License for more details.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** You should have received a copy of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License along with this library; if not, write to the
dbda8d6ce9 2007-07-21       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
dbda8d6ce9 2007-07-21       drh: ** Boston, MA  02111-1307, USA.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Author contact information:
dbda8d6ce9 2007-07-21       drh: **   drh@hwaci.com
dbda8d6ce9 2007-07-21       drh: **   http://www.hwaci.com/drh/
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: *******************************************************************************
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This file contains code used to rebuild the database.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: #include "config.h"
dbda8d6ce9 2007-07-21       drh: #include "rebuild.h"
dbda8d6ce9 2007-07-21       drh: #include <assert.h>
dbda8d6ce9 2007-07-21       drh: 
e00384d26d 2007-08-29       aku: /*
62f37c9722 2007-11-26       drh: ** Schema changes
62f37c9722 2007-11-26       drh: */
62f37c9722 2007-11-26       drh: static const char zSchemaUpdates[] =
62f37c9722 2007-11-26       drh: @ -- Index on the delta table
62f37c9722 2007-11-26       drh: @ --
f088412c49 2007-11-28       drh: @ CREATE INDEX IF NOT EXISTS delta_i1 ON delta(srcid);
62f37c9722 2007-11-26       drh: @
62f37c9722 2007-11-26       drh: @ -- Artifacts that should not be processed are identified in the
62f37c9722 2007-11-26       drh: @ -- "shun" table.  Artifacts that are control-file forgeries or
525cc35bf3 2008-05-17       drh: @ -- spam or artifacts whose contents violate administrative policy
525cc35bf3 2008-05-17       drh: @ -- can be shunned in order to prevent them from contaminating
62f37c9722 2007-11-26       drh: @ -- the repository.
62f37c9722 2007-11-26       drh: @ --
525cc35bf3 2008-05-17       drh: @ -- Shunned artifacts do not exist in the blob table.  Hence they
525cc35bf3 2008-05-17       drh: @ -- have not artifact ID (rid) and we thus must store their full
525cc35bf3 2008-05-17       drh: @ -- UUID.
525cc35bf3 2008-05-17       drh: @ --
62f37c9722 2007-11-26       drh: @ CREATE TABLE IF NOT EXISTS shun(uuid UNIQUE);
525cc35bf3 2008-05-17       drh: @
525cc35bf3 2008-05-17       drh: @ -- Artifacts that should not be pushed are stored in the "private"
525cc35bf3 2008-05-17       drh: @ -- table.
525cc35bf3 2008-05-17       drh: @ --
525cc35bf3 2008-05-17       drh: @ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
62f37c9722 2007-11-26       drh: @
62f37c9722 2007-11-26       drh: @ -- An entry in this table describes a database query that generates a
62f37c9722 2007-11-26       drh: @ -- table of tickets.
62f37c9722 2007-11-26       drh: @ --
62f37c9722 2007-11-26       drh: @ CREATE TABLE IF NOT EXISTS reportfmt(
62f37c9722 2007-11-26       drh: @    rn integer primary key,  -- Report number
62f37c9722 2007-11-26       drh: @    owner text,              -- Owner of this report format (not used)
62f37c9722 2007-11-26       drh: @    title text,              -- Title of this report
62f37c9722 2007-11-26       drh: @    cols text,               -- A color-key specification
62f37c9722 2007-11-26       drh: @    sqlcode text             -- An SQL SELECT statement for this report
62f37c9722 2007-11-26       drh: @ );
5b74febbcc 2008-05-16       drh: @
f46fe42d6d 2008-07-24       drh: @ -- Some ticket content (such as the originators email address or contact
f46fe42d6d 2008-07-24       drh: @ -- information) needs to be obscured to protect privacy.  This is achieved
f46fe42d6d 2008-07-24       drh: @ -- by storing an SHA1 hash of the content.  For display, the hash is
f46fe42d6d 2008-07-24       drh: @ -- mapped back into the original text using this table.
f46fe42d6d 2008-07-24       drh: @ --
f46fe42d6d 2008-07-24       drh: @ -- This table contains sensitive information and should not be shared
f46fe42d6d 2008-07-24       drh: @ -- with unauthorized users.
5b74febbcc 2008-05-16       drh: @ --
f46fe42d6d 2008-07-24       drh: @ CREATE TABLE IF NOT EXISTS concealed(
f46fe42d6d 2008-07-24       drh: @   hash TEXT PRIMARY KEY,
f46fe42d6d 2008-07-24       drh: @   content TEXT
5b74febbcc 2008-05-16       drh: @ );
62f37c9722 2007-11-26       drh: ;
61ddd63b72 2008-03-06       drh: 
61ddd63b72 2008-03-06       drh: /*
61ddd63b72 2008-03-06       drh: ** Variables used for progress information
61ddd63b72 2008-03-06       drh: */
61ddd63b72 2008-03-06       drh: static int totalSize;       /* Total number of artifacts to process */
61ddd63b72 2008-03-06       drh: static int processCnt;      /* Number processed so far */
61ddd63b72 2008-03-06       drh: static int ttyOutput;       /* Do progress output */
791a513c28 2008-05-18       drh: static Bag bagDone;         /* Bag of records rebuilt */
61ddd63b72 2008-03-06       drh: 
61ddd63b72 2008-03-06       drh: /*
61ddd63b72 2008-03-06       drh: ** Called after each artifact is processed
61ddd63b72 2008-03-06       drh: */
791a513c28 2008-05-18       drh: static void rebuild_step_done(rid){
cfb1341ae3 2008-06-02       drh:   /* assert( bag_find(&bagDone, rid)==0 ); */
791a513c28 2008-05-18       drh:   bag_insert(&bagDone, rid);
61ddd63b72 2008-03-06       drh:   if( ttyOutput ){
61ddd63b72 2008-03-06       drh:     processCnt++;
137d653a06 2009-12-14    Jeremy:     if (!g.fQuiet) {
137d653a06 2009-12-14    Jeremy:       printf("%d (%d%%)...\r", processCnt, (processCnt*100/totalSize));
137d653a06 2009-12-14    Jeremy:       fflush(stdout);
137d653a06 2009-12-14    Jeremy:     }
61ddd63b72 2008-03-06       drh:   }
61ddd63b72 2008-03-06       drh: }
61ddd63b72 2008-03-06       drh: 
61ddd63b72 2008-03-06       drh: /*
61ddd63b72 2008-03-06       drh: ** Rebuild cross-referencing information for the artifact
6458f020fc 2008-05-14       drh: ** rid with content pBase and all of its descendants.  This
61ddd63b72 2008-03-06       drh: ** routine clears the content buffer before returning.
61ddd63b72 2008-03-06       drh: */
5b74febbcc 2008-05-16       drh: static void rebuild_step(int rid, int size, Blob *pBase){
61ddd63b72 2008-03-06       drh:   Stmt q1;
61ddd63b72 2008-03-06       drh:   Bag children;
61ddd63b72 2008-03-06       drh:   Blob copy;
61ddd63b72 2008-03-06       drh:   Blob *pUse;
61ddd63b72 2008-03-06       drh:   int nChild, i, cid;
61ddd63b72 2008-03-06       drh: 
5b74febbcc 2008-05-16       drh:   /* Fix up the "blob.size" field if needed. */
5b74febbcc 2008-05-16       drh:   if( size!=blob_size(pBase) ){
5b74febbcc 2008-05-16       drh:     db_multi_exec(
5b74febbcc 2008-05-16       drh:        "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid
5b74febbcc 2008-05-16       drh:     );
5b74febbcc 2008-05-16       drh:   }
5b74febbcc 2008-05-16       drh: 
61ddd63b72 2008-03-06       drh:   /* Find all children of artifact rid */
61ddd63b72 2008-03-06       drh:   db_prepare(&q1, "SELECT rid FROM delta WHERE srcid=%d", rid);
61ddd63b72 2008-03-06       drh:   bag_init(&children);
61ddd63b72 2008-03-06       drh:   while( db_step(&q1)==SQLITE_ROW ){
791a513c28 2008-05-18       drh:     int cid = db_column_int(&q1, 0);
791a513c28 2008-05-18       drh:     if( !bag_find(&bagDone, cid) ){
791a513c28 2008-05-18       drh:       bag_insert(&children, cid);
791a513c28 2008-05-18       drh:     }
61ddd63b72 2008-03-06       drh:   }
61ddd63b72 2008-03-06       drh:   nChild = bag_count(&children);
61ddd63b72 2008-03-06       drh:   db_finalize(&q1);
61ddd63b72 2008-03-06       drh: 
61ddd63b72 2008-03-06       drh:   /* Crosslink the artifact */
61ddd63b72 2008-03-06       drh:   if( nChild==0 ){
61ddd63b72 2008-03-06       drh:     pUse = pBase;
61ddd63b72 2008-03-06       drh:   }else{
61ddd63b72 2008-03-06       drh:     blob_copy(&copy, pBase);
61ddd63b72 2008-03-06       drh:     pUse = &copy;
61ddd63b72 2008-03-06       drh:   }
61ddd63b72 2008-03-06       drh:   manifest_crosslink(rid, pUse);
61ddd63b72 2008-03-06       drh:   blob_reset(pUse);
61ddd63b72 2008-03-06       drh: 
61ddd63b72 2008-03-06       drh:   /* Call all children recursively */
61ddd63b72 2008-03-06       drh:   for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){
61ddd63b72 2008-03-06       drh:     Stmt q2;
61ddd63b72 2008-03-06       drh:     int sz;
61ddd63b72 2008-03-06       drh:     if( nChild==i ){
61ddd63b72 2008-03-06       drh:       pUse = pBase;
61ddd63b72 2008-03-06       drh:     }else{
61ddd63b72 2008-03-06       drh:       blob_copy(&copy, pBase);
61ddd63b72 2008-03-06       drh:       pUse = &copy;
61ddd63b72 2008-03-06       drh:     }
61ddd63b72 2008-03-06       drh:     db_prepare(&q2, "SELECT content, size FROM blob WHERE rid=%d", cid);
61ddd63b72 2008-03-06       drh:     if( db_step(&q2)==SQLITE_ROW && (sz = db_column_int(&q2,1))>=0 ){
61ddd63b72 2008-03-06       drh:       Blob delta;
61ddd63b72 2008-03-06       drh:       db_ephemeral_blob(&q2, 0, &delta);
61ddd63b72 2008-03-06       drh:       blob_uncompress(&delta, &delta);
61ddd63b72 2008-03-06       drh:       blob_delta_apply(pUse, &delta, pUse);
61ddd63b72 2008-03-06       drh:       blob_reset(&delta);
61ddd63b72 2008-03-06       drh:       db_finalize(&q2);
5b74febbcc 2008-05-16       drh:       rebuild_step(cid, sz, pUse);
61ddd63b72 2008-03-06       drh:     }else{
61ddd63b72 2008-03-06       drh:       db_finalize(&q2);
61ddd63b72 2008-03-06       drh:       blob_reset(pUse);
61ddd63b72 2008-03-06       drh:     }
61ddd63b72 2008-03-06       drh:   }
61ddd63b72 2008-03-06       drh:   bag_clear(&children);
791a513c28 2008-05-18       drh:   rebuild_step_done(rid);
791a513c28 2008-05-18       drh: }
791a513c28 2008-05-18       drh: 
791a513c28 2008-05-18       drh: /*
7c7edde116 2009-01-21       drh: ** Check to see if the the "sym-trunk" tag exists.  If not, create it
7c7edde116 2009-01-21       drh: ** and attach it to the very first check-in.
7c7edde116 2009-01-21       drh: */
7c7edde116 2009-01-21       drh: static void rebuild_tag_trunk(void){
7c7edde116 2009-01-21       drh:   int tagid = db_int(0, "SELECT 1 FROM tag WHERE tagname='sym-trunk'");
7c7edde116 2009-01-21       drh:   int rid;
7c7edde116 2009-01-21       drh:   char *zUuid;
7c7edde116 2009-01-21       drh: 
7c7edde116 2009-01-21       drh:   if( tagid>0 ) return;
7c7edde116 2009-01-21       drh:   rid = db_int(0, "SELECT pid FROM plink AS x WHERE NOT EXISTS("
7c7edde116 2009-01-21       drh:                   "  SELECT 1 FROM plink WHERE cid=x.pid)");
7c7edde116 2009-01-21       drh:   if( rid==0 ) return;
7c7edde116 2009-01-21       drh: 
7c7edde116 2009-01-21       drh:   /* Add the trunk tag to the root of the whole tree */
7c7edde116 2009-01-21       drh:   zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
7c7edde116 2009-01-21       drh:   if( zUuid==0 ) return;
7c7edde116 2009-01-21       drh:   tag_add_artifact("sym-", "trunk", zUuid, 0, 2);
42c2a18e73 2009-01-22       drh:   tag_add_artifact("", "branch", zUuid, "trunk", 2);
61ddd63b72 2008-03-06       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
e00384d26d 2007-08-29       aku: ** Core function to rebuild the infomration in the derived tables of a
e00384d26d 2007-08-29       aku: ** fossil repository from the blobs. This function is shared between
e00384d26d 2007-08-29       aku: ** 'rebuild_database' ('rebuild') and 'reconstruct_cmd'
e00384d26d 2007-08-29       aku: ** ('reconstruct'), both of which have to regenerate this information
e00384d26d 2007-08-29       aku: ** from scratch.
dbda8d6ce9 2007-07-21       drh: **
ce1c1a2907 2007-09-21       drh: ** If the randomize parameter is true, then the BLOBs are deliberately
ce1c1a2907 2007-09-21       drh: ** extracted in a random order.  This feature is used to test the
ce1c1a2907 2007-09-21       drh: ** ability of fossil to accept records in any order and still
ce1c1a2907 2007-09-21       drh: ** construct a sane repository.
dbda8d6ce9 2007-07-21       drh: */
61ddd63b72 2008-03-06       drh: int rebuild_db(int randomize, int doOut){
dbda8d6ce9 2007-07-21       drh:   Stmt s;
e00384d26d 2007-08-29       aku:   int errCnt = 0;
dbda8d6ce9 2007-07-21       drh:   char *zTable;
dbda8d6ce9 2007-07-21       drh: 
791a513c28 2008-05-18       drh:   bag_init(&bagDone);
61ddd63b72 2008-03-06       drh:   ttyOutput = doOut;
61ddd63b72 2008-03-06       drh:   processCnt = 0;
137d653a06 2009-12-14    Jeremy:   if (!g.fQuiet) {
137d653a06 2009-12-14    Jeremy:     printf("0 (0%%)...\r");
137d653a06 2009-12-14    Jeremy:     fflush(stdout);
dbda8d6ce9 2007-07-21       drh:   }
62f37c9722 2007-11-26       drh:   db_multi_exec(zSchemaUpdates);
dbda8d6ce9 2007-07-21       drh:   for(;;){
dbda8d6ce9 2007-07-21       drh:     zTable = db_text(0,
dbda8d6ce9 2007-07-21       drh:        "SELECT name FROM sqlite_master"
dbda8d6ce9 2007-07-21       drh:        " WHERE type='table'"
525cc35bf3 2008-05-17       drh:        " AND name NOT IN ('blob','delta','rcvfrom','user',"
f46fe42d6d 2008-07-24       drh:                          "'config','shun','private','reportfmt',"
f46fe42d6d 2008-07-24       drh:                          "'concealed')"
525cc35bf3 2008-05-17       drh:     );
dbda8d6ce9 2007-07-21       drh:     if( zTable==0 ) break;
dbda8d6ce9 2007-07-21       drh:     db_multi_exec("DROP TABLE %Q", zTable);
dbda8d6ce9 2007-07-21       drh:     free(zTable);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   db_multi_exec(zRepositorySchema2);
fb358ca492 2007-11-24       drh:   ticket_create_table(0);
a48474bc75 2008-05-29       drh:   shun_artifacts();
dbda8d6ce9 2007-07-21       drh: 
525cc35bf3 2008-05-17       drh:   db_multi_exec(
525cc35bf3 2008-05-17       drh:      "INSERT INTO unclustered"
525cc35bf3 2008-05-17       drh:      " SELECT rid FROM blob EXCEPT SELECT rid FROM private"
525cc35bf3 2008-05-17       drh:   );
70d5cc86b7 2007-10-05       drh:   db_multi_exec(
70d5cc86b7 2007-10-05       drh:      "DELETE FROM unclustered"
70d5cc86b7 2007-10-05       drh:      " WHERE rid IN (SELECT rid FROM shun JOIN blob USING(uuid))"
70d5cc86b7 2007-10-05       drh:   );
ba486fec5a 2007-09-03       drh:   db_multi_exec(
ba486fec5a 2007-09-03       drh:     "DELETE FROM config WHERE name IN ('remote-code', 'remote-maxid')"
ba486fec5a 2007-09-03       drh:   );
61ddd63b72 2008-03-06       drh:   totalSize = db_int(0, "SELECT count(*) FROM blob");
ce1c1a2907 2007-09-21       drh:   db_prepare(&s,
61ddd63b72 2008-03-06       drh:      "SELECT rid, size FROM blob"
61ddd63b72 2008-03-06       drh:      " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
61ddd63b72 2008-03-06       drh:      "   AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
ce1c1a2907 2007-09-21       drh:   );
95f5520a09 2009-09-14       drh:   manifest_crosslink_begin();
73bddaebb9 2007-08-09       drh:   while( db_step(&s)==SQLITE_ROW ){
73bddaebb9 2007-08-09       drh:     int rid = db_column_int(&s, 0);
73bddaebb9 2007-08-09       drh:     int size = db_column_int(&s, 1);
73bddaebb9 2007-08-09       drh:     if( size>=0 ){
73bddaebb9 2007-08-09       drh:       Blob content;
73bddaebb9 2007-08-09       drh:       content_get(rid, &content);
5b74febbcc 2008-05-16       drh:       rebuild_step(rid, size, &content);
791a513c28 2008-05-18       drh:     }
791a513c28 2008-05-18       drh:   }
791a513c28 2008-05-18       drh:   db_finalize(&s);
791a513c28 2008-05-18       drh:   db_prepare(&s,
791a513c28 2008-05-18       drh:      "SELECT rid, size FROM blob"
791a513c28 2008-05-18       drh:      " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
791a513c28 2008-05-18       drh:   );
dbda8d6ce9 2007-07-21       drh:   while( db_step(&s)==SQLITE_ROW ){
dbda8d6ce9 2007-07-21       drh:     int rid = db_column_int(&s, 0);
791a513c28 2008-05-18       drh:     int size = db_column_int(&s, 1);
791a513c28 2008-05-18       drh:     if( size>=0 ){
791a513c28 2008-05-18       drh:       if( !bag_find(&bagDone, rid) ){
791a513c28 2008-05-18       drh:         Blob content;
791a513c28 2008-05-18       drh:         content_get(rid, &content);
791a513c28 2008-05-18       drh:         rebuild_step(rid, size, &content);
791a513c28 2008-05-18       drh:       }
73bddaebb9 2007-08-09       drh:     }else{
e1c1877c99 2007-09-08       drh:       db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid);
791a513c28 2008-05-18       drh:       rebuild_step_done(rid);
73bddaebb9 2007-08-09       drh:     }
73bddaebb9 2007-08-09       drh:   }
e38fc922a5 2007-10-11       drh:   db_finalize(&s);
95f5520a09 2009-09-14       drh:   manifest_crosslink_end();
7c7edde116 2009-01-21       drh:   rebuild_tag_trunk();
137d653a06 2009-12-14    Jeremy:   if(!g.fQuiet && ttyOutput ){
e38fc922a5 2007-10-11       drh:     printf("\n");
dbda8d6ce9 2007-07-21       drh:   }
e00384d26d 2007-08-29       aku:   return errCnt;
e00384d26d 2007-08-29       aku: }
e00384d26d 2007-08-29       aku: 
e00384d26d 2007-08-29       aku: /*
e00384d26d 2007-08-29       aku: ** COMMAND:  rebuild
e00384d26d 2007-08-29       aku: **
d0fc1ad062 2009-08-22       drh: ** Usage: %fossil rebuild ?REPOSITORY?
e00384d26d 2007-08-29       aku: **
e00384d26d 2007-08-29       aku: ** Reconstruct the named repository database from the core
e00384d26d 2007-08-29       aku: ** records.  Run this command after updating the fossil
e00384d26d 2007-08-29       aku: ** executable in a way that changes the database schema.
e00384d26d 2007-08-29       aku: */
e00384d26d 2007-08-29       aku: void rebuild_database(void){
e00384d26d 2007-08-29       aku:   int forceFlag;
ce1c1a2907 2007-09-21       drh:   int randomizeFlag;
e00384d26d 2007-08-29       aku:   int errCnt;
dbda8d6ce9 2007-07-21       drh: 
e00384d26d 2007-08-29       aku:   forceFlag = find_option("force","f",0)!=0;
ce1c1a2907 2007-09-21       drh:   randomizeFlag = find_option("randomize", 0, 0)!=0;
d0fc1ad062 2009-08-22       drh:   if( g.argc==3 ){
d0fc1ad062 2009-08-22       drh:     db_open_repository(g.argv[2]);
d0fc1ad062 2009-08-22       drh:   }else{
d0fc1ad062 2009-08-22       drh:     db_find_and_open_repository(1);
d0fc1ad062 2009-08-22       drh:     if( g.argc!=2 ){
d0fc1ad062 2009-08-22       drh:       usage("?REPOSITORY-FILENAME?");
d0fc1ad062 2009-08-22       drh:     }
d0fc1ad062 2009-08-22       drh:     db_close();
d0fc1ad062 2009-08-22       drh:     db_open_repository(g.zRepositoryName);
e38fc922a5 2007-10-11       drh:   }
e00384d26d 2007-08-29       aku:   db_begin_transaction();
61ddd63b72 2008-03-06       drh:   ttyOutput = 1;
e38fc922a5 2007-10-11       drh:   errCnt = rebuild_db(randomizeFlag, 1);
dbda8d6ce9 2007-07-21       drh:   if( errCnt && !forceFlag ){
dbda8d6ce9 2007-07-21       drh:     printf("%d errors. Rolling back changes. Use --force to force a commit.\n",
dbda8d6ce9 2007-07-21       drh:             errCnt);
dbda8d6ce9 2007-07-21       drh:     db_end_transaction(1);
dbda8d6ce9 2007-07-21       drh:   }else{
3f6edbc779 2008-11-10       drh:     db_end_transaction(0);
3f6edbc779 2008-11-10       drh:   }
3f6edbc779 2008-11-10       drh: }
3f6edbc779 2008-11-10       drh: 
3f6edbc779 2008-11-10       drh: /*
3f6edbc779 2008-11-10       drh: ** COMMAND:  test-detach
3f6edbc779 2008-11-10       drh: **
3f6edbc779 2008-11-10       drh: ** Change the project-code and make other changes in order to prevent
3f6edbc779 2008-11-10       drh: ** the repository from ever again pushing or pulling to other
3f6edbc779 2008-11-10       drh: ** repositories.  Used to create a "test" repository for development
3f6edbc779 2008-11-10       drh: ** testing by cloning a working project repository.
3f6edbc779 2008-11-10       drh: */
3f6edbc779 2008-11-10       drh: void test_detach_cmd(void){
3f6edbc779 2008-11-10       drh:   db_find_and_open_repository(1);
3f6edbc779 2008-11-10       drh:   db_begin_transaction();
3f6edbc779 2008-11-10       drh:   db_multi_exec(
3f6edbc779 2008-11-10       drh:     "DELETE FROM config WHERE name='last-sync-url';"
3f6edbc779 2008-11-10       drh:     "UPDATE config SET value=lower(hex(randomblob(20)))"
3f6edbc779 2008-11-10       drh:     " WHERE name='project-code';"
3f6edbc779 2008-11-10       drh:     "UPDATE config SET value='detached-' || value"
3f6edbc779 2008-11-10       drh:     " WHERE name='project-name' AND value NOT GLOB 'detached-*';"
3f6edbc779 2008-11-10       drh:   );
3f6edbc779 2008-11-10       drh:   db_end_transaction(0);
6c6a978a53 2009-09-14       drh: }
6c6a978a53 2009-09-14       drh: 
6c6a978a53 2009-09-14       drh: /*
6c6a978a53 2009-09-14       drh: ** COMMAND: scrub
6c6a978a53 2009-09-14       drh: ** %fossil scrub [--verily] [--force] [REPOSITORY]
6c6a978a53 2009-09-14       drh: **
6c6a978a53 2009-09-14       drh: ** The command removes sensitive information (such as passwords) from a
6c6a978a53 2009-09-14       drh: ** repository so that the respository can be sent to an untrusted reader.
6c6a978a53 2009-09-14       drh: **
6c6a978a53 2009-09-14       drh: ** By default, only passwords are removed.  However, if the --verily option
6c6a978a53 2009-09-14       drh: ** is added, then private branches, concealed email addresses, IP
6c6a978a53 2009-09-14       drh: ** addresses of correspondents, and similar privacy-sensitive fields
6c6a978a53 2009-09-14       drh: ** are also purged.
6c6a978a53 2009-09-14       drh: **
6c6a978a53 2009-09-14       drh: ** This command permanently deletes the scrubbed information.  The effects
6c6a978a53 2009-09-14       drh: ** of this command are irreversible.  Use with caution.
6c6a978a53 2009-09-14       drh: **
6c6a978a53 2009-09-14       drh: ** The user is prompted to confirm the scrub unless the --force option
6c6a978a53 2009-09-14       drh: ** is used.
6c6a978a53 2009-09-14       drh: */
6c6a978a53 2009-09-14       drh: void scrub_cmd(void){
6c6a978a53 2009-09-14       drh:   int bVerily = find_option("verily",0,0)!=0;
6c6a978a53 2009-09-14       drh:   int bForce = find_option("force", "f", 0)!=0;
6c6a978a53 2009-09-14       drh:   int bNeedRebuild = 0;
6c6a978a53 2009-09-14       drh:   if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
6c6a978a53 2009-09-14       drh:   if( g.argc==2 ){
6c6a978a53 2009-09-14       drh:     db_must_be_within_tree();
6c6a978a53 2009-09-14       drh:   }else{
6c6a978a53 2009-09-14       drh:     db_open_repository(g.argv[2]);
6c6a978a53 2009-09-14       drh:   }
6c6a978a53 2009-09-14       drh:   if( !bForce ){
6c6a978a53 2009-09-14       drh:     Blob ans;
6c6a978a53 2009-09-14       drh:     blob_zero(&ans);
6c6a978a53 2009-09-14       drh:     prompt_user("Scrubbing the repository will permanently remove user\n"
6c6a978a53 2009-09-14       drh:                 "passwords and other information. Changes cannot be undone.\n"
6ae51190cc 2009-12-10   rwilson:                 "Continue (y/N)? ", &ans);
6c6a978a53 2009-09-14       drh:     if( blob_str(&ans)[0]!='y' ){
6c6a978a53 2009-09-14       drh:       exit(1);
6c6a978a53 2009-09-14       drh:     }
6c6a978a53 2009-09-14       drh:   }
6c6a978a53 2009-09-14       drh:   db_begin_transaction();
6c6a978a53 2009-09-14       drh:   db_multi_exec(
6c6a978a53 2009-09-14       drh:     "UPDATE user SET pw='';"
6c6a978a53 2009-09-14       drh:     "DELETE FROM config WHERE name='last-sync-url';"
6c6a978a53 2009-09-14       drh:   );
6c6a978a53 2009-09-14       drh:   if( bVerily ){
6c6a978a53 2009-09-14       drh:     bNeedRebuild = db_exists("SELECT 1 FROM private");
6c6a978a53 2009-09-14       drh:     db_multi_exec(
6c6a978a53 2009-09-14       drh:       "DELETE FROM concealed;"
6c6a978a53 2009-09-14       drh:       "UPDATE rcvfrom SET ipaddr='unknown';"
6c6a978a53 2009-09-14       drh:       "UPDATE user SET photo=NULL, info='';"
6c6a978a53 2009-09-14       drh:       "INSERT INTO shun SELECT uuid FROM blob WHERE rid IN private;"
6c6a978a53 2009-09-14       drh:     );
6c6a978a53 2009-09-14       drh:   }
6c6a978a53 2009-09-14       drh:   if( !bNeedRebuild ){
6c6a978a53 2009-09-14       drh:     db_end_transaction(0);
6c6a978a53 2009-09-14       drh:     db_multi_exec("VACUUM;");
6c6a978a53 2009-09-14       drh:   }else{
6c6a978a53 2009-09-14       drh:     rebuild_db(0, 1);
dbda8d6ce9 2007-07-21       drh:     db_end_transaction(0);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }