Richard W.M. Jones
2017-Aug-01 14:00 UTC
[Libguestfs] [PATCH 0/2] Add lightweight bindings for PCRE.
We'd like to use PCRE instead of the awful Str module. However I don't necessarily want to pull in the extra dependency of ocaml-pcre, and in any case ocaml-pcre is rather difficult to use. This introduces very simplified and lightweight bindings for PCRE. They work rather like Str in that there is some global state (actually thread-local in this implementation) between the matching and the getting the substring, so you can write code like this: let re = PCRE.compile "(a+)b" ... if PCRE.matches re "ccaaaabb" then ( let whole = PCRE.sub 0 in (* returns "aaaab" *) let first = PCRE.sub 1 in (* returns "aaaa" *) ... I also introduced the switch from Str -> PCRE in virt-builder to show that it simplifies code while allowing you to use the much more powerful PCRE regular expressions. Rich.
Richard W.M. Jones
2017-Aug-01 14:00 UTC
[Libguestfs] [PATCH 1/2] common: Add a lightweight OCaml binding for PCRE.
This uses the gnulib TLS macros. --- .gitignore | 2 + Makefile.am | 1 + bootstrap | 1 + common/mlpcre/Makefile.am | 142 +++++++++++++++++++++++++++++ common/mlpcre/PCRE.ml | 32 +++++++ common/mlpcre/PCRE.mli | 74 ++++++++++++++++ common/mlpcre/dummy.c | 2 + common/mlpcre/pcre-c.c | 212 ++++++++++++++++++++++++++++++++++++++++++++ common/mlpcre/pcre_tests.ml | 70 +++++++++++++++ configure.ac | 1 + m4/.gitignore | 1 + 11 files changed, 538 insertions(+) diff --git a/.gitignore b/.gitignore index 4699933d3..0e7a649f8 100644 --- a/.gitignore +++ b/.gitignore @@ -123,6 +123,8 @@ Makefile.in /common/errnostring/errnostring-gperf.gperf /common/errnostring/errnostring.h /common/miniexpect/miniexpect.3 +/common/mlpcre/.depend +/common/mlpcre/pcre_tests /common/mlprogress/.depend /common/mlstdutils/.depend /common/mlstdutils/bytes.ml diff --git a/Makefile.am b/Makefile.am index 84b00393d..fb4c99db5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -156,6 +156,7 @@ SUBDIRS += csharp # OCaml tools. Note 'common/ml*', 'mllib' and 'customize' contain # shared code used by other OCaml tools, so these must come first. if HAVE_OCAML +SUBDIRS += common/mlpcre SUBDIRS += common/mlprogress SUBDIRS += common/mlvisit SUBDIRS += common/mlxml diff --git a/bootstrap b/bootstrap index 77a95a25b..4e3d4bc51 100755 --- a/bootstrap +++ b/bootstrap @@ -95,6 +95,7 @@ symlinkat sys_select sys_types sys_wait +tls vasprintf vc-list-files warnings diff --git a/common/mlpcre/Makefile.am b/common/mlpcre/Makefile.am new file mode 100644 index 000000000..aa638cd94 --- /dev/null +++ b/common/mlpcre/Makefile.am @@ -0,0 +1,142 @@ +# Bindings for Perl-compatible Regular Expressions. +# Copyright (C) 2017 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. + +include $(top_srcdir)/subdir-rules.mk + +EXTRA_DIST = \ + $(SOURCES_MLI) \ + $(SOURCES_ML) \ + $(SOURCES_C) \ + pcre_tests.ml + +SOURCES_MLI = \ + PCRE.mli + +SOURCES_ML = \ + PCRE.ml + +SOURCES_C = \ + pcre-c.c + +if HAVE_OCAML + +# We pretend that we're building a C library. automake handles the +# compilation of the C sources for us. At the end we take the C +# objects and OCaml objects and link them into the OCaml library. +# This C library is never used. + +noinst_LIBRARIES = libmlpcre.a + +if !HAVE_OCAMLOPT +MLPCRE_CMA = mlpcre.cma +else +MLPCRE_CMA = mlpcre.cmxa +endif + +noinst_DATA = $(MLPCRE_CMA) + +libmlpcre_a_SOURCES = $(SOURCES_C) +libmlpcre_a_CPPFLAGS = \ + -I. \ + -I$(top_builddir) \ + -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \ + -I$(top_srcdir)/common/utils -I$(top_builddir)/common/utils \ + -I$(shell $(OCAMLC) -where) +libmlpcre_a_CFLAGS = \ + $(WARN_CFLAGS) $(WERROR_CFLAGS) \ + -fPIC + +BOBJECTS = $(SOURCES_ML:.ml=.cmo) +XOBJECTS = $(BOBJECTS:.cmo=.cmx) + +# -I $(top_builddir)/lib/.libs is a hack which forces corresponding -L +# option to be passed to gcc, so we don't try linking against an +# installed copy of libguestfs. +OCAMLPACKAGES = \ + -I $(top_builddir)/gnulib/lib/.libs \ + -I $(top_builddir)/common/utils/.libs \ + -I $(builddir) +OCAMLPACKAGES_TESTS = $(MLPCRE_CMA) + +OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) + +if !HAVE_OCAMLOPT +OBJECTS = $(BOBJECTS) +else +OBJECTS = $(XOBJECTS) +endif + +libmlpcre_a_DEPENDENCIES = $(OBJECTS) + +$(MLPCRE_CMA): $(OBJECTS) libmlpcre.a + $(OCAMLFIND) mklib $(OCAMLPACKAGES) \ + $(OBJECTS) $(libmlpcre_a_OBJECTS) -cclib -lpcre -o mlpcre + +# Tests. + +pcre_tests_SOURCES = dummy.c +pcre_tests_BOBJECTS = pcre_tests.cmo +pcre_tests_XOBJECTS = $(pcre_tests_BOBJECTS:.cmo=.cmx) + +# Can't call the following as <test>_OBJECTS because automake gets confused. +if !HAVE_OCAMLOPT +pcre_tests_THEOBJECTS = $(pcre_tests_BOBJECTS) +pcre_tests.cmo: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS) +else +pcre_tests_THEOBJECTS = $(pcre_tests_XOBJECTS) +pcre_tests.cmx: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS) +endif + +OCAMLLINKFLAGS = $(LINK_CUSTOM_OCAMLC_ONLY) + +pcre_tests_DEPENDENCIES = \ + $(pcre_tests_THEOBJECTS) \ + $(MLPCRE_CMA) \ + $(top_srcdir)/ocaml-link.sh +pcre_tests_LINK = \ + $(top_srcdir)/ocaml-link.sh \ + -cclib '-lutils -lpcre -lgnu' -- \ + $(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLLINKFLAGS) \ + $(OCAMLPACKAGES) $(OCAMLPACKAGES_TESTS) \ + $(pcre_tests_THEOBJECTS) -o $@ + +TESTS_ENVIRONMENT = $(top_builddir)/run --test +LOG_COMPILER = $(VG) + +check_PROGRAMS = pcre_tests +TESTS = pcre_tests + +check-valgrind: + $(MAKE) VG="@VG@" check + +# Dependencies. +depend: .depend + +.depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml) + rm -f $@ $@-t + $(OCAMLFIND) ocamldep -I ../../ocaml -I $(abs_srcdir) $^ | \ + $(SED) 's/ *$$//' | \ + $(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \ + $(SED) -e 's,$(abs_srcdir)/,$(builddir)/,g' | \ + sort > $@-t + mv $@-t $@ + +-include .depend + +endif + +.PHONY: depend docs diff --git a/common/mlpcre/PCRE.ml b/common/mlpcre/PCRE.ml new file mode 100644 index 000000000..94eea4b34 --- /dev/null +++ b/common/mlpcre/PCRE.ml @@ -0,0 +1,32 @@ +(* Bindings for Perl-compatible Regular Expressions. + * Copyright (C) 2017 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. + *) + +(* Lightweight bindings for the PCRE library. *) + +exception Error of string * int + +type regexp + +external compile : string -> regexp = "guestfs_int_pcre_compile" + +external matches : regexp -> string -> bool = "guestfs_int_pcre_matches" + +external sub : int -> string = "guestfs_int_pcre_sub" + +let () + Callback.register_exception "PCRE.Error" (Error ("", 0)) diff --git a/common/mlpcre/PCRE.mli b/common/mlpcre/PCRE.mli new file mode 100644 index 000000000..882fb6a79 --- /dev/null +++ b/common/mlpcre/PCRE.mli @@ -0,0 +1,74 @@ +(* Bindings for Perl-compatible Regular Expressions. + * Copyright (C) 2017 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. + *) + +(** Lightweight bindings for the PCRE library. + + Note this is {i not} Markus Mottl's ocaml-pcre, and doesn't + work like that library. + + To match a regular expression: + +{v +let re = PCRE.compile "(a+)b" +... + +if PCRE.matches re "ccaaaabb" then ( + let whole = PCRE.sub 0 in (* returns "aaaab" *) + let first = PCRE.sub 1 in (* returns "aaaa" *) + ... +) +v} + + Note that there is implicit global state stored between the + call to {!matches} and {!sub}. This is stored in thread + local storage so it is safe provided there are no other calls + to {!matches} in the same thread. +*) + +exception Error of string * int +(** PCRE error raised by various functions. + + The string is the printable error message. The integer is one + of the negative [PCRE_*] error codes (see pcreapi(3)), but may + be 0 if there was no error code information. *) + +type regexp +(** The type of a compiled regular expression. *) + +val compile : string -> regexp +(** Compile a regular expression. This can raise {!Error}. *) + +val matches : regexp -> string -> bool +(** Test whether the regular expression matches the string. This + returns true if the regexp matches or false otherwise. + + This also saves any matched substrings in thread-local storage + until either the next call to {!matches} in the current thread + or the program exits. + + This can raise {!Error} if PCRE returns an error. *) + +val sub : int -> string +(** Return the nth sub matched by the previous call to + {!matches} in the current thread. + + If [n == 0] it returns the whole matching part of the string. + + If [n >= 1] it returns the nth substring. + + If there was no nth substring then this raises [Not_found]. *) diff --git a/common/mlpcre/dummy.c b/common/mlpcre/dummy.c new file mode 100644 index 000000000..ebab6198c --- /dev/null +++ b/common/mlpcre/dummy.c @@ -0,0 +1,2 @@ +/* Dummy source, to be used for OCaml-based tools with no C sources. */ +enum { foo = 1 }; diff --git a/common/mlpcre/pcre-c.c b/common/mlpcre/pcre-c.c new file mode 100644 index 000000000..15de16570 --- /dev/null +++ b/common/mlpcre/pcre-c.c @@ -0,0 +1,212 @@ +/* Bindings for Perl-compatible Regular Expressions. + * Copyright (C) 2017 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. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include <pcre.h> + +#include <caml/alloc.h> +#include <caml/callback.h> +#include <caml/custom.h> +#include <caml/fail.h> +#include <caml/memory.h> +#include <caml/mlvalues.h> + +#include "cleanups.h" + +#include "glthread/tls.h" + +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + +/* Data on the most recent match is stored in this thread-local + * variable. It is freed either by the next call to PCRE.matches or + * by (clean) thread exit. + */ +static gl_tls_key_t last_match; + +struct last_match { + char *subject; /* subject string */ + int *vec; + int r; /* value returned by pcre_exec */ +}; + +static void +free_last_match (struct last_match *data) +{ + if (data) { + free (data->subject); + free (data->vec); + free (data); + } +} + +static void init (void) __attribute__((constructor)); + +static void +init (void) +{ + gl_tls_key_init (last_match, (void (*) (void *))free_last_match); +} + +static void +raise_error (const char *msg, int errcode) +{ + value *exn = caml_named_value ("PCRE.Error"); + value args[2]; + + args[0] = caml_copy_string (msg); + args[1] = Val_int (errcode); + caml_raise_with_args (*exn, 2, args); +} + +/* Wrap and unwrap pcre regular expression handles, with a finalizer. */ +#define Regexp_val(rv) (*(pcre **)Data_custom_val(rv)) + +static void +regexp_finalize (value rev) +{ + pcre *re = Regexp_val (rev); + if (re) pcre_free (re); +} + +static struct custom_operations custom_operations = { + (char *) "pcre_custom_operations", + regexp_finalize, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +}; + +static value +Val_regexp (pcre *re) +{ + CAMLparam0 (); + CAMLlocal1 (rv); + + rv = caml_alloc_custom (&custom_operations, sizeof (pcre *), 0, 1); + Regexp_val (rv) = re; + + CAMLreturn (rv); +} + +value +guestfs_int_pcre_compile (value pattv) +{ + CAMLparam1 (pattv); + pcre *re; + const char *err; + int offset; + + re = pcre_compile (String_val (pattv), 0, &err, &offset, NULL); + if (re == NULL) + raise_error (err, 0); + + CAMLreturn (Val_regexp (re)); +} + +value +guestfs_int_pcre_matches (value rev, value strv) +{ + CAMLparam2 (rev, strv); + pcre *re = Regexp_val (rev); + struct last_match *m, *oldm; + size_t len = caml_string_length (strv); + int capcount, r; + int veclen; + + /* Calculate maximum number of substrings, and hence the vector needed. */ + r = pcre_fullinfo (re, NULL, PCRE_INFO_CAPTURECOUNT, (int *) &capcount); + /* I believe that errors should never occur because of OCaml + * type safety, so we should abort here. If this ever happens + * we will need to look at it again. + */ + assert (r == 0); + veclen = 3 * (1 + capcount); + + m = malloc (sizeof *m); + if (m == NULL) + caml_raise_out_of_memory (); + + /* We will need the original subject string when fetching + * substrings, so take a copy. + */ + m->subject = malloc (len+1); + if (m->subject == NULL) { + free (m); + caml_raise_out_of_memory (); + } + memcpy (m->subject, String_val (strv), len+1); + + m->vec = malloc (veclen * sizeof (int)); + if (m->vec == NULL) { + free (m->subject); + free (m); + caml_raise_out_of_memory (); + } + + m->r = pcre_exec (re, NULL, m->subject, len, 0, 0, m->vec, veclen); + if (m->r < 0 && m->r != PCRE_ERROR_NOMATCH) + /* The C code in lib/match.c ignores errors. */ + raise_error ("pcre_exec", m->r); + + /* This error would indicate that pcre_exec ran out of space in the + * vector. However if we are calculating the size of the vector + * correctly above, then this should never happen. + */ + assert (m->r != 0); + + /* Replace the old TLS match data. */ + oldm = gl_tls_get (last_match); + free_last_match (oldm); + gl_tls_set (last_match, m); + + CAMLreturn (m->r == PCRE_ERROR_NOMATCH ? Val_false : Val_true); +} + +value +guestfs_int_pcre_sub (value nv) +{ + CAMLparam1 (nv); + CAMLlocal1 (strv); + int len; + CLEANUP_FREE char *str = NULL; + struct last_match *m = gl_tls_get (last_match); + + if (m == NULL) + raise_error ("PCRE.sub called without calling PCRE.matches", 0); + + len = pcre_get_substring (m->subject, m->vec, m->r, Int_val (nv), + (const char **) &str); + + if (len == PCRE_ERROR_NOSUBSTRING) + caml_raise_not_found (); + + if (len < 0) + raise_error ("pcre_get_substring", len); + + strv = caml_alloc_string (len); + memcpy (String_val (strv), str, len); + CAMLreturn (strv); +} diff --git a/common/mlpcre/pcre_tests.ml b/common/mlpcre/pcre_tests.ml new file mode 100644 index 000000000..59be2b36d --- /dev/null +++ b/common/mlpcre/pcre_tests.ml @@ -0,0 +1,70 @@ +(* Test bindings for Perl-compatible Regular Expressions. + * Copyright (C) 2017 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 Printf + +let compile patt + eprintf "PCRE.compile %s\n%!" patt; + PCRE.compile patt + +let matches re str + eprintf "PCRE.matches %s ->%!" str; + let r = PCRE.matches re str in + eprintf " %b\n%!" r; + r + +let sub i + eprintf "PCRE.sub %d ->%!" i; + let r = PCRE.sub i in + eprintf " %s\n%!" r; + r + +let () + try + let re0 = compile "a+b" in + let re1 = compile "(a+)b" in + let re2 = compile "(a+)(b*)" in + + assert (matches re0 "ccaaabbbb" = true); + assert (sub 0 = "aaab"); + + assert (matches re0 "aaa" = false); + + assert (matches re0 "xyz" = false); + + assert (matches re0 "aaabc" = true); + assert (sub 0 = "aaab"); + + assert (matches re1 "ccaaabb" = true); + assert (sub 1 = "aaa"); + assert (sub 0 = "aaab"); + + assert (matches re2 "ccabbc" = true); + assert (sub 1 = "a"); + assert (sub 2 = "bb"); + assert (sub 0 = "abb"); + + assert (matches re2 "ccac" = true); + assert (sub 1 = "a"); + assert (sub 2 = ""); + assert (sub 0 = "a"); + with + | Not_found -> + failwith "one of the PCRE.sub functions unexpectedly raised Not_found" + | PCRE.Error (msg, code) -> + failwith (sprintf "PCRE error: %s (PCRE error code %d)" msg code) diff --git a/configure.ac b/configure.ac index 3cf9d0a28..651b48b3b 100644 --- a/configure.ac +++ b/configure.ac @@ -196,6 +196,7 @@ AC_CONFIG_FILES([Makefile common/errnostring/Makefile common/edit/Makefile common/miniexpect/Makefile + common/mlpcre/Makefile common/mlprogress/Makefile common/mlstdutils/Makefile common/mlstdutils/guestfs_config.ml diff --git a/m4/.gitignore b/m4/.gitignore index 07960ed7b..a84b22e5c 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -248,6 +248,7 @@ /thread.m4 /time_h.m4 /timespec.m4 +/tls.m4 /ttyname_r.m4 /ulonglong.m4 /ungetc.m4 -- 2.13.2
Richard W.M. Jones
2017-Aug-01 14:00 UTC
[Libguestfs] [PATCH 2/2] builder: Replace small usage of Str with new PCRE module.
--- builder/Makefile.am | 6 +++++- builder/languages.ml | 13 ++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/builder/Makefile.am b/builder/Makefile.am index e64c8991f..1b51376be 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -126,6 +126,7 @@ OCAMLPACKAGES = \ -I $(top_builddir)/ocaml \ -I $(top_builddir)/common/mlstdutils \ -I $(top_builddir)/common/mlutils \ + -I $(top_builddir)/common/mlpcre \ -I $(top_builddir)/mllib \ -I $(top_builddir)/customize OCAMLPACKAGES_TESTS @@ -156,6 +157,7 @@ OBJECTS = $(XOBJECTS) endif OCAMLLINKFLAGS = \ + mlpcre.$(MLARCHIVE) \ mlstdutils.$(MLARCHIVE) \ mlguestfs.$(MLARCHIVE) \ mlcutils.$(MLARCHIVE) \ @@ -165,6 +167,7 @@ OCAMLLINKFLAGS = \ virt_builder_DEPENDENCIES = \ $(OBJECTS) \ + ../common/mlpcre/mlpcre.$(MLARCHIVE) \ ../common/mlstdutils/mlstdutils.$(MLARCHIVE) \ ../common/mlutils/mlcutils.$(MLARCHIVE) \ ../mllib/mllib.$(MLARCHIVE) \ @@ -238,6 +241,7 @@ endif yajl_tests_DEPENDENCIES = \ $(yajl_tests_THEOBJECTS) \ + ../common/mlpcre/mlpcre.$(MLARCHIVE) \ ../common/mlstdutils/mlstdutils.$(MLARCHIVE) \ ../common/mlutils/mlcutils.$(MLARCHIVE) \ ../mllib/mllib.$(MLARCHIVE) \ @@ -311,7 +315,7 @@ depend: .depend .depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml) rm -f $@ $@-t - $(OCAMLFIND) ocamldep -I ../ocaml -I $(abs_srcdir) -I $(abs_top_builddir)/common/mlstdutils -I $(abs_top_builddir)/common/mlutils -I $(abs_top_builddir)/mllib -I $(abs_top_builddir)/customize $^ | \ + $(OCAMLFIND) ocamldep -I ../ocaml -I $(abs_srcdir) -I $(abs_top_builddir)/common/mlstdutils -I $(abs_top_builddir)/common/mlutils -I $(abs_top_builddir)/common/mlpcre -I $(abs_top_builddir)/mllib -I $(abs_top_builddir)/customize $^ | \ $(SED) 's/ *$$//' | \ $(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \ $(SED) -e 's,$(abs_srcdir)/,$(builddir)/,g' | \ diff --git a/builder/languages.ml b/builder/languages.ml index d94f97c5c..89d173999 100644 --- a/builder/languages.ml +++ b/builder/languages.ml @@ -19,15 +19,14 @@ open Std_utils open Common_utils +let re_locale + PCRE.compile "^([A-Za-z]+)(_([A-Za-z]+))?(\\.([A-Za-z0-9-]+))?(@([A-Za-z]+))?$" + let split_locale loc - let regex = Str.regexp "^\\([A-Za-z]+\\)\\(_\\([A-Za-z]+\\)\\)?\\(\\.\\([A-Za-z0-9-]+\\)\\)?\\(@\\([A-Za-z]+\\)\\)?$" in let l = ref [] in - if Str.string_match regex loc 0 then ( - let match_or_empty n - try Str.matched_group n loc with - | Not_found -> "" - in - let lang = Str.matched_group 1 loc in + if PCRE.matches re_locale loc then ( + let match_or_empty n = try PCRE.sub n with Not_found -> "" in + let lang = PCRE.sub 1 in let territory = match_or_empty 3 in (match territory with | "" -> () -- 2.13.2
Richard Jones
2017-Aug-01 15:29 UTC
[Libguestfs] check-release success (was: Re: [PATCH 2/2] builder: Replace small usage of Str with new PCRE module.)
ntering directory '/var/tmp/tmpCnSJf8/libguestfs/lua' ln -sf .libs/libluaguestfs.so guestfs.so make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/lua' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/lua' PASS: tests/025-create-flags.lua PASS: tests/020-create.lua PASS: run-bindtests PASS: tests/015-globals.lua PASS: tests/010-load.lua PASS: tests/027-create-multiple.lua PASS: tests/400-events.lua PASS: tests/070-optargs.lua PASS: tests/900-errors.lua PASS: tests/030-config.lua PASS: tests/060-readdir.lua PASS: tests/050-lvcreate.lua PASS: tests/400-progress.lua ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 13 # PASS: 13 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/lua' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/lua' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/lua' Making check in lua/examples make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/lua/examples' make[1]: Nothing to be done for 'check'. make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/lua/examples' Making check in gobject make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/gobject' make check-am make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/gobject' make check-TESTS make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/gobject' make[4]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/gobject' SKIP: run-tests PASS: run-tests-retvalues PASS: run-live-tests ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 3 # PASS: 2 # SKIP: 1 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[4]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/gobject' make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/gobject' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/gobject' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/gobject' Making check in csharp make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/csharp' make[1]: Nothing to be done for 'check'. make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/csharp' Making check in common/mlpcre make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlpcre' make pcre_tests make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlpcre' CC dummy.o OCAMLOPT pcre_tests.cmx GEN pcre_tests make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlpcre' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlpcre' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlpcre' PASS: pcre_tests ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 1 # PASS: 1 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlpcre' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlpcre' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlpcre' Making check in common/mlprogress make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlprogress' make[1]: Nothing to be done for 'check'. make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlprogress' Making check in common/mlvisit make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlvisit' make visit_tests make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlvisit' CC dummy.o OCAMLOPT visit_tests.cmx File "visit_tests.ml", line 111, characters 25-31: Warning 52: Code should not depend on the actual values of this constructor's arguments. They are only for information and may change in future versions. (See manual section 8.5) File "visit_tests.ml", line 119, characters 16-23: Warning 52: Code should not depend on the actual values of this constructor's arguments. They are only for information and may change in future versions. (See manual section 8.5) GEN visit_tests make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlvisit' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlvisit' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlvisit' PASS: visit_tests ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 1 # PASS: 1 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlvisit' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlvisit' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlvisit' Making check in common/mlxml make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlxml' make[1]: Nothing to be done for 'check'. make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/common/mlxml' Making check in mllib make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/mllib' make getopt_tests common_utils_tests JSON_tests make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/mllib' OCAMLOPT getopt_tests.cmx CC getopt_tests-dummy.o CC common_utils_tests-dummy.o OCAMLOPT common_utils_tests.cmx CC dummy.o OCAMLOPT JSON_tests.cmx GEN getopt_tests GEN JSON_tests GEN common_utils_tests make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/mllib' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/mllib' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/mllib' PASS: JSON_tests PASS: common_utils_tests PASS: test-getopt.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 3 # PASS: 3 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/mllib' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/mllib' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/mllib' Making check in customize make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/customize' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/customize' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/customize' rm -f test-firstboot-rhel-4.9.sh test-firstboot-rhel-4.9.sh-t rm -f test-firstboot-rhel-5.11.sh test-firstboot-rhel-5.11.sh-t f=`echo "test-firstboot-rhel-4.9.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-rhel-4.9.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-rhel-4.9.sh-t f=`echo "test-firstboot-rhel-5.11.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-rhel-5.11.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-rhel-5.11.sh-t rm -f test-firstboot-rhel-6.8.sh test-firstboot-rhel-6.8.sh-t f=`echo "test-firstboot-rhel-6.8.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-rhel-6.8.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-rhel-6.8.sh-t chmod 0755 test-firstboot-rhel-4.9.sh-t chmod 0755 test-firstboot-rhel-5.11.sh-t chmod 0755 test-firstboot-rhel-6.8.sh-t mv test-firstboot-rhel-4.9.sh-t test-firstboot-rhel-4.9.sh mv test-firstboot-rhel-5.11.sh-t test-firstboot-rhel-5.11.sh mv test-firstboot-rhel-6.8.sh-t test-firstboot-rhel-6.8.sh rm -f test-firstboot-rhel-7.2.sh test-firstboot-rhel-7.2.sh-t rm -f test-firstboot-debian-6.sh test-firstboot-debian-6.sh-t f=`echo "test-firstboot-rhel-7.2.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-rhel-7.2.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-rhel-7.2.sh-t f=`echo "test-firstboot-debian-6.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-debian-6.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-debian-6.sh-t rm -f test-firstboot-debian-7.sh test-firstboot-debian-7.sh-t f=`echo "test-firstboot-debian-7.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-debian-7.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-debian-7.sh-t chmod 0755 test-firstboot-rhel-7.2.sh-t chmod 0755 test-firstboot-debian-6.sh-t chmod 0755 test-firstboot-debian-7.sh-t mv test-firstboot-rhel-7.2.sh-t test-firstboot-rhel-7.2.sh mv test-firstboot-debian-6.sh-t test-firstboot-debian-6.sh mv test-firstboot-debian-7.sh-t test-firstboot-debian-7.sh rm -f test-firstboot-debian-8.sh test-firstboot-debian-8.sh-t rm -f test-firstboot-fedora-25.sh test-firstboot-fedora-25.sh-t f=`echo "test-firstboot-debian-8.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-debian-8.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-debian-8.sh-t f=`echo "test-firstboot-fedora-25.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-fedora-25.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-fedora-25.sh-t rm -f test-firstboot-fedora-26.sh test-firstboot-fedora-26.sh-t chmod 0755 test-firstboot-debian-8.sh-t f=`echo "test-firstboot-fedora-26.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-fedora-26.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-fedora-26.sh-t chmod 0755 test-firstboot-fedora-25.sh-t mv test-firstboot-debian-8.sh-t test-firstboot-debian-8.sh chmod 0755 test-firstboot-fedora-26.sh-t mv test-firstboot-fedora-25.sh-t test-firstboot-fedora-25.sh mv test-firstboot-fedora-26.sh-t test-firstboot-fedora-26.sh rm -f test-firstboot-ubuntu-10.04.sh test-firstboot-ubuntu-10.04.sh-t rm -f test-firstboot-ubuntu-12.04.sh test-firstboot-ubuntu-12.04.sh-t f=`echo "test-firstboot-ubuntu-10.04.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-ubuntu-10.04.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-ubuntu-10.04.sh-t f=`echo "test-firstboot-ubuntu-12.04.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-ubuntu-12.04.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-ubuntu-12.04.sh-t rm -f test-firstboot-ubuntu-14.04.sh test-firstboot-ubuntu-14.04.sh-t chmod 0755 test-firstboot-ubuntu-10.04.sh-t chmod 0755 test-firstboot-ubuntu-12.04.sh-t f=`echo "test-firstboot-ubuntu-14.04.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-ubuntu-14.04.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-ubuntu-14.04.sh-t mv test-firstboot-ubuntu-10.04.sh-t test-firstboot-ubuntu-10.04.sh mv test-firstboot-ubuntu-12.04.sh-t test-firstboot-ubuntu-12.04.sh rm -f test-firstboot-ubuntu-16.04.sh test-firstboot-ubuntu-16.04.sh-t f=`echo "test-firstboot-ubuntu-16.04.sh" | /usr/bin/sed 's/test-firstboot-\(.*\).sh/\1/'`; \ echo 'script=test-firstboot-ubuntu-16.04.sh exec $srcdir/test-firstboot.sh' "$f" > test-firstboot-ubuntu-16.04.sh-t chmod 0755 test-firstboot-ubuntu-14.04.sh-t rm -f test-password-centos-7.2.sh test-password-centos-7.2.sh-t chmod 0755 test-firstboot-ubuntu-16.04.sh-t mv test-firstboot-ubuntu-14.04.sh-t test-firstboot-ubuntu-14.04.sh f=`echo "test-password-centos-7.2.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-centos-7.2.sh exec $srcdir/test-password.pl' "$f" > test-password-centos-7.2.sh-t mv test-firstboot-ubuntu-16.04.sh-t test-firstboot-ubuntu-16.04.sh rm -f test-password-debian-6.sh test-password-debian-6.sh-t chmod 0755 test-password-centos-7.2.sh-t f=`echo "test-password-debian-6.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-debian-6.sh exec $srcdir/test-password.pl' "$f" > test-password-debian-6.sh-t mv test-password-centos-7.2.sh-t test-password-centos-7.2.sh rm -f test-password-debian-7.sh test-password-debian-7.sh-t chmod 0755 test-password-debian-6.sh-t f=`echo "test-password-debian-7.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-debian-7.sh exec $srcdir/test-password.pl' "$f" > test-password-debian-7.sh-t mv test-password-debian-6.sh-t test-password-debian-6.sh chmod 0755 test-password-debian-7.sh-t rm -f test-password-debian-8.sh test-password-debian-8.sh-t mv test-password-debian-7.sh-t test-password-debian-7.sh f=`echo "test-password-debian-8.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-debian-8.sh exec $srcdir/test-password.pl' "$f" > test-password-debian-8.sh-t rm -f test-password-fedora-25.sh test-password-fedora-25.sh-t rm -f test-password-rhel-3.9.sh test-password-rhel-3.9.sh-t chmod 0755 test-password-debian-8.sh-t f=`echo "test-password-fedora-25.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-fedora-25.sh exec $srcdir/test-password.pl' "$f" > test-password-fedora-25.sh-t f=`echo "test-password-rhel-3.9.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-rhel-3.9.sh exec $srcdir/test-password.pl' "$f" > test-password-rhel-3.9.sh-t mv test-password-debian-8.sh-t test-password-debian-8.sh chmod 0755 test-password-rhel-3.9.sh-t rm -f test-password-rhel-4.9.sh test-password-rhel-4.9.sh-t mv test-password-rhel-3.9.sh-t test-password-rhel-3.9.sh f=`echo "test-password-rhel-4.9.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-rhel-4.9.sh exec $srcdir/test-password.pl' "$f" > test-password-rhel-4.9.sh-t chmod 0755 test-password-fedora-25.sh-t chmod 0755 test-password-rhel-4.9.sh-t mv test-password-fedora-25.sh-t test-password-fedora-25.sh mv test-password-rhel-4.9.sh-t test-password-rhel-4.9.sh rm -f test-password-rhel-5.11.sh test-password-rhel-5.11.sh-t rm -f test-password-rhel-6.9.sh test-password-rhel-6.9.sh-t f=`echo "test-password-rhel-5.11.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-rhel-5.11.sh exec $srcdir/test-password.pl' "$f" > test-password-rhel-5.11.sh-t f=`echo "test-password-rhel-6.9.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-rhel-6.9.sh exec $srcdir/test-password.pl' "$f" > test-password-rhel-6.9.sh-t rm -f test-password-rhel-7.2.sh test-password-rhel-7.2.sh-t chmod 0755 test-password-rhel-5.11.sh-t chmod 0755 test-password-rhel-6.9.sh-t f=`echo "test-password-rhel-7.2.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-rhel-7.2.sh exec $srcdir/test-password.pl' "$f" > test-password-rhel-7.2.sh-t mv test-password-rhel-5.11.sh-t test-password-rhel-5.11.sh mv test-password-rhel-6.9.sh-t test-password-rhel-6.9.sh chmod 0755 test-password-rhel-7.2.sh-t rm -f test-password-ubuntu-10.04.sh test-password-ubuntu-10.04.sh-t mv test-password-rhel-7.2.sh-t test-password-rhel-7.2.sh f=`echo "test-password-ubuntu-10.04.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-ubuntu-10.04.sh exec $srcdir/test-password.pl' "$f" > test-password-ubuntu-10.04.sh-t rm -f test-password-ubuntu-12.04.sh test-password-ubuntu-12.04.sh-t rm -f test-password-ubuntu-14.04.sh test-password-ubuntu-14.04.sh-t f=`echo "test-password-ubuntu-12.04.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-ubuntu-12.04.sh exec $srcdir/test-password.pl' "$f" > test-password-ubuntu-12.04.sh-t f=`echo "test-password-ubuntu-14.04.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-ubuntu-14.04.sh exec $srcdir/test-password.pl' "$f" > test-password-ubuntu-14.04.sh-t chmod 0755 test-password-ubuntu-10.04.sh-t chmod 0755 test-password-ubuntu-12.04.sh-t mv test-password-ubuntu-10.04.sh-t test-password-ubuntu-10.04.sh chmod 0755 test-password-ubuntu-14.04.sh-t mv test-password-ubuntu-12.04.sh-t test-password-ubuntu-12.04.sh mv test-password-ubuntu-14.04.sh-t test-password-ubuntu-14.04.sh rm -f test-password-ubuntu-16.04.sh test-password-ubuntu-16.04.sh-t rm -f test-settings-rhel-4.9.sh test-settings-rhel-4.9.sh-t f=`echo "test-password-ubuntu-16.04.sh" | /usr/bin/sed 's/test-password-\(.*\).sh/\1/'`; \ echo 'script=test-password-ubuntu-16.04.sh exec $srcdir/test-password.pl' "$f" > test-password-ubuntu-16.04.sh-t f=`echo "test-settings-rhel-4.9.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-rhel-4.9.sh exec $srcdir/test-settings.sh' "$f" > test-settings-rhel-4.9.sh-t rm -f test-settings-rhel-5.11.sh test-settings-rhel-5.11.sh-t chmod 0755 test-password-ubuntu-16.04.sh-t chmod 0755 test-settings-rhel-4.9.sh-t f=`echo "test-settings-rhel-5.11.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-rhel-5.11.sh exec $srcdir/test-settings.sh' "$f" > test-settings-rhel-5.11.sh-t mv test-password-ubuntu-16.04.sh-t test-password-ubuntu-16.04.sh mv test-settings-rhel-4.9.sh-t test-settings-rhel-4.9.sh rm -f test-settings-rhel-6.8.sh test-settings-rhel-6.8.sh-t rm -f test-settings-rhel-7.2.sh test-settings-rhel-7.2.sh-t chmod 0755 test-settings-rhel-5.11.sh-t f=`echo "test-settings-rhel-6.8.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-rhel-6.8.sh exec $srcdir/test-settings.sh' "$f" > test-settings-rhel-6.8.sh-t f=`echo "test-settings-rhel-7.2.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-rhel-7.2.sh exec $srcdir/test-settings.sh' "$f" > test-settings-rhel-7.2.sh-t mv test-settings-rhel-5.11.sh-t test-settings-rhel-5.11.sh rm -f test-settings-debian-6.sh test-settings-debian-6.sh-t f=`echo "test-settings-debian-6.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-debian-6.sh exec $srcdir/test-settings.sh' "$f" > test-settings-debian-6.sh-t chmod 0755 test-settings-rhel-7.2.sh-t chmod 0755 test-settings-rhel-6.8.sh-t mv test-settings-rhel-7.2.sh-t test-settings-rhel-7.2.sh mv test-settings-rhel-6.8.sh-t test-settings-rhel-6.8.sh chmod 0755 test-settings-debian-6.sh-t rm -f test-settings-debian-7.sh test-settings-debian-7.sh-t mv test-settings-debian-6.sh-t test-settings-debian-6.sh f=`echo "test-settings-debian-7.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-debian-7.sh exec $srcdir/test-settings.sh' "$f" > test-settings-debian-7.sh-t rm -f test-settings-debian-8.sh test-settings-debian-8.sh-t rm -f test-settings-fedora-25.sh test-settings-fedora-25.sh-t f=`echo "test-settings-debian-8.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-debian-8.sh exec $srcdir/test-settings.sh' "$f" > test-settings-debian-8.sh-t chmod 0755 test-settings-debian-7.sh-t f=`echo "test-settings-fedora-25.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-fedora-25.sh exec $srcdir/test-settings.sh' "$f" > test-settings-fedora-25.sh-t mv test-settings-debian-7.sh-t test-settings-debian-7.sh chmod 0755 test-settings-debian-8.sh-t chmod 0755 test-settings-fedora-25.sh-t mv test-settings-debian-8.sh-t test-settings-debian-8.sh mv test-settings-fedora-25.sh-t test-settings-fedora-25.sh rm -f test-settings-ubuntu-10.04.sh test-settings-ubuntu-10.04.sh-t rm -f test-settings-ubuntu-12.04.sh test-settings-ubuntu-12.04.sh-t rm -f test-settings-ubuntu-14.04.sh test-settings-ubuntu-14.04.sh-t f=`echo "test-settings-ubuntu-10.04.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-ubuntu-10.04.sh exec $srcdir/test-settings.sh' "$f" > test-settings-ubuntu-10.04.sh-t f=`echo "test-settings-ubuntu-12.04.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-ubuntu-12.04.sh exec $srcdir/test-settings.sh' "$f" > test-settings-ubuntu-12.04.sh-t f=`echo "test-settings-ubuntu-14.04.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-ubuntu-14.04.sh exec $srcdir/test-settings.sh' "$f" > test-settings-ubuntu-14.04.sh-t chmod 0755 test-settings-ubuntu-12.04.sh-t mv test-settings-ubuntu-12.04.sh-t test-settings-ubuntu-12.04.sh rm -f test-settings-ubuntu-16.04.sh test-settings-ubuntu-16.04.sh-t chmod 0755 test-settings-ubuntu-10.04.sh-t chmod 0755 test-settings-ubuntu-14.04.sh-t f=`echo "test-settings-ubuntu-16.04.sh" | /usr/bin/sed 's/test-settings-\(.*\).sh/\1/'`; \ echo 'script=test-settings-ubuntu-16.04.sh exec $srcdir/test-settings.sh' "$f" > test-settings-ubuntu-16.04.sh-t mv test-settings-ubuntu-10.04.sh-t test-settings-ubuntu-10.04.sh mv test-settings-ubuntu-14.04.sh-t test-settings-ubuntu-14.04.sh chmod 0755 test-settings-ubuntu-16.04.sh-t mv test-settings-ubuntu-16.04.sh-t test-settings-ubuntu-16.04.sh SKIP: test-firstboot-rhel-6.8.sh PASS: test-virt-customize-docs.sh SKIP: test-firstboot-rhel-4.9.sh SKIP: test-firstboot-rhel-5.11.sh SKIP: test-firstboot-rhel-7.2.sh SKIP: test-firstboot-debian-6.sh SKIP: test-firstboot-debian-7.sh SKIP: test-firstboot-debian-8.sh SKIP: test-firstboot-fedora-25.sh SKIP: test-firstboot-ubuntu-10.04.sh SKIP: test-firstboot-fedora-26.sh SKIP: test-firstboot-ubuntu-12.04.sh SKIP: test-firstboot-ubuntu-14.04.sh SKIP: test-password-centos-7.2.sh SKIP: test-firstboot-ubuntu-16.04.sh SKIP: test-password-debian-6.sh SKIP: test-password-debian-7.sh SKIP: test-password-debian-8.sh SKIP: test-password-fedora-25.sh SKIP: test-password-rhel-3.9.sh SKIP: test-password-rhel-5.11.sh SKIP: test-password-rhel-4.9.sh SKIP: test-password-rhel-6.9.sh SKIP: test-password-rhel-7.2.sh SKIP: test-password-ubuntu-10.04.sh SKIP: test-password-ubuntu-12.04.sh SKIP: test-password-ubuntu-14.04.sh SKIP: test-password-ubuntu-16.04.sh SKIP: test-settings-rhel-4.9.sh SKIP: test-settings-rhel-5.11.sh SKIP: test-settings-rhel-6.8.sh SKIP: test-settings-rhel-7.2.sh SKIP: test-settings-debian-6.sh SKIP: test-settings-debian-7.sh SKIP: test-settings-debian-8.sh SKIP: test-settings-ubuntu-10.04.sh SKIP: test-settings-fedora-25.sh SKIP: test-settings-ubuntu-12.04.sh SKIP: test-settings-ubuntu-14.04.sh SKIP: test-settings-ubuntu-16.04.sh PASS: test-virt-customize.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 41 # PASS: 2 # SKIP: 39 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/customize' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/customize' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/customize' Making check in builder make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/builder' make yajl_tests debian.xz fedora.xz ubuntu.xz windows.xz fedora.qcow2 fedora.qcow2.xz make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/builder' CC yajl_tests-yajl-c.o OCAMLOPT yajl_tests.cmx rm -f debian.xz debian.xz-t rm -f fedora.xz fedora.xz-t rm -f ubuntu.xz ubuntu.xz-t xz --best -c ../test-data/phony-guests/debian.img > debian.xz-t xz --best -c ../test-data/phony-guests/fedora.img > fedora.xz-t xz --best -c ../test-data/phony-guests/ubuntu.img > ubuntu.xz-t rm -f windows.xz windows.xz-t xz --best -c ../test-data/phony-guests/windows.img > windows.xz-t rm -f fedora.qcow2 fedora.qcow2-t qemu-img convert -f raw -O qcow2 ../test-data/phony-guests/fedora.img fedora.qcow2-t mv fedora.qcow2-t fedora.qcow2 GEN yajl_tests rm -f fedora.qcow2.xz fedora.qcow2.xz-t xz --best -c fedora.qcow2 > fedora.qcow2.xz-t mv fedora.qcow2.xz-t fedora.qcow2.xz mv ubuntu.xz-t ubuntu.xz mv windows.xz-t windows.xz mv debian.xz-t debian.xz mv fedora.xz-t fedora.xz make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/builder' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/builder' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/builder' rm -f test-console-centos-7.2.sh test-console-centos-7.2.sh-t rm -f test-console-rhel-6.8.sh test-console-rhel-6.8.sh-t f=`echo "test-console-centos-7.2.sh" | /usr/bin/sed 's/test-console-\(.*\).sh/\1/'`; \ echo 'script=test-console-centos-7.2.sh exec $srcdir/test-console.sh' "$f" > test-console-centos-7.2.sh-t f=`echo "test-console-rhel-6.8.sh" | /usr/bin/sed 's/test-console-\(.*\).sh/\1/'`; \ echo 'script=test-console-rhel-6.8.sh exec $srcdir/test-console.sh' "$f" > test-console-rhel-6.8.sh-t chmod 0755 test-console-centos-7.2.sh-t mv test-console-centos-7.2.sh-t test-console-centos-7.2.sh chmod 0755 test-console-rhel-6.8.sh-t rm -f test-console-rhel-7.2.sh test-console-rhel-7.2.sh-t mv test-console-rhel-6.8.sh-t test-console-rhel-6.8.sh f=`echo "test-console-rhel-7.2.sh" | /usr/bin/sed 's/test-console-\(.*\).sh/\1/'`; \ echo 'script=test-console-rhel-7.2.sh exec $srcdir/test-console.sh' "$f" > test-console-rhel-7.2.sh-t rm -f test-console-debian-7.sh test-console-debian-7.sh-t f=`echo "test-console-debian-7.sh" | /usr/bin/sed 's/test-console-\(.*\).sh/\1/'`; \ echo 'script=test-console-debian-7.sh exec $srcdir/test-console.sh' "$f" > test-console-debian-7.sh-t chmod 0755 test-console-rhel-7.2.sh-t mv test-console-rhel-7.2.sh-t test-console-rhel-7.2.sh rm -f test-console-debian-8.sh test-console-debian-8.sh-t f=`echo "test-console-debian-8.sh" | /usr/bin/sed 's/test-console-\(.*\).sh/\1/'`; \ echo 'script=test-console-debian-8.sh exec $srcdir/test-console.sh' "$f" > test-console-debian-8.sh-t chmod 0755 test-console-debian-7.sh-t mv test-console-debian-7.sh-t test-console-debian-7.sh rm -f test-console-fedora-24.sh test-console-fedora-24.sh-t f=`echo "test-console-fedora-24.sh" | /usr/bin/sed 's/test-console-\(.*\).sh/\1/'`; \ echo 'script=test-console-fedora-24.sh exec $srcdir/test-console.sh' "$f" > test-console-fedora-24.sh-t chmod 0755 test-console-debian-8.sh-t chmod 0755 test-console-fedora-24.sh-t mv test-console-debian-8.sh-t test-console-debian-8.sh mv test-console-fedora-24.sh-t test-console-fedora-24.sh rm -f test-console-ubuntu-12.04.sh test-console-ubuntu-12.04.sh-t rm -f test-console-ubuntu-14.04.sh test-console-ubuntu-14.04.sh-t f=`echo "test-console-ubuntu-12.04.sh" | /usr/bin/sed 's/test-console-\(.*\).sh/\1/'`; \ echo 'script=test-console-ubuntu-12.04.sh exec $srcdir/test-console.sh' "$f" > test-console-ubuntu-12.04.sh-t f=`echo "test-console-ubuntu-14.04.sh" | /usr/bin/sed 's/test-console-\(.*\).sh/\1/'`; \ echo 'script=test-console-ubuntu-14.04.sh exec $srcdir/test-console.sh' "$f" > test-console-ubuntu-14.04.sh-t chmod 0755 test-console-ubuntu-12.04.sh-t mv test-console-ubuntu-12.04.sh-t test-console-ubuntu-12.04.sh rm -f test-console-ubuntu-16.04.sh test-console-ubuntu-16.04.sh-t chmod 0755 test-console-ubuntu-14.04.sh-t f=`echo "test-console-ubuntu-16.04.sh" | /usr/bin/sed 's/test-console-\(.*\).sh/\1/'`; \ echo 'script=test-console-ubuntu-16.04.sh exec $srcdir/test-console.sh' "$f" > test-console-ubuntu-16.04.sh-t mv test-console-ubuntu-14.04.sh-t test-console-ubuntu-14.04.sh chmod 0755 test-console-ubuntu-16.04.sh-t mv test-console-ubuntu-16.04.sh-t test-console-ubuntu-16.04.sh PASS: test-virt-index-validate.sh SKIP: test-virt-builder-planner.sh PASS: test-virt-builder-docs.sh PASS: test-virt-builder-list.sh PASS: test-virt-builder-list-simplestreams.sh SKIP: test-console-rhel-6.8.sh PASS: yajl_tests SKIP: test-console-centos-7.2.sh SKIP: test-console-rhel-7.2.sh SKIP: test-console-debian-8.sh SKIP: test-console-debian-7.sh SKIP: test-console-fedora-24.sh SKIP: test-console-ubuntu-12.04.sh SKIP: test-console-ubuntu-16.04.sh SKIP: test-console-ubuntu-14.04.sh PASS: test-virt-builder.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 16 # PASS: 6 # SKIP: 10 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/builder' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/builder' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/builder' Making check in builder/templates make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/builder/templates' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/builder/templates' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/builder/templates' PASS: validate.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 1 # PASS: 1 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/builder/templates' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/builder/templates' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/builder/templates' Making check in get-kernel make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/get-kernel' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/get-kernel' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/get-kernel' PASS: test-virt-get-kernel-docs.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 1 # PASS: 1 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/get-kernel' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/get-kernel' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/get-kernel' Making check in resize make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/resize' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/resize' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/resize' PASS: test-virt-resize-docs.sh PASS: test-virt-resize.pl ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 2 # PASS: 2 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/resize' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/resize' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/resize' Making check in sparsify make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/sparsify' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/sparsify' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/sparsify' PASS: test-virt-sparsify-docs.sh PASS: test-virt-sparsify-in-place.sh PASS: test-virt-sparsify.sh PASS: test-virt-sparsify-in-place-fstrim-unsupported.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 4 # PASS: 4 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/sparsify' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/sparsify' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/sparsify' Making check in sysprep make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/sysprep' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/sysprep' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/sysprep' PASS: test-virt-sysprep-docs.sh PASS: test-virt-sysprep-passwords.sh PASS: test-virt-sysprep-backup-files.sh PASS: test-virt-sysprep.sh PASS: test-virt-sysprep-script.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 5 # PASS: 5 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/sysprep' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/sysprep' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/sysprep' Making check in v2v make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/v2v' make v2v_unit_tests windows.vmdk make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/v2v' CC v2v_unit_tests-libvirt_utils-c.o CC v2v_unit_tests-qemuopts-c.o rm -f windows.vmdk windows.vmdk-t OCAMLOPT v2v_unit_tests.cmx if [ -s ../test-data/phony-guests/windows.img ]; then \ qemu-img convert -f raw ../test-data/phony-guests/windows.img -O vmdk windows.vmdk-t; \ mv windows.vmdk-t windows.vmdk; \ else \ touch windows.vmdk; \ fi GEN v2v_unit_tests make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/v2v' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/v2v' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/v2v' PASS: test-v2v-docs.sh PASS: test-v2v-i-ova-bad-sha256.sh PASS: test-v2v-i-ova-bad-sha1.sh PASS: test-v2v-i-ova-good-checksums.sh PASS: test-v2v-i-ova-formats.sh PASS: test-v2v-i-ova-invalid-manifest2.sh PASS: test-v2v-i-ova-gz.sh PASS: test-v2v-i-ova-invalid-manifest1.sh PASS: test-v2v-i-ova-subfolders.sh PASS: test-v2v-i-ova-tar.sh PASS: test-v2v-i-ova-two-disks.sh PASS: test-v2v-copy-to-local.sh PASS: test-v2v-i-vmx.sh PASS: v2v_unit_tests PASS: test-v2v-bad-networks-and-bridges.sh PASS: test-v2v-machine-readable.sh PASS: test-v2v-i-disk.sh PASS: test-v2v-cdrom.sh PASS: test-v2v-i-ova.sh PASS: test-v2v-windows-conversion.sh PASS: test-v2v-floppy.sh PASS: test-v2v-networks-and-bridges.sh PASS: test-v2v-virtio-win-iso.sh PASS: test-v2v-in-place.sh PASS: test-v2v-o-glance.sh PASS: test-v2v-o-libvirt.sh PASS: test-v2v-o-null.sh PASS: test-v2v-no-copy.sh PASS: test-v2v-o-qemu.sh PASS: test-v2v-o-vdsm-options.sh PASS: test-v2v-o-rhv.sh PASS: test-v2v-print-source.sh rm -f test-v2v-conversion-of-centos-6.sh test-v2v-conversion-of-centos-6.sh-t f=`echo "test-v2v-conversion-of-centos-6.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-centos-6.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-centos-6.sh-t chmod 0755 test-v2v-conversion-of-centos-6.sh-t mv test-v2v-conversion-of-centos-6.sh-t test-v2v-conversion-of-centos-6.sh rm -f test-v2v-conversion-of-centos-7.0.sh test-v2v-conversion-of-centos-7.0.sh-t f=`echo "test-v2v-conversion-of-centos-7.0.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-centos-7.0.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-centos-7.0.sh-t chmod 0755 test-v2v-conversion-of-centos-7.0.sh-t mv test-v2v-conversion-of-centos-7.0.sh-t test-v2v-conversion-of-centos-7.0.sh rm -f test-v2v-conversion-of-debian-6.sh test-v2v-conversion-of-debian-6.sh-t f=`echo "test-v2v-conversion-of-debian-6.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-debian-6.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-debian-6.sh-t chmod 0755 test-v2v-conversion-of-debian-6.sh-t mv test-v2v-conversion-of-debian-6.sh-t test-v2v-conversion-of-debian-6.sh rm -f test-v2v-conversion-of-debian-7.sh test-v2v-conversion-of-debian-7.sh-t f=`echo "test-v2v-conversion-of-debian-7.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-debian-7.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-debian-7.sh-t chmod 0755 test-v2v-conversion-of-debian-7.sh-t mv test-v2v-conversion-of-debian-7.sh-t test-v2v-conversion-of-debian-7.sh rm -f test-v2v-conversion-of-debian-8.sh test-v2v-conversion-of-debian-8.sh-t f=`echo "test-v2v-conversion-of-debian-8.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-debian-8.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-debian-8.sh-t chmod 0755 test-v2v-conversion-of-debian-8.sh-t mv test-v2v-conversion-of-debian-8.sh-t test-v2v-conversion-of-debian-8.sh rm -f test-v2v-conversion-of-fedora-20.sh test-v2v-conversion-of-fedora-20.sh-t f=`echo "test-v2v-conversion-of-fedora-20.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-fedora-20.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-fedora-20.sh-t chmod 0755 test-v2v-conversion-of-fedora-20.sh-t mv test-v2v-conversion-of-fedora-20.sh-t test-v2v-conversion-of-fedora-20.sh rm -f test-v2v-conversion-of-fedora-23.sh test-v2v-conversion-of-fedora-23.sh-t f=`echo "test-v2v-conversion-of-fedora-23.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-fedora-23.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-fedora-23.sh-t chmod 0755 test-v2v-conversion-of-fedora-23.sh-t mv test-v2v-conversion-of-fedora-23.sh-t test-v2v-conversion-of-fedora-23.sh rm -f test-v2v-conversion-of-opensuse-13.1.sh test-v2v-conversion-of-opensuse-13.1.sh-t f=`echo "test-v2v-conversion-of-opensuse-13.1.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-opensuse-13.1.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-opensuse-13.1.sh-t chmod 0755 test-v2v-conversion-of-opensuse-13.1.sh-t mv test-v2v-conversion-of-opensuse-13.1.sh-t test-v2v-conversion-of-opensuse-13.1.sh rm -f test-v2v-conversion-of-opensuse-13.2.sh test-v2v-conversion-of-opensuse-13.2.sh-t f=`echo "test-v2v-conversion-of-opensuse-13.2.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-opensuse-13.2.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-opensuse-13.2.sh-t chmod 0755 test-v2v-conversion-of-opensuse-13.2.sh-t mv test-v2v-conversion-of-opensuse-13.2.sh-t test-v2v-conversion-of-opensuse-13.2.sh rm -f test-v2v-conversion-of-opensuse-42.1.sh test-v2v-conversion-of-opensuse-42.1.sh-t f=`echo "test-v2v-conversion-of-opensuse-42.1.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-opensuse-42.1.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-opensuse-42.1.sh-t chmod 0755 test-v2v-conversion-of-opensuse-42.1.sh-t mv test-v2v-conversion-of-opensuse-42.1.sh-t test-v2v-conversion-of-opensuse-42.1.sh rm -f test-v2v-conversion-of-rhel-5.10.sh test-v2v-conversion-of-rhel-5.10.sh-t f=`echo "test-v2v-conversion-of-rhel-5.10.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-rhel-5.10.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-rhel-5.10.sh-t chmod 0755 test-v2v-conversion-of-rhel-5.10.sh-t mv test-v2v-conversion-of-rhel-5.10.sh-t test-v2v-conversion-of-rhel-5.10.sh rm -f test-v2v-conversion-of-rhel-6.8.sh test-v2v-conversion-of-rhel-6.8.sh-t f=`echo "test-v2v-conversion-of-rhel-6.8.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-rhel-6.8.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-rhel-6.8.sh-t chmod 0755 test-v2v-conversion-of-rhel-6.8.sh-t mv test-v2v-conversion-of-rhel-6.8.sh-t test-v2v-conversion-of-rhel-6.8.sh rm -f test-v2v-conversion-of-rhel-7.0.sh test-v2v-conversion-of-rhel-7.0.sh-t f=`echo "test-v2v-conversion-of-rhel-7.0.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-rhel-7.0.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-rhel-7.0.sh-t chmod 0755 test-v2v-conversion-of-rhel-7.0.sh-t mv test-v2v-conversion-of-rhel-7.0.sh-t test-v2v-conversion-of-rhel-7.0.sh rm -f test-v2v-conversion-of-rhel-7.2.sh test-v2v-conversion-of-rhel-7.2.sh-t f=`echo "test-v2v-conversion-of-rhel-7.2.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-rhel-7.2.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-rhel-7.2.sh-t chmod 0755 test-v2v-conversion-of-rhel-7.2.sh-t mv test-v2v-conversion-of-rhel-7.2.sh-t test-v2v-conversion-of-rhel-7.2.sh rm -f test-v2v-conversion-of-ubuntu-10.04.sh test-v2v-conversion-of-ubuntu-10.04.sh-t f=`echo "test-v2v-conversion-of-ubuntu-10.04.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-ubuntu-10.04.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-ubuntu-10.04.sh-t chmod 0755 test-v2v-conversion-of-ubuntu-10.04.sh-t mv test-v2v-conversion-of-ubuntu-10.04.sh-t test-v2v-conversion-of-ubuntu-10.04.sh rm -f test-v2v-conversion-of-ubuntu-12.04.sh test-v2v-conversion-of-ubuntu-12.04.sh-t f=`echo "test-v2v-conversion-of-ubuntu-12.04.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-ubuntu-12.04.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-ubuntu-12.04.sh-t chmod 0755 test-v2v-conversion-of-ubuntu-12.04.sh-t mv test-v2v-conversion-of-ubuntu-12.04.sh-t test-v2v-conversion-of-ubuntu-12.04.sh rm -f test-v2v-conversion-of-ubuntu-14.04.sh test-v2v-conversion-of-ubuntu-14.04.sh-t f=`echo "test-v2v-conversion-of-ubuntu-14.04.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-ubuntu-14.04.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-ubuntu-14.04.sh-t chmod 0755 test-v2v-conversion-of-ubuntu-14.04.sh-t mv test-v2v-conversion-of-ubuntu-14.04.sh-t test-v2v-conversion-of-ubuntu-14.04.sh rm -f test-v2v-conversion-of-ubuntu-16.04.sh test-v2v-conversion-of-ubuntu-16.04.sh-t f=`echo "test-v2v-conversion-of-ubuntu-16.04.sh" | /usr/bin/sed 's/test-v2v-conversion-of-\(.*\).sh/\1/'`; \ echo 'script=test-v2v-conversion-of-ubuntu-16.04.sh exec $srcdir/test-v2v-conversion-of.sh' "$f" > test-v2v-conversion-of-ubuntu-16.04.sh-t chmod 0755 test-v2v-conversion-of-ubuntu-16.04.sh-t mv test-v2v-conversion-of-ubuntu-16.04.sh-t test-v2v-conversion-of-ubuntu-16.04.sh SKIP: test-v2v-trim.sh SKIP: test-v2v-i-ova-as-root.sh SKIP: test-v2v-conversion-of-centos-6.sh SKIP: test-v2v-conversion-of-centos-7.0.sh PASS: test-v2v-oa-option.sh PASS: test-v2v-of-option.sh SKIP: test-v2v-conversion-of-debian-6.sh SKIP: test-v2v-conversion-of-debian-7.sh SKIP: test-v2v-conversion-of-debian-8.sh SKIP: test-v2v-conversion-of-fedora-20.sh SKIP: test-v2v-conversion-of-fedora-23.sh SKIP: test-v2v-conversion-of-opensuse-13.1.sh SKIP: test-v2v-conversion-of-opensuse-13.2.sh SKIP: test-v2v-conversion-of-opensuse-42.1.sh SKIP: test-v2v-conversion-of-rhel-5.10.sh SKIP: test-v2v-conversion-of-rhel-6.8.sh SKIP: test-v2v-conversion-of-rhel-7.0.sh SKIP: test-v2v-conversion-of-rhel-7.2.sh SKIP: test-v2v-conversion-of-ubuntu-10.04.sh SKIP: test-v2v-conversion-of-ubuntu-14.04.sh SKIP: test-v2v-conversion-of-ubuntu-12.04.sh SKIP: test-v2v-conversion-of-ubuntu-16.04.sh PASS: test-v2v-on-option.sh PASS: test-v2v-sound.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 56 # PASS: 36 # SKIP: 20 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/v2v' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/v2v' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/v2v' Making check in v2v/test-harness make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/v2v/test-harness' make[1]: Nothing to be done for 'check'. make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/v2v/test-harness' Making check in dib make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/dib' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/dib' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/dib' PASS: test-virt-dib-docs.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 1 # PASS: 1 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/dib' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/dib' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/dib' Making check in tools make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/tools' for f in tools/virt-list-filesystems tools/virt-list-partitions tools/virt-tar tools/virt-win-reg; do echo $f; done > ../po/POTFILES-pl make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/tools' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/tools' PASS: test-virt-list-filesystems.sh PASS: test-virt-tar.sh ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 2 # PASS: 2 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/tools' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/tools' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/tools' Making check in fuse make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/fuse' make test-fuse test-guestmount-fd test-guestunmount-fd make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/fuse' CC test_fuse-test-fuse.o CC test_guestmount_fd-test-guestmount-fd.o CC test_guestunmount_fd-test-guestunmount-fd.o CCLD test-guestunmount-fd CCLD test-guestmount-fd CCLD test-fuse make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/fuse' make check-TESTS make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/fuse' make[3]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/fuse' SKIP: test-fuse-umount-race.sh PASS: test-guestunmount-not-mounted.sh PASS: test-docs.sh SKIP: /var/tmp/tmpCnSJf8/libguestfs/fuse/.libs/lt-test-guestmount-fd PASS: /var/tmp/tmpCnSJf8/libguestfs/fuse/.libs/lt-test-guestunmount-fd PASS: /var/tmp/tmpCnSJf8/libguestfs/fuse/.libs/lt-test-fuse ===========================================================================Testsuite summary for libguestfs 1.37.19 ===========================================================================# TOTAL: 6 # PASS: 4 # SKIP: 2 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ===========================================================================make[3]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/fuse' make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/fuse' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/fuse' Making check in utils/boot-analysis make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/utils/boot-analysis' make[1]: Nothing to be done for 'check'. make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/utils/boot-analysis' Making check in utils/boot-benchmark make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/utils/boot-benchmark' make[1]: Nothing to be done for 'check'. make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/utils/boot-benchmark' Making check in utils/qemu-boot make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/utils/qemu-boot' make[1]: Nothing to be done for 'check'. make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/utils/qemu-boot' Making check in utils/qemu-speed-test make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/utils/qemu-speed-test' make[1]: Nothing to be done for 'check'. make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/utils/qemu-speed-test' Making check in po-docs make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/po-docs' Making check in ja make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/po-docs/ja' make[2]: Nothing to be done for 'check'. make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/po-docs/ja' Making check in uk make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/po-docs/uk' make[2]: Nothing to be done for 'check'. make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/po-docs/uk' make[2]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs/po-docs' make[2]: Nothing to be done for 'check-am'. make[2]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/po-docs' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs/po-docs' make[1]: Entering directory '/var/tmp/tmpCnSJf8/libguestfs' make[1]: Leaving directory '/var/tmp/tmpCnSJf8/libguestfs'
Pino Toscano
2017-Aug-02 10:33 UTC
Re: [Libguestfs] [PATCH 0/2] Add lightweight bindings for PCRE.
Hi, (replying here since v2 of the series does not have this explanation.) On Tuesday, 1 August 2017 16:00:15 CEST Richard W.M. Jones wrote:> We'd like to use PCRE instead of the awful Str module. However I > don't necessarily want to pull in the extra dependency of ocaml-pcre, > and in any case ocaml-pcre is rather difficult to use. > > This introduces very simplified and lightweight bindings for PCRE. > > They work rather like Str in that there is some global state (actually > thread-local in this implementation) between the matching and the > getting the substring, so you can write code like this: > > let re = PCRE.compile "(a+)b" > ... > > if PCRE.matches re "ccaaaabb" then ( > let whole = PCRE.sub 0 in (* returns "aaaab" *) > let first = PCRE.sub 1 in (* returns "aaaa" *) > ...Since we are providing a better module, with a different API (which needs changes), what about removing the usage of a global state, in favour of a match object holding the captures? Something like (starting from your example above): let re = PCRE.compile "(a+)b" in try let m = PCRE.match re "ccaaaabb" in let whole = PCRE.sub m 0 in (* returns "aaaab" *) let first = PCRE.sub m 1 in (* returns "aaaa" *) with Not_matched _ -> ... This makes it possible to stop thinking about what was the last saved state, and even keep the multiple results of matches at the same time. Also the results are properly GC'ed once they get out of scope, and not linger until the thread finish (or the program shutdown). The drawback I see is that many of the Str usages are in chains of "if ... else if ...", which could make the code slightly more complex. Of course PCRE.matches ought to be left, but it would just return whether the re matched, without changing any global state, and without any result available. WDYT? -- Pino Toscano
Richard W.M. Jones
2017-Aug-02 11:52 UTC
Re: [Libguestfs] [PATCH 0/2] Add lightweight bindings for PCRE.
On Wed, Aug 02, 2017 at 12:33:14PM +0200, Pino Toscano wrote:> Hi, > > (replying here since v2 of the series does not have this explanation.) > > On Tuesday, 1 August 2017 16:00:15 CEST Richard W.M. Jones wrote: > > We'd like to use PCRE instead of the awful Str module. However I > > don't necessarily want to pull in the extra dependency of ocaml-pcre, > > and in any case ocaml-pcre is rather difficult to use. > > > > This introduces very simplified and lightweight bindings for PCRE. > > > > They work rather like Str in that there is some global state (actually > > thread-local in this implementation) between the matching and the > > getting the substring, so you can write code like this: > > > > let re = PCRE.compile "(a+)b" > > ... > > > > if PCRE.matches re "ccaaaabb" then ( > > let whole = PCRE.sub 0 in (* returns "aaaab" *) > > let first = PCRE.sub 1 in (* returns "aaaa" *) > > ... > > Since we are providing a better module, with a different API (which > needs changes), what about removing the usage of a global state, in > favour of a match object holding the captures? Something like > (starting from your example above): > > let re = PCRE.compile "(a+)b" in > try > let m = PCRE.match re "ccaaaabb" in > let whole = PCRE.sub m 0 in (* returns "aaaab" *) > let first = PCRE.sub m 1 in (* returns "aaaa" *) > with Not_matched _ -> > ...That's what I was trying to avoid. I think the if statement with global state is much easier to use.> This makes it possible to stop thinking about what was the last saved > state, and even keep the multiple results of matches at the same time.I've converted all of the daemon code to this form, and this is not an issue that came up.> Also the results are properly GC'ed once they get out of scope, and not > linger until the thread finish (or the program shutdown). > The drawback I see is that many of the Str usages are in chains of > "if ... else if ...", which could make the code slightly more complex. > > Of course PCRE.matches ought to be left, but it would just return > whether the re matched, without changing any global state, and without > any result available.I think you're suggesting this: let m = PCRE.exec re "ccaaaabb" in if PCRE.matches m then ( let whole = PCRE.sub m 0 in ... (‘match’ is a reserved word, and I've got rid of the ‘Not_matched’ exception which is a pain to deal with), which is sort of OK but still more code than what I'm writing which is: else if PCRE.matches re_xdev spec then ( debug_matching "xdev"; let typ = PCRE.sub 1 and disk = PCRE.sub 2 and part = int_of_string (PCRE.sub 3) in resolve_xdev typ disk part default ) else if PCRE.matches re_cciss spec then ( debug_matching "cciss"; let disk = PCRE.sub 1 and part = try Some (int_of_string (PCRE.sub 2)) with Not_found -> None in resolve_cciss disk part default ) else if PCRE.matches re_mdN spec then ( debug_matching "md<N>"; try Mountable.of_device (StringMap.find spec md_map) with | Not_found -> default ) Rewriting if/else chains without the global state is a pain too. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW
Xiang Hua Chen
2017-Aug-03 01:06 UTC
Re: [Libguestfs] [PATCH 0/2] Add lightweight bindings for PCRE.
Hi Rjones, So, will we add dependency of ocaml-pcre in RHEL7.5 ? Just like the new bug you filed to add dependency of ocaml-camlp4 & ocaml-labltk ? -- Thanks & Best regards, Chen Xiang Hua Raycom office Beijing (NAY), Red Hat Inc. Red Hat Telephony: 86 10 62608040 internal extension: 8388040 Team: Virt QE IRC: xchen@#S1, #virt ----- Original Message -----> From: "Richard W.M. Jones" <rjones@redhat.com> > To: libguestfs@redhat.com > Sent: Tuesday, August 1, 2017 10:00:15 PM > Subject: [Libguestfs] [PATCH 0/2] Add lightweight bindings for PCRE. > > We'd like to use PCRE instead of the awful Str module. However I > don't necessarily want to pull in the extra dependency of ocaml-pcre, > and in any case ocaml-pcre is rather difficult to use. > > This introduces very simplified and lightweight bindings for PCRE. > > They work rather like Str in that there is some global state (actually > thread-local in this implementation) between the matching and the > getting the substring, so you can write code like this: > > let re = PCRE.compile "(a+)b" > ... > > if PCRE.matches re "ccaaaabb" then ( > let whole = PCRE.sub 0 in (* returns "aaaab" *) > let first = PCRE.sub 1 in (* returns "aaaa" *) > ... > > I also introduced the switch from Str -> PCRE in virt-builder to show > that it simplifies code while allowing you to use the much more > powerful PCRE regular expressions. > > Rich. > > _______________________________________________ > Libguestfs mailing list > Libguestfs@redhat.com > https://www.redhat.com/mailman/listinfo/libguestfs >
Richard W.M. Jones
2017-Aug-03 07:35 UTC
Re: [Libguestfs] [PATCH 0/2] Add lightweight bindings for PCRE.
On Wed, Aug 02, 2017 at 09:06:15PM -0400, Xiang Hua Chen wrote:> > Hi Rjones, > So, will we add dependency of ocaml-pcre in RHEL7.5 ?No, this doesn't require ocaml-pcre. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-builder quickly builds VMs from scratch http://libguestfs.org/virt-builder.1.html