/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ #if !defined(NET_FOSSIL_SCM_FSL_CONFDB_H_INCLUDED) #define NET_FOSSIL_SCM_FSL_CONFDB_H_INCLUDED /* 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/ ****************************************************************************** This file declares public APIs for working with fossil's persistent configuration settings. */ #include "fossil-core.h" /* MUST come first b/c of config macros */ #if defined(__cplusplus) extern "C" { #endif /** A flag type for specifying which configuration database a given API should be applied to. Used by fsl_config_get_int32() and friends. */ enum fsl_confdb_t { /** Signfies the global-level (per system user) configuration area. */ FSL_CONFDB_GLOBAL = 1, /** Signfies the repository-level configuration area. */ FSL_CONFDB_REPO = 2, /** Signfies the checkout-level (a.k.a. "local") configuration area. */ FSL_CONFDB_CKOUT = 3, /** Signifies the versioned-level (via ".fossil-settings") configuration area. */ FSL_CONFDB_VERSIONED = 4, /** Signifies the default-level (and other settings metadata) configuration area. This are is read-only, and only contains the publicly documented settings. */ FSL_CONFDB_METADATA = 5 }; typedef enum fsl_confdb_t fsl_confdb_t; /** Returns the name of the db table associated with the given mode. Results are undefined if mode is an invalid value. The returned bytes are static and constant. */ FSL_EXPORT char const * fsl_config_table_for_role(fsl_confdb_t mode); /** Returns a handle to the db associates with the given fsl_confdb_t value. Returns NULL if !f or if f has no db opened for that configuration role. Results are undefined if mode is an invalid value. */ FSL_EXPORT fsl_db * fsl_config_for_role(fsl_cx * f, fsl_confdb_t mode); /** Returns the int32 value of a property from one of f's config dbs, as specified by the mode parameter. Returns dflt if !f, f does not have the requested config db opened, no entry is found, or on db-level errors. */ FSL_EXPORT fsl_int32_t fsl_config_get_int32( fsl_cx * f, fsl_confdb_t mode, fsl_int32_t dflt, char const * key ); /** int64_t counterpart of fsl_config_get_int32(). */ FSL_EXPORT fsl_int64_t fsl_config_get_int64( fsl_cx * f, fsl_confdb_t mode, fsl_int64_t dflt, char const * key ); /** fsl_id_t counterpart of fsl_config_get_int32(). */ FSL_EXPORT fsl_id_t fsl_config_get_id( fsl_cx * f, fsl_confdb_t mode, fsl_id_t dflt, char const * key ); /** fsl_double_t counterpart of fsl_config_get_int32(). */ FSL_EXPORT fsl_double_t fsl_config_get_double( fsl_cx * f, fsl_confdb_t mode, fsl_double_t dflt, char const * key ); /** Boolean countertpart of fsl_config_get_int32(). fsl_str_bool() is used to determine the booleanness (booleanity?) of a given config option. */ FSL_EXPORT char fsl_config_get_bool( fsl_cx * f, fsl_confdb_t mode, char dflt, char const * key ); /** The string-type counterpart of fsl_config_get_int32(). Returns a copy of the configuration value if it finds one, else returns NULL. The returned memory must eventually be freed using fsl_free(). If len is not NULL then it is set to the length of the returned string. Returns NULL for any sort of error or for a NULL db value. */ FSL_EXPORT char * fsl_config_get_text( fsl_cx * f, fsl_confdb_t mode, char const * key, fsl_size_t * len ); /** Like fsl_config_get_text() with one notable exception: regardless of the mode parameter if key refers to a versionable property and such a property is readable in the current checkout, the contents of that versioned property is returned (as per fsl_config_get_versionable()), otherwise this behaves exactly like fsl_config_get_text(). */ FSL_EXPORT char * fsl_config_get_text2( fsl_cx * f, fsl_confdb_t mode, char const * key, fsl_size_t * len ); /** fsl_buffer counterpart of fsl_config_get_text(). Appends the value from the config table to b. Returns 0 on success, FSL_RC_NOT_FOUND if no row was found or the requested db is not opened, FSL_RC_OOM on allocation errror. */ FSL_EXPORT int fsl_config_get_buffer( fsl_cx * f, fsl_confdb_t mode, char const * key, fsl_buffer * b ); /** fsl_buffer counterpart of fsl_config_get_text2(). Appends the value from the config table to b. Returns 0 on success, FSL_RC_NOT_FOUND if no row was found or the requested db is not opened, FSL_RC_OOM on allocation errror. */ FSL_EXPORT int fsl_config_get_buffer2( fsl_cx * f, fsl_confdb_t mode, char const * key, fsl_buffer * b ); /** Sets a configuration variable in one of f's config databases, as specified by the mode parameter. Returns 0 on success. val may be NULL. Returns FSL_RC_MISUSE if !f, f does not have that database opened, or !key, FSL_RC_RANGE if !key. If val is NULL then an SQL NULL is bound instead of an empty string. */ FSL_EXPORT int fsl_config_set_text( fsl_cx * f, fsl_confdb_t mode, char const * key, char const * val ); /** The blob counterpart of fsl_config_set_text(). If len is negative then fsl_strlen(mem) is used to determine the length of the memory. If mem is NULL then an SQL NULL is bound instead of an empty blob. */ FSL_EXPORT int fsl_config_set_blob( fsl_cx * f, fsl_confdb_t mode, char const * key, void const * mem, fsl_int_t len ); /** int32 counterpart of fsl_config_set_text(). */ FSL_EXPORT int fsl_config_set_int32( fsl_cx * f, fsl_confdb_t mode, char const * key, fsl_int32_t val ); /** int64 counterpart of fsl_config_set_text(). */ FSL_EXPORT int fsl_config_set_int64( fsl_cx * f, fsl_confdb_t mode, char const * key, fsl_int64_t val ); /** fsl_id_t counterpart of fsl_config_set_text(). */ FSL_EXPORT int fsl_config_set_id( fsl_cx * f, fsl_confdb_t mode, char const * key, fsl_id_t val ); /** fsl_double counterpart of fsl_config_set_text(). */ FSL_EXPORT int fsl_config_set_double( fsl_cx * f, fsl_confdb_t mode, char const * key, fsl_double_t val ); /** Boolean counterpart of fsl_config_set_text(). See fsl_str_bool() for what string values are considered to be "true" vs "false". */ FSL_EXPORT int fsl_config_set_bool( fsl_cx * f, fsl_confdb_t mode, char const * key, char val ); /** "Unsets" (removes) the given key from the given configuration database. It is not considered to be an error if the config table does not contain that key. */ FSL_EXPORT int fsl_config_unset( fsl_cx * f, fsl_confdb_t mode, char const * key ); /** Begins (or recurses) a transaction on the given configuration database. Returns 0 on success, non-0 on error. On success, fsl_config_transaction_end() must eventually be called with the same parameters to pop the transaction stack. Returns FSL_RC_MISUSE if no db handle is opened for the given configuration mode. Assuming all arguments are valid, this returns the result of fsl_db_transaction_end() and propagates any db-side error into the f object's error state. This is primarily intended as an optimization when an app is making many changes to a config database. It is not needed when the app is only making one or two changes. @see fsl_config_transaction_end() @see fsl_db_transaction_begin() */ FSL_EXPORT int fsl_config_transaction_begin(fsl_cx * f, fsl_confdb_t mode); /** Pops the transaction stack pushed by fsl_config_transaction_begin(). If rollback is true then the transaction is set roll back, otherwise it is allowed to continue (if recursive) or committed immediately (if not recursive). Returns 0 on success, non-0 on error. Returns FSL_RC_MISUSE if no db handle is opened for the given configuration mode. Assuming all arguments are valid, this returns the result of fsl_db_transaction_end() and propagates any db-side error into the f object's error state. @see fsl_config_transaction_begin() @see fsl_db_transaction_end() */ FSL_EXPORT int fsl_config_transaction_end(fsl_cx * f, fsl_confdb_t mode, char rollback); /** Holds metadata for fossil-defined configuration settings. @see fsl_config_ctrl_get() @see fsl_config_has_versionable() @see fsl_config_get_versionable() @see fsl_config_key_is_valid() @see fsl_config_key_is_versionable() @see fsl_config_key_default_value() */ struct fsl_config_ctrl { /** Name of the setting */ char const *name; /** Historical (fossil(1)) internal variable name used by db_set(). Not currently used by this impl. */ char const *var; /** Historical (HTML UI). Width of display. 0 for boolean values. */ int width; /** Is this setting versionable? */ int versionable; /** Default value */ char const *def; }; typedef struct fsl_config_ctrl fsl_config_ctrl; /** If key is the name of a fossil-defined config key, this returns the fsl_config_ctrl value describing that configuration property, else it returns NULL. */ FSL_EXPORT fsl_config_ctrl const * fsl_config_ctrl_get(char const * key); /** Returns true if key is the name of a config property as defined by fossil(1). */ FSL_EXPORT char fsl_config_key_is_valid(char const * key); /** Returns true if key is the name of a versionable property, as defined by fossil(1). */ FSL_EXPORT char fsl_config_key_is_versionable(char const * key); /** If key refers to a fossil-defined configuration setting, this returns its default value as a NUL-terminated string. Its bytes are static and immutable. Returns NULL if key is not a known configuration key. */ FSL_EXPORT char const * fsl_config_key_default_value(char const * key); /** Tries to load a "versionable property" in a file named CKOUT/.fossil-settings/KEY, where CKOUT is the root directory of f's current checkout and key is the name of a versionable configuration setting. If it finds one and it can read the file's contents, it returns 0 and assigns *pOut to the contents, which are owned by the caller, who must eventually fsl_free() them. As a special case, if an empty file is read, 0 is returned but *pOut will be NULL. On any sort of error, non-0 is returned. In the grand scheme of things, the inability to load a versionable setting is not truly any error, so f's error state is not updated by this function and clients are not expected to treat it as fatal unless perhaps it returns FSL_RC_OOM, in which case it likely is. Note that versionable properties are always treated as strings, and there is not (yet) a family of getter APIs for various value types as there is for the db-level configuration storage. Example usage: @code char const * rv = NULL; int rc = fsl_config_get_versionable(f, "ignore-glob", &rv); if(rc){ // error. Just for example's sake: assert(!rv); }else{ assert(rv); ...use rv... } @endcode */ FSL_EXPORT int fsl_config_get_versionable( fsl_cx * f, char const * key, char **pOut ); /** Returns true if f's current checkout contains the given versionable configuration setting, else false. @see fsl_config_ctrl */ FSL_EXPORT char fsl_config_has_versionable( fsl_cx * f, char const * key ); /** Populates li as a glob list from the given configuration key. Uses (versionable/repo/global) config settings, in that order. It is not an error if one or more of those sources is missing - they are simply skipped. Note that gets any new globs appended to it, as per fsl_glob_list_append(), as opposed to replacing any existing contents. Returns 0 on success, but that only means that there were no errors, not that any entries were necessarily added to li. Arguably a bug: this function does not open the global config if it was not already opened, but will use it if it is opened. This function should arbuably open and close it in that case. */ FSL_EXPORT int fsl_config_globs_load(fsl_cx * f, fsl_list * li, char const * key); #if defined(__cplusplus) } /*extern "C"*/ #endif #endif /* NET_FOSSIL_SCM_FSL_CONFDB_H_INCLUDED */