summaryrefslogtreecommitdiff
path: root/config.c
diff options
context:
space:
mode:
authorHeiko Voigt <hvoigt@hvoigt.net>2013-07-11 22:46:47 (GMT)
committerJunio C Hamano <gitster@pobox.com>2013-07-12 16:34:57 (GMT)
commit1bc888193e1044db317a45b9a4c8d2b87b998f40 (patch)
tree79065e0a9e226c1da33366688e0b41d9d45b5463 /config.c
parent4d8dd1494e9f3af2e9738edaca40ada096f7bf10 (diff)
downloadgit-1bc888193e1044db317a45b9a4c8d2b87b998f40.zip
git-1bc888193e1044db317a45b9a4c8d2b87b998f40.tar.gz
git-1bc888193e1044db317a45b9a4c8d2b87b998f40.tar.bz2
teach config --blob option to parse config from database
This can be used to read configuration values directly from git's database. For example it is useful for reading to be checked out .gitmodules files directly from the database. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Acked-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'config.c')
-rw-r--r--config.c86
1 files changed, 84 insertions, 2 deletions
diff --git a/config.c b/config.c
index fc27967..10a015b 100644
--- a/config.c
+++ b/config.c
@@ -14,6 +14,11 @@ struct config_source {
struct config_source *prev;
union {
FILE *file;
+ struct config_buf {
+ const char *buf;
+ size_t len;
+ size_t pos;
+ } buf;
} u;
const char *name;
int linenr;
@@ -45,6 +50,28 @@ static long config_file_ftell(struct config_source *conf)
return ftell(conf->u.file);
}
+
+static int config_buf_fgetc(struct config_source *conf)
+{
+ if (conf->u.buf.pos < conf->u.buf.len)
+ return conf->u.buf.buf[conf->u.buf.pos++];
+
+ return EOF;
+}
+
+static int config_buf_ungetc(int c, struct config_source *conf)
+{
+ if (conf->u.buf.pos > 0)
+ return conf->u.buf.buf[--conf->u.buf.pos];
+
+ return EOF;
+}
+
+static long config_buf_ftell(struct config_source *conf)
+{
+ return conf->u.buf.pos;
+}
+
#define MAX_INCLUDE_DEPTH 10
static const char include_depth_advice[] =
"exceeded maximum include depth (%d) while including\n"
@@ -961,6 +988,57 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
return ret;
}
+int git_config_from_buf(config_fn_t fn, const char *name, const char *buf,
+ size_t len, void *data)
+{
+ struct config_source top;
+
+ top.u.buf.buf = buf;
+ top.u.buf.len = len;
+ top.u.buf.pos = 0;
+ top.name = name;
+ top.fgetc = config_buf_fgetc;
+ top.ungetc = config_buf_ungetc;
+ top.ftell = config_buf_ftell;
+
+ return do_config_from(&top, fn, data);
+}
+
+static int git_config_from_blob_sha1(config_fn_t fn,
+ const char *name,
+ const unsigned char *sha1,
+ void *data)
+{
+ enum object_type type;
+ char *buf;
+ unsigned long size;
+ int ret;
+
+ buf = read_sha1_file(sha1, &type, &size);
+ if (!buf)
+ return error("unable to load config blob object '%s'", name);
+ if (type != OBJ_BLOB) {
+ free(buf);
+ return error("reference '%s' does not point to a blob", name);
+ }
+
+ ret = git_config_from_buf(fn, name, buf, size, data);
+ free(buf);
+
+ return ret;
+}
+
+static int git_config_from_blob_ref(config_fn_t fn,
+ const char *name,
+ void *data)
+{
+ unsigned char sha1[20];
+
+ if (get_sha1(name, sha1) < 0)
+ return error("unable to resolve config blob '%s'", name);
+ return git_config_from_blob_sha1(fn, name, sha1, data);
+}
+
const char *git_etc_gitconfig(void)
{
static const char *system_wide;
@@ -1026,7 +1104,9 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
}
int git_config_with_options(config_fn_t fn, void *data,
- const char *filename, int respect_includes)
+ const char *filename,
+ const char *blob_ref,
+ int respect_includes)
{
char *repo_config = NULL;
int ret;
@@ -1045,6 +1125,8 @@ int git_config_with_options(config_fn_t fn, void *data,
*/
if (filename)
return git_config_from_file(fn, filename, data);
+ else if (blob_ref)
+ return git_config_from_blob_ref(fn, blob_ref, data);
repo_config = git_pathdup("config");
ret = git_config_early(fn, data, repo_config);
@@ -1055,7 +1137,7 @@ int git_config_with_options(config_fn_t fn, void *data,
int git_config(config_fn_t fn, void *data)
{
- return git_config_with_options(fn, data, NULL, 1);
+ return git_config_with_options(fn, data, NULL, NULL, 1);
}
/*