[Checkins] SVN: z3c.vcsync/trunk/ Report more info about a
synchronization.
Martijn Faassen
faassen at infrae.com
Tue Dec 11 18:32:40 EST 2007
Log message for revision 82258:
Report more info about a synchronization.
Changed:
U z3c.vcsync/trunk/CHANGES.txt
U z3c.vcsync/trunk/setup.py
U z3c.vcsync/trunk/src/z3c/vcsync/README.txt
U z3c.vcsync/trunk/src/z3c/vcsync/interfaces.py
U z3c.vcsync/trunk/src/z3c/vcsync/tests.py
U z3c.vcsync/trunk/src/z3c/vcsync/vc.py
-=-
Modified: z3c.vcsync/trunk/CHANGES.txt
===================================================================
--- z3c.vcsync/trunk/CHANGES.txt 2007-12-11 20:47:52 UTC (rev 82257)
+++ z3c.vcsync/trunk/CHANGES.txt 2007-12-11 23:32:40 UTC (rev 82258)
@@ -1,11 +1,17 @@
z3c.vcsync changes
==================
-0.9.2 (unreleased)
+0.10 (unreleased)
------------------
-* ...
+Features added
+~~~~~~~~~~~~~~
+* The ``.sync()`` method now does not return the revision number, but
+ an ``ISynchronizationInfo`` object. This has a ``revision_nr``
+ attribute and also contains some information on what happened during
+ the synchronization process.
+
0.9.1 (2007-11-29)
------------------
Modified: z3c.vcsync/trunk/setup.py
===================================================================
--- z3c.vcsync/trunk/setup.py 2007-12-11 20:47:52 UTC (rev 82257)
+++ z3c.vcsync/trunk/setup.py 2007-12-11 23:32:40 UTC (rev 82258)
@@ -2,7 +2,7 @@
import sys, os
setup(name='z3c.vcsync',
- version='0.9.2dev',
+ version='0.10dev',
description="Sync ZODB data with version control system, currently SVN",
package_dir={'': 'src'},
packages=find_packages('src'),
Modified: z3c.vcsync/trunk/src/z3c/vcsync/README.txt
===================================================================
--- z3c.vcsync/trunk/src/z3c/vcsync/README.txt 2007-12-11 20:47:52 UTC (rev 82257)
+++ z3c.vcsync/trunk/src/z3c/vcsync/README.txt 2007-12-11 23:32:40 UTC (rev 82258)
@@ -676,10 +676,39 @@
>>> checkout._files = [alpha_path]
>>> checkout._removed = []
+The revision number before full synchronization::
+
+ >>> checkout.revision_nr()
+ 7
+
Now we'll synchronize with the memory structure::
- >>> s.sync(None)
+ >>> info = s.sync(None)
+ >>> info.revision_nr
+ 8
+We can get a report of what happened. No files were removed::
+
+ >>> info.files_removed()
+ []
+
+One file, alpha, was added to the checkout during our update (by
+someone else)::
+
+ >>> info.files_changed()
+ [local('.../root/alpha.test')]
+
+We removed no objects from our database since the last update::
+
+ >>> info.objects_removed()
+ []
+
+We did change one object, 'hoi', but the test infrastructure always returns
+all objects here (returning more objects is allowed)::
+
+ >>> info.objects_changed()
+ ['/root/foo', '/root/hoi', '/root', '/root/sub/qux', '/root/sub']
+
We expect the checkout to reflect the changed state of the ``hoi`` object::
>>> root.join('hoi.test').read()
Modified: z3c.vcsync/trunk/src/z3c/vcsync/interfaces.py
===================================================================
--- z3c.vcsync/trunk/src/z3c/vcsync/interfaces.py 2007-12-11 20:47:52 UTC (rev 82257)
+++ z3c.vcsync/trunk/src/z3c/vcsync/interfaces.py 2007-12-11 23:32:40 UTC (rev 82258)
@@ -50,8 +50,9 @@
control system such as SVN controls these.
message - message to commit any version control changes.
- Returns the revision number of the version control system that
- we have now synchronized with.
+ Returns a ISynchronizationInfo object with a report of the
+ synchronization, including the new revision number after
+ synchronization.
"""
def save(revision_nr):
@@ -128,3 +129,36 @@
safe to return paths of objects returned by the 'objects'
method.
"""
+
+class ISynchronizationInfo(Interface):
+ """Information on what happened during a synchronization.
+ """
+
+ revision_nr = Attribute("""
+ The revision number of the version control system that
+ we have synchronized with.
+ """)
+
+ def objects_removed():
+ """Paths of objects removed in synchronization.
+
+ The paths are state internal paths.
+ """
+
+ def objects_changed():
+ """Paths of objects added or changed in synchronization.
+
+ The paths are state internal paths.
+ """
+
+ def files_removed():
+ """Paths of files removed in synchronization.
+
+ The paths are filesystem paths (py.path objects)
+ """
+
+ def files_changed():
+ """The paths of files added or changed in synchronization.
+
+ The paths are filesystem paths (py.path objects)
+ """
Modified: z3c.vcsync/trunk/src/z3c/vcsync/tests.py
===================================================================
--- z3c.vcsync/trunk/src/z3c/vcsync/tests.py 2007-12-11 20:47:52 UTC (rev 82257)
+++ z3c.vcsync/trunk/src/z3c/vcsync/tests.py 2007-12-11 23:32:40 UTC (rev 82258)
@@ -22,11 +22,13 @@
self.update_function = None
self._files = []
self._removed = []
+ self._revision_nr = 0
def up(self):
# call update_function which will modify the checkout as might
# happen in a version control update. Function should be set before
# calling this in testing code
+ self._revision_nr += 1
self.update_function()
def resolve(self):
@@ -42,8 +44,8 @@
return self._removed
def revision_nr(self):
- return None
-
+ return self._revision_nr
+
class TestState(vc.AllState):
def __init__(self, root):
Modified: z3c.vcsync/trunk/src/z3c/vcsync/vc.py
===================================================================
--- z3c.vcsync/trunk/src/z3c/vcsync/vc.py 2007-12-11 20:47:52 UTC (rev 82257)
+++ z3c.vcsync/trunk/src/z3c/vcsync/vc.py 2007-12-11 23:32:40 UTC (rev 82258)
@@ -8,7 +8,8 @@
from zope.traversing.interfaces import IPhysicallyLocatable
from z3c.vcsync.interfaces import (IVcDump, ISerializer,
- IState, IVcFactory, ISynchronizer)
+ IState, IVcFactory, ISynchronizer,
+ ISynchronizationInfo)
import grok
@@ -38,6 +39,14 @@
path.ensure(dir=True)
def resolve(root, root_path, path):
+ """Resolve checkout path to obj in state.
+
+ root - the root container in the state
+ root_path - a py.path reference to the checkout
+ path - a py.path reference to the file in the checkout
+
+ Returns the object in the state, or None.
+ """
rel_path = path.relto(root_path)
steps = rel_path.split(os.path.sep)
steps = [step for step in steps if step != '']
@@ -52,6 +61,14 @@
return obj
def resolve_container(root, root_path, path):
+ """Resolve checkout path to container in state.
+
+ root - the root container in the state
+ root_path - a py.path reference to the checkout
+ path - a py.path reference to the directory in the checkout
+
+ Returns the container in the state, or None.
+ """
rel_path = path.relto(root_path)
steps = rel_path.split(os.path.sep)
steps = [step for step in steps if step != '']
@@ -66,6 +83,20 @@
return None
return obj
+def get_object_path(root, obj):
+ """Return state-specific path for obj.
+
+ Given state root container and obj, return internal path to this obj.
+ """
+ steps = []
+ while True:
+ steps.append(obj.__name__)
+ if obj is root:
+ break
+ obj = obj.__parent__
+ steps.reverse()
+ return '/' + '/'.join(steps)
+
class Synchronizer(object):
grok.implements(ISynchronizer)
@@ -75,8 +106,16 @@
self._to_remove = []
def sync(self, revision_nr, message=''):
+ # store these to report in SynchronizationInfo below
+ objects_removed = list(self.state.removed(revision_nr))
+ root = self.state.root
+ objects_changed = [get_object_path(root, obj) for obj in
+ self.state.objects(revision_nr)]
+ # now save the state to the checkout
self.save(revision_nr)
+ # update the checkout
self.checkout.up()
+ # resolve any conflicts
self.checkout.resolve()
# now after doing an up, remove dirs that can be removed
# it is not safe to do this during safe, as an 'svn up' will
@@ -85,10 +124,17 @@
# the ZODB when we do a load.
for to_remove in self._to_remove:
py.path.local(to_remove).remove(rec=True)
+ # store what was removed and modified in checkout now
+ files_removed = self.checkout.removed(revision_nr)
+ files_changed = self.checkout.files(revision_nr)
+ # now load the checkout state back into the ZODB state
self.load(revision_nr)
+ # and commit the checkout state
self.checkout.commit(message)
- return self.checkout.revision_nr()
-
+ return SynchronizationInfo(self.checkout.revision_nr(),
+ objects_removed, objects_changed,
+ files_removed, files_changed)
+
def save(self, revision_nr):
# remove all files that have been removed in the database
path = self.checkout.path
@@ -194,3 +240,43 @@
continue
for sub_container in self._containers_helper(obj):
yield sub_container
+
+class SynchronizationInfo(object):
+ grok.implements(ISynchronizationInfo)
+
+ def __init__(self, revision_nr,
+ objects_removed, objects_changed,
+ files_removed, files_changed):
+ self.revision_nr = revision_nr
+ self._objects_removed = objects_removed
+ self._objects_changed = objects_changed
+ self._files_removed = files_removed
+ self._files_changed = files_changed
+
+ def objects_removed(self):
+ """Paths of objects removed in synchronization.
+
+ The paths are state internal paths.
+ """
+ return self._objects_removed
+
+ def objects_changed(self):
+ """Paths of objects added or changed in synchronization.
+
+ The paths are state internal paths.
+ """
+ return self._objects_changed
+
+ def files_removed(self):
+ """Paths of files removed in synchronization.
+
+ The paths are filesystem paths (py.path objects)
+ """
+ return self._files_removed
+
+ def files_changed(self):
+ """The paths of files added or changed in synchronization.
+
+ The paths are filesystem paths (py.path objects)
+ """
+ return self._files_changed
More information about the Checkins
mailing list