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

Commit

Permalink
moving more code into the new backend structure
Browse files Browse the repository at this point in the history
git-svn-id: https://django-rcsfield.googlecode.com/svn/trunk@39 d91cc5cc-1343-0410-b1ed-e1360c4e4ba3
  • Loading branch information
arneb committed Jul 18, 2008
1 parent 0d1b927 commit 2479215
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 81 deletions.
31 changes: 28 additions & 3 deletions rcsfield/backends/bzr.py
Expand Up @@ -4,9 +4,11 @@
Uses bzrlib http://bazaar-vcs.org to versionize content.
"""

import os
from django.conf import settings
from bzrlib import bzrdir, workingtree, revisiontree, tree, workingtree_4, dirstate
from bzrlib.errors import NoSuchRevision as BzrNoSuchRevision
from bzrlib.errors import FileExists
from rcsfield.backends.base import BaseBackend


Expand All @@ -17,12 +19,27 @@ class BzrBackend(BaseBackend):
"""

def initial(self):
def initial(self, prefix):
"""
Set up the brz repo at ``settings.BZR_WC_PATH``.
And add initial directory to the repo.
"""
pass
checkout_path = os.path.normpath(settings.BZR_WC_PATH)
if not os.path.exists(checkout_path):
os.makedirs(checkout_path)

try:
wt = bzrdir.BzrDir.create_standalone_workingtree(checkout_path)
except FileExists:
# already under version control
wt = workingtree.WorkingTree.open(checkout_path)

field_path = os.path.normpath(os.path.join(checkout_path, prefix))
if not os.path.exists(field_path):
os.makedirs(field_path)
wt.smart_add(['%s' % field_path,])
wt.commit(message="adding initial directory for %s" % prefix)


def fetch(self, key, rev):
Expand Down Expand Up @@ -57,7 +74,15 @@ def commit(self, key, data):
commit changed ``data`` to the entity identified by ``key``.
"""
pass
fobj = open(os.path.join(settings.BZR_WC_PATH, key), 'w')
fobj.write(data)
fobj.close()
wt = workingtree.WorkingTree.open(settings.BZR_WC_PATH)
try:
wt.add([key,])
except:
raise
wt.commit(message='auto commit from django')



Expand Down
21 changes: 9 additions & 12 deletions rcsfield/fields.py
Expand Up @@ -8,6 +8,9 @@
from manager import RevisionManager
import urlparse

from rcsfield.backends import backend


class RcsTextField(models.TextField):
'''save contents of the TextField in a svn repository.
The field has a mandatory argument: the base path, where
Expand Down Expand Up @@ -41,24 +44,18 @@ def get_internal_type(self):
return "TextField"

def post_save(self, instance=None):
'''
"""
create a file and add to the repository, if not already existing
called via post_save signal
FIXME: currently hardcoded for bzr
'''
"""
data = getattr(instance, self.attname)
#if data is not None: #@@FIXME: I think if data is None, an empty file should be written.
fobj = open(settings.BZR_WC_PATH+'/%s/%s_%s-%s.txt' % (instance._meta.app_label,instance.__class__.__name__,self.attname,instance.id), 'w')
fobj.write(data)
fobj.close()
from bzrlib import workingtree
wt = workingtree.WorkingTree.open(settings.BZR_WC_PATH)
key = "%s/%s/%s/%s.txt" % (instance._meta.app_label,instance.__class__.__name__,self.attname,instance.id)
try:
wt.add(['%s/%s_%s-%s.txt' % (instance._meta.app_label,instance.__class__.__name__,self.attname,instance.id),])
backend.commit(key, data)
except:
pass
wt.commit(message='auto commit from django')
raise


def get_revisions(self, instance, raw=False):
wt = workingtree.WorkingTree.open(settings.BZR_WC_PATH)
Expand Down
27 changes: 9 additions & 18 deletions rcsfield/management.py
@@ -1,42 +1,33 @@
'''
"""
this file is used to hook an initial checkout (working copy)
into django's syncdb process
'''
"""

import os
from django.conf import settings
from django.dispatch import dispatcher
from django.db.models import get_models, signals
from fields import RcsTextField



