commit 874827860088477d3add9548aedeaffbd292d2ff
Author: Tristan Van Berkom <tristan.van.berkom@gmail.com>
Date:   Thu Aug 4 21:30:35 2011 -0400

    Added e_cal_get_revision().
    
    Adds e_cal_get_revision() async/sync api to access an
    opaque revision string which will be NULL for a backend that
    does not implement it. Adds all the needed gdbus machinery and
    implements a revision in the file backend.
    
    This is implemented by checking the calendar file timestamp and
    maintaining a modification counter to ensure there are no races
    then multiple revisions happen in the same second. When the backend
    is asked for it's revision and it's currently dirty... the calendar
    file is forcefully saved to ensure a correct revision string.
    
    Bug: https://bugzilla.gnome.org/show_bug.cgi?id=652177

diff --git a/calendar/backends/file/e-cal-backend-file.c b/calendar/backends/file/e-cal-backend-file.c
index 0c59542..e3cfe3d 100644
--- a/calendar/backends/file/e-cal-backend-file.c
+++ b/calendar/backends/file/e-cal-backend-file.c
@@ -112,6 +112,9 @@ struct _ECalBackendFilePrivate {
 
 	/* timeour id for refresh type "2" */
 	guint refresh_timeout_id;
+
+	/* Just an incremental number to ensure uniqueness across revisions */
+	guint revision_counter;
 };
 
 
@@ -265,6 +268,7 @@ save (ECalBackendFile *cbfile)
 
 	g_static_rec_mutex_lock (&priv->idle_save_rmutex);
 	priv->is_dirty = TRUE;
+	priv->revision_counter++;
 
 	if (!priv->dirty_idle_id)
 		priv->dirty_idle_id = g_idle_add ((GSourceFunc) save_file_when_idle, cbfile);
@@ -2117,6 +2121,55 @@ e_cal_backend_file_internal_get_timezone (ECalBackend *backend,
 	return zone;
 }
 
+/* Get_revision handler for the file backend */
+static gchar *
+get_revision_string (ECalBackendFile *cbfile)
+{
+	gchar time_string[100] = {0};
+	struct stat sb;
+	struct tm  *timeval;
+
+	if (g_stat (cbfile->priv->path, &sb) < 0)
+		/* Called before ical file exists, shouldn't happen */
+		return NULL;
+
+	timeval = gmtime (&sb.st_mtime);
+
+	if (timeval)
+		strftime (time_string, 100, "%Y-%m-%dT%H:%M:%SZ", timeval);
+	else
+		g_critical ("Failed to generate revision string");
+
+	return g_strdup_printf ("%s(%d)", time_string, cbfile->priv->revision_counter);
+}
+
+static void
+e_cal_backend_file_get_revision (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable)
+{
+	ECalBackendFile *cbfile = E_CAL_BACKEND_FILE (backend);
+	gchar *revision;
+
+	/* Sync the file right now because we need a timestamp to
+	 * make a revision
+	 */
+	if (cbfile->priv->is_dirty) {
+		if (cbfile->priv->dirty_idle_id) {
+			g_source_remove (cbfile->priv->dirty_idle_id);
+			cbfile->priv->dirty_idle_id = 0;
+		}
+		save_file_when_idle (cbfile);
+
+		/* Do we need to reset 'refresh_skip' here ?? */
+		/* priv->refresh_skip = 0; */
+	}
+
+	/* Notify with the revision */
+	revision = get_revision_string (cbfile);
+
+	e_data_cal_respond_get_revision (cal, opid, NULL, revision);
+	g_free (revision);
+}
+
 static void
 sanitize_component (ECalBackendFile *cbfile,
                     ECalComponent *comp)
@@ -3369,6 +3422,7 @@ e_cal_backend_file_class_init (ECalBackendFileClass *class)
 
 	backend_class->start_view		= e_cal_backend_file_start_view;
 	backend_class->internal_get_timezone	= e_cal_backend_file_internal_get_timezone;
+	backend_class->get_revision             = e_cal_backend_file_get_revision;
 }
 
 void
diff --git a/calendar/libecal/e-cal-client.c b/calendar/libecal/e-cal-client.c
index 4d5b1b9..ea29634 100644
--- a/calendar/libecal/e-cal-client.c
+++ b/calendar/libecal/e-cal-client.c
@@ -4942,6 +4942,84 @@ e_cal_client_add_timezone_sync (ECalClient *client,
 	return res;
 }
 
