]> git.sur5r.net Git - i3/i3/commitdiff
ipc: implement GET_VERSION to find out the i3 version
authorMichael Stapelberg <michael@stapelberg.de>
Sun, 5 Aug 2012 12:29:19 +0000 (14:29 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Sun, 5 Aug 2012 12:30:05 +0000 (14:30 +0200)
This is useful for third-party scripts which require certain features
and want to error out cleanly when they are run with an old i3 version.

Additionally, i3 --version might be different from what’s actually
running (an old version of the binary), so i3-msg -t get_version will be
the best way to figure out the i3 version you are actually running from
this commit on.

common.mk
docs/ipc
i3-msg/main.c
include/i3/ipc.h
man/i3-msg.man
src/ipc.c
testcases/t/193-ipc-version.t [new file with mode: 0644]

index f202166df5b1f20b576a23fcbc3fd8ce1577ab12..21e10257e9a86ddbe89da22b20a936063087e7b9 100644 (file)
--- a/common.mk
+++ b/common.mk
@@ -23,6 +23,12 @@ else
 VERSION := ${I3_VERSION}
 endif
 
+MAJOR_VERSION := $(shell echo ${VERSION} | cut -d '.' -f 1)
+MINOR_VERSION := $(shell echo ${VERSION} | cut -d '.' -f 2)
+PATCH_VERSION := $(shell echo ${VERSION} | cut -d '.' -f 3)
+ifeq (${PATCH_VERSION},)
+PATCH_VERSION := 0
+endif
 
 ## Generic flags
 
@@ -46,6 +52,9 @@ I3_CFLAGS += -Wunused-value
 I3_CFLAGS += -Iinclude
 
 I3_CPPFLAGS  = -DI3_VERSION=\"${I3_VERSION}\"
+I3_CPPFLAGS += -DMAJOR_VERSION=${MAJOR_VERSION}
+I3_CPPFLAGS += -DMINOR_VERSION=${MINOR_VERSION}
+I3_CPPFLAGS += -DPATCH_VERSION=${PATCH_VERSION}
 I3_CPPFLAGS += -DSYSCONFDIR=\"${SYSCONFDIR}\"
 
 
index 525e9968421e3fd83071939e228e233cd66d3a7c..508e789cd31855715bdbc5f3ebe8f13b44e105a4 100644 (file)
--- a/docs/ipc
+++ b/docs/ipc
@@ -70,6 +70,9 @@ GET_BAR_CONFIG (6)::
        Gets the configuration (as JSON map) of the workspace bar with the
        given ID. If no ID is provided, an array with all configured bar IDs is
        returned instead.
+GET_VERSION (7)::
+       Gets the version of i3. The reply will be a JSON-encoded dictionary
+       with the major, minor, patch and human-readable version.
 
 So, a typical message could look like this:
 --------------------------------------------------
@@ -125,6 +128,8 @@ MARKS (5)::
        Reply to the GET_MARKS message.
 BAR_CONFIG (6)::
        Reply to the GET_BAR_CONFIG message.
+VERSION (7)::
+       Reply to the GET_VERSION message.
 
 === COMMAND reply
 
@@ -534,6 +539,35 @@ urgent_workspace_text/urgent_workspace_bar::
 }
 --------------
 
+=== Version reply
+
+The reply consists of a single JSON dictionary with the following keys:
+
+major (integer)::
+       The major version of i3, such as +4+.
+minor (integer)::
+       The minor version of i3, such as +2+. Changes in the IPC interface (new
+       features) will only occur with new minor (or major) releases. However,
+       bugfixes might be introduced in patch releases, too.
+patch (integer)::
+       The patch version of i3, such as +1+ (when the complete version is
+       +4.2.1+).
+human_readable (string)::
+       A human-readable version of i3 containing the precise git version,
+       build date and branch name. When you need to display the i3 version to
+       your users, use the human-readable version whenever possible (since
+       this is what +i3 --version+ displays, too).
+
+*Example:*
+-------------------
+{
+   "human_readable" : "4.2-169-gf80b877 (2012-08-05, branch \"next\")",
+   "minor" : 2,
+   "patch" : 0,
+   "major" : 4
+}
+-------------------
+
 == Events
 
 [[events]]
index ccf6e10f276a54ce8d2716b593db7d9895890442..a04e6690e67fa4a177df81dd86cbab5dd87748a4 100644 (file)
@@ -2,7 +2,7 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2010 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
  *
  * i3-msg/main.c: Utility which sends messages to a running i3-instance using
  * IPC via UNIX domain sockets.
