Initial step towards callbacks support
authorKlaus Kämpf <kkaempf@suse.de>
Sat, 6 Nov 2010 21:11:06 +0000 (22:11 +0100)
committerKlaus Kämpf <kkaempf@suse.de>
Sat, 6 Nov 2010 21:11:06 +0000 (22:11 +0100)
This commit introduces generic (all target languages) support for
callbacks.

Callbacks are sent to a 'callback object instance' which must be
instantiated.
Currently implemented are commit callbacks, requiring an instance
of 'CommitCallbacks'

** this is work in progress **

Next: Provide example code and tests for Python and Ruby

swig/Callbacks.i [new file with mode: 0644]
swig/CommitCallbacks.h [new file with mode: 0644]
swig/perl5/CMakeLists.txt
swig/python/CMakeLists.txt
swig/ruby/CMakeLists.txt
swig/zypp.i

diff --git a/swig/Callbacks.i b/swig/Callbacks.i
new file mode 100644 (file)
index 0000000..016fdc4
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Callbacks.i
+ *
+ * Callback glue code
+ *
+ * Author: Klaus Kaempf <kkaempf@suse.de>
+ *
+ */
+
+
+/*
+ * Commit callbacks
+ *
+ */
+
+%{
+
+/*
+ * Patch message
+ *
+ */
+
+struct PatchMessageReportReceiver : public zypp::callback::ReceiveReport<zypp::target::PatchMessageReport>
+{
+
+  private:
+    Target_Type _instance;
+  public:
+  PatchMessageReportReceiver(Target_Type instance) { _instance = instance; }
+  /** Display \c patch->message().
+   * Return \c true to continue, \c false to abort commit.
+   */
+  virtual bool show( zypp::Patch::constPtr & patch )
+  {
+    return true;
+  }
+};
+
+
+/*
+ * Patch script
+ *
+ */
+
+struct PatchScriptReportReceiver : public zypp::callback::ReceiveReport<zypp::target::PatchScriptReport>
+{
+
+  private:
+    Target_Type _instance;
+  public:
+  PatchScriptReportReceiver(Target_Type instance) { _instance = instance; }
+
+  virtual void start( const zypp::Package::constPtr & package,
+                     const zypp::Pathname & path_r ) // script path
+  {
+  }
+
+  /**
+   * Progress provides the script output. If the script is quiet,
+   * from time to time still-alive pings are sent to the ui. (Notify=PING)
+   * Returning \c FALSE aborts script execution.
+   */
+  virtual bool progress( Notify kind, const std::string &output )
+  {
+    return true;
+  }
+
+  /** Report error. */
+  virtual Action problem( const std::string & description )
+  {
+    return zypp::target::PatchScriptReport::ABORT;
+  }
+
+  /** Report success. */
+  virtual void finish()
+  {
+  }
+};
+
+
+/*
+ * Remove
+ *
+ */
+
+struct RemoveResolvableReportReceiver : public zypp::callback::ReceiveReport<zypp::target::rpm::RemoveResolvableReport>
+{
+
+  private:
+    Target_Type _instance;
+  public:
+  RemoveResolvableReportReceiver(Target_Type instance) { _instance = instance; }
+
+  virtual void start( zypp::Resolvable::constPtr resolvable )
+  {
+    Target_Type r = SWIG_NewPointerObj((void *)&(*resolvable), SWIGTYPE_p_zypp__Resolvable, 0);
+#if defined(SWIGPYTHON)
+    PyObject *pyfunc = PyObject_GetAttrString(_instance, "removal_start"); 
+    PyObject *prv = NULL;
+
+    if (pyfunc == NULL)
+    {
+        PyErr_Print(); 
+        PyErr_Clear(); 
+        goto cleanup;
+    }
+    if (! PyCallable_Check(pyfunc)) 
+    {
+        goto cleanup; 
+    }
+    
+    prv = PyObject_CallObject(pyfunc, r);
+    if (PyErr_Occurred())
+    {
+        PyErr_Clear(); 
+        goto cleanup; 
+    }
+
+cleanup:
+    if (pyfunc) Py_DecRef(pyfunc);
+    if (prv) Py_DecRef(prv);
+#endif
+
+#if defined(SWIGRUBY)
+#if SWIG_VERSION < 0x010340
+#define COMMIT_CLASS cTransport
+#else
+#define COMMIT_CLASS SwigClassTransport
+#endif
+    VALUE result = rb_funcall( _instance, rb_intern("removal_start" ), 1, r );
+#endif
+    return;
+  }
+
+  virtual bool progress(int value, zypp::Resolvable::constPtr resolvable)
+  {
+    return true;
+  }
+
+  virtual Action problem( zypp::Resolvable::constPtr resolvable, Error error, const std::string & description )
+  {
+    return RemoveResolvableReportReceiver::ABORT;
+  }
+
+  virtual void finish( zypp::Resolvable::constPtr resolvable, Error error, const std::string & reason )
+  {
+  }
+};
+
+
+/*
+ * Install
+ *
+ */
+
+struct InstallResolvableReportReceiver : public zypp::callback::ReceiveReport<zypp::target::rpm::InstallResolvableReport>
+{
+
+  private:
+    Target_Type _instance;
+  public:
+  InstallResolvableReportReceiver(Target_Type instance) { _instance = instance; }
+
+  void display_step( zypp::Resolvable::constPtr resolvable, int value )
+  {
+  }
+
+  virtual void start( zypp::Resolvable::constPtr resolvable )
+  {
+  }
+
+  virtual bool progress(int value, zypp::Resolvable::constPtr resolvable)
+  {
+    return true;
+  }
+
+  virtual Action problem( zypp::Resolvable::constPtr resolvable, Error error, const std::string & description, RpmLevel level )
+  {
+    return ABORT;
+  }
+
+  virtual void finish( zypp::Resolvable::constPtr resolvable, Error error, const std::string & reason, RpmLevel level )
+  {
+  }
+};
+
+#include "CommitCallbacks.h"
+
+%}
+
+%include "CommitCallbacks.h"
diff --git a/swig/CommitCallbacks.h b/swig/CommitCallbacks.h
new file mode 100644 (file)
index 0000000..e02cb73
--- /dev/null
@@ -0,0 +1,33 @@
+class CommitCallbacks {
+
+  private:
+    PatchMessageReportReceiver _messageReceiver;
+    PatchScriptReportReceiver _scriptReceiver;
+    RemoveResolvableReportReceiver _installReceiver;
+    InstallResolvableReportReceiver _removeReceiver;
+
+    Target_Type _instance;
+  public:
+    CommitCallbacks(Target_Type instance)
+      : _messageReceiver(instance)
+      , _scriptReceiver(instance)
+      , _installReceiver(instance)
+      , _removeReceiver(instance)
+    {
+      _instance = instance;
+      Target_INCREF(_instance);
+      _messageReceiver.connect();
+      _scriptReceiver.connect();
+      _installReceiver.connect();
+      _removeReceiver.connect();
+    }
+
+    ~CommitCallbacks()
+    {
+      _removeReceiver.disconnect();
+      _installReceiver.disconnect();
+      _scriptReceiver.disconnect();
+      _messageReceiver.disconnect();
+      Target_DECREF(_instance);
+    }
+};
index 80c4420..7c16b9d 100644 (file)
@@ -46,6 +46,7 @@ SET_TARGET_PROPERTIES( zypp_perl
 )
 
 INCLUDE_DIRECTORIES( ${PERL_CORE_DIR} )
+INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/swig )
 INCLUDE_DIRECTORIES( ${ZYPP_INCLUDE_DIR} )
 TARGET_LINK_LIBRARIES( zypp_perl ${ZYPP_LIBRARY} )
 
index 2542f5a..8aab73b 100644 (file)
@@ -40,6 +40,7 @@ SET_TARGET_PROPERTIES( zypp_python
 )
 
 INCLUDE_DIRECTORIES( ${PYTHON_INCLUDE_PATH} )
+INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/swig )
 INCLUDE_DIRECTORIES( ${ZYPP_INCLUDE_DIR} )
 TARGET_LINK_LIBRARIES( zypp_python ${ZYPP_LIBRARY} )
 
index 41c7efd..2a7730a 100644 (file)
@@ -29,6 +29,7 @@ ADD_LIBRARY( zypp_ruby SHARED ${SWIG_OUTPUT} )
 SET_TARGET_PROPERTIES( zypp_ruby PROPERTIES OUTPUT_NAME "zypp" PREFIX "" )
 
 INCLUDE_DIRECTORIES( ${RUBY_INCLUDE_PATH} )
+INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/swig )
 INCLUDE_DIRECTORIES( ${ZYPP_INCLUDE_DIR} )
 
 TARGET_LINK_LIBRARIES( zypp_ruby ${RUBY_LIBRARY} )
index d005d51..7dd31e6 100644 (file)
 #define REG_NOSUB (REG_NEWLINE << 1)
 #endif
 
