[Libguestfs] [PATCH 5/8] builder: switch sources to .conf files

Pino Toscano ptoscano at redhat.com
Tue Feb 25 16:29:10 UTC 2014


Introduce and use simple .conf files to configure the sources of indexes
for virt-builder. The location of these files is in XDG_CONFIG_DIRS /
XDG_CONFIG_HOME, so it can be easily overridden.

There are three .conf(.in) files shipped with this commit:
- "test-index.conf.in" (in "test-config"), which points to the
  "test-index" index (used in tests only); the tests are adapted to
  point to the hierarchy containing this .conf
- "libguestfs.conf.in" (in "test-website"), which points to the local
  "index.asc" (i.e. the offline copy of the libguestfs.org index);
  run(.in) will point to the hierarchy providing this .conf
- "libguestfs.conf.in" (directly among the other sources), which points
  to the online "index.asc" and it is installed in sysconfdir, along
  with the key of this repository

The tests are adapted, other than to the different way to pick sources,
to the different output of --list, as "test-index" is not signed.
---
 .gitignore                                         |   3 +
 builder/Makefile.am                                |  10 +-
 builder/builder.ml                                 |  10 ++
 builder/libguestfs.conf.in                         |   3 +
 builder/sources.ml                                 | 122 +++++++++++++++++++++
 builder/sources.mli                                |  25 +++++
 .../virt-builder/repos.d/test-index.conf.in        |   2 +
 builder/test-virt-builder-list.sh                  |   8 +-
 builder/test-virt-builder-planner.sh               |   2 +-
 builder/test-virt-builder.sh                       |   2 +-
 .../virt-builder/repos.d/libguestfs.conf.in        |   3 +
 configure.ac                                       |   9 ++
 po/POTFILES-ml                                     |   1 +
 run.in                                             |   6 +-
 14 files changed, 195 insertions(+), 11 deletions(-)
 create mode 100644 builder/libguestfs.conf.in
 create mode 100644 builder/sources.ml
 create mode 100644 builder/sources.mli
 create mode 100644 builder/test-config/virt-builder/repos.d/test-index.conf.in
 create mode 100644 builder/test-website/virt-builder/repos.d/libguestfs.conf.in

diff --git a/.gitignore b/.gitignore
index 1ee7775..844df3c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,10 +61,13 @@ Makefile.in
 /builder/index-parse.c
 /builder/index-parse.h
 /builder/index-scan.c