@@ -73,9 +73,11 @@ int main(int argc, char *argv[]) {
                 message_type = I3_IPC_MESSAGE_TYPE_GET_MARKS;
             else if (strcasecmp(optarg, "get_bar_config") == 0)
                 message_type = I3_IPC_MESSAGE_TYPE_GET_BAR_CONFIG;
+            else if (strcasecmp(optarg, "get_version") == 0)
+                message_type = I3_IPC_MESSAGE_TYPE_GET_VERSION;
             else {
                 printf("Unknown message type\n");
-                printf("Known types: command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config\n");
+                printf("Known types: command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_version\n");
                 exit(EXIT_FAILURE);
             }
         } else if (o == 'q') {
index bfadf4cf87d086571c96584c54b3c34e49cd6362..0906b7f919bbb98d1e21598557aec29b00b2ad7b 100644 (file)
@@ -2,7 +2,7 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2010 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
  *
  * This public header defines the different constants and message types to use
  * for the IPC interface to i3 (see docs/ipc for more information).
@@ -40,6 +40,9 @@
 /** Request the configuration for a specific 'bar' */
 #define I3_IPC_MESSAGE_TYPE_GET_BAR_CONFIG      6
 
+/** Request the i3 version */
+#define I3_IPC_MESSAGE_TYPE_GET_VERSION         7
+
 /*
  * Messages from i3 to clients
  *
@@ -66,6 +69,9 @@
 /** Bar config reply type */
 #define I3_IPC_REPLY_TYPE_BAR_CONFIG            6
 
+/** i3 version reply type */
+#define I3_IPC_REPLY_TYPE_VERSION               7
+
 /*
  * Events from i3 to clients. Events have the first bit set high.
  *
index 891c6c283dd7ab17fa6db541f5a1007e96865361..6b548d363bb01d5beea1c13835d35b76da429995 100644 (file)
@@ -1,7 +1,7 @@
 i3-msg(1)
 =========
-Michael Stapelberg <michael+i3@stapelberg.de>
-v4.2, January 2012
+Michael Stapelberg <michael@i3wm.org>
+v4.2, August 2012
 
 == NAME
 
@@ -38,6 +38,9 @@ get_bar_config::
 Gets the configuration (as JSON map) of the workspace bar with the given ID. If
 no ID is provided, an array with all configured bar IDs is returned instead.
 
+get_version::
+Gets the version of i3. The reply will be a JSON-encoded dictionary with the
+major, minor, patch and human-readable version.
 
 == DESCRIPTION
 
index 1d19fc6cd7e1134bc321040f5876015ad275bf3a..77b8dbb391101eb50c32a80e8b69d669f7aff7a7 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -536,6 +536,44 @@ IPC_HANDLER(get_marks) {
     y(free);
 }
 
+/*
+ * Returns the version of i3
+ *
+ */
+IPC_HANDLER(get_version) {
+#if YAJL_MAJOR >= 2
+    yajl_gen gen = yajl_gen_alloc(NULL);
+#else
+    yajl_gen gen = yajl_gen_alloc(NULL, NULL);
+#endif
+    y(map_open);
+
+    ystr("major");
+    y(integer, MAJOR_VERSION);
+
+    ystr("minor");
+    y(integer, MINOR_VERSION);
+
+    ystr("patch");
+    y(integer, PATCH_VERSION);
+
+    ystr("human_readable");
+    ystr(I3_VERSION);
+
+    y(map_close);
+
+    const unsigned char *payload;
+#if YAJL_MAJOR >= 2
+    size_t length;
+#else
+    unsigned int length;
+#endif
+    y(get_buf, &payload, &length);
+
+    ipc_send_message(fd, length, I3_IPC_REPLY_TYPE_VERSION, payload);
+    y(free);
+}
+
 /*
  * Formats the reply message for a GET_BAR_CONFIG request and sends it to the
  * client.
@@ -792,7 +830,7 @@ IPC_HANDLER(subscribe) {
 
 /* The index of each callback function corresponds to the numeric
  * value of the message type (see include/i3/ipc.h) */
-handler_t handlers[7] = {
+handler_t handlers[8] = {
     handle_command,
     handle_get_workspaces,
     handle_subscribe,
@@ -800,6 +838,7 @@ handler_t handlers[7] = {
     handle_tree,
     handle_get_marks,
     handle_get_bar_config,
+    handle_get_version,
 };
 
 /*
diff --git a/testcases/t/193-ipc-version.t b/testcases/t/193-ipc-version.t
new file mode 100644 (file)
index 0000000..172dd8f
--- /dev/null
@@ -0,0 +1,23 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+# Verifies that we can get the version number of i3 via IPC.
+use i3test;
+
+my $i3 = i3(get_socket_path());
+$i3->connect->recv;
+# We explicitly send the version message because AnyEvent::I3’s 'version' sugar
+# method has a fallback which tries to parse the version number from i3
+# --version for older versions, and we want to avoid using that.
+my $version = $i3->message(7, "")->recv;
+
+# We need to change this when the major version changes (but we need to touch a
+# lot of changes then anyways).
+is($version->{major}, 4, 'major version is 4');
+
+cmp_ok($version->{minor}, '>', 0, 'minor version > 0');
+
+is(int($version->{minor}), $version->{minor}, 'minor version is an integer');
+is(int($version->{patch}), $version->{patch}, 'patch version is an integer');
+like($version->{human_readable}, qr/branch/, 'human readable version contains branch name');
+
+done_testing;