Hi all,

attached is a patch to make 'import foo' relative to the importing source file,
and a patch to remove the error upon duplicate 'include'.

vcl that comes from the cli or f_arg doesn't get a path, but in this
case we fallback to vcl_dir. This means the same behavior for absolute
paths and one-directory deep relative includes under vcl_dir.

Use case: These two patches together make it possible to write and
release a self-contained vcl package which you can include into your
vcl.

PRs are on github fwiw.

0K
From 0e0b6b7885f83b7cb84d2a4bd8120f78c8f612e0 Mon Sep 17 00:00:00 2001
From: Kacper Wysocki <[email protected]>
Date: Tue, 17 Nov 2015 04:30:01 +0100
Subject: [PATCH] Allow duplicate vmod imports.

The first vcl to import the vmod counts.
---
 bin/varnishtest/tests/m00001.vtc |  9 ++++++++-
 lib/libvcc/vcc_vmod.c            | 24 ++++++++++--------------
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/bin/varnishtest/tests/m00001.vtc b/bin/varnishtest/tests/m00001.vtc
index 1e0b45f..260162a 100644
--- a/bin/varnishtest/tests/m00001.vtc
+++ b/bin/varnishtest/tests/m00001.vtc
@@ -47,11 +47,18 @@ varnish v1 -cliok "vcl.discard vcl1"
 varnish v1 -cliok "vcl.list"
 varnish v1 -cliok "debug.vmod"
 