+/builder/libguestfs.conf
 /builder/*.qcow2
 /builder/stamp-virt-builder.pod
 /builder/stamp-virt-index-validate.pod
+/builder/test-config/virt-builder/repos.d/test-index.conf
 /builder/test-index
+/builder/test-website/virt-builder/repos.d/libguestfs.conf
 /builder/virt-builder
 /builder/virt-builder.1
 /builder/virt-index-validate
diff --git a/builder/Makefile.am b/builder/Makefile.am
index a72b7ac..f0cb1dd 100644
--- a/builder/Makefile.am
+++ b/builder/Makefile.am
@@ -58,7 +58,9 @@ SOURCES = \
 	setlocale.mli \
 	setlocale-c.c \
 	sigchecker.mli \
-	sigchecker.ml
+	sigchecker.ml \
+	sources.mli \
+	sources.ml
 
 man_MANS =
 noinst_DATA =
@@ -103,6 +105,7 @@ OBJECTS = \
 	sigchecker.cmx \
 	index_parser.cmx \
 	list_entries.cmx \
+	sources.cmx \
 	cmdline.cmx \
 	builder.cmx
 
@@ -221,6 +224,11 @@ DISTCLEANFILES = .depend
 
 .PHONY: depend docs
 
+# virt-builder's default repository
+
+repoconfdir = $(sysconfdir)/xdg/virt-builder/repos.d
+repoconf_DATA = libguestfs.conf libguestfs.gpg
+
 # Build a small C index validator program.
 bin_PROGRAMS = virt-index-validate
 
diff --git a/builder/builder.ml b/builder/builder.ml
index 1ddbd0a..1800f2d 100644
--- a/builder/builder.ml
+++ b/builder/builder.ml
@@ -136,10 +136,20 @@ let main () =
 
   (* Download the sources. *)
   let downloader = Downloader.create ~debug ~curl ~cache in
+  let repos = Sources.read_sources ~prog ~debug in
+  let repos = List.map (
+    fun { Sources.uri = uri; Sources.gpgkey = gpgkey } ->
+      let gpgkey =
+        match gpgkey with
+        | None -> Sigchecker.No_Key
+        | Some key -> Sigchecker.KeyFile key in
+      uri, gpgkey
+  ) repos in
   let sources = List.map (
     fun (source, fingerprint) ->
       source, Sigchecker.Fingerprint fingerprint
   ) sources in
+  let sources = List.append repos sources in
   let index : Index_parser.index =
     List.concat (
       List.map (
diff --git a/builder/libguestfs.conf.in b/builder/libguestfs.conf.in
new file mode 100644
index 0000000..633a0ab
--- /dev/null
+++ b/builder/libguestfs.conf.in
@@ -0,0 +1,3 @@
+[libguestfs.org]
+uri=http://libguestfs.org/download/builder/index.asc
+gpgkey=file://@SYSCONFDIR@/xdg/virt-builder/repos.d/libguestfs.gpg
diff --git a/builder/sources.ml b/builder/sources.ml
new file mode 100644
index 0000000..fd0b236
--- /dev/null
+++ b/builder/sources.ml
@@ -0,0 +1,122 @@
+(* virt-builder
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Printf
+open Unix
+
+type source = {
+  name : string;
+  uri : string;
+  gpgkey : string option;
+}
+
+let parse_conf ~prog ~debug file =
+  if debug then (
+    eprintf (f_"%s: trying to read %s\n") prog file;
+  );
+  let sections = Ini_reader.read_ini file in
+
+  let sources = List.fold_right (
+    fun (n, fields) acc ->
+      let give_source n fields =
+        let fields = List.map (fun (k, sk, v) -> (k, sk), v) fields in
+        let uri =
+          try List.assoc ("uri", None) fields
+          with Not_found as ex ->
+            eprintf (f_"%s: no 'uri' entry for '%s' in %s, skipping it\n") prog n file;
+            raise ex in
+        let gpgkey =
+          let k =
+            try Some (URI.parse_uri (List.assoc ("gpgkey", None) fields)) with
+            | Not_found -> None
+            | Invalid_argument "URI.parse_uri" as ex ->
+              if debug then (
+                eprintf (f_"%s: '%s' has invalid gpgkey URI\n") prog n;
+              );
+              raise ex in
+          match k with
+          | None -> None
+          | Some uri ->
+            (match uri.URI.protocol with
+            | "file" -> Some uri.URI.path
+            | _ ->
+              if debug then (
+                eprintf (f_"%s: '%s' has non-local gpgkey URI\n") prog n;
+              );
+              None
+            ) in
+        {
+          name = n; uri = uri; gpgkey = gpgkey;
+        }
+      in
+      try (give_source n fields) :: acc
+      with Not_found | Invalid_argument _ -> acc
+  ) sections [] in
+
+  if debug then (
+    eprintf (f_"%s: ... read %d sources\n") prog (List.length sources);
+  );
+
+  sources
+
+let merge_sources current_sources new_sources =
+  List.fold_right (
+    fun source acc ->
+      if List.exists (fun { name = n } -> n = source.name) acc then
+        acc
+      else
+        source :: acc
+  ) new_sources current_sources
+
+let filter_filenames filename =
+  let suffix = ".conf" in
+  let n = String.length filename in
+  let ns = String.length suffix in
+  n >= ns && String.sub filename (n - ns) ns = suffix
+
+let read_sources ~prog ~debug =
+  let dirs = Paths.xdg_config_dirs ~prog in
+  let dirs =
+    match Paths.xdg_config_home ~prog with
+    | None -> dirs
+    | Some dir -> dir :: dirs in
+  let dirs = List.map (fun x -> x // "repos.d") dirs in
+  List.fold_right (
+    fun dir acc ->
+      let files =
+        try List.filter filter_filenames (Array.to_list (Sys.readdir dir))
+        with Sys_error _ -> [] in
+      let files = List.map (fun x -> dir // x) files in
+      List.fold_left (
+        fun acc file ->
+          try merge_sources acc (parse_conf ~prog ~debug file) with
+          | Unix_error (code, fname, _) ->
+            if debug then (
+              eprintf (f_"%s: file error: %s: %s\n") prog fname (error_message code)
+            );
+            acc
+          | Invalid_argument msg ->
+            if debug then (
+              eprintf (f_"%s: internal error: invalid argument: %s\n") prog msg
+            );
+            acc
+      ) acc files
+  ) dirs []
diff --git a/builder/sources.mli b/builder/sources.mli
new file mode 100644
index 0000000..76feeda
--- /dev/null
+++ b/builder/sources.mli
@@ -0,0 +1,25 @@
+(* virt-builder
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+type source = {
+  name : string;
+  uri : string;
+  gpgkey : string option;
+}
+
+val read_sources : prog:string -> debug:bool -> source list
diff --git a/builder/test-config/virt-builder/repos.d/test-index.conf.in b/builder/test-config/virt-builder/repos.d/test-index.conf.in
new file mode 100644
index 0000000..3755e75
--- /dev/null
+++ b/builder/test-config/virt-builder/repos.d/test-index.conf.in
@@ -0,0 +1,2 @@
+[test-index]
+uri=file://@abs_top_srcdir@/builder/test-index
diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh
index 6db9b78..2f9b319 100755
--- a/builder/test-virt-builder-list.sh
+++ b/builder/test-virt-builder-list.sh
@@ -23,7 +23,7 @@ set -e
 
 abs_builddir=$(pwd)
 
-export VIRT_BUILDER_SOURCE=file://$abs_builddir/test-index
+export XDG_CONFIG_DIRS="$abs_builddir/test-config"
 
 short_list=$($VG ./virt-builder --no-check-signature --no-cache --list)
 
@@ -41,8 +41,7 @@ fi
 
 long_list=$(./virt-builder --no-check-signature --no-cache --list --long)
 
-if [ "$long_list" != "Source URI: $VIRT_BUILDER_SOURCE
-Fingerprint: F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0
+if [ "$long_list" != "Source URI: file://$abs_builddir/test-index
 
 os-version:              phony-debian
 Full name:               Phony Debian
@@ -117,8 +116,7 @@ if [ "$json_list" != "{
   \"version\": 1,
   \"sources\": [
   {
-    \"fingerprint\": \"F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0\",
-    \"uri\": \"$VIRT_BUILDER_SOURCE\"
+    \"uri\": \"file://$abs_builddir/test-index\"
   }
   ],
   \"templates\": [
diff --git a/builder/test-virt-builder-planner.sh b/builder/test-virt-builder-planner.sh
index 738b299..386de5c 100755
--- a/builder/test-virt-builder-planner.sh
+++ b/builder/test-virt-builder-planner.sh
@@ -21,7 +21,7 @@ set -e
 
 abs_builddir=$(pwd)
 
-export VIRT_BUILDER_SOURCE=file://$abs_builddir/test-index
+export XDG_CONFIG_DIRS="$abs_builddir/test-config"
 
 if [ ! -f fedora.xz -o ! -f fedora.qcow2 -o ! -f fedora.qcow2.xz ]; then
     echo "$0: test skipped because there is no fedora.xz, fedora.qcow2 or fedora.qcow2.xz in the build directory"
diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
index 3c8eb60..85a7888 100755
--- a/builder/test-virt-builder.sh
+++ b/builder/test-virt-builder.sh
@@ -21,7 +21,7 @@ set -e
 
 abs_builddir=$(pwd)
 
-export VIRT_BUILDER_SOURCE=file://$abs_builddir/test-index
+export XDG_CONFIG_DIRS="$abs_builddir/test-config"
 
 if [ ! -f fedora.xz ]; then
     echo "$0: test skipped because there is no fedora.xz in the build directory"
diff --git a/builder/test-website/virt-builder/repos.d/libguestfs.conf.in b/builder/test-website/virt-builder/repos.d/libguestfs.conf.in
new file mode 100644
index 0000000..7bbc28d
--- /dev/null
+++ b/builder/test-website/virt-builder/repos.d/libguestfs.conf.in
@@ -0,0 +1,3 @@
+[libguestfs.org]
+uri=file://@abs_top_srcdir@/builder/website/index.asc
+gpgkey=file://@abs_top_srcdir@/builder/libguestfs.gpg
diff --git a/configure.ac b/configure.ac
index 96ae786..17e5229 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1587,6 +1587,12 @@ dnl http://lists.fedoraproject.org/pipermail/devel/2010-November/146343.html
 LIBTOOL='bash $(top_srcdir)/libtool-kill-dependency_libs.sh $(top_builddir)/libtool'
 AC_SUBST([LIBTOOL])
 
+dnl Work around autoconf's lack of expanded variables.
+eval my_sysconfdir="\"[$]sysconfdir\""
+eval my_sysconfdir="\"$my_sysconfdir\""
+SYSCONFDIR="${my_sysconfdir}"
+AC_SUBST(SYSCONFDIR)
+
 dnl Produce output files.
 
 AC_CONFIG_HEADERS([config.h])
@@ -1618,7 +1624,10 @@ AC_CONFIG_FILES([Makefile
                  appliance/Makefile
                  bash/Makefile
                  builder/Makefile
+                 builder/libguestfs.conf
+                 builder/test-config/virt-builder/repos.d/test-index.conf
                  builder/test-index
+                 builder/test-website/virt-builder/repos.d/libguestfs.conf
                  builder/website/Makefile
                  cat/Makefile
                  csharp/Makefile
diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index 2c9f5dc..8725e5e 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -9,6 +9,7 @@ builder/paths.ml
 builder/pxzcat.ml
 builder/setlocale.ml
 builder/sigchecker.ml
+builder/sources.ml
 mllib/common_gettext.ml
 mllib/common_utils.ml
 mllib/common_utils_tests.ml
diff --git a/run.in b/run.in
index f77db95..c804b84 100755
--- a/run.in
+++ b/run.in
@@ -87,9 +87,9 @@ export LD_LIBRARY_PATH
 
 # Make virt-builder use the local website copy to avoid hitting
 # the network all the time.
-if [ -z "$VIRT_BUILDER_SOURCE" ]; then
-    VIRT_BUILDER_SOURCE="file://$s/builder/website/index.asc"
-    export VIRT_BUILDER_SOURCE
+if [ -z "$XDG_CONFIG_DIRS" ]; then
+    XDG_CONFIG_DIRS="$b/builder/test-website"
+    export XDG_CONFIG_DIRS
 fi
 
 # For Perl.
-- 
1.8.3.1




More information about the Libguestfs mailing list