Skip to content
This repository has been archived by the owner on Jan 14, 2019. It is now read-only.

Commit

Permalink
adding code to support diffs between versions out of the box. additio…
Browse files Browse the repository at this point in the history
…nally objects now have a FIELD_revision attribute if they contain content from an old revision

git-svn-id: https://django-rcsfield.googlecode.com/svn/trunk@51 d91cc5cc-1343-0410-b1ed-e1360c4e4ba3
  • Loading branch information
arneb committed Jul 31, 2008
1 parent d53d611 commit ee06e5e
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
19 changes: 18 additions & 1 deletion rcsfield/backends/bzr.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,23 @@ def move(self, key_from, key_to):
return True
except:
return False


def diff(self, key1, rev1, key2, rev2):
"""
Returns a textual unified diff of two entities at specified revisions.
Takes two parameters for keyname to support diffing renamed files.
"""
import difflib
c1 = self.fetch(key1, rev1)
c2 = self.fetch(key2, rev2)
diff = difflib.unified_diff(c1.splitlines(1),
c2.splitlines(1),
'Revision: %s' % rev1,
'Revision: %s' % rev2
)
return diff



Expand All @@ -152,7 +168,8 @@ def move(self, key_from, key_to):
initial = rcs.initial
get_revisions = rcs.get_revisions
move = rcs.move
diff = rcs.diff

__all__ = ('fetch', 'commit', 'initial', 'get_revisions', 'move')
__all__ = ('fetch', 'commit', 'initial', 'get_revisions', 'move', 'diff')


52 changes: 52 additions & 0 deletions rcsfield/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,63 @@ def get_FIELD_revisions(self, instance, field):
field.attname,
instance.id))


def get_FIELD_diff(self, instance, rev1, rev2=None, field=None):
"""
Returns a generator which yields lines of a textual diff between
two revisions.
Supports two operation modes:
ObjectA.get_field_diff(3): returns a diff between the contents of
the field ``field`` at revision 3 against revision of ObjectA.
Direction is ---3 / +++ObjectA
ObjectA.get_field_diff(3,7): returns a diff between the contents of
the field ``field`` at revision 7 against revision 3..
Direction is ---3/+++7
"""


if rev2 is None:
rev2 = getattr(instance, '%s_revision' % field.attname, 'head')

if rev1 == rev2: #do not attempt to diff identical content for performance reasons
return ""

if rev2 == 'head':
import difflib
old = backend.fetch(self.rcskey_format % (instance._meta.app_label,
instance.__class__.__name__,
field.attname,
instance.id),
rev1,
)
diff = difflib.unified_diff(old.splitlines(1),
getattr(instance, field.attname).splitlines(1),
'Revision: %s' % rev1,
'Revision: %s' % getattr(instance, "%s_revision" % field.attname, 'head'),
)
return diff

else: #diff two arbitrary revisions
return backend.diff(self.rcskey_format % (instance._meta.app_label,
instance.__class__.__name__,
field.attname,
instance.id),
rev1,
self.rcskey_format % (instance._meta.app_label,
instance.__class__.__name__,
field.attname,
instance.id),
rev2,
)

def contribute_to_class(self, cls, name):
super(RcsTextField, self).contribute_to_class(cls, name)
setattr(cls, 'get_%s_revisions' % self.name, curry(self.get_FIELD_revisions, field=self))
setattr(cls, 'get_changed_revisions', curry(self.get_changed_revisions, field=self))
setattr(cls, 'get_%s_diff' % self.name, curry(self.get_FIELD_diff, field=self))
dispatcher.connect(self.post_save, signal=signals.post_save, sender=cls)


Expand Down
1 change: 1 addition & 0 deletions rcsfield/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def iterator(self):
try:
olddata = backend.fetch(file_path, self._rev)
setattr(obj, field.attname, olddata)
setattr(obj, '%s_revision' % field.attname, self._rev)
except:
# for now just ignore errors raised in the backend
# and return the content from the db (aka head revision)
Expand Down

0 comments on commit ee06e5e

Please sign in to comment.