-varnish v1 -errvcl {Module std already imported.} {
+varnish v1 -vcl+backend {
 	import ${vmod_std};
 	import ${vmod_std};
 }
 
+varnish v1 -vcl+backend {
+}
+
+varnish v1 -cliok "vcl.discard vcl3"
+varnish v1 -cliok "vcl.list"
+varnish v1 -cliok "debug.vmod"
+
 varnish v1 -errvcl {Symbol not found: 'std' (expected type BOOL):} {
 	import ${vmod_std};
 
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index e8bab4f..9ab9ab6 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -68,21 +68,15 @@ vcc_ParseImport(struct vcc *tl)
 		vcc_ErrWhere2(tl, t1, tl->t);
 		return;
 	}
-	if (osym != NULL) {
-		VSB_printf(tl->sb, "Module %.*s already imported.\n",
-		    PF(mod));
-		vcc_ErrWhere2(tl, t1, tl->t);
-		VSB_printf(tl->sb, "Previous import was here:\n");
-		vcc_ErrWhere2(tl, osym->def_b, osym->def_e);
-		return;
-	}
 
-	bprintf(fn, "%.*s", PF(mod));
-	sym = VCC_AddSymbolStr(tl, fn, SYM_VMOD);
-	ERRCHK(tl);
-	AN(sym);
-	sym->def_b = t1;
-	sym->def_e = tl->t;
+	if(osym == NULL) {
+		bprintf(fn, "%.*s", PF(mod));
+		sym = VCC_AddSymbolStr(tl, fn, SYM_VMOD);
+		ERRCHK(tl);
+		AN(sym);
+		sym->def_b = t1;
+		sym->def_e = tl->t;
+	}
 
 	if (tl->t->tok == ID) {
 		if (!tl->unsafe_path) {
@@ -106,6 +100,8 @@ vcc_ParseImport(struct vcc *tl)
 	}
 
 	SkipToken(tl, ';');
+	if (osym != NULL)
+		return;
 
 	hdl = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
 	if (hdl == NULL) {
-- 
2.6.2

From 448a5cd912a20f4fd3b6a88270031d379fec997a Mon Sep 17 00:00:00 2001
From: Kacper Wysocki <[email protected]>
Date: Tue, 17 Nov 2015 04:11:08 +0100
Subject: [PATCH] VCL relative includes

Modify vcl include resolution so that the include is relative to
the including file's location, falling back to vcl_dir for default
vcl and vcl defined on the console where file path is not available.
---
 bin/varnishtest/tests/v00045.vtc | 63 ++++++++++++++++++++++++++++++++++++++++
 lib/libvcc/vcc_compile.c         | 60 ++++++++++++++++++++++++++++++++++----
 lib/libvcc/vcc_compile.h         |  1 +
 3 files changed, 119 insertions(+), 5 deletions(-)
 create mode 100644 bin/varnishtest/tests/v00045.vtc

diff --git a/bin/varnishtest/tests/v00045.vtc b/bin/varnishtest/tests/v00045.vtc
new file mode 100644
index 0000000..cbc620f
--- /dev/null
+++ b/bin/varnishtest/tests/v00045.vtc
@@ -0,0 +1,63 @@
+varnishtest "Test relative and absolute includes"
+
+# relative plain
+shell "true > ${tmpdir}/_start.vcl"
+varnish v1 -arg "-p vcl_dir=${tmpdir}" -vcl {
+	backend b { .host = "127.0.0.1"; }
+	include "_start.vcl" ;
+}
+
+# absolute include
+varnish v1 -vcl {
+	backend b { .host = "127.0.0.1"; }
+	include "${tmpdir}/_start.vcl" ;
+}
+
+# absolute -> relative include
+shell "mkdir -p ${tmpdir}/1/2/3"
+shell "true  > ${tmpdir}/1/2/b.vcl"
+shell "echo 'include \"2/b.vcl\";' > ${tmpdir}/1/a.vcl"
+varnish v1 -vcl {
+	backend b { .host = "127.0.0.1"; }
+	include "${tmpdir}/1/a.vcl" ;
+}
+
+# relative -> relative
+varnish v1 -vcl {
+	backend b { .host = "127.0.0.1"; }
+	include "1/a.vcl" ;
+}
+
+# relative -> relative -> relative
+shell "echo 'include \"3/c.vcl\";' > ${tmpdir}/1/2/b.vcl"
+shell "true  > ${tmpdir}/1/2/3/c.vcl"
+varnish v1 -vcl {
+	backend b { .host = "127.0.0.1"; }
+	include "1/a.vcl" ;
+}
+
+# relative -> absolute
+shell "echo 'include \"${tmpdir}/1/2/3/c.vcl\";' > ${tmpdir}/1/aa.vcl"
+varnish v1 -vcl {
+	backend b { .host = "127.0.0.1"; }
+	include "1/aa.vcl" ;
+}
+
+# relative -> absolute -> relative
+shell "echo 'include \"${tmpdir}/1/2/b.vcl\";' > ${tmpdir}/1/aaa.vcl"
+varnish v1 -vcl {
+	backend b { .host = "127.0.0.1"; }
+	include "1/aaa.vcl" ;
+}
+
+# includes and parses out
+shell "echo 'zool' > ${tmpdir}/1/2/3/c.vcl"
+varnish v1 -errvcl {Found: 'zool' at} {
+	backend b { .host = "127.0.0.1"; }
+	include "1/a.vcl";
+}
+
+shell "rm -f ${tmpdir}/a"
+shell "rm -f ${tmpdir}/_start.vcl"
+
+
diff --git a/lib/libvcc/vcc_compile.c b/lib/libvcc/vcc_compile.c
index e79597f..699169f 100644
--- a/lib/libvcc/vcc_compile.c
+++ b/lib/libvcc/vcc_compile.c
@@ -422,7 +422,7 @@ EmitStruct(const struct vcc *tl)
 /*--------------------------------------------------------------------*/
 
 static struct source *
-vcc_new_source(const char *b, const char *e, const char *name)
+vcc_new_source(const char *b, const char *e, const char *name, const char *path)
 {
 	struct source *sp;
 
@@ -434,6 +434,10 @@ vcc_new_source(const char *b, const char *e, const char *name)
 	AN(sp->name);
 	sp->b = b;
 	sp->e = e;
+	if (path != NULL) {
+		sp->path = strdup(path);
+		AN(sp->path);
+	}
 	return (sp);
 }
 
@@ -447,6 +451,48 @@ vcc_destroy_source(struct source *sp)
 	free(sp);
 }
 
+/*--------------------------------------------------------------------
+ * Include files relative to source's path
+ *
+ */
+
+static struct vsb *vcc_include_path(const struct vcc *tl, const char *fn) {
+	struct vsb *vsb;
+	char *p, *relp;
+	const char *fsrc;
+	vsb = VSB_new_auto();
+	AN(vsb);
+	VSB_clear(vsb);
+	/* absolute paths .. are relative to / */
+	if(fn[0] == '/'){
+		fsrc = fn + 1;
+		goto dirname;
+	}
+
+	/* relative paths are relative to includers source path */
+	relp = tl->vcl_dir;
+	if(tl->src->path)
+		relp = tl->src->path;
+
+	VSB_cat(vsb, relp);
+	/* including source may have a relative prefix we need to add */
+	fsrc = tl->src->name;
+	if(fsrc[0] == '/'){
+		VSB_finish(vsb);
+		return vsb;
+	}
+dirname:
+	p = strrchr(fsrc, '/');
+	if(p == NULL){
+		VSB_finish(vsb);
+		return vsb;
+	}
+	VSB_putc(vsb, '/');
+	VSB_bcat(vsb, fsrc, p - fsrc);
+	VSB_finish(vsb);
+	return vsb;
+}
+
 /*--------------------------------------------------------------------*/
 
 static struct source *
@@ -454,19 +500,23 @@ vcc_file_source(const struct vcc *tl, struct vsb *sb, const char *fn)
 {
 	char *f;
 	struct source *sp;
+	struct vsb *fb;
 
 	if (!tl->unsafe_path && strchr(fn, '/') != NULL) {
 		VSB_printf(sb, "Include path is unsafe '%s'\n", fn);
 		return (NULL);
 	}
-	f = VFIL_readfile(tl->vcl_dir, fn, NULL);
+	fb = vcc_include_path(tl, fn);
+	f = VFIL_readfile(VSB_data(fb), fn, NULL);
 	if (f == NULL) {
 		VSB_printf(sb, "Cannot read file '%s': %s\n",
 		    fn, strerror(errno));
+		VSB_delete(fb);
 		return (NULL);
 	}
-	sp = vcc_new_source(f, NULL, fn);
+	sp = vcc_new_source(f, NULL, fn, VSB_data(fb));
 	sp->freeit = f;
+	VSB_delete(fb);
 	return (sp);
 }
 
@@ -649,7 +699,7 @@ vcc_CompileSource(const struct vcc *tl0, struct vsb *sb, struct source *sp)
 		return (vcc_DestroyTokenList(tl, NULL));
 
 	/* Register and lex the builtin VCL */
-	sp = vcc_new_source(tl->builtin_vcl, NULL, "Builtin");
+	sp = vcc_new_source(tl->builtin_vcl, NULL, "Builtin", NULL);
 	assert(sp != NULL);
 	VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
 	sp->idx = tl->nsources++;
@@ -764,7 +814,7 @@ VCC_Compile(const struct vcc *tl, struct vsb *sb, const char *b)
 	struct source *sp;
 	char *r;
 
-	sp = vcc_new_source(b, NULL, "input");
+	sp = vcc_new_source(b, NULL, "input", NULL);
 	if (sp == NULL)
 		return (NULL);
 	r = vcc_CompileSource(tl, sb, sp);
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 4c155a1..fcb9c35 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -87,6 +87,7 @@ struct source {
 	const char		*e;
 	unsigned		idx;
 	char			*freeit;
+	char			*path;
 };
 
 struct token {
-- 
2.6.2

_______________________________________________
varnish-dev mailing list
[email protected]
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to