def initial_checkout(sender, created_models, verbosity):
'''
"""
creates the repository / does the initial checkout
for all fields that are versionized.
called via post_syncdb signal from django.
TODO:currently hardcoded for bzr
'''
from bzrlib import bzrdir, workingtree
"""
from rcsfield.backends import backend
sender_name = sender.__name__.split('.')[-2]
checkout_path = os.path.normpath(settings.BZR_WC_PATH)
for model in created_models:
app_label = model._meta.app_label
for field in model._meta.fields:
if field.__class__ == RcsTextField:
if sender_name == app_label:
if verbosity >= 1:
print "%s found in %s.models.%s" % (RcsTextField.__name__, sender_name, model.__name__)
print "Will create an empty bzr branch in %s" % checkout_path
if not os.path.exists(checkout_path):
os.mkdir(checkout_path)
else:
raise Exception('Directory %s already exists, please change your settings or delete the directory' % checkout_path)
field_path = os.path.normpath(os.path.join(checkout_path, app_label))
if not os.path.exists(field_path):
os.mkdir(field_path)
wt = bzrdir.BzrDir.create_standalone_workingtree(checkout_path)
wt.add(['%s' % app_label,])
wt.commit(message="initial directory added")
print "Will run init procedure for %s backend" % backend.__name__
backend.initial("%s/%s/%s" % (app_label, model.__name__, field.name))

dispatcher.connect(initial_checkout, signal=signals.post_syncdb)
70 changes: 22 additions & 48 deletions rcsfield/manager.py
Expand Up @@ -4,56 +4,44 @@
from django.db.models.query import QuerySet

try:
#django pre-qsrf
from django.db.models.query import GET_ITERATOR_CHUNK_SIZE
except ImportError:
#django post-qsrf
from django.db.models.query import CHUNK_SIZE as GET_ITERATOR_CHUNK_SIZE


from rcsfield.backends import backend


class RevisionQuerySet(QuerySet):
'''subclasses QuerySet to fetch older revisions from rcs backend'''
"""
subclasses QuerySet to fetch older revisions from rcs backend
"""
def __init__(self, model=None, revision='head', **kwargs):
self._rev = revision
super(RevisionQuerySet, self).__init__(model=model, **kwargs)


def iterator(self):
'''wraps the original iterator and replaces versioned fields with the
apropriate data from the given revision'''
"""
wraps the original iterator and replaces versioned fields with the
apropriate data from the given revision
"""
for obj in super(RevisionQuerySet, self).iterator():
for field in obj._meta.fields:
if hasattr(field, 'IS_VERSIONED') and field.IS_VERSIONED and hasattr(self, '_rev') and not self._rev == 'head':
#from bzrlib import workingtree, revisiontree, tree, workingtree_4, dirstate
#from bzrlib.errors import NoSuchRevision
#wt = workingtree.WorkingTree.open(settings.BZR_WC_PATH)
#try:
# rt = wt.branch.repository.revision_tree(wt.branch.get_rev_id(int(self._rev)))
#except NoSuchRevision:
#if the revision does not exist, we take the head
#FIXME: is this a good choice??
# rt = wt
#rt.lock_read()
#try:
#file_path is relative to the repository-root
#file_path = '%s/%s_%s-%s.txt' % (obj._meta.app_label,obj.__class__.__name__,field.attname,obj.id)
# olddata = rt.get_file(rt.path2id(file_path)).read()
#except:
#raise
# may raise bzrlib.errors.
# olddata = '' #None
#finally:
# rt.unlock()
file_path = '%s/%s_%s-%s.txt' % (obj._meta.app_label,obj.__class__.__name__,field.attname,obj.id)
olddata = backend.fetch(file_path, self._rev)
setattr(obj, field.attname, olddata)
file_path = '%s/%s/%s/%s.txt' % (obj._meta.app_label,obj.__class__.__name__, field.attname,obj.id)
try:
olddata = backend.fetch(file_path, self._rev)
setattr(obj, field.attname, olddata)
except:
# for now just ignore errors raised in the backend
# and return the content from the db (aka head revision)
pass
yield obj

# def _filter_or_exclude(self, mapper, *args, **kwargs):
# '''this method makes sure cloned QuerySets inherit the _rev attribute'''
# clone = super(BzrQuerySet, self)._filter_or_exclude(mapper, *args, **kwargs)
# clone._rev = self._rev
# return clone


def _clone(self, klass=None, setup=False, **kwargs):
"""
Expand All @@ -71,19 +59,7 @@ def _clone(self, klass=None, setup=False, **kwargs):
c._setup_query()
c._rev = self._rev
return c

#def _filter_or_exclude(self, negate, *args, **kwargs):
# if args or kwargs:
# assert self.query.can_filter(), \
# "Cannot filter a query once a slice has been taken."

#clone = self._clone()
#if negate:
# clone.query.add_q(~Q(*args, **kwargs))
#else:
# clone.query.add_q(Q(*args, **kwargs))
#clone._rev = self._rev
#return clone


class RevisionManager(models.Manager):
Expand All @@ -102,11 +78,9 @@ def get_query_set(self, rev='head'):
return RevisionQuerySet(self.model, revision=rev)

def rev(self, rev='head'):
if integer_re.search(str(rev)):
if integer_re.search(str(rev)): #FIXME
if rev < 0:
raise NotImplementedError
#TODO: fetch head minus x if rev is < 0
#get head revision and substract rev
#c = pysvn.Client()

return self.get_query_set(rev)

0 comments on commit 2479215

Please sign in to comment.