From dee9f17b595ea903a982d31d1124b302bb17e2ff Mon Sep 17 00:00:00 2001 From: root Date: Wed, 17 Jul 2013 00:58:52 -0700 Subject: Wed Jul 17 00:58:51 PDT 2013 --- community/lxsession/PKGBUILD | 33 -- .../lxsession-0.4.6.1-logind-support.patch | 608 --------------------- 2 files changed, 641 deletions(-) delete mode 100644 community/lxsession/PKGBUILD delete mode 100644 community/lxsession/lxsession-0.4.6.1-logind-support.patch (limited to 'community/lxsession') diff --git a/community/lxsession/PKGBUILD b/community/lxsession/PKGBUILD deleted file mode 100644 index 178291ceb..000000000 --- a/community/lxsession/PKGBUILD +++ /dev/null @@ -1,33 +0,0 @@ -# $Id: PKGBUILD 80231 2012-11-18 09:34:03Z bpiotrowski $ -# Maintainer: Bartłomiej Piotrowski -# Contributor: Angel Velasquez -# Contributor: Juergen Hoetzel - -pkgname=lxsession -pkgver=0.4.6.1 -pkgrel=3 -pkgdesc='Lightweight X11 session manager' -arch=('i686' 'x86_64') -url="http://lxde.org/" -license=('GPL2') -groups=('lxde') -depends=('gtk2' 'dbus') -makedepends=('pkgconfig' 'intltool') -replaces=('lxde-settings-daemon' 'lxsession-lite') -conflicts=('lxsession-lite' 'lxde-settings-daemon') -source=(http://downloads.sourceforge.net/lxde/$pkgname-$pkgver.tar.gz - lxsession-0.4.6.1-logind-support.patch) -md5sums=('e456b64c5ab3652a4dec661ec706dc6e' - '7459321f5dc263493837768dcb03f852') - -build() { - cd $srcdir/$pkgname-$pkgver - patch -Np2 -i $srcdir/lxsession-0.4.6.1-logind-support.patch - ./configure --sysconfdir=/etc --prefix=/usr - make -} - -package() { - cd $srcdir/$pkgname-$pkgver - make DESTDIR=$pkgdir install -} diff --git a/community/lxsession/lxsession-0.4.6.1-logind-support.patch b/community/lxsession/lxsession-0.4.6.1-logind-support.patch deleted file mode 100644 index 44829e615..000000000 --- a/community/lxsession/lxsession-0.4.6.1-logind-support.patch +++ /dev/null @@ -1,608 +0,0 @@ ---- src/lxsession-0.4.6.1/lxsession-logout/dbus-interface.c 2011-07-27 21:26:36.000000000 +0200 -+++ src/lxsession-0.4.6.1/lxsession-logout-logind/dbus-interface.c 2012-11-13 17:26:30.807070976 +0100 -@@ -51,13 +51,20 @@ - char * dbus_HAL_Reboot(void); - char * dbus_HAL_Suspend(void); - char * dbus_HAL_Hibernate(void); -+gboolean dbus_logind_CanPowerOff(void); -+gboolean dbus_logind_CanReboot(void); -+gboolean dbus_logind_CanSuspend(void); -+gboolean dbus_logind_CanHibernate(void); -+char * dbus_logind_PowerOff(void); -+char * dbus_logind_Reboot(void); -+char * dbus_logind_Suspend(void); -+char * dbus_logind_Hibernate(void); -+char * dbus_LXDE_Logout(void); - /* End FORWARDS */ - - /* Connect to the system bus. Once a connection is made, it is saved for reuse. */ --static DBusConnection * dbus_connect(void) -+static DBusConnection * dbus_connect_system(void) - { -- if ((dbus_context.connection == NULL) && ( ! dbus_context.connection_tried)) -- { - DBusError error; - dbus_error_init(&error); - dbus_context.connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); -@@ -67,16 +74,57 @@ - dbus_error_free(&error); - } - dbus_context.connection_tried = TRUE; -- } - - return dbus_context.connection; - } - -+static DBusConnection * dbus_connect_session(void) -+{ -+ DBusError error; -+ dbus_error_init(&error); -+ dbus_context.connection = dbus_bus_get(DBUS_BUS_SESSION, &error); -+ if (dbus_context.connection == NULL) -+ { -+ g_warning(G_STRLOC ": Failed to connect to the session message bus: %s", error.message); -+ dbus_error_free(&error); -+ } -+ dbus_context.connection_tried = TRUE; -+ -+ return dbus_context.connection; -+} -+ -+ - /* Send a message. */ --static DBusMessage * dbus_send_message(DBusMessage * message, char * * error_text) -+static DBusMessage * dbus_send_message_system(DBusMessage * message, char * * error_text) - { - /* Get a connection handle. */ -- DBusConnection * connection = dbus_connect(); -+ DBusConnection * connection = dbus_connect_system(); -+ if (connection == NULL) -+ return FALSE; -+ -+ /* Send the message. */ -+ DBusError error; -+ dbus_error_init(&error); -+ DBusMessage * reply = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT, &error); -+ dbus_message_unref(message); -+ if (reply == NULL) -+ { -+ if ((error.name == NULL) || (strcmp(error.name, DBUS_ERROR_NO_REPLY) != 0)) -+ { -+ if (error_text != NULL) -+ *error_text = g_strdup(error.message); -+ g_warning(G_STRLOC ": DBUS: %s", error.message); -+ } -+ dbus_error_free(&error); -+ } -+ return reply; -+} -+ -+/* Send a message. */ -+static DBusMessage * dbus_send_message_session(DBusMessage * message, char * * error_text) -+{ -+ /* Get a connection handle. */ -+ DBusConnection * connection = dbus_connect_session(); - if (connection == NULL) - return FALSE; - -@@ -132,6 +180,36 @@ - } - return result; - } -+ -+/* Read a result for a method that returns a string encoded boolean. */ -+static gboolean dbus_read_result_sboolean(DBusMessage * reply) -+{ -+ gboolean result = FALSE; -+ char* string_result; -+ if (reply != NULL) -+ { -+ /* Get the string result. */ -+ DBusError error; -+ dbus_error_init(&error); -+ dbus_bool_t status = dbus_message_get_args( -+ reply, -+ &error, -+ DBUS_TYPE_STRING, &string_result, -+ DBUS_TYPE_INVALID); -+ if ( ! status) -+ { -+ g_warning(G_STRLOC ": DBUS: %s", error.message); -+ dbus_error_free(&error); -+ } -+ else -+ { -+ if (!strcmp(string_result, "yes")) -+ result = TRUE; -+ } -+ dbus_message_unref(reply); -+ } -+ return result; -+} - #endif - - /*** ConsoleKit mechanism ***/ -@@ -152,7 +230,7 @@ - static gboolean dbus_ConsoleKit_query(const char * const query) - { - #ifdef HAVE_DBUS -- return dbus_read_result_boolean(dbus_send_message(dbus_ConsoleKit_formulate_message(query), NULL)); -+ return dbus_read_result_boolean(dbus_send_message_system(dbus_ConsoleKit_formulate_message(query), NULL)); - #else - return FALSE; - #endif -@@ -163,7 +241,7 @@ - { - #ifdef HAVE_DBUS - char * error = NULL; -- dbus_read_result_void(dbus_send_message(dbus_ConsoleKit_formulate_message(command), &error)); -+ dbus_read_result_void(dbus_send_message_system(dbus_ConsoleKit_formulate_message(command), &error)); - return error; - #else - return NULL; -@@ -225,7 +303,7 @@ - DBUS_TYPE_INVALID); - - /* Send the message. */ -- DBusMessage * reply = dbus_send_message(message, NULL); -+ DBusMessage * reply = dbus_send_message_system(message, NULL); - if (reply == NULL) - return FALSE; - -@@ -252,7 +330,7 @@ - { - #ifdef HAVE_DBUS - char * error = NULL; -- dbus_read_result_void(dbus_send_message(dbus_UPower_formulate_command(command), &error)); -+ dbus_read_result_void(dbus_send_message_system(dbus_UPower_formulate_command(command), &error)); - return error; - #else - return NULL; -@@ -329,7 +407,7 @@ - DBusMessage * message = dbus_HAL_formulate_string_property_query(property); - if (message == NULL) - return FALSE; -- DBusMessage * reply = dbus_send_message(message, NULL); -+ DBusMessage * reply = dbus_send_message_system(message, NULL); - if (reply == NULL) - return FALSE; - dbus_message_unref(reply); -@@ -343,7 +421,7 @@ - static gboolean dbus_HAL_boolean_query(const char * const property) - { - #ifdef HAVE_DBUS -- return dbus_read_result_boolean(dbus_send_message(dbus_HAL_formulate_boolean_property_query(property), NULL)); -+ return dbus_read_result_boolean(dbus_send_message_system(dbus_HAL_formulate_boolean_property_query(property), NULL)); - #else - return FALSE; - #endif -@@ -367,7 +445,7 @@ - - /* Send the message and wait for a reply. */ - char * error = NULL; -- dbus_read_result_void(dbus_send_message(message, &error)); -+ dbus_read_result_void(dbus_send_message_system(message, &error)); - return error; - #else - return NULL; -@@ -421,3 +499,185 @@ - { - return dbus_HAL_command("Hibernate"); - } -+ -+/*** logind mechanism ***/ -+ -+#ifdef HAVE_DBUS -+/* Formulate a message to the logind Manager interface to query a property. */ -+static DBusMessage * dbus_logind_formulate_query(const char * const query) -+{ -+ return dbus_message_new_method_call( -+ "org.freedesktop.login1", -+ "/org/freedesktop/login1", -+ "org.freedesktop.login1.Manager", -+ query); -+} -+ -+/* Formulate a message to the logind Manager interface. */ -+static DBusMessage * dbus_logind_formulate_message(const char * const method) -+{ -+ static dbus_bool_t interactive = FALSE; -+ DBusMessage * message = dbus_message_new_method_call( -+ "org.freedesktop.login1", -+ "/org/freedesktop/login1", -+ "org.freedesktop.login1.Manager", -+ method); -+ if (message != NULL) -+ dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &interactive, DBUS_TYPE_INVALID); -+ return message; -+} -+#endif -+ -+/* Send a specified query to the logind interface and process a boolean result. */ -+static gboolean dbus_logind_query(const char * const query) -+{ -+#ifdef HAVE_DBUS -+ return dbus_read_result_sboolean(dbus_send_message_system(dbus_logind_formulate_query(query), NULL)); -+#else -+ return FALSE; -+#endif -+} -+ -+/* Send a specified command to the logind interface and process a void result. */ -+static char * dbus_logind_command(const char * const command) -+{ -+#ifdef HAVE_DBUS -+ char * error = NULL; -+ dbus_read_result_void(dbus_send_message_system(dbus_logind_formulate_message(command), &error)); -+ return error; -+#else -+ return NULL; -+#endif -+} -+ -+/* Read the can-poweroff property of logind. */ -+gboolean dbus_logind_CanPowerOff(void) -+{ -+ return dbus_logind_query("CanPowerOff"); -+} -+ -+/* Read the can-reboot property of logind. */ -+gboolean dbus_logind_CanReboot(void) -+{ -+ return dbus_logind_query("CanReboot"); -+} -+ -+/* Read the can-suspend property of logind. */ -+gboolean dbus_logind_CanSuspend(void) -+{ -+ return dbus_logind_query("CanSuspend"); -+} -+ -+/* Read the can-hibernate property of logind. */ -+gboolean dbus_logind_CanHibernate(void) -+{ -+ return dbus_logind_query("CanHibernate"); -+} -+ -+/* Invoke the PowerOff method on logind. */ -+char * dbus_logind_PowerOff(void) -+{ -+ return dbus_logind_command("PowerOff"); -+} -+ -+/* Invoke the Reboot method on logind. */ -+char * dbus_logind_Reboot(void) -+{ -+ return dbus_logind_command("Reboot"); -+} -+ -+/* Invoke the Suspend method on logind. */ -+char * dbus_logind_Suspend(void) -+{ -+ return dbus_logind_command("Suspend"); -+} -+ -+/* Invoke the Hibernate method on logind. */ -+char * dbus_logind_Hibernate(void) -+{ -+ return dbus_logind_command("Hibernate"); -+} -+ -+/*** LXDE mechanism ***/ -+ -+#ifdef HAVE_DBUS -+/* Formulate a message to the LXDE Session Manager interface. */ -+static DBusMessage * dbus_LXDE_formulate_message(const char * const query) -+{ -+ return dbus_message_new_method_call( -+ "org.lxde.SessionManager", -+ "/org/lxde/SessionManager", -+ "org.lxde.SessionManager", -+ query); -+} -+#endif -+ -+/* Send a specified message to the LXDE interface and process a boolean result. */ -+static gboolean dbus_LXDE_query(const char * const query) -+{ -+#ifdef HAVE_DBUS -+ return dbus_read_result_boolean(dbus_send_message_session(dbus_LXDE_formulate_message(query), NULL)); -+#else -+ return FALSE; -+#endif -+} -+ -+/* Send a specified message to the LXDE interface and process a void result. */ -+static char * dbus_LXDE_command(const char * const command) -+{ -+#ifdef HAVE_DBUS -+ char * error = NULL; -+ dbus_read_result_void(dbus_send_message_session(dbus_LXDE_formulate_message(command), &error)); -+ return error; -+#else -+ return NULL; -+#endif -+} -+ -+/* Invoke the Logout method on LXDE. */ -+char * dbus_LXDE_Logout(void) -+{ -+ return dbus_LXDE_command("Logout"); -+} -+ -+/*** Lightdm mechanism ***/ -+ -+#ifdef HAVE_DBUS -+/* Formulate a message to the Lightdm interface. */ -+static DBusMessage * dbus_Lightdm_formulate_message(const char * const query) -+{ -+ return dbus_message_new_method_call( -+ "org.freedesktop.DisplayManager", -+ g_getenv ("XDG_SEAT_PATH"), -+ "org.freedesktop.DisplayManager.Seat", -+ query); -+} -+#endif -+ -+/* Send a specified message to the Lightdm interface and process a boolean result. */ -+static gboolean dbus_Lightdm_query(const char * const query) -+{ -+#ifdef HAVE_DBUS -+ return dbus_read_result_boolean(dbus_send_message_session(dbus_Lightdm_formulate_message(query), NULL)); -+#else -+ return FALSE; -+#endif -+} -+ -+/* Send a specified message to the Lightdm interface and process a void result. */ -+static char * dbus_Lightdm_command(const char * const command) -+{ -+#ifdef HAVE_DBUS -+ char * error = NULL; -+ dbus_read_result_void(dbus_send_message_session(dbus_Lightdm_formulate_message(command), &error)); -+ return error; -+#else -+ return NULL; -+#endif -+} -+ -+/* Invoke the Logout method on LXDE. */ -+char * dbus_Lightdm_SwitchToGreeter(void) -+{ -+ return dbus_Lightdm_command("SwitchToGreeter"); -+} ---- src/lxsession-0.4.6.1/lxsession-logout/dbus-interface.h 2011-07-27 21:26:36.000000000 +0200 -+++ src/lxsession-0.4.6.1/lxsession-logout-logind/dbus-interface.h 2012-11-13 17:26:30.807070976 +0100 -@@ -44,4 +44,18 @@ - extern char * dbus_HAL_Suspend(void); - extern char * dbus_HAL_Hibernate(void); - -+/* Interface to logind for shutdown, reboot, suspend, and hibernate. */ -+extern gboolean dbus_logind_CanPowerOff(void); -+extern gboolean dbus_logind_CanRestart(void); -+extern char * dbus_logind_PowerOff(void); -+extern char * dbus_logind_Restart(void); -+extern gboolean dbus_logind_CanSuspend(void); -+extern gboolean dbus_logind_CanHibernate(void); -+extern char * dbus_logind_Suspend(void); -+extern char * dbus_logind_Hibernate(void); -+ -+extern char * dbus_LXDE_Logout(void); -+ -+extern char * dbus_Lightdm_SwitchToGreeter(); -+ - #endif ---- src/lxsession-0.4.6.1/lxsession-logout/lxsession-logout.c 2011-07-27 21:26:36.000000000 +0200 -+++ src/lxsession-0.4.6.1/lxsession-logout-logind/lxsession-logout.c 2012-11-13 17:26:30.807070976 +0100 -@@ -69,12 +69,21 @@ - int reboot_HAL : 1; /* Reboot is available via HAL */ - int suspend_HAL : 1; /* Suspend is available via HAL */ - int hibernate_HAL : 1; /* Hibernate is available via HAL */ -+ int shutdown_logind : 1; /* Shutdown is available via logind */ -+ int reboot_logind : 1; /* Reboot is available via logind */ -+ int suspend_logind : 1; /* Suspend is available via logind */ -+ int hibernate_logind : 1; /* Hibernate is available via logind */ - int switch_user_GDM : 1; /* Switch User is available via GDM */ -- int switch_user_KDM : 1; /* Switch User is available via KDM */ -+ int switch_user_LIGHTDM : 1; /* Switch User is available via GDM */ -+ int switch_user_KDM : 1; /* Switch User is available via LIGHTDM */ - int ltsp : 1; /* Shutdown and reboot is accomplished via LTSP */ -+ -+ int lock_screen : 1; /* Lock screen available */ -+ - } HandlerContext; - - static gboolean lock_screen(void); -+static const gchar* determine_lock_screen(void); - static gboolean verify_running(const char * display_manager, const char * executable); - static void logout_clicked(GtkButton * button, HandlerContext * handler_context); - static void change_root_property(GtkWidget* w, const char* prop_name, const char* value); -@@ -93,13 +102,32 @@ - */ - static gboolean lock_screen(void) - { -- if (!g_spawn_command_line_async("lxlock", NULL)) -+ const gchar* program = determine_lock_screen(); -+ -+ if (program) - { -+ g_spawn_command_line_async(program, NULL); - return TRUE; - } - return FALSE; - } - -+static const gchar* determine_lock_screen(void) -+{ -+ const gchar* program = NULL; -+ -+ if (g_find_program_in_path("xdg-screensaver")) -+ { -+ program = "xdg-screensaver lock"; -+ } -+ else if (g_find_program_in_path("lxlock")) -+ { -+ program = "lxlock"; -+ } -+ return program; -+} -+ -+ - /* Verify that a program is running and that an executable is available. */ - static gboolean verify_running(const char * display_manager, const char * executable) - { -@@ -187,6 +215,8 @@ - error_result = dbus_ConsoleKit_Stop(); - else if (handler_context->shutdown_HAL) - error_result = dbus_HAL_Shutdown(); -+ else if (handler_context->shutdown_logind) -+ error_result = dbus_logind_PowerOff(); - - if (error_result != NULL) - gtk_label_set_text(GTK_LABEL(handler_context->error_label), error_result); -@@ -208,6 +238,8 @@ - error_result = dbus_ConsoleKit_Restart(); - else if (handler_context->reboot_HAL) - error_result = dbus_HAL_Reboot(); -+ else if (handler_context->reboot_logind) -+ error_result = dbus_logind_Reboot(); - - if (error_result != NULL) - gtk_label_set_text(GTK_LABEL(handler_context->error_label), error_result); -@@ -225,6 +257,8 @@ - error_result = dbus_UPower_Suspend(); - else if (handler_context->suspend_HAL) - error_result = dbus_HAL_Suspend(); -+ else if (handler_context->suspend_logind) -+ error_result = dbus_logind_Suspend(); - - if (error_result != NULL) - gtk_label_set_text(GTK_LABEL(handler_context->error_label), error_result); -@@ -242,6 +276,8 @@ - error_result = dbus_UPower_Hibernate(); - else if (handler_context->hibernate_HAL) - error_result = dbus_HAL_Hibernate(); -+ else if (handler_context->hibernate_logind) -+ error_result = dbus_logind_Hibernate(); - - if (error_result != NULL) - gtk_label_set_text(GTK_LABEL(handler_context->error_label), error_result); -@@ -258,6 +294,17 @@ - g_spawn_command_line_sync("gdmflexiserver --startnew", NULL, NULL, NULL, NULL); - else if (handler_context->switch_user_KDM) - g_spawn_command_line_sync("kdmctl reserve", NULL, NULL, NULL, NULL); -+ else if (handler_context->switch_user_LIGHTDM) -+ dbus_Lightdm_SwitchToGreeter(); -+ gtk_main_quit(); -+} -+ -+/* Handler for "clicked" signal on Lock button. */ -+static void lock_screen_clicked(GtkButton * button, HandlerContext * handler_context) -+{ -+ gtk_label_set_text(GTK_LABEL(handler_context->error_label), NULL); -+ -+ lock_screen(); - gtk_main_quit(); - } - -@@ -435,6 +482,28 @@ - handler_context.hibernate_HAL = TRUE; - } - -+ /* Initialize capabilities of the logind mechanism. */ -+ if (!handler_context.shutdown_available && dbus_logind_CanPowerOff()) -+ { -+ handler_context.shutdown_available = TRUE; -+ handler_context.shutdown_logind = TRUE; -+ } -+ if (!handler_context.reboot_available && dbus_logind_CanReboot()) -+ { -+ handler_context.reboot_available = TRUE; -+ handler_context.reboot_logind = TRUE; -+ } -+ if (!handler_context.suspend_available && dbus_logind_CanSuspend()) -+ { -+ handler_context.suspend_available = TRUE; -+ handler_context.suspend_logind = TRUE; -+ } -+ if (!handler_context.hibernate_available && dbus_logind_CanHibernate()) -+ { -+ handler_context.hibernate_available = TRUE; -+ handler_context.hibernate_logind = TRUE; -+ } -+ - /* If we are under GDM, its "Switch User" is available. */ - if (verify_running("gdm", "gdmflexiserver")) - { -@@ -442,6 +511,34 @@ - handler_context.switch_user_GDM = TRUE; - } - -+ /* If we are under GDM3, its "Switch User" is available. */ -+ if (verify_running("gdm3", "gdmflexiserver")) -+ { -+ handler_context.switch_user_available = TRUE; -+ handler_context.switch_user_GDM = TRUE; -+ } -+ -+ /* lightdm also use gdmflexiserver */ -+ if (verify_running("lightdm", "gdmflexiserver")) -+ { -+ handler_context.switch_user_available = TRUE; -+ handler_context.switch_user_GDM = TRUE; -+ } -+ -+ /* lightdm also use gdmflexiserver */ -+ if (verify_running("lightdm", "gdmflexiserver")) -+ { -+ handler_context.switch_user_available = TRUE; -+ handler_context.switch_user_GDM = TRUE; -+ } -+ -+ /* lightdm can also be find by the env */ -+ if (g_getenv("XDG_SEAT_PATH")) -+ { -+ handler_context.switch_user_available = TRUE; -+ handler_context.switch_user_LIGHTDM = TRUE; -+ } -+ - /* If we are under KDM, its "Switch User" is available. */ - if (verify_running("kdm", "kdmctl")) - { -@@ -451,7 +548,18 @@ - - /* LTSP support */ - if (g_getenv("LTSP_CLIENT")) -+ { - handler_context.ltsp = TRUE; -+ handler_context.shutdown_available = TRUE; -+ handler_context.reboot_available = TRUE; -+ } -+ -+ /* Lock screen */ -+ const gchar* very_lock_screen = determine_lock_screen(); -+ if (very_lock_screen) -+ { -+ handler_context.lock_screen = TRUE; -+ } - - /* Make the button images accessible. */ - gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), PACKAGE_DATA_DIR "/lxsession/images"); -@@ -596,6 +704,17 @@ - gtk_box_pack_start(GTK_BOX(controls), switch_user_button, FALSE, FALSE, 4); - } - -+ /* Create the Lock Screen button. */ -+ if (handler_context.lock_screen && !handler_context.ltsp) -+ { -+ GtkWidget * lock_screen_button = gtk_button_new_with_mnemonic(_("L_ock Screen")); -+ GtkWidget * image = gtk_image_new_from_icon_name("system-lock-screen", GTK_ICON_SIZE_BUTTON); -+ gtk_button_set_image(GTK_BUTTON(lock_screen_button), image); -+ gtk_button_set_alignment(GTK_BUTTON(lock_screen_button), 0.0, 0.5); -+ g_signal_connect(G_OBJECT(lock_screen_button), "clicked", G_CALLBACK(lock_screen_clicked), &handler_context); -+ gtk_box_pack_start(GTK_BOX(controls), lock_screen_button, FALSE, FALSE, 4); -+ } -+ - /* Create the Logout button. */ - GtkWidget * logout_button = gtk_button_new_with_mnemonic(_("_Logout")); - GtkWidget * image = gtk_image_new_from_icon_name("system-log-out", GTK_ICON_SIZE_BUTTON); -- cgit v1.2.3-54-g00ecf