You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2011/08/30 23:00:57 UTC

svn commit: r1163379 - in /subversion/branches/fs-py/subversion: libsvn_fs_py/fs_fs.c libsvn_fs_py/py_util.c libsvn_fs_py/py_util.h python/svn/fs/__init__.py python/svn/hash.py

Author: hwright
Date: Tue Aug 30 21:00:57 2011
New Revision: 1163379

URL: http://svn.apache.org/viewvc?rev=1163379&view=rev
Log:
On the fs-py branch:
Fetch revprops using Python, not C.

* subversion/python/svn/fs/__init__.py
  (FS.revision_proplist): New.

* subversion/python/svn/hash.py
  (read): New.

* subversion/libsvn_fs_py/fs_fs.c
  (revision_proplist): Remove implementation in favor of Python one.
 
* subversion/libsvn_fs_py/py_util.c
  (make_string_from_ob, make_svn_string_from_ob, svn_fs_py__prophash_from_dict):
    New.

* subversion/libsvn_fs_py/py_util.h
  (svn_fs_py__prophash_from_dict): New.

Modified:
    subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c
    subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c
    subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h
    subversion/branches/fs-py/subversion/python/svn/fs/__init__.py
    subversion/branches/fs-py/subversion/python/svn/hash.py

Modified: subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c?rev=1163379&r1=1163378&r2=1163379&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c Tue Aug 30 21:00:57 2011
@@ -2875,65 +2875,15 @@ revision_proplist(apr_hash_t **proplist_
                   svn_revnum_t rev,
                   apr_pool_t *pool)
 {
-  apr_hash_t *proplist;
-
-  SVN_ERR(ensure_revision_exists(fs, rev, pool));
-
-  if (1)
-    {
-      apr_file_t *revprop_file = NULL;
-      svn_error_t *err = SVN_NO_ERROR;
-      int i;
-      apr_pool_t *iterpool;
-
-      proplist = apr_hash_make(pool);
-      iterpool = svn_pool_create(pool);
-      for (i = 0; i < RECOVERABLE_RETRY_COUNT; i++)
-        {
-          svn_pool_clear(iterpool);
-
-          /* Clear err here rather than after finding a recoverable error so
-           * we can return that error on the last iteration of the loop. */
-          svn_error_clear(err);
-          err = svn_io_file_open(&revprop_file, path_revprops(fs, rev,
-                                                              iterpool),
-                                 APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
-                                 iterpool);
-          if (err)
-            {
-              if (APR_STATUS_IS_ENOENT(err->apr_err))
-                {
-                  svn_error_clear(err);
-                  return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
-                                           _("No such revision %ld"), rev);
-                }
-#ifdef ESTALE
-              else if (APR_TO_OS_ERROR(err->apr_err) == ESTALE
-                       || APR_TO_OS_ERROR(err->apr_err) == EIO
-                       || APR_TO_OS_ERROR(err->apr_err) == ENOENT)
-                continue;
-#endif
-              return svn_error_trace(err);
-            }
-
-          SVN_ERR(svn_hash__clear(proplist, iterpool));
-          RETRY_RECOVERABLE(err, revprop_file,
-                            svn_hash_read2(proplist,
-                                           svn_stream_from_aprfile2(
-                                                revprop_file, TRUE, iterpool),
-                                           SVN_HASH_TERMINATOR, pool));
+  fs_fs_data_t *ffd = fs->fsap_data;
+  PyObject *p_proplist;
 
-          IGNORE_RECOVERABLE(err, svn_io_file_close(revprop_file, iterpool));
+  SVN_ERR(svn_fs_py__call_method(&p_proplist, ffd->p_fs, "revision_proplist",
+                                 "(l)", rev));
 
-          break;
-        }
+  *proplist_p = svn_fs_py__prophash_from_dict(p_proplist, pool);
 
-      if (err)
-        return svn_error_trace(err);
-      svn_pool_destroy(iterpool);
-    }
-
-  *proplist_p = proplist;
+  Py_DECREF(p_proplist);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c?rev=1163379&r1=1163378&r2=1163379&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c Tue Aug 30 21:00:57 2011
@@ -620,6 +620,80 @@ svn_fs_py__load_module(fs_fs_data_t *ffd
   return svn_error_trace(load_module(&ffd->p_module, FS_MODULE_NAME));
 }
 