+/*
+ * type definitions to keep the C code generic
+ */
+#if defined(SWIGPYTHON)
+#define Target_Null_p(x) (x == Py_None)
+#define Target_INCREF(x) Py_INCREF(x)
+#define Target_DECREF(x) Py_DECREF(x)
+#define Target_True Py_True
+#define Target_False Py_False
+#define Target_Null NULL
+#define Target_Void Py_None
+#define Target_Type PyObject*
+#define Target_Bool(x) PyBool_FromLong(x)
+#define Target_WChar(x) PyInt_FromLong(x)
+#define Target_Int(x) PyInt_FromLong(x)
+#define Target_String(x) PyString_FromString(x)
+#define Target_Real(x) Py_None
+#define Target_Array() PyList_New(0)
+#define Target_SizedArray(len) PyList_New(len)
+#define Target_Append(x,y) PyList_Append(x,y)
+#define Target_DateTime(x) Py_None
+#include <Python.h>
+#define TARGET_THREAD_BEGIN_BLOCK SWIG_PYTHON_THREAD_BEGIN_BLOCK
+#define TARGET_THREAD_END_BLOCK SWIG_PYTHON_THREAD_END_BLOCK
+#define TARGET_THREAD_BEGIN_ALLOW SWIG_PYTHON_THREAD_BEGIN_ALLOW
+#define TARGET_THREAD_END_ALLOW SWIG_PYTHON_THREAD_END_ALLOW
+#endif
+
+#if defined(SWIGRUBY)
+#define Target_Null_p(x) NIL_P(x)
+#define Target_INCREF(x) 
+#define Target_DECREF(x) 
+#define Target_True Qtrue
+#define Target_False Qfalse
+#define Target_Null Qnil
+#define Target_Void Qnil
+#define Target_Type VALUE
+#define Target_Bool(x) ((x)?Qtrue:Qfalse)
+#define Target_WChar(x) INT2FIX(x)
+#define Target_Int(x) INT2FIX(x)
+#define Target_String(x) rb_str_new2(x)
+#define Target_Real(x) rb_float_new(x)
+#define Target_Array() rb_ary_new()
+#define Target_SizedArray(len) rb_ary_new2(len)
+#define Target_Append(x,y) rb_ary_push(x,y)
+#define Target_DateTime(x) Qnil
+#define TARGET_THREAD_BEGIN_BLOCK do {} while(0)
+#define TARGET_THREAD_END_BLOCK do {} while(0)
+#define TARGET_THREAD_BEGIN_ALLOW do {} while(0)
+#define TARGET_THREAD_END_ALLOW do {} while(0)
+#include <ruby.h>
+#include <rubyio.h>
+#endif
+
+#if defined(SWIGPERL)
+#define TARGET_THREAD_BEGIN_BLOCK do {} while(0)
+#define TARGET_THREAD_END_BLOCK do {} while(0)
+#define TARGET_THREAD_BEGIN_ALLOW do {} while(0)
+#define TARGET_THREAD_END_ALLOW do {} while(0)
+
+SWIGINTERNINLINE SV *SWIG_From_long  SWIG_PERL_DECL_ARGS_1(long value);
+SWIGINTERNINLINE SV *SWIG_FromCharPtr(const char *cptr);
+SWIGINTERNINLINE SV *SWIG_From_double  SWIG_PERL_DECL_ARGS_1(double value);
+
+#define Target_Null_p(x) (x == NULL)
+#define Target_INCREF(x) 
+#define Target_DECREF(x) 
+#define Target_True (&PL_sv_yes)
+#define Target_False (&PL_sv_no)
+#define Target_Null NULL
+#define Target_Void NULL
+#define Target_Type SV *
+#define Target_Bool(x) (x)?Target_True:Target_False
+#define Target_WChar(x) NULL
+#define Target_Int(x) SWIG_From_long(x)
+#define Target_String(x) SWIG_FromCharPtr(x)
+#define Target_Real(x) SWIG_From_double(x)
+#define Target_Array() (SV *)newAV()
+#define Target_SizedArray(len) (SV *)newAV()
+#define Target_Append(x,y) av_push(((AV *)(x)), y)
+#define Target_DateTime(x) NULL
+#include <perl.h>
+#include <EXTERN.h>
+#endif
+
+
 #include <sstream>
 #include "zypp/base/PtrTypes.h"
 #include "zypp/base/ReferenceCounted.h"
@@ -51,6 +138,7 @@ using namespace zypp::resfilter;
 using namespace zypp::filesystem;
 
 typedef std::list<std::string> StringList;
+
 %}
 
 %nodefault ByKind;
@@ -143,9 +231,7 @@ namespace zypp {
 %include "TmpPath.i"
 %include "Resolver.i"
 %include "ZConfig.i"
-#ifdef SWIGPYTHON
-%include "python/callbacks.i"
-#endif
+%include "Callbacks.i"
 
 %ignore zypp::ZYpp::setTextLocale;
 %ignore zypp::ZYpp::getTextLocale;