+/**
+ * e_cal_client_get_revision:
+ * @client: an #ECalClient
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Query @client for an opaque revision string representing
+ * the current state of the calendar. The call is finished 
+ * by e_cal_client_get_view_finish() from the @callback.
+ *
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_get_revision (ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+	e_client_proxy_call_void (E_CLIENT (client), cancellable, callback, user_data,
+				  e_cal_client_get_revision,
+				  e_gdbus_cal_call_get_revision,
+				  NULL, NULL, e_gdbus_cal_call_get_revision_finish, NULL, NULL);
+}
+
+/**
+ * e_cal_client_get_revision_finish:
+ * @client: an #ECalClient
+ * @result: a #GAsyncResult
+ * @revision: (out) (transfer full): an opaque revision string if the backend supports it, otherwise %NULL.
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_cal_client_get_revision().
+ * If the call is successful and the backend in use reports opaque
+ * revision strings, then the @revision is set to newly allocated opaque
+ * revision string which should be freed with g_free().
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_revision_finish (ECalClient *client, GAsyncResult *result, gchar **revision, GError **error)
+{
+	g_return_val_if_fail (revision != NULL, FALSE);
+
+	return e_client_proxy_call_finish_string (E_CLIENT (client), result, revision, error, 
+						  e_cal_client_get_revision);
+}
+
+/**
+ * e_cal_client_get_revision_sync:
+ * @client: an #ECalClient
+ * @revision: (out) (transfer full): a location to store an opaque revision string
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Query @client for an opaque revision string representing
+ * the current state of the calendar.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_get_revision_sync (ECalClient *client, gchar **revision, GCancellable *cancellable, GError **error)
+{
+	g_return_val_if_fail (client != NULL, FALSE);
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	g_return_val_if_fail (client->priv != NULL, FALSE);
+	g_return_val_if_fail (revision != NULL, FALSE);
+
+	if (!client->priv->gdbus_cal) {
+		set_proxy_gone_error (error);
+		return FALSE;
+	}
+
+	return e_client_proxy_call_sync_void__string (E_CLIENT (client), revision, cancellable, error, 
+						      e_gdbus_cal_call_get_revision_sync);
+}
+
+
 static GDBusProxy *
 cal_client_get_dbus_proxy (EClient *client)
 {
diff --git a/calendar/libecal/e-cal-client.h b/calendar/libecal/e-cal-client.h
index 3e77baf..f9fefc1 100644
--- a/calendar/libecal/e-cal-client.h
+++ b/calendar/libecal/e-cal-client.h
@@ -242,6 +242,10 @@ void		e_cal_client_add_timezone			(ECalClient *client, /* const */ icaltimezone
 gboolean	e_cal_client_add_timezone_finish		(ECalClient *client, GAsyncResult *result, GError **error);
 gboolean	e_cal_client_add_timezone_sync			(ECalClient *client, /* const */ icaltimezone *zone, GCancellable *cancellable, GError **error);
 