+/* Conversion from Python single objects (not hashes/lists/etc.) to
+   Subversion types. */
+static const char *
+make_string_from_ob(PyObject *ob, apr_pool_t *pool)
+{
+  if (ob == Py_None)
+    return NULL;
+  if (! PyString_Check(ob))
+    {
+      PyErr_SetString(PyExc_TypeError, "not a string");
+      return NULL;
+    }
+  return apr_pstrdup(pool, PyString_AS_STRING(ob));
+}
+
+static svn_string_t *
+make_svn_string_from_ob(PyObject *ob, apr_pool_t *pool)
+{
+  if (ob == Py_None)
+    return NULL;
+  if (! PyString_Check(ob))
+    {
+      PyErr_SetString(PyExc_TypeError, "not a string");
+      return NULL;
+    }
+  return svn_string_create(PyString_AS_STRING(ob), pool);
+}
+
+/* ### We may need to wrap this in something to catch any Python errors which
+ * ### are generated. */
+apr_hash_t *
+svn_fs_py__prophash_from_dict(PyObject *dict, apr_pool_t *pool)
+{
+  apr_hash_t *hash;
+  PyObject *keys;
+  long num_keys;
+  long i;
+
+  if (dict == Py_None)
+    return NULL;
+
+  if (!PyDict_Check(dict))
+    {
+      PyErr_SetString(PyExc_TypeError, "not a dictionary");
+      return NULL;
+    }
+
+  hash = apr_hash_make(pool);
+  keys = PyDict_Keys(dict);
+  num_keys = PyList_Size(keys);
+  for (i = 0; i < num_keys; i++)
+    {
+      PyObject *key = PyList_GetItem(keys, i);
+      PyObject *value = PyDict_GetItem(dict, key);
+      const char *propname = make_string_from_ob(key, pool);
+      svn_string_t *propval = make_svn_string_from_ob(value, pool);
+
+      if (! (propname && propval))
+        {
+          PyErr_SetString(PyExc_TypeError,
+                          "dictionary keys/values aren't strings");
+          Py_DECREF(keys);
+          return NULL;
+        }
+      apr_hash_set(hash, propname, APR_HASH_KEY_STRING, propval);
+    }
+  Py_DECREF(keys);
+  return hash;
+}
+
+
+/**********************
+ * Wrapping C callback functions
+ */
 static PyObject *
 notify_func_wrapper(PyObject *p_tuple, PyObject *args)
 {

Modified: subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h?rev=1163379&r1=1163378&r2=1163379&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h (original)
+++ subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h Tue Aug 30 21:00:57 2011
@@ -46,6 +46,9 @@ svn_fs_py__convert_cstring_hash(void *ob
 PyObject *
 svn_fs_py__convert_proplist(void *object);
 
+apr_hash_t *
+svn_fs_py__prophash_from_dict(PyObject *dict, apr_pool_t *pool);
+
 /* Load a reference to the FS Python module into the shared data. */
 svn_error_t *
 svn_fs_py__load_module(fs_fs_data_t *ffd);

Modified: subversion/branches/fs-py/subversion/python/svn/fs/__init__.py
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/python/svn/fs/__init__.py?rev=1163379&r1=1163378&r2=1163379&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/python/svn/fs/__init__.py (original)
+++ subversion/branches/fs-py/subversion/python/svn/fs/__init__.py Tue Aug 30 21:00:57 2011
@@ -553,6 +553,14 @@ class FS(object):
                 self._pack_shard(shard, notify)
 
 
+    def revision_proplist(self, rev):
+        'Return a dictionary of revprops'
+
+        self._ensure_revision_exists(rev)
+        with open(self.__path_revprops(rev), 'rb') as f:
+            return svn.hash.read(f, svn.hash.TERMINATOR)
+
+
 
 # A few helper functions for C callers
 def _create_fs(path, config=None):

Modified: subversion/branches/fs-py/subversion/python/svn/hash.py
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/python/svn/hash.py?rev=1163379&r1=1163378&r2=1163379&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/python/svn/hash.py (original)
+++ subversion/branches/fs-py/subversion/python/svn/hash.py Tue Aug 30 21:00:57 2011
@@ -20,6 +20,8 @@
 
 TERMINATOR = "END"
 
+import svn
+
 def encode(h, terminator):
     output = []
     for k in sorted(h.keys()):
@@ -29,3 +31,49 @@ def encode(h, terminator):
         output.append('%s\n' % terminator)
 
     return ''.join(output)
+
+
+def read(f, terminator):
+    'Return a hash as read from the file-like object F.'
+
+    h = {}
+    while True:
+        line = f.readline().rstrip()
+
+        if line == terminator:
+            break
+
+        if line[0:2] == 'K ':
+            # Read length and data into a buffer.
+            keylen = int(line[2:])
+            keybuf = f.read(keylen)
+
+            # Suck up extra newline after key data
+            c = f.read(1)
+            if c != '\n':
+                raise svn.SubversionException(svn.err.MALFORMED_FILE,
+                                              "Serialized hash malformed")
+
+            # Read a val length line
+            line = f.readline().rstrip()
+            if line[0:2] == 'V ':
+                vallen = int(line[2:])
+                valbuf = f.read(vallen)
+
+                # Suck up extra newline after val data
+                c = f.read(1)
+                if c != '\n':
+                    raise svn.SubversionException(svn.err.MALFORMED_FILE,
+                                                  "Serialized hash malformed")
+
+                h[keybuf] = valbuf
+            else:
+                raise svn.SubversionException(svn.err.MALFORMED_FILE,
+                                              "Serialized hash malformed")
+
+        else:
+            print line
+            raise svn.SubversionException(svn.err.MALFORMED_FILE,
+                                          "Serialized hash malformed")
+
+    return h