File Annotation
Not logged in
e06ae9f6d2 2008-05-22       drh: /*
e06ae9f6d2 2008-05-22       drh: ** Copyright (c) 2008 D. Richard Hipp
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: ** This program is free software; you can redistribute it and/or
e06ae9f6d2 2008-05-22       drh: ** modify it under the terms of the GNU General Public
e06ae9f6d2 2008-05-22       drh: ** License version 2 as published by the Free Software Foundation.
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: ** This program is distributed in the hope that it will be useful,
e06ae9f6d2 2008-05-22       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
e06ae9f6d2 2008-05-22       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
e06ae9f6d2 2008-05-22       drh: ** General Public License for more details.
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: ** You should have received a copy of the GNU General Public
e06ae9f6d2 2008-05-22       drh: ** License along with this library; if not, write to the
e06ae9f6d2 2008-05-22       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
e06ae9f6d2 2008-05-22       drh: ** Boston, MA  02111-1307, USA.
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: ** Author contact information:
e06ae9f6d2 2008-05-22       drh: **   drh@hwaci.com
e06ae9f6d2 2008-05-22       drh: **   http://www.hwaci.com/drh/
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: *******************************************************************************
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: ** This file contains code used to manage repository configurations.
e06ae9f6d2 2008-05-22       drh: ** By "responsitory configure" we mean the local state of a repository
e06ae9f6d2 2008-05-22       drh: ** distinct from the versioned files.
e06ae9f6d2 2008-05-22       drh: */
e06ae9f6d2 2008-05-22       drh: #include "config.h"
e06ae9f6d2 2008-05-22       drh: #include "configure.h"
e06ae9f6d2 2008-05-22       drh: #include <assert.h>
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: #if INTERFACE
e06ae9f6d2 2008-05-22       drh: /*
e06ae9f6d2 2008-05-22       drh: ** Configuration transfers occur in groups.  These are the allowed
e06ae9f6d2 2008-05-22       drh: ** groupings:
e06ae9f6d2 2008-05-22       drh: */
e06ae9f6d2 2008-05-22       drh: #define CONFIGSET_SKIN   0x000001     /* WWW interface appearance */
e06ae9f6d2 2008-05-22       drh: #define CONFIGSET_TKT    0x000002     /* Ticket configuration */
e06ae9f6d2 2008-05-22       drh: #define CONFIGSET_PROJ   0x000004     /* Project name */
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: #define CONFIGSET_ALL    0xffffff     /* Everything */
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: #endif /* INTERFACE */
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: /*
e06ae9f6d2 2008-05-22       drh: ** Names of the configuration sets
e06ae9f6d2 2008-05-22       drh: */
e06ae9f6d2 2008-05-22       drh: static struct {
e06ae9f6d2 2008-05-22       drh:   const char *zName;   /* Name of the configuration set */
e06ae9f6d2 2008-05-22       drh:   int groupMask;       /* Mask for that configuration set */
e06ae9f6d2 2008-05-22       drh: } aGroupName[] = {
e06ae9f6d2 2008-05-22       drh:   { "skin",         CONFIGSET_SKIN },
e06ae9f6d2 2008-05-22       drh:   { "ticket",       CONFIGSET_TKT  },
e06ae9f6d2 2008-05-22       drh:   { "project",      CONFIGSET_PROJ },
e06ae9f6d2 2008-05-22       drh:   { "all",          CONFIGSET_ALL  },
e06ae9f6d2 2008-05-22       drh: };
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: /*
e06ae9f6d2 2008-05-22       drh: ** The following is a list of settings that we are willing to
e06ae9f6d2 2008-05-22       drh: ** transfer.
e06ae9f6d2 2008-05-22       drh: */
e06ae9f6d2 2008-05-22       drh: static struct {
e06ae9f6d2 2008-05-22       drh:   const char *zName;   /* Name of the configuration parameter */
e06ae9f6d2 2008-05-22       drh:   int groupMask;       /* Which config groups is it part of */
e06ae9f6d2 2008-05-22       drh: } aSafeConfig[] = {
e06ae9f6d2 2008-05-22       drh:   { "css",                   CONFIGSET_SKIN },
e06ae9f6d2 2008-05-22       drh:   { "header",                CONFIGSET_SKIN },
e06ae9f6d2 2008-05-22       drh:   { "footer",                CONFIGSET_SKIN },
e06ae9f6d2 2008-05-22       drh:   { "project-name",          CONFIGSET_PROJ },
e06ae9f6d2 2008-05-22       drh:   { "project-description",   CONFIGSET_PROJ },
e06ae9f6d2 2008-05-22       drh:   { "index-page",            CONFIGSET_SKIN },
e06ae9f6d2 2008-05-22       drh:   { "timeline-block-markup", CONFIGSET_SKIN },
e06ae9f6d2 2008-05-22       drh:   { "timeline-max-comment",  CONFIGSET_SKIN },
e06ae9f6d2 2008-05-22       drh: };
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: /*
e06ae9f6d2 2008-05-22       drh: ** Return TRUE if a particular configuration parameter zName is
e06ae9f6d2 2008-05-22       drh: ** safely exportable.
e06ae9f6d2 2008-05-22       drh: */
e06ae9f6d2 2008-05-22       drh: int configure_is_exportable(const char *zName){
e06ae9f6d2 2008-05-22       drh:   int i;
e06ae9f6d2 2008-05-22       drh:   for(i=0; i<count(aSafeConfig); i++){
e06ae9f6d2 2008-05-22       drh:     if( strcmp(zName, aSafeConfig[i].zName)==0 ) return 1;
e06ae9f6d2 2008-05-22       drh:   }
e06ae9f6d2 2008-05-22       drh:   return 0;
e06ae9f6d2 2008-05-22       drh: }
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: /*
e06ae9f6d2 2008-05-22       drh: ** Identify a configuration group by name.  Return its mask.
e06ae9f6d2 2008-05-22       drh: ** Throw an error if no match.
e06ae9f6d2 2008-05-22       drh: */
e06ae9f6d2 2008-05-22       drh: static int find_area(const char *z){
e06ae9f6d2 2008-05-22       drh:   int i;
e06ae9f6d2 2008-05-22       drh:   int n = strlen(z);
e06ae9f6d2 2008-05-22       drh:   for(i=0; i<count(aGroupName); i++){
e06ae9f6d2 2008-05-22       drh:     if( strncmp(z, aGroupName[i].zName, n)==0 ){
e06ae9f6d2 2008-05-22       drh:       return aGroupName[i].groupMask;
e06ae9f6d2 2008-05-22       drh:     }
e06ae9f6d2 2008-05-22       drh:   }
e06ae9f6d2 2008-05-22       drh:   fossil_fatal("no such configuration area: \"%s\"", z);
e06ae9f6d2 2008-05-22       drh:   return 0;
e06ae9f6d2 2008-05-22       drh: }
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: 
e06ae9f6d2 2008-05-22       drh: /*
e06ae9f6d2 2008-05-22       drh: ** COMMAND: configure
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: ** Usage: %fossil configure METHOD ...
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: ** Where METHOD is one of: export import pull reset.  All methods
e06ae9f6d2 2008-05-22       drh: ** accept the -R or --repository option to specific a repository.
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: **    %fossil config export AREA FILENAME
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: **         Write to FILENAME exported configuraton information for AREA.
e06ae9f6d2 2008-05-22       drh: **         AREA can be one of:  all ticket skin project
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: **    %fossil config import FILENAME
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: **         Read a configuration from FILENAME, overwriting the current
e06ae9f6d2 2008-05-22       drh: **         configuration.  Warning:  Do not read a configuration from
e06ae9f6d2 2008-05-22       drh: **         an untrusted source since the configuration is not checked
e06ae9f6d2 2008-05-22       drh: **         for safety and can introduce security threats.
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: **    %fossil config pull AREA URL
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: **         Pull and install the configuration from a different server
e06ae9f6d2 2008-05-22       drh: **         identified by URL.  AREA is as in "export".
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: **    %fossil configure reset AREA
e06ae9f6d2 2008-05-22       drh: **
e06ae9f6d2 2008-05-22       drh: **         Restore the configuration to the default.  AREA as above.
e06ae9f6d2 2008-05-22       drh: */
e06ae9f6d2 2008-05-22       drh: void configure_cmd(void){
e06ae9f6d2 2008-05-22       drh:   int n;
e06ae9f6d2 2008-05-22       drh:   const char *zMethod;
e06ae9f6d2 2008-05-22       drh:   if( g.argc<3 ){
e06ae9f6d2 2008-05-22       drh:     usage("METHOD ...");
e06ae9f6d2 2008-05-22       drh:   }
e06ae9f6d2 2008-05-22       drh:   db_find_and_open_repository(1);
e06ae9f6d2 2008-05-22       drh:   zMethod = g.argv[2];
e06ae9f6d2 2008-05-22       drh:   n = strlen(zMethod);
e06ae9f6d2 2008-05-22       drh:   if( strncmp(zMethod, "export", n)==0 ){
e06ae9f6d2 2008-05-22       drh:     int i;
e06ae9f6d2 2008-05-22       drh:     int mask;
e06ae9f6d2 2008-05-22       drh:     const char *zSep;
e06ae9f6d2 2008-05-22       drh:     Blob sql;
e06ae9f6d2 2008-05-22       drh:     Stmt q;
e06ae9f6d2 2008-05-22       drh:     Blob out;
e06ae9f6d2 2008-05-22       drh:     if( g.argc!=5 ){
e06ae9f6d2 2008-05-22       drh:       usage("export AREA FILENAME");
e06ae9f6d2 2008-05-22       drh:     }
e06ae9f6d2 2008-05-22       drh:     mask = find_area(g.argv[3]);
e06ae9f6d2 2008-05-22       drh:     blob_zero(&sql);
e06ae9f6d2 2008-05-22       drh:     blob_zero(&out);
e06ae9f6d2 2008-05-22       drh:     blob_appendf(&sql,
e06ae9f6d2 2008-05-22       drh:        "SELECT 'REPLACE INTO config(name,value) VALUES('''"
e06ae9f6d2 2008-05-22       drh:        "         || name || ''',' || quote(value) || ');'"
e06ae9f6d2 2008-05-22       drh:        "  FROM config WHERE name IN "
e06ae9f6d2 2008-05-22       drh:     );
e06ae9f6d2 2008-05-22       drh:     zSep = "(";
e06ae9f6d2 2008-05-22       drh:     for(i=0; i<count(aSafeConfig); i++){
e06ae9f6d2 2008-05-22       drh:       if( aSafeConfig[i].groupMask & mask ){
e06ae9f6d2 2008-05-22       drh:         blob_appendf(&sql, "%s'%s'", zSep, aSafeConfig[i].zName);
e06ae9f6d2 2008-05-22       drh:         zSep = ",";
e06ae9f6d2 2008-05-22       drh:       }
e06ae9f6d2 2008-05-22       drh:     }
e06ae9f6d2 2008-05-22       drh:     blob_appendf(&sql, ") ORDER BY name");
e06ae9f6d2 2008-05-22       drh:     db_prepare(&q, blob_str(&sql));
e06ae9f6d2 2008-05-22       drh:     blob_reset(&sql);
e06ae9f6d2 2008-05-22       drh:     blob_appendf(&out,
e06ae9f6d2 2008-05-22       drh:         "-- The \"%s\" configuration exported from\n"
e06ae9f6d2 2008-05-22       drh:         "-- repository \"%s\"\n"
e06ae9f6d2 2008-05-22       drh:         "-- on %s\nBEGIN;\n",
e06ae9f6d2 2008-05-22       drh:         g.argv[3], g.zRepositoryName,
e06ae9f6d2 2008-05-22       drh:         db_text(0, "SELECT datetime('now')")
e06ae9f6d2 2008-05-22       drh:     );
e06ae9f6d2 2008-05-22       drh:     while( db_step(&q)==SQLITE_ROW ){
e06ae9f6d2 2008-05-22       drh:       blob_appendf(&out, "%s\n", db_column_text(&q, 0));
e06ae9f6d2 2008-05-22       drh:     }
e06ae9f6d2 2008-05-22       drh:     db_finalize(&q);
e06ae9f6d2 2008-05-22       drh:     blob_appendf(&out, "COMMIT;\n");
e06ae9f6d2 2008-05-22       drh:     blob_write_to_file(&out, g.argv[4]);
e06ae9f6d2 2008-05-22       drh:     blob_reset(&out);
e06ae9f6d2 2008-05-22       drh:   }else
e06ae9f6d2 2008-05-22       drh:   if( strncmp(zMethod, "import", n)==0 ){
e06ae9f6d2 2008-05-22       drh:   }else
e06ae9f6d2 2008-05-22       drh:   if( strncmp(zMethod, "pull", n)==0 ){
e06ae9f6d2 2008-05-22       drh:   }else
e06ae9f6d2 2008-05-22       drh:   if( strncmp(zMethod, "reset", n)==0 ){
e06ae9f6d2 2008-05-22       drh:   }else
e06ae9f6d2 2008-05-22       drh:   {
e06ae9f6d2 2008-05-22       drh:     fossil_fatal("METHOD should be one of:  export import pull reset");
e06ae9f6d2 2008-05-22       drh:   }
e06ae9f6d2 2008-05-22       drh: }