+void		e_cal_client_get_revision			(ECalClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_cal_client_get_revision_finish		(ECalClient *client, GAsyncResult *result, gchar **revision, GError **error);
+gboolean	e_cal_client_get_revision_sync			(ECalClient *client, gchar **revision, GCancellable *cancellable, GError **error);
+
 G_END_DECLS
 
 #endif /* E_CAL_CLIENT_H */
diff --git a/calendar/libedata-cal/e-cal-backend.c b/calendar/libedata-cal/e-cal-backend.c
index abf046d..5c9a75d 100644
--- a/calendar/libedata-cal/e-cal-backend.c
+++ b/calendar/libedata-cal/e-cal-backend.c
@@ -1327,6 +1327,31 @@ e_cal_backend_internal_get_timezone (ECalBackend *backend,
 }
 
 /**
+ * e_cal_backend_get_revision:
+ * @backend: an #ECalBackend
+ * @cal: an #EDataCal
+ * @opid: the ID to use for this operation
+ *
+ * Executes a 'get revision' request specified by @opid on @cal
+ * using @backend.
+ **/
+void
+e_cal_backend_get_revision (ECalBackend  *backend,
+			     EDataCal     *cal,
+			     guint32        opid,
+			     GCancellable  *cancellable)
+{
+	g_return_if_fail (E_IS_CAL_BACKEND (backend));
+	g_return_if_fail (E_IS_DATA_CAL (cal));
+
+	if (E_CAL_BACKEND_GET_CLASS (backend)->get_revision)
+		(* E_CAL_BACKEND_GET_CLASS (backend)->get_revision) (backend, cal, opid, cancellable);
+	else
+		/* If the backend does not implement, successfully return a NULL string */
+		e_data_cal_respond_get_revision (cal, opid, NULL, NULL);
+}
+
+/**
  * e_cal_backend_start_view:
  * @backend: an #ECalBackend
  * @view: The view to be started.
diff --git a/calendar/libedata-cal/e-cal-backend.h b/calendar/libedata-cal/e-cal-backend.h
index 73198c6..3cafe48 100644
--- a/calendar/libedata-cal/e-cal-backend.h
+++ b/calendar/libedata-cal/e-cal-backend.h
@@ -158,6 +158,7 @@ struct _ECalBackendClass {
 	void	(* discard_alarm)		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *uid, const gchar *rid, const gchar *auid);
 	void	(* get_timezone)		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzid);
 	void	(* add_timezone)		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzobject);
+	void    (* get_revision)                (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable); 
 
 	void	(* start_view)			(ECalBackend *backend, EDataCalView *view);
 	void	(* stop_view)			(ECalBackend *backend, EDataCalView *view);
@@ -211,6 +212,8 @@ void		e_cal_backend_discard_alarm		(ECalBackend *backend, EDataCal *cal, guint32
 void		e_cal_backend_get_timezone		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzid);
 void		e_cal_backend_add_timezone		(ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *tzobject);
 icaltimezone *	e_cal_backend_internal_get_timezone	(ECalBackend *backend, const gchar *tzid);
+void            e_cal_backend_get_revision              (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable);
+
 void		e_cal_backend_start_view		(ECalBackend *backend, EDataCalView *view);
 void		e_cal_backend_stop_view			(ECalBackend *backend, EDataCalView *view);
 
diff --git a/calendar/libedata-cal/e-data-cal.c b/calendar/libedata-cal/e-data-cal.c
index b78fa98..8379d1d 100644
--- a/calendar/libedata-cal/e-data-cal.c
+++ b/calendar/libedata-cal/e-data-cal.c
@@ -81,6 +81,7 @@ typedef enum {
 	OP_GET_VIEW,
 	OP_GET_TIMEZONE,
 	OP_ADD_TIMEZONE,
+	OP_GET_REVISION,
 	OP_CANCEL_OPERATION,
 	OP_CANCEL_ALL,
 	OP_CLOSE
@@ -304,6 +305,9 @@ operation_thread (gpointer data,
 		e_cal_backend_add_timezone (backend, op->cal, op->id, op->cancellable, op->d.tzobject);
 		g_free (op->d.tzobject);
 		break;
+	case OP_GET_REVISION:
+		e_cal_backend_get_revision (backend, op->cal, op->id, op->cancellable);
+		break;
 	case OP_AUTHENTICATE:
 		e_cal_backend_authenticate_user (backend, op->cancellable, op->d.credentials);
 		e_credentials_free (op->d.credentials);
@@ -853,6 +857,19 @@ impl_Cal_add_timezone (EGdbusCal *object,
 }
 
 static gboolean
+impl_Cal_get_revision (EGdbusCal *object, GDBusMethodInvocation *invocation, EDataCal *cal)
+{
+	OperationData *op;
+
+	op = op_new (OP_GET_REVISION, cal);
+
+	e_gdbus_cal_complete_get_revision (cal->priv->gdbus_object, invocation, op->id);
+	e_operation_pool_push (ops_pool, op);
+
+	return TRUE;
+}
+
+static gboolean
 impl_Cal_authenticate_user (EGdbusCal *object,
                             GDBusMethodInvocation *invocation,
                             const gchar * const *in_credentials,
@@ -1463,6 +1480,36 @@ e_data_cal_respond_add_timezone (EDataCal *cal,
 }
 
 /**
+ * e_data_cal_respond_get_revision:
+ * @cal: A calendar client interface.
+ * @error: Operation error, if any, automatically freed if passed it.
+ * @revision: The revision to report
+ *
+ * Notifies listeners of the completion of the get_revision method call
+ * and delivers the @revision.
+ *
+ * Since: 3.2
+ */
+void
+e_data_cal_respond_get_revision (EDataCal *cal, guint32 opid, GError *error, const gchar *revision)
+{
+	gchar *gdbus_revision = NULL;
+
+	op_complete (cal, opid);
+
+	/* Translators: This is prefix to a detailed error message */
+	g_prefix_error (&error, "%s", _("Cannot get revision of calendar: "));
+
+	e_gdbus_cal_emit_get_revision_done (cal->priv->gdbus_object, opid, error,
+					    e_util_ensure_gdbus_string (revision, &gdbus_revision));
+
+	if (error)
+		g_error_free (error);
+
+	g_free (gdbus_revision);
+}
+
+/**
  * e_data_cal_report_error:
  *
  * FIXME: Document me.
@@ -1798,6 +1845,9 @@ e_data_cal_init (EDataCal *ecal)
 		gdbus_object, "handle-add-timezone",
 		G_CALLBACK (impl_Cal_add_timezone), ecal);
 	g_signal_connect (
+		gdbus_object, "handle-get-revision",
+		G_CALLBACK (impl_Cal_get_revision), ecal);
+	g_signal_connect (
 		gdbus_object, "handle-cancel-operation",
 		G_CALLBACK (impl_Cal_cancel_operation), ecal);
 	g_signal_connect (
diff --git a/calendar/libedata-cal/e-data-cal.h b/calendar/libedata-cal/e-data-cal.h
index 4bb9788..23a7319 100644
--- a/calendar/libedata-cal/e-data-cal.h
+++ b/calendar/libedata-cal/e-data-cal.h
@@ -146,6 +146,7 @@ void		e_data_cal_respond_discard_alarm		(EDataCal *cal, guint32 opid, GError *er
 void		e_data_cal_respond_get_view			(EDataCal *cal, guint32 opid, GError *error, const gchar *view_path);
 void		e_data_cal_respond_get_timezone			(EDataCal *cal, guint32 opid, GError *error, const gchar *tzobject);
 void		e_data_cal_respond_add_timezone			(EDataCal *cal, guint32 opid, GError *error);
+void		e_data_cal_respond_get_revision 		(EDataCal *cal, guint32 opid, GError *error, const gchar *revision);
 
 void		e_data_cal_report_error				(EDataCal *cal, const gchar *message);
 void		e_data_cal_report_readonly			(EDataCal *cal, gboolean is_readonly);
diff --git a/calendar/libegdbus/e-gdbus-cal.c b/calendar/libegdbus/e-gdbus-cal.c
index fb7aefb..573757a 100644
--- a/calendar/libegdbus/e-gdbus-cal.c
+++ b/calendar/libegdbus/e-gdbus-cal.c
@@ -79,6 +79,8 @@ enum
 	__GET_TIMEZONE_DONE_SIGNAL,
 	__ADD_TIMEZONE_METHOD,
 	__ADD_TIMEZONE_DONE_SIGNAL,
+	__GET_REVISION_METHOD,
+	__GET_REVISION_DONE_SIGNAL,
 	__AUTHENTICATE_USER_METHOD,
 	__CANCEL_OPERATION_METHOD,
 	__CANCEL_ALL_METHOD,
@@ -179,6 +181,8 @@ E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_CAL_INTERFACE_NAME
                                                         get_timezone)
 E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_VOID (GDBUS_CAL_INTERFACE_NAME,
                                                       add_timezone)
+E_DECLARE_GDBUS_METHOD_DONE_EMISSION_HOOK_ASYNC_STRING (GDBUS_CAL_INTERFACE_NAME, 
+							get_revision)
 
 static void
 e_gdbus_cal_default_init (EGdbusCalIface *iface)
@@ -217,6 +221,7 @@ e_gdbus_cal_default_init (EGdbusCalIface *iface)
 	E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusCalIface, "get_view",			get_view, __GET_VIEW_METHOD, __GET_VIEW_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_STRING__STRING(EGdbusCalIface, "get_timezone",		get_timezone, __GET_TIMEZONE_METHOD, __GET_TIMEZONE_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_ASYNC_STRING__VOID	(EGdbusCalIface, "add_timezone",		add_timezone, __ADD_TIMEZONE_METHOD, __ADD_TIMEZONE_DONE_SIGNAL)
+	E_INIT_GDBUS_METHOD_ASYNC_VOID__STRING  (EGdbusCalIface, "get_revision",		get_revision, __GET_REVISION_METHOD, __GET_REVISION_DONE_SIGNAL)
 	E_INIT_GDBUS_METHOD_STRV		(EGdbusCalIface, "authenticate_user",		authenticate_user, __AUTHENTICATE_USER_METHOD)
 	E_INIT_GDBUS_METHOD_UINT		(EGdbusCalIface, "cancel_operation",		cancel_operation, __CANCEL_OPERATION_METHOD)
 	E_INIT_GDBUS_METHOD_VOID		(EGdbusCalIface, "cancel_all",			cancel_all, __CANCEL_ALL_METHOD)
@@ -1025,6 +1030,35 @@ e_gdbus_cal_call_add_timezone_sync (GDBusProxy *proxy,
 }
 
 void
+e_gdbus_cal_call_get_revision (GDBusProxy         *proxy,
+			       GCancellable       *cancellable,
+			       GAsyncReadyCallback callback,
+			       gpointer            user_data)
+{
+	e_gdbus_proxy_call_void ("get_revision", e_gdbus_cal_call_get_revision, E_GDBUS_ASYNC_OP_KEEPER (proxy), cancellable, callback, user_data);
+}
+
+gboolean
+e_gdbus_cal_call_get_revision_finish (GDBusProxy   *proxy,
+				      GAsyncResult *result,
+				      gchar       **out_revision,
+				      GError      **error)
+{
+	return e_gdbus_proxy_finish_call_string (E_GDBUS_ASYNC_OP_KEEPER (proxy), result, out_revision, error, e_gdbus_cal_call_get_revision);
+}
+
+gboolean
+e_gdbus_cal_call_get_revision_sync (GDBusProxy   *proxy,
+				    gchar       **out_revision,
+				    GCancellable *cancellable,
+				    GError      **error)
+{
+  return e_gdbus_proxy_call_sync_void__string (proxy, out_revision, cancellable, error,
+		e_gdbus_cal_call_get_revision,
+		e_gdbus_cal_call_get_revision_finish);
+}
+
+void
 e_gdbus_cal_call_authenticate_user (GDBusProxy *proxy,
                                     const gchar * const *in_credentials,
                                     GCancellable *cancellable,
@@ -1186,6 +1220,9 @@ DECLARE_EMIT_DONE_SIGNAL_1 (get_timezone,
                             const gchar *)
 DECLARE_EMIT_DONE_SIGNAL_0 (add_timezone,
                             __ADD_TIMEZONE_DONE_SIGNAL)
+DECLARE_EMIT_DONE_SIGNAL_1 (get_revision,
+			    __GET_REVISION_DONE_SIGNAL,
+			    const gchar *)
 
 void
 e_gdbus_cal_emit_backend_error (EGdbusCal *object,
@@ -1267,6 +1304,7 @@ E_DECLARE_GDBUS_ASYNC_METHOD_1			(cal, discard_alarm, uid_rid_auid, "as")
 E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(cal, get_view, sexp, "s", view_path, "s")
 E_DECLARE_GDBUS_ASYNC_METHOD_1_WITH_RETURN	(cal, get_timezone, tzid, "s", tzobject, "s")
 E_DECLARE_GDBUS_ASYNC_METHOD_1			(cal, add_timezone, tzobject, "s")
+E_DECLARE_GDBUS_ASYNC_METHOD_0_WITH_RETURN	(cal, get_revision, revision, "s")
 
 E_DECLARE_GDBUS_SYNC_METHOD_1			(cal, authenticate_user, credentials, "as")
 E_DECLARE_GDBUS_SYNC_METHOD_1			(cal, cancel_operation, opid, "u")
@@ -1295,6 +1333,7 @@ static const GDBusMethodInfo * const e_gdbus_cal_method_info_pointers[] =
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, get_view),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, get_timezone),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, add_timezone),
+	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, get_revision),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, authenticate_user),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, cancel_operation),
 	&E_DECLARED_GDBUS_METHOD_INFO_NAME (cal, cancel_all),
@@ -1330,6 +1369,7 @@ static const GDBusSignalInfo * const e_gdbus_cal_signal_info_pointers[] =
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, get_view_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, get_timezone_done),
 	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, add_timezone_done),
+	&E_DECLARED_GDBUS_SIGNAL_INFO_NAME (cal, get_revision_done),
 	NULL
 };
 
@@ -1569,6 +1609,7 @@ e_gdbus_cal_proxy_init (EGdbusCalProxy *proxy)
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_view);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_timezone);
 	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_VOID   (add_timezone);
+	E_GDBUS_CONNECT_METHOD_DONE_SIGNAL_STRING (get_revision);
 }
 
 static void
diff --git a/calendar/libegdbus/e-gdbus-cal.h b/calendar/libegdbus/e-gdbus-cal.h
index 695d13b..61effe5 100644
--- a/calendar/libegdbus/e-gdbus-cal.h
+++ b/calendar/libegdbus/e-gdbus-cal.h
@@ -165,6 +165,8 @@ struct _EGdbusCalIface
 
 	gboolean (*handle_add_timezone)			(EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar *in_tzobject);
 	void	 (*add_timezone_done)			(EGdbusCal *object, guint arg_opid, const GError *arg_error);
+	gboolean (*handle_get_revision)		        (EGdbusCal *object, GDBusMethodInvocation *invocation);
+	void	 (*get_revision_done)		        (EGdbusCal *object, guint arg_opid, const GError *arg_error, gchar **out_revision);
 
 	gboolean (*handle_authenticate_user)		(EGdbusCal *object, GDBusMethodInvocation *invocation, const gchar * const *in_credentials);
 	gboolean (*handle_cancel_operation)		(EGdbusCal *object, GDBusMethodInvocation *invocation, guint in_opid);
@@ -261,6 +263,10 @@ void		e_gdbus_cal_call_add_timezone			(GDBusProxy *proxy, const gchar *in_tzobje
 gboolean	e_gdbus_cal_call_add_timezone_finish		(GDBusProxy *proxy, GAsyncResult *result, GError **error);
 gboolean	e_gdbus_cal_call_add_timezone_sync		(GDBusProxy *proxy, const gchar *in_tzobject, GCancellable *cancellable, GError **error);
 
+void		e_gdbus_cal_call_get_revision                   (GDBusProxy *proxy, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean	e_gdbus_cal_call_get_revision_finish            (GDBusProxy *proxy, GAsyncResult *result, gchar **out_revision, GError **error);
+gboolean	e_gdbus_cal_call_get_revision_sync              (GDBusProxy *proxy, gchar **out_revision, GCancellable *cancellable, GError **error);
+
 void		e_gdbus_cal_call_authenticate_user		(GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
 gboolean	e_gdbus_cal_call_authenticate_user_finish	(GDBusProxy *proxy, GAsyncResult *result, GError **error);
 gboolean	e_gdbus_cal_call_authenticate_user_sync		(GDBusProxy *proxy, const gchar * const *in_credentials, GCancellable *cancellable, GError **error);
@@ -296,6 +302,7 @@ gboolean	e_gdbus_cal_call_close_sync			(GDBusProxy *proxy, GCancellable *cancell
 #define e_gdbus_cal_complete_get_view			e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_get_timezone		e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_add_timezone		e_gdbus_complete_async_method
+#define e_gdbus_cal_complete_get_revision		e_gdbus_complete_async_method
 #define e_gdbus_cal_complete_authenticate_user		e_gdbus_complete_sync_method_void
 #define e_gdbus_cal_complete_cancel_operation		e_gdbus_complete_sync_method_void
 #define e_gdbus_cal_complete_cancel_all			e_gdbus_complete_sync_method_void
@@ -320,6 +327,7 @@ void e_gdbus_cal_emit_discard_alarm_done		(EGdbusCal *object, guint arg_opid, co
 void e_gdbus_cal_emit_get_view_done			(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_view_path);
 void e_gdbus_cal_emit_get_timezone_done			(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_object);
 void e_gdbus_cal_emit_add_timezone_done			(EGdbusCal *object, guint arg_opid, const GError *arg_error);
+void e_gdbus_cal_emit_get_revision_done 		(EGdbusCal *object, guint arg_opid, const GError *arg_error, const gchar *out_revision);
 
 /* D-Bus Signal Emission Helpers */
 void e_gdbus_cal_emit_backend_error	(EGdbusCal *object, const gchar *arg_message);
