[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.
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
--- 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
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'
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
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
On Wednesday, 2 August 2017 13:52:06 CEST Richard W.M. Jones wrote:
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.
Right, because we have already these constraints because of Str.
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
Not really, my suggestion was to have a separate object representing the result of a regex match -- much like other language have in their regex APIs. OTOH, this solution LGTM as well: the result of the regex is not saved in a thread-local variable, but directly in the same regex object, so can be kept/used around, and it is GC'ed when not needed anymore. If you could apply that change, that'd be a LGTM. Thanks, -- Pino Toscano
On Wed, Aug 02, 2017 at 03:01:53PM +0200, Pino Toscano wrote:
On Wednesday, 2 August 2017 13:52:06 CEST Richard W.M. Jones wrote:
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
Not really, my suggestion was to have a separate object representing the result of a regex match -- much like other language have in their regex APIs.
OTOH, this solution LGTM as well: the result of the regex is not saved in a thread-local variable, but directly in the same regex object, so can be kept/used around, and it is GC'ed when not needed anymore. If you could apply that change, that'd be a LGTM.
But the problem still is this makes the if/else chains more awkward. What's really wrong with the thread-local variable? It only stores a single string and a vector of integers per thread (at most). The final string/vector is reliably freed on exit - I know that because I've checked it with valgrind. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into KVM guests. http://libguestfs.org/virt-v2v
On Wednesday, 2 August 2017 20:18:43 CEST Richard W.M. Jones wrote:
On Wed, Aug 02, 2017 at 03:01:53PM +0200, Pino Toscano wrote:
On Wednesday, 2 August 2017 13:52:06 CEST Richard W.M. Jones wrote:
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
Not really, my suggestion was to have a separate object representing the result of a regex match -- much like other language have in their regex APIs.
OTOH, this solution LGTM as well: the result of the regex is not saved in a thread-local variable, but directly in the same regex object, so can be kept/used around, and it is GC'ed when not needed anymore. If you could apply that change, that'd be a LGTM.
But the problem still is this makes the if/else chains more awkward.
What's really wrong with the thread-local variable? It only stores a single string and a vector of integers per thread (at most). The final string/vector is reliably freed on exit - I know that because I've checked it with valgrind.
I've no doubts that the patch cleanes the memory correctly. I simply not in favour of global variables in complex/big contests, since they can be used by every place (thus hard to trace), their data linger longer than the actual usage (like in this case), and the possible (sometimes subtle) iterations among them makes the code harder to follow. But I guess I have no chance to change the current patch (even adding a test using asserts, instead of oUnit, for which I still did not get a reason why a new test using it would be unacceptable), so ... -- Pino Toscano
On Thu, Aug 03, 2017 at 06:08:24PM +0200, Pino Toscano wrote:
But I guess I have no chance to change the current patch (even adding a test using asserts, instead of oUnit, for which I still did not get a reason why a new test using it would be unacceptable), so ...
Fewer dependencies make the code easier for others to consume, and that's especially true when (like oUnit) those dependencies add little value. (That's different from dependencies like, say, Augeas which bring huge value.) So by adding a test with asserts I'm gradually working towards reducing -- or at least not increasing -- the amount of oUnit being used. Practically, someone who compiles libguestfs and runs the tests but doesn't have oUnit installed will be able to run this test, whereas the oUnit-based tests would be skipped. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org
You asked me to reply to some other points (copied from https://www.redhat.com/archives/libguestfs/2017-July/msg00189.html):
Sure. OTOH, we already do use oUnit2, so these reasonings were already discussed in the past, and (considered we have tests based on oUnit2) deemed not a problem.
I don't think that every past decision should be unchangable.
What I still don't understand is why adding a new test based on oUnit2 would be a problem, while the rest of the tests are fine as they are.
I think we should remove oUnit tests and replace them with asserts. But it's not of such critical importance that we need to do that right now, or even soon. However adding more oUnit tests means adding more tests which can't be run unless you have oUnit installed.
If packagers don't have it and they run the tests then the oUnit2 tests are skipped (see ‘if HAVE_OCAML_PKG_OUNIT’ in the makefiles).
Packagers rarely run our unit tests, since they make the build times much longer, even on fast builders. (Not to mention that sometimes they use VMs, and thus this adds more issues to that.) Even in Fedora the general test suite is disabled, only `make quickcheck` is run. This means it is mostly us developers (or CI) building and testing the full test suite.
[Although it's incidental to this, I should say that in Fedora the full test suite is enabled, it's just run in two different places (not Koji because of the complexity and time involved running it in Koji). ‘make check-release’ is run when the tarball is built, and ‘make installcheck’ is run manually by me after the package has been built.]
Regarding the availability: oUnit2 is available in the latest stable versions of all the major distros, even in older versions.
A simpler test framework which didn't use an external dependency wouldn't be skipped.
Surely I'm not an expert OCaml hacker, but at least to me oUnit2 does not seem that complex, and a manually written framework would end up reimplementing most of it, in the end.
If you compare an oUnit test: https://github.com/libguestfs/libguestfs/blob/master/common/mlutils/c_utils_... to an assert test: https://github.com/libguestfs/libguestfs/blob/master/daemon/daemon_utils_tes... There is barely any difference to me. This is my point really: oUnit doesn't bring any particular benefit. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://people.redhat.com/~rjones/virt-df/
On Friday, 4 August 2017 10:01:28 CEST Richard W.M. Jones wrote:
You asked me to reply to some other points (copied from https://www.redhat.com/archives/libguestfs/2017-July/msg00189.html):
Sure. OTOH, we already do use oUnit2, so these reasonings were already discussed in the past, and (considered we have tests based on oUnit2) deemed not a problem.
I don't think that every past decision should be unchangable.
I agree, but there should be reasons to switch back, since we already invested into this.
What I still don't understand is why adding a new test based on oUnit2 would be a problem, while the rest of the tests are fine as they are.
I think we should remove oUnit tests and replace them with asserts.
And I strongly beg to disagree here. Also, I don't understand why this idea is brought to the table at this point, after I reply (to the limit of annoyingly poking) to get more information about it. When I proposed using oUnit I asked about it, it was deemed good, and then implemented. I don't see why reversing it should be done in a subtle way like this.
But it's not of such critical importance that we need to do that right now, or even soon. However adding more oUnit tests means adding more tests which can't be run unless you have oUnit installed.
As I already wrote, the availability of oUnit is not a problem at all, and neither is its weight.
If packagers don't have it and they run the tests then the oUnit2 tests are skipped (see ‘if HAVE_OCAML_PKG_OUNIT’ in the makefiles).
Packagers rarely run our unit tests, since they make the build times much longer, even on fast builders. (Not to mention that sometimes they use VMs, and thus this adds more issues to that.) Even in Fedora the general test suite is disabled, only `make quickcheck` is run. This means it is mostly us developers (or CI) building and testing the full test suite.
[Although it's incidental to this, I should say that in Fedora the full test suite is enabled, it's just run in two different places (not Koji because of the complexity and time involved running it in Koji).
OK, but still Fedora falls into the "has oUnit" category, and it's even maintained by you.
‘make check-release’ is run when the tarball is built, and ‘make installcheck’ is run manually by me after the package has been built.]
Both operations are run by whoever does the release, which is you (using Fedora, and thus with oUnit available).
Regarding the availability: oUnit2 is available in the latest stable versions of all the major distros, even in older versions.
A simpler test framework which didn't use an external dependency wouldn't be skipped.
Surely I'm not an expert OCaml hacker, but at least to me oUnit2 does not seem that complex, and a manually written framework would end up reimplementing most of it, in the end.
If you compare an oUnit test:
https://github.com/libguestfs/libguestfs/blob/master/common/mlutils/c_utils_...
to an assert test:
https://github.com/libguestfs/libguestfs/blob/master/daemon/daemon_utils_tes...
There is barely any difference to me. This is my point really: oUnit doesn't bring any particular benefit.
Just few points that come into my mind: - better reporting for expected/got values - better interaction for exceptions (e.g. expect/don't expect one) - logging - possibility to run stuff in subprocesses (which we don't use, although I used it on something private) - possibility to run only some of the tests, which greatly helps debugging the failure of one All those thigs at least help _me_ when debugging tests, and as such they provide value to me. Sure, all the above things can be done manually; what would be the gain though, other basically rewriting oUnit? -- Pino Toscano
On Fri, Aug 04, 2017 at 10:21:36AM +0200, Pino Toscano wrote:
Just few points that come into my mind: - better reporting for expected/got values - better interaction for exceptions (e.g. expect/don't expect one) - logging - possibility to run stuff in subprocesses (which we don't use, although I used it on something private) - possibility to run only some of the tests, which greatly helps debugging the failure of one
All those thigs at least help _me_ when debugging tests, and as such they provide value to me.
Sure, all the above things can be done manually; what would be the gain though, other basically rewriting oUnit?
Do you want to submit a patch to convert the assert tests to oUnit then? I'll ACK it (assuming it's correct). Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org
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
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
participants (4)
-
Pino Toscano -
Richard Jones -
Richard W.M. Jones -
Xiang Hua Chen