ipc: implement GET_VERSION to find out the i3 version
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.
This commit is contained in:
parent
f80b877c6b
commit
78f5f2204d
|
@ -23,6 +23,12 @@ else
|
||||||
VERSION := ${I3_VERSION}
|
VERSION := ${I3_VERSION}
|
||||||
endif
|
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
|
## Generic flags
|
||||||
|
|
||||||
|
@ -46,6 +52,9 @@ I3_CFLAGS += -Wunused-value
|
||||||
I3_CFLAGS += -Iinclude
|
I3_CFLAGS += -Iinclude
|
||||||
|
|
||||||
I3_CPPFLAGS = -DI3_VERSION=\"${I3_VERSION}\"
|
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}\"
|
I3_CPPFLAGS += -DSYSCONFDIR=\"${SYSCONFDIR}\"
|
||||||
|
|
||||||
|
|
||||||
|
|
34
docs/ipc
34
docs/ipc
|
@ -70,6 +70,9 @@ GET_BAR_CONFIG (6)::
|
||||||
Gets the configuration (as JSON map) of the workspace bar with the
|
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
|
given ID. If no ID is provided, an array with all configured bar IDs is
|
||||||
returned instead.
|
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:
|
So, a typical message could look like this:
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
@ -125,6 +128,8 @@ MARKS (5)::
|
||||||
Reply to the GET_MARKS message.
|
Reply to the GET_MARKS message.
|
||||||
BAR_CONFIG (6)::
|
BAR_CONFIG (6)::
|
||||||
Reply to the GET_BAR_CONFIG message.
|
Reply to the GET_BAR_CONFIG message.
|
||||||
|
VERSION (7)::
|
||||||
|
Reply to the GET_VERSION message.
|
||||||
|
|
||||||
=== COMMAND reply
|
=== 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
|
||||||
|
|
||||||
[[events]]
|
[[events]]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* vim:ts=4:sw=4:expandtab
|
* vim:ts=4:sw=4:expandtab
|
||||||
*
|
*
|
||||||
* i3 - an improved dynamic tiling window manager
|
* 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
|
* i3-msg/main.c: Utility which sends messages to a running i3-instance using
|
||||||
* IPC via UNIX domain sockets.
|
* IPC via UNIX domain sockets.
|
||||||
|
@ -73,9 +73,11 @@ int main(int argc, char *argv[]) {
|
||||||
message_type = I3_IPC_MESSAGE_TYPE_GET_MARKS;
|
message_type = I3_IPC_MESSAGE_TYPE_GET_MARKS;
|
||||||
else if (strcasecmp(optarg, "get_bar_config") == 0)
|
else if (strcasecmp(optarg, "get_bar_config") == 0)
|
||||||
message_type = I3_IPC_MESSAGE_TYPE_GET_BAR_CONFIG;
|
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 {
|
else {
|
||||||
printf("Unknown message type\n");
|
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);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else if (o == 'q') {
|
} else if (o == 'q') {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* vim:ts=4:sw=4:expandtab
|
* vim:ts=4:sw=4:expandtab
|
||||||
*
|
*
|
||||||
* i3 - an improved dynamic tiling window manager
|
* 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
|
* This public header defines the different constants and message types to use
|
||||||
* for the IPC interface to i3 (see docs/ipc for more information).
|
* for the IPC interface to i3 (see docs/ipc for more information).
|
||||||
|
@ -40,6 +40,9 @@
|
||||||
/** Request the configuration for a specific 'bar' */
|
/** Request the configuration for a specific 'bar' */
|
||||||
#define I3_IPC_MESSAGE_TYPE_GET_BAR_CONFIG 6
|
#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
|
* Messages from i3 to clients
|
||||||
*
|
*
|
||||||
|
@ -66,6 +69,9 @@
|
||||||
/** Bar config reply type */
|
/** Bar config reply type */
|
||||||
#define I3_IPC_REPLY_TYPE_BAR_CONFIG 6
|
#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.
|
* Events from i3 to clients. Events have the first bit set high.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
i3-msg(1)
|
i3-msg(1)
|
||||||
=========
|
=========
|
||||||
Michael Stapelberg <michael+i3@stapelberg.de>
|
Michael Stapelberg <michael@i3wm.org>
|
||||||
v4.2, January 2012
|
v4.2, August 2012
|
||||||
|
|
||||||
== NAME
|
== NAME
|
||||||
|
|
||||||
|
@ -38,6 +38,9 @@ get_bar_config::
|
||||||
Gets the configuration (as JSON map) of the workspace bar with the given ID. If
|
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.
|
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
|
== DESCRIPTION
|
||||||
|
|
||||||
|
|
41
src/ipc.c
41
src/ipc.c
|
@ -536,6 +536,44 @@ IPC_HANDLER(get_marks) {
|
||||||
y(free);
|
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
|
* Formats the reply message for a GET_BAR_CONFIG request and sends it to the
|
||||||
* client.
|
* client.
|
||||||
|
@ -792,7 +830,7 @@ IPC_HANDLER(subscribe) {
|
||||||
|
|
||||||
/* The index of each callback function corresponds to the numeric
|
/* The index of each callback function corresponds to the numeric
|
||||||
* value of the message type (see include/i3/ipc.h) */
|
* value of the message type (see include/i3/ipc.h) */
|
||||||
handler_t handlers[7] = {
|
handler_t handlers[8] = {
|
||||||
handle_command,
|
handle_command,
|
||||||
handle_get_workspaces,
|
handle_get_workspaces,
|
||||||
handle_subscribe,
|
handle_subscribe,
|
||||||
|
@ -800,6 +838,7 @@ handler_t handlers[7] = {
|
||||||
handle_tree,
|
handle_tree,
|
||||||
handle_get_marks,
|
handle_get_marks,
|
||||||
handle_get_bar_config,
|
handle_get_bar_config,
|
||||||
|
handle_get_version,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue