[PATCH] Allow config files to be included

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The syntax is:

   [include "filename"]

which is somewhat branch/remote-alike. There are a few differences, though:
filenames happen to be long, so a backslash is supported to split the
names into multiple lines. No bare LF allowed, so this is illegal:
   [include "path/
   name"]
On the other hand, this is allowed:
   [include "path/\
   name"]

Backslash is just to quote characters (as in shell).
Only one quoted string allowed, so this is bad too:

   [include "path/" "name"]

Signed-off-by: Alex Riesen <raa.lkml@xxxxxxxxx>
---

This is a resend, I have no idea what happened to original,
but it never appeared on vger. And this will probably horribly
garbled by gmail. Will see.

Alex Riesen, Thu, Feb 15, 2007 12:35:57 +0100:
I suggest to ignore /etc/gitconfig completely if ~/.gitconfig exists,
but allow inclusion of /etc/gitconfig from ~/.gitconfig (there are
very singular and preciuos exceptions).

config.c |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 100 insertions(+), 3 deletions(-)

diff --git a/config.c b/config.c
index d821071..b42a7ea 100644
--- a/config.c
+++ b/config.c
@@ -12,6 +12,57 @@
static FILE *config_file;
static const char *config_file_name;
static int config_linenr;
+
+struct fileinfo
+{
+       char *name;
+       int linenr;
+       FILE *file;
+       struct fileinfo *prev;
+};
+static struct fileinfo *config_stack = NULL;
+
+static void include_file(const char *filename)
+{
+       struct fileinfo *prev;
+       FILE *file;
+       file = fopen(filename, "r");
+       if (!file) {
+               error("ignored \"%s\": %s", filename, strerror(errno));
+               return;
+       }
+       prev = malloc(sizeof(*prev));
+       prev->name = (char *)config_file_name;
+       prev->linenr = config_linenr;
+       prev->file = config_file;
+       prev->prev = config_stack;
+       config_stack = prev;
+
+       config_file = file;
+       config_file_name = xstrdup(filename);
+       config_linenr = 0;
+}
+
+static FILE *pop_file(void)
+{
+       struct fileinfo *prev;
+
+       if (!config_stack)
+               /* The last file on stack does not belong to us.
+                * Free the names and close all included files. */
+               return NULL;
+
+       free((void*)config_file_name);
+       fclose(config_file);
+       config_file = config_stack->file;
+       config_file_name = config_stack->name;
+       config_linenr = 0;
+       prev = config_stack->prev;
+       free(config_stack);
+       config_stack = prev;
+       return config_file;
+}
+
static int get_next_char(void)
{
       int c;
@@ -31,13 +82,51 @@ static int get_next_char(void)
               if (c == '\n')
                       config_linenr++;
               if (c == EOF) {
-                       config_file = NULL;
+                       config_file = pop_file();
                       c = '\n';
               }
       }
       return c;
}

+static int parse_include(void)
+{
+       char name[PATH_MAX];
+       int quote = 0, len = 0;
+
+       for (;;) {
+               int c = get_next_char();
+               if (len >= sizeof(name))
+                       return -1;
+               if (c == '"') {
+                       quote++;
+                       continue;
+               }
+               if (c == '\n')
+                       /* do not allow bare \n anywhere in path */
+                       return -1;
+               if (quote == 1) {
+                       if (c == '\\') {
+                               c = get_next_char();
+                               if (c == '\n')
+                                       continue;
+                       }
+                       name[len++] = c;
+               }
+               if (quote == 2 && c == ']') {
+                       do
+                               c = get_next_char();
+                       while (c != '\n');
+                       break;
+               }
+               if ((quote < 1 || quote >= 2) && !isspace(c) )
+                       return -1;
+       }
+       name[len] = '\0';
+       include_file(name);
+       return 0;
+}
+
static char *parse_value(void)
{
       static char value[1024];
@@ -181,8 +270,13 @@ static int get_base_var(char *name)
               int c = get_next_char();
               if (c == EOF)
                       return -1;
+               if (!isalpha(c) && !strncmp(name, "include", baselen) &&
+                   config_file) {
+                       ungetc(c, config_file);
+                       return parse_include();
+               }
               if (c == ']')
-                       return baselen;
+                       return baselen ? baselen: -1;
               if (isspace(c))
                       return get_extended_base_var(name, baselen, c);
               if (!iskeychar(c) && c != '.')
@@ -216,8 +310,11 @@ static int git_parse_file(config_fn_t fn)
               }
               if (c == '[') {
                       baselen = get_base_var(var);
-                       if (baselen <= 0)
+                       if (baselen < 0)
                               break;
+                       if (!baselen)
+                               /* [include "..."]*/
+                               continue;
                       var[baselen++] = '.';
                       var[baselen] = 0;
                       continue;
--
1.5.0.138.g36f81
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]