[libvirt] [PATCH] qemu: Stop recursive detection of image chains when an image is missing
by Peter Krempa
Commit e0c469e58b93f852a72265919703cb6abd3779f8 that fixes the detection
of image chain wasn't complete. Iteration through the backing image
chain has to stop at the last existing image if some of the images are
missing otherwise the backing chain that is cached contains entries with
paths being set to NULL resulting to:
error: Unable to allow access for disk path (null): Bad address
Fortunately stat() is kind enough not to crash when it's presented with
a NULL argument.
---
src/util/storage_file.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
index 2249212..e7cbea7 100644
--- a/src/util/storage_file.c
+++ b/src/util/storage_file.c
@@ -729,6 +729,8 @@ virStorageFileGetMetadataFromBuf(int format,
if (meta->backingStore == NULL) {
/* the backing file is (currently) unavailable, treat this
* file as standalone */
+ VIR_FREE(meta->backingStoreRaw);
+ meta->backingStoreIsFile = false;
backingFormat = VIR_STORAGE_FILE_NONE;
}
}
--
1.8.0
12 years
[libvirt] [PATCH v2] Correct include-password option and rewrite domdisplay
by Martin Kletzander
The 'virsh domdisplay' command is able to display the password
configured for spice, but it was missing for vnc type graphics.
Also, there were some inconsistencies that are cleaned now.
---
tools/virsh-domain.c | 74 +++++++++++++++++++++++++++++-----------------------
1 file changed, 42 insertions(+), 32 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index cc47383..cc5c830 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -7038,8 +7038,11 @@ cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
/* Attempt to grab our display info */
for (iter = 0; scheme[iter] != NULL; iter++) {
/* Create our XPATH lookup for the current display's port */
- virAsprintf(&xpath, "string(/domain/devices/graphics[@type='%s']"
- "/@port)", scheme[iter]);
+ virAsprintf(&xpath,
+ "string(/domain/devices/graphics[@type='%s']"
+ "/@port)",
+ scheme[iter]);
+
if (!xpath) {
virReportOOMError();
goto cleanup;
@@ -7056,8 +7059,10 @@ cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
continue;
/* Create our XPATH lookup for the current display's address */
- virAsprintf(&xpath, "string(/domain/devices/graphics[@type='%s']"
- "/@listen)", scheme[iter]);
+ virAsprintf(&xpath,
+ "string(/domain/devices/graphics[@type='%s']"
+ "/@listen)",
+ scheme[iter]);
if (!xpath) {
virReportOOMError();
goto cleanup;
@@ -7069,14 +7074,36 @@ cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
listen_addr = virXPathString(xpath, ctxt);
VIR_FREE(xpath);
+ /* We can query this info for all the graphics types since we'll
+ * get nothing for the unsupported ones (just rdp for now) */
+ if (vshCommandOptBool(cmd, "include-password")) {
+ /* Create our XPATH lookup for the password */
+ virAsprintf(&xpath,
+ "string(/domain/devices/graphics"
+ "[@type='%s']/@passwd)",
+ scheme[iter]);
+
+ if (!xpath) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Attempt to get the password */
+ passwd = virXPathString(xpath, ctxt);
+ VIR_FREE(xpath);
+ }
+
/* Per scheme data mangling */
if (STREQ(scheme[iter], "vnc")) {
- /* VNC protocol handlers take their port number as 'port' - 5900 */
+ /* VNC protocol handlers take their port number as
+ * 'port' - 5900 */
port -= 5900;
} else if (STREQ(scheme[iter], "spice")) {
/* Create our XPATH lookup for the SPICE TLS Port */
- virAsprintf(&xpath, "string(/domain/devices/graphics[@type='%s']"
- "/@tlsPort)", scheme[iter]);
+ virAsprintf(&xpath,
+ "string(/domain/devices/graphics[@type='%s']"
+ "/@tlsPort)",
+ scheme[iter]);
if (!xpath) {
virReportOOMError();
goto cleanup;
@@ -7087,25 +7114,17 @@ cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
VIR_FREE(xpath);
if (tmp)
tls_port = 0;
-
- if (vshCommandOptBool(cmd, "include-password")) {
- /* Create our XPATH lookup for the SPICE password */
- virAsprintf(&xpath, "string(/domain/devices/graphics"
- "[@type='%s']/@passwd)", scheme[iter]);
- if (!xpath) {
- virReportOOMError();
- goto cleanup;
- }
-
- /* Attempt to get the SPICE password */
- passwd = virXPathString(xpath, ctxt);
- VIR_FREE(xpath);
- }
}
/* Build up the full URI, starting with the scheme */
virBufferAsprintf(&buf, "%s://", scheme[iter]);
+ /* There is no user, so just append password if there's any */
+ if (passwd) {
+ virBufferAsprintf(&buf, ":%s@", passwd);
+ VIR_FREE(passwd);
+ }
+
/* Then host name or IP */
if (!listen_addr || STREQ((const char *)listen_addr, "0.0.0.0"))
virBufferAddLit(&buf, "localhost");
@@ -7115,20 +7134,11 @@ cmdDomDisplay(vshControl *ctl, const vshCmd *cmd)
VIR_FREE(listen_addr);
/* Add the port */
- if (STREQ(scheme[iter], "spice"))
- virBufferAsprintf(&buf, "?port=%d", port);
- else
- virBufferAsprintf(&buf, ":%d", port);
+ virBufferAsprintf(&buf, ":%d", port);
/* TLS Port */
if (tls_port)
- virBufferAsprintf(&buf, "&tls-port=%d", tls_port);
-
- /* Password */
- if (passwd) {
- virBufferAsprintf(&buf, "&password=%s", passwd);
- VIR_FREE(passwd);
- }
+ virBufferAsprintf(&buf, "?tls-port=%d", tls_port);
/* Ensure we can print our URI */
if (virBufferError(&buf)) {
--
1.8.0
12 years
[libvirt] [PATCH] virsh: Report error when taking a snapshot with empty --memspec argument
by Peter Krempa
When the value of memspec was empty taking of a snapshot failed without
reporting an error.
---
This is only a quick fix. I think we should improve vshCommandOptStr to detect
this for us and report an appropriate error, but this change will require
a lot of changes not relevant to this problem.
---
tools/virsh-snapshot.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c
index 398730c..057ae2d 100644
--- a/tools/virsh-snapshot.c
+++ b/tools/virsh-snapshot.c
@@ -358,7 +358,12 @@ cmdSnapshotCreateAs(vshControl *ctl, const vshCmd *cmd)
if (desc)
virBufferEscapeString(&buf, " <description>%s</description>\n", desc);
- if (vshCommandOptString(cmd, "memspec", &memspec) < 0 ||
+ if (vshCommandOptString(cmd, "memspec", &memspec) < 0) {
+ vshError(ctl, _("memspec argument must not be empty"));
+ goto cleanup;
+ }
+
+ if (memspec &&
vshParseSnapshotMemspec(ctl, &buf, memspec) < 0) {
virBufferFreeAndReset(&buf);
goto cleanup;
--
1.8.0
12 years
[libvirt] [PATCH] Add device operations for lxc v1
by Heiher
Hello,
Operations:
1. lxcDomainAttachDevice
2. lxcDomainAttachDeviceFlags
3. lxcDomainDetachDevice
4. lxcDomainDetachDeviceFlags
5. lxcDomainUpdateDeviceFlags
In live mode, set devices.allow/deny to instance's cgroup and insert
disk config into current domain.
In config mode, just insert disk config into current domain.
--
Best regards!
Heiher
https://heiher.info
12 years
[libvirt] [libvirt-glib v2] gobject: Also delete storage volume from its pool's list
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
Without this patch, storage pool still lists the volume even after it is
deleted.
Related Boxes bug: https://bugzilla.gnome.org/show_bug.cgi?id=688724
---
.../libvirt-gobject-storage-pool-private.h | 33 ++++++++++++++++++++++
libvirt-gobject/libvirt-gobject-storage-pool.c | 20 +++++++++++++
libvirt-gobject/libvirt-gobject-storage-vol.c | 3 ++
3 files changed, 56 insertions(+)
create mode 100644 libvirt-gobject/libvirt-gobject-storage-pool-private.h
diff --git a/libvirt-gobject/libvirt-gobject-storage-pool-private.h b/libvirt-gobject/libvirt-gobject-storage-pool-private.h
new file mode 100644
index 0000000..5492e5b
--- /dev/null
+++ b/libvirt-gobject/libvirt-gobject-storage-pool-private.h
@@ -0,0 +1,33 @@
+/*
+ * libvirt-gobject-storage-pool-private.h: libvirt gobject integration
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak(a)gnome.org>
+ */
+
+#ifndef __LIBVIRT_GOBJECT_STORAGE_POOL_PRIVATE_H__
+#define __LIBVIRT_GOBJECT_STORAGE_POOL_PRIVATE_H__
+
+G_BEGIN_DECLS
+
+G_GNUC_INTERNAL void gvir_storage_pool_delete_vol(GVirStoragePool *pool,
+ GVirStorageVol *volume);
+
+G_END_DECLS
+
+#endif /* __LIBVIRT_GOBJECT_STORAGE_POOL_PRIVATE_H__ */
diff --git a/libvirt-gobject/libvirt-gobject-storage-pool.c b/libvirt-gobject/libvirt-gobject-storage-pool.c
index 8f579a1..107efa6 100644
--- a/libvirt-gobject/libvirt-gobject-storage-pool.c
+++ b/libvirt-gobject/libvirt-gobject-storage-pool.c
@@ -29,6 +29,7 @@
#include "libvirt-glib/libvirt-glib.h"
#include "libvirt-gobject/libvirt-gobject.h"
#include "libvirt-gobject-compat.h"
+#include "libvirt-gobject-storage-pool-private.h"
#define GVIR_STORAGE_POOL_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_TYPE_STORAGE_POOL, GVirStoragePoolPrivate))
@@ -1129,3 +1130,22 @@ gboolean gvir_storage_pool_delete_finish(GVirStoragePool *pool,
return TRUE;
}
+
+G_GNUC_INTERNAL void gvir_storage_pool_delete_vol(GVirStoragePool *pool,
+ GVirStorageVol *volume)
+{
+ GVirStoragePoolPrivate *priv;
+
+ g_return_if_fail(GVIR_IS_STORAGE_POOL(pool));
+ g_return_if_fail(GVIR_IS_STORAGE_VOL(volume));
+
+ priv = pool->priv;
+ g_mutex_lock(priv->lock);
+ if (priv->volumes != NULL) {
+ const gchar *name = gvir_storage_vol_get_name(volume);
+ g_hash_table_remove(priv->volumes, name);
+ } else {
+ g_warn_if_reached();
+ }
+ g_mutex_unlock(priv->lock);
+}
diff --git a/libvirt-gobject/libvirt-gobject-storage-vol.c b/libvirt-gobject/libvirt-gobject-storage-vol.c
index c7ebb45..3a08450 100644
--- a/libvirt-gobject/libvirt-gobject-storage-vol.c
+++ b/libvirt-gobject/libvirt-gobject-storage-vol.c
@@ -29,6 +29,7 @@
#include "libvirt-glib/libvirt-glib.h"
#include "libvirt-gobject/libvirt-gobject.h"
#include "libvirt-gobject-compat.h"
+#include "libvirt-gobject-storage-pool-private.h"
#define GVIR_STORAGE_VOL_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_TYPE_STORAGE_VOL, GVirStorageVolPrivate))
@@ -309,6 +310,8 @@ gboolean gvir_storage_vol_delete(GVirStorageVol *vol,
g_return_val_if_fail(GVIR_IS_STORAGE_VOL(vol), FALSE);
g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
+ gvir_storage_pool_delete_vol(vol->priv->pool, vol);
+
if (virStorageVolDelete(vol->priv->handle, flags) < 0) {
gvir_set_error_literal(err,
GVIR_STORAGE_VOL_ERROR,
--
1.8.0
12 years
[libvirt] [PATCH v4 0/3] Qemu/Gluster support in Libvirt
by Harsh Prateek Bora
Changelog:
v4:
- Addressed review comment by Jiri on v3 updated series.
v3 updated:
- Fix other network backends (nbd, rbd, sheepdog) to initialize new members
(transport, socket) of _virDomainDiskHostDef appropriately so that garbage
values doesnt break the argv2xml tests.
v3:
- RNG schema updated as required for unix transport [Paolo]
- introduced another new attribute 'socket' for unix transport [Paolo]
- Uses virURIFormat and virURIParse for URI parsing. [danpb]
- updated documentation as required. [Jirka]
v2:
- Addressed review comments by Jiri
- Updated patcheset as per new URI spec
Ref: http://lists.gnu.org/archive/html/qemu-devel/2012-09/msg05199.html
v1:
- Initial prototype
Harsh Prateek Bora (3):
Add Gluster protocol as supported network disk backend
qemu: Add support for gluster protocol based network storage backend.
tests: Add tests for gluster protocol based network disks support
docs/formatdomain.html.in | 24 ++-
docs/schemas/domaincommon.rng | 33 +++-
src/conf/domain_conf.c | 77 ++++++--
src/conf/domain_conf.h | 12 ++
src/libvirt_private.syms | 2 +
src/qemu/qemu_command.c | 198 ++++++++++++++++++++-
tests/qemuargv2xmltest.c | 1 +
.../qemuxml2argv-disk-drive-network-gluster.args | 1 +
.../qemuxml2argv-disk-drive-network-gluster.xml | 34 ++++
tests/qemuxml2argvtest.c | 2 +
10 files changed, 355 insertions(+), 29 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-gluster.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-gluster.xml
--
1.7.11.7
12 years
[libvirt] [PATCH v1 1/2] change qemu_driver's qemuImgBinary field
by liguang
qemuImgBinary is a poor name, change to qemuImgTool,
and init it at qemu driver start-up phase, before this
change, if we need qemu-img or kvm-img we have to call
qemuFindQemuImgBinary every time, seems a little boring,
from then on, we can use qemuImgTool directly,
e.g.
use virCommandRun(driver->qemuImgTool, ...)
instead of
img_tool = qemuFindQemuImgBinary(driver);
qemuFindQemuImgBinary(img_tool, ...);
Signed-off-by: liguang <lig.fnst(a)cn.fujitsu.com>
---
src/qemu/qemu_conf.h | 2 +-
src/qemu/qemu_domain.c | 22 ++--------------------
src/qemu/qemu_domain.h | 2 --
src/qemu/qemu_driver.c | 12 ++++++++++--
4 files changed, 13 insertions(+), 25 deletions(-)
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 2c7f70c..47f349c 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -84,7 +84,7 @@ struct qemud_driver {
char *cacheDir;
char *saveDir;
char *snapshotDir;
- char *qemuImgBinary;
+ char *qemuImgTool;
unsigned int vncAutoUnixSocket : 1;
unsigned int vncTLS : 1;
unsigned int vncTLSx509verify : 1;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index e0d6951..97e4fa1 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1588,22 +1588,6 @@ cleanup:
return ret;
}
-/* Locate an appropriate 'qemu-img' binary. */
-const char *
-qemuFindQemuImgBinary(struct qemud_driver *driver)
-{
- if (!driver->qemuImgBinary) {
- driver->qemuImgBinary = virFindFileInPath("kvm-img");
- if (!driver->qemuImgBinary)
- driver->qemuImgBinary = virFindFileInPath("qemu-img");
- if (!driver->qemuImgBinary)
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("unable to find kvm-img or qemu-img"));
- }
-
- return driver->qemuImgBinary;
-}
-
int
qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm,
virDomainSnapshotObjPtr snapshot,
@@ -1659,11 +1643,9 @@ qemuDomainSnapshotForEachQcow2Raw(struct qemud_driver *driver,
int i;
bool skipped = false;
- qemuimgarg[0] = qemuFindQemuImgBinary(driver);
- if (qemuimgarg[0] == NULL) {
- /* qemuFindQemuImgBinary set the error */
+ qemuimgarg[0] = driver->qemuImgTool;
+ if (qemuimgarg[0] == NULL)
return -1;
- }
qemuimgarg[2] = op;
qemuimgarg[3] = name;
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index a2acc0a..548cd20 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -300,8 +300,6 @@ int qemuDomainAppendLog(struct qemud_driver *driver,
int logFD,
const char *fmt, ...) ATTRIBUTE_FMT_PRINTF(4, 5);
-const char *qemuFindQemuImgBinary(struct qemud_driver *driver);
-
int qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm,
virDomainSnapshotObjPtr snapshot,
char *snapshotDir);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 436e853..e87e7b4 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -643,6 +643,14 @@ qemudStartup(int privileged) {
if (!qemu_driver->domainEventState)
goto error;
+ /* find kvm-img or qemu-img */
+ qemu_driver->qemuImgTool = virFindFileInPath("kvm-img");
+ if (!qemu_driver->qemuImgTool)
+ qemu_driver->qemuImgTool = virFindFileInPath("qemu-img");
+ if (!qemu_driver->qemuImgTool)
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("unable to find kvm-img or qemu-img"));
+
/* read the host sysinfo */
if (privileged)
qemu_driver->hostsysinfo = virSysinfoRead();
@@ -1029,7 +1037,7 @@ qemudShutdown(void) {
VIR_FREE(qemu_driver->cacheDir);
VIR_FREE(qemu_driver->saveDir);
VIR_FREE(qemu_driver->snapshotDir);
- VIR_FREE(qemu_driver->qemuImgBinary);
+ VIR_FREE(qemu_driver->qemuImgTool);
VIR_FREE(qemu_driver->autoDumpPath);
VIR_FREE(qemu_driver->vncTLSx509certdir);
VIR_FREE(qemu_driver->vncListen);
@@ -10706,7 +10714,7 @@ qemuDomainSnapshotCreateInactiveExternal(struct qemud_driver *driver,
int ret = -1;
- if (!(qemuImgPath = qemuFindQemuImgBinary(driver)))
+ if (!(qemuImgPath = driver->qemuImgTool))
return -1;
if (!(created = virBitmapNew(snap->def->ndisks))) {
--
1.7.1
12 years
[libvirt] [PATCH] storage: Improve virStorageBackendFileSystemStop
by Osier Yang
It's actually not used for DIR pool. So removing the checking.
---
src/storage/storage_backend_fs.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 3322677..10daee3 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -933,7 +933,7 @@ no_memory:
* @conn connection to report errors against
* @pool storage pool to start
*
- * Stops a directory or FS based storage pool.
+ * Stops a FS based storage pool.
*
* - If it is a FS based pool, unmounts the unlying source device on the pool
* - Releases all cached data about volumes
@@ -943,8 +943,7 @@ static int
virStorageBackendFileSystemStop(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool)
{
- if (pool->def->type != VIR_STORAGE_POOL_DIR &&
- virStorageBackendFileSystemUnmount(pool) < 0)
+ if (virStorageBackendFileSystemUnmount(pool) < 0)
return -1;
return 0;
--
1.7.7.6
12 years
[libvirt] [PATCH] storage: Fix bug of fs pool destroying
by Osier Yang
Regression introduced by commit 258e06c85b7, "ret" could be set to 1
or 0 by virStorageBackendFileSystemIsMounted before goto cleanup.
This could mislead the callers (up to the public API
virStoragePoolDestroy) to return success even the underlying umount
command fails.
---
src/storage/storage_backend_fs.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 10daee3..cbcbe34 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -449,6 +449,7 @@ static int
virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
virCommandPtr cmd = NULL;
int ret = -1;
+ int rc;
if (pool->def->type == VIR_STORAGE_POOL_NETFS) {
if (pool->def->source.nhost != 1) {
@@ -475,8 +476,8 @@ virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
}
/* Short-circuit if already unmounted */
- if ((ret = virStorageBackendFileSystemIsMounted(pool)) != 1) {
- if (ret < 0)
+ if ((rc = virStorageBackendFileSystemIsMounted(pool)) != 1) {
+ if (rc < 0)
return -1;
else
return 0;
--
1.7.7.6
12 years
[libvirt] [PATCH] run bootstrap if .gnulib is not present
by Hu Tao
If .gnulib is deleted unexpectedly, autogen.sh will fail with message:
fatal: ambiguous argument '.gnulib': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
which is actually given by git diff .gnulib, which doesn't exist.
In the case to run bootstrap to create .gnulib.
---
autogen.sh | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/autogen.sh b/autogen.sh
index d183397..07c58a1 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -62,7 +62,9 @@ bootstrap_hash()
# Only run bootstrap from a git checkout, never from a tarball.
if test -d .git; then
curr_status=.git-module-status
- t=$(bootstrap_hash; git diff .gnulib)
+ if test -d .gnulib; then
+ t=$(bootstrap_hash; git diff .gnulib)
+ fi
case $t:${CLEAN_SUBMODULE+set} in
*:set) ;;
*-dirty*)
--
1.7.11.7
12 years