1
0
forked from drath/libratbag

ratbagd: Add an APIVersion property to make version checks easier

While the DBus API is still in flux, things can break at any time.

Keeping piper and libratbag in version-step works terribly, doubly so where
piper is flatpaked but ratbagd comes from some repo somewhere. We can't check
at build-time, we can't run ratbagd --version at runtime.

so let's add a version field for now and drop it if we ever get to stable.
Meanwhile, ratbagd.py will throw an exception if the expected version doesn't
match exactly.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer
2019-07-29 06:58:41 +10:00
parent d458305f93
commit b4009669b9
6 changed files with 57 additions and 8 deletions

View File

@@ -80,6 +80,19 @@ org.freedesktop.ratbag1.Manager
The **org.freedesktop.ratbag1.Manager** interface is the entry point to
interact with ratbagd.
.. attribute:: APIVersion
:type: i
:flags: read-only,constant
The DBus API version. This is a stopgap feature while the DBus API
is still in flux. The version has no backwards or
forward-compatibilty guarantees - your client must understand
**exactly** the same version, it is not enough to support an older
or a newer version.
This API will be removed once the DBus API is declared stable.
.. attribute:: Devices
:type: ao

View File

@@ -4,6 +4,12 @@ project('libratbag', 'c',
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
meson_version : '>= 0.40.0')
# The DBus API version. Increase this every time the DBus API changes.
# No backwards/forwards guarantee, clients are expected to understand
# whatever ratbagd speaks or bail out. This should be removed if we ever
# finish the API and declare it stable.
ratbagd_api_version = 1
# We use libtool-version numbers because it's easier to understand.
# Before making a release, the libratbag_so_* and liblur_so_*
# numbers should be modified. The components are of the form C:R:A.
@@ -35,6 +41,7 @@ add_project_arguments(cflags, language: 'c')
config_h = configuration_data()
config_h.set('_GNU_SOURCE', '1')
config_h.set_quoted('RATBAG_VERSION', meson.project_version())
config_h.set('RATBAGD_API_VERSION', ratbagd_api_version)
libratbag_data_dir = join_paths(get_option('prefix'),
get_option('datadir'),
'libratbag')
@@ -520,15 +527,22 @@ else
py3 = pymod.find_installation()
endif
config_ratbagctl = configuration_data()
config_ratbagctl.set('RATBAGD_API_VERSION', ratbagd_api_version)
config_ratbagctl.set('version', meson.project_version())
ratbagctl_in = configure_file(input : 'tools/ratbagctl.in.in',
output : 'ratbagctl.in',
configuration: config_ratbagctl)
# ratbagctl is the commandline tool to interact with ratbagd over DBus.
custom_target('ratbagctl',
output : 'ratbagctl',
input : ['tools/ratbagctl.in', 'tools/ratbagd.py'],
input : [ratbagctl_in, 'tools/ratbagd.py'],
build_by_default : true,
command : [py3, join_paths(meson.source_root(), 'tools', 'merge_ratbagd.py'),
'@INPUT@',
'--output', '@OUTPUT@',
'--version', meson.project_version()],
'--output', '@OUTPUT@'],
install: true,
install_dir: get_option('bindir'))
@@ -543,6 +557,7 @@ man_ratbagctl = configure_file (
config_ratbagctl_devel = configuration_data()
config_ratbagctl_devel.set('MESON_BUILD_ROOT', meson.build_root())
config_ratbagctl_devel.set('LIBRATBAG_DATA_DIR', libratbag_data_dir_devel)
config_ratbagctl_devel.set('RATBAGD_API_VERSION', ratbagd_api_version)
configure_file(input : 'tools/toolbox.py',
output : 'toolbox.py',
@@ -610,12 +625,11 @@ ratbagc_py = configure_file(input: 'tools/ratbagc.py.in',
# development tool for protocol debugging etc.
custom_target('ratbag-command',
output : 'ratbag-command',
input : ['tools/ratbagctl.in', ratbagc_py],
input : [ratbagctl_in, ratbagc_py],
build_by_default : true,
command : [py3, join_paths(meson.source_root(), 'tools', 'merge_ratbagd.py'),
'@INPUT@',
'--output', '@OUTPUT@',
'--version', meson.project_version()],
'--output', '@OUTPUT@'],
install: false)
#### output files ####

View File

@@ -166,6 +166,7 @@ static int ratbagd_get_devices(sd_bus *bus,
static const sd_bus_vtable ratbagd_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("APIVersion", "i", 0, offsetof(struct ratbagd, api_version), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Devices", "ao", ratbagd_get_devices, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
#ifdef RATBAG_DEVELOPER_EDITION
SD_BUS_METHOD("LoadTestDevice", "s", "i", ratbagd_load_test_device, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -345,6 +346,7 @@ static int ratbagd_new(struct ratbagd **out)
int r;
ctx = zalloc(sizeof(*ctx));
ctx->api_version = RATBAGD_API_VERSION;
r = sd_event_default(&ctx->event);
if (r < 0)

View File

@@ -218,6 +218,8 @@ struct ratbagd_device *ratbagd_device_next(struct ratbagd_device *device);
*/
struct ratbagd {
int api_version;
sd_event *event;
struct ratbag *lib_ctx;
struct udev_monitor *monitor;

View File

@@ -1465,7 +1465,7 @@ def on_device_added(ratbagd, device):
def open_ratbagd(ratbagd_process=None, verbose=0):
try:
r = Ratbagd()
r = Ratbagd(@RATBAGD_API_VERSION@)
r.verbose = verbose
try:
r.connect('device-added', on_device_added)

View File

@@ -62,6 +62,18 @@ class RatbagErrorCode(IntEnum):
IMPLEMENTATION = -1004
class RatbagdIncompatible(Exception):
"""ratbagd is incompatible with this client"""
def __init__(self, ratbagd_version, required_version):
super().__init__()
self.ratbagd_version = ratbagd_version
self.required_version = required_version
self.message = "ratbagd API version is {} but we require {}".format(ratbagd_version, required_version)
def __str__(self):
return self.message
class RatbagdUnavailable(Exception):
"""Signals DBus is unavailable or the ratbagd daemon is not available."""
pass
@@ -238,11 +250,13 @@ class Ratbagd(_RatbagdDBus):
(GObject.SignalFlags.RUN_FIRST, None, ()),
}
def __init__(self):
def __init__(self, api_version):
super().__init__("Manager", None)
result = self._get_dbus_property("Devices") or []
self._devices = [RatbagdDevice(objpath) for objpath in result]
self._proxy.connect("notify::g-name-owner", self._on_name_owner_changed)
if self.api_version != api_version:
raise RatbagdIncompatible(self.api_version or -1, api_version)
def _on_name_owner_changed(self, *kwargs):
self.emit("daemon-disappeared")
@@ -261,6 +275,10 @@ class Ratbagd(_RatbagdDBus):
self.emit("device-removed", device)
self.notify("devices")
@GObject.Property
def api_version(self):
return self._get_dbus_property("APIVersion")
@GObject.Property
def devices(self):
"""A list of RatbagdDevice objects supported by ratbagd."""