/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/*
Copyright (c) 2013 D. Richard Hipp
This program is free software; you can redistribute it and/or
modify it under the terms of the Simplified BSD License (also
known as the "2-Clause License" or "FreeBSD License".)
This program is distributed in the hope that it will be useful,
but without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.
Author contact information:
drh@hwaci.com
http://www.hwaci.com/drh/
*****************************************************************************
A simple tool for dumping blobs to stdout.
*/
#include "fossil-scm/fossil-cli.h"
#include "fossil-scm/fossil-internal.h"
static void fcli_local_help(){
printf("Usage:\n\t%s [options] command [command-options]\n\n", fcli.appName);
puts("Views and manipulates fossil configuration data.\n");
puts("Options:\n");
puts("\t-g|--global Uses the global config table.\n");
puts("\t-r|--repo Uses the repository config table.\n");
puts("\t-c|--checkout Uses the checkout-local config table.\n");
puts("Commands:\n");
puts("\tls [-glob STRING] [-v]"
"\n\tLists the config entries from the specified config. "
"The --glob=STRING option can be used to filter by property names. "
"The -v|--values flag enables display of the config values.\n"
);
puts("\tset KEY [VALUE]\n\tSets a configuration value. If the value "
"is not provided then it is assumed to represent a boolean flag "
"and is set to \"1\".\n");
puts("\tunset KEY\n\tRemoves the given config key from the db.\n");
}
static struct ConfigApp {
char doGlobal;
char doLocal;
char doRepo;
char showValues;
char * lsGlob;
fsl_confdb_t mode0;
} ConfigApp = {
0,0,0,
0/*showValues*/,
NULL/*lsGlob*/,
FSL_CONFDB_GLOBAL/*mode0*/
};
static int fapp_ls(fsl_cx * f, fsl_confdb_t mode,
char const * nameGlob, char showVals){
int rc;
fsl_db * db = fsl_config_for_role(f, mode);
fsl_stmt st = fsl_stmt_empty;
int nameWidth = -30;
if(!db){
if(FSL_CONFDB_GLOBAL==mode){ /* special case: auto-open config db */
rc = fsl_config_open(f, NULL);
if(!rc){
db = fsl_cx_db_config(f);
assert(db);
}
}
if(!db){
return fcli_err_set(FSL_RC_MISUSE,
"Config db role #%d is not opened.",
mode);
}
}
rc = fsl_db_prepare(db, &st, "SELECT name, value FROM %s ORDER BY name",
fsl_config_table_for_role(mode));
while(FSL_RC_STEP_ROW==fsl_stmt_step(&st)){
char const * name = fsl_stmt_g_text(&st, 0, NULL);
if(nameGlob && !fsl_str_glob(nameGlob, name)) continue;
if(showVals){
f_out("%*s %s\n",
nameWidth, name,
fsl_stmt_g_text(&st,1,NULL));
}else{
f_out("%s\n", name);
}
}
fsl_stmt_finalize(&st);
return rc;
}
static int fcmd_ls(){
fsl_cx * f = fcli_cx();
int rc = 0;
int didSomething = 0;
ConfigApp.showValues = fcli_flag2("v", "values", NULL);
fcli_flag("glob", &ConfigApp.lsGlob);
if(fcli_has_unused_flags(0)) return fcli_error()->code;
/* f_out("Global config db: %s\n", fsl_cx_db_file_config(f, NULL)); */
#define DUMP(MODE) \
++didSomething; \
rc = fapp_ls(f, MODE, ConfigApp.lsGlob, ConfigApp.showValues)
if(ConfigApp.doGlobal){
DUMP(FSL_CONFDB_GLOBAL);
}
if(!rc && ConfigApp.doRepo){
DUMP(FSL_CONFDB_REPO);
}
if(!rc && ConfigApp.doLocal){
DUMP(FSL_CONFDB_CKOUT);
}
#undef DUMP
assert(didSomething);
return rc;
}
static int fcmd_set(){
char * key = NULL;
char * val = NULL;
fsl_cx * f = fcli_cx();
int rc;
key = fcli_next_arg(1);
if(!key){
return fcli_err_set(FSL_RC_MISUSE,"Missing property key argument.");
}
val = fcli_next_arg(1);
if(fcli_has_unused_flags(0)){
rc = fcli_error()->code;
}else{
FCLI_V(("Setting %s = %s\n", key, (val && *val) ? val : "1"));
rc = fsl_config_set_text(f, ConfigApp.mode0, key,
(val && *val) ? val : "1");
}
fsl_free(key);
fsl_free(val);
return rc;
}
static int fcmd_unset(){
char * key = NULL;
fsl_cx * f = fcli_cx();
int rc = 0;
int count = 0;
if(fcli_has_unused_flags(0)) return fcli_error()->code;
rc = fsl_config_transaction_begin(f, ConfigApp.mode0);
if(!rc){
while( !rc && (key = fcli_next_arg(1)) ){
++count;
FCLI_V(("Unsetting: %s\n", key));
rc = fsl_config_unset(f, ConfigApp.mode0, key);
fsl_free(key);
}
fsl_config_transaction_end(f, ConfigApp.mode0, rc ? 1 : 0);
}
if(!count){
rc = fcli_err_set(FSL_RC_MISUSE,"Missing property key argument.");
}
return rc;
}
static const FossilCommand ConfigCmds[] = {
{"ls", fcmd_ls},
{"set", fcmd_set},
{"unset", fcmd_unset},
{NULL,NULL}
};
static int fapp_main(fsl_cx * f){
ConfigApp.doGlobal = fcli_flag2("g","global",NULL);
ConfigApp.doRepo = fcli_flag2("r","repo",NULL);
ConfigApp.doLocal = fcli_flag2("c","checkout",NULL);
/*
Set the main config mode for commands which use only
one config. Priority order: -c -r -g
*/
if(ConfigApp.doGlobal){
int rc;
ConfigApp.mode0 = FSL_CONFDB_GLOBAL;
rc = fsl_config_open( f, 0 );
if(rc) return rc;
}
else if(ConfigApp.doLocal) ConfigApp.mode0 = FSL_CONFDB_CKOUT;
else if(ConfigApp.doRepo) ConfigApp.mode0 = FSL_CONFDB_REPO;
else{
return fcli_err_set(FSL_RC_MISUSE,
"No config db specified. Use one of: "
"-g[lobal], -r[epo], -c[heckout]");
}
return fcli_dispatch_commands(ConfigCmds, 0);
}
int main(int argc, char * const * argv ){
int rc = 0;
fcli.appHelp = fcli_local_help;
rc = fcli_setup(argc, argv);
if(FSL_RC_BREAK==rc) /* --help */ return 0;
else if(rc) goto end;
rc = fapp_main(fcli_cx());
fsl_free(ConfigApp.lsGlob);
end:
return fcli_end_of_main(rc);
}