Re: [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.

It was horribly garbled by gmail. Resending as attachment.

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(-)
From 10c6dc89128fda0b4de89d69bd0ca2087f531a29 Mon Sep 17 00:00:00 2001
From: Alex Riesen <raa@xxxxxxxxxx>
Date: Thu, 15 Feb 2007 18:34:30 +0100
Subject: [PATCH] Allow config files to be included

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>
---
 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


[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]