]> git.ipfire.org Git - thirdparty/git.git/blobdiff - config.c
teach config --blob option to parse config from database
[thirdparty/git.git] / config.c
index fc2796771b689e85daf0a400488eeae3f7a48cd9..10a015be4a7f5f10ac32f4a9aab0fba86b70fe0f 100644 (file)
--- 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);
 }
 
 /*