Commits

Anonymous committed 8de2346

new revisions system. according to couchdb team we
shouldnt rely on internal revisions system.

Comments (0)

Files changed (4)

friendpaste/couchdb_views.py

 # -*- coding: utf-8 -
-
-
-def get_designs(db):
-    

friendpaste/paste/models.py

 # -*- coding: utf-8 -
 from datetime import datetime
+import binascii
+import base64
+import sha
 
 from couchdb.client import ResourceNotFound
 from couchdb.schema import *
+import simplejson
 
 from friendpaste.utils import local
 
+hex = binascii.hexlify
+_sha = sha.new
+
+def hash(text, p):
+    """generate a hash from the given text and its parent hashes
+
+    This hash combines both the current file contents and its history
+    in a manner that makes it easy to distinguish nodes with the same
+    content in the revision graph.
+    """
+    s = _sha(p)
+    s.update(text)
+    return s.digest()
+
+def short(node):
+    return hex(node[:6])
 
 class Snippet(Document):
     title=TextField()
+    type=TextField(default='snippet')
+    parent=TextField(default='')
+    revid = TextField()
     snippet=TextField()
     language=TextField()
     created = DateTimeField()
         self.updated = datetime.now()
         if getattr(self._data, 'id', None) is None:
             self.created = datetime.now()
+            node = hash(self.snippet+self.title+self.language,'')
+            self.revid = short(node)
             stored=False
             docid=None
             while not stored:
                 if docid: stored=True
             self._data = db.get(docid)
         else:
-            db[self._data.id] = self._data
+            old_data = db.get(self._data.id)
+            old_hash = hash(old_data['snippet']+old_data['title']+old_data['language'], '')
+            new_hash = hash(self.snippet+self.title+self.language, '')
+            if old_hash != new_hash:
+                #no need to save changes if there isn't
+                old_data['type']='revision'
+                old_data['parent']=self._data.id
+                db.create(old_data)
+
+                # get new revid
+                node = hash(self.snippet+self.title+self.language, old_data['revid'])
+                self.revid = short(node)
+            
+                # save changes
+                db[self._data.id] = self._data
+        
         return self
 
-    def get_revisions(self, db):
-        revisions = []
-        try:
-            data = dict(db.resource.get(path='/%s' % str(self.id), 
-                    **{ 'revs_info': 'true' }))
-        except ResourceNotFound:
-            pass
-        
-        if '_revs_info' in data: 
-            for rev in data['_revs_info']:
-                if rev['status']=='disk':
-                    revisions.append(rev['rev'])
- 
-        return revisions
+
+    

friendpaste/paste/views.py

 from pygments.styles import get_all_styles
 from pygments.formatters import HtmlFormatter
 from werkzeug import redirect
+from werkzeug.utils import url_quote
 
 from friendpaste.settings import SHARED_DATA
 from friendpaste.utils import local
     if request.method=='POST' and form.validate():
         s = Snippet(title=form.data['title'], snippet=form.data['snippet'], language=form.data['language'])
         s.store(local.application.db)
-        print s.get_revisions(local.application.db)
         return redirect ('/%s' % s.id)
 
     return render_response('paste/index.html', form=form)
         'language': str(s.language)
     })
     if request.method=='POST' or request.method=='PUT' and form.validate():
+        old_revid = s.revid
         s.title=form.data['title']
         s.snippet = form.data['snippet']
         s.language = form.data['language']
         s.store(local.application.db)
-        print s.get_revisions(local.application.db)
+
+        if s.revid == old_revid:
+            return redirect ('/%s?msg=%s' % (s.id, url_quote("No changes detected.")))           
 
         return redirect ('/%s' % s.id)
     return render_response('paste/edit.html', form=form, snippet=s) 
 
 def view_snippet(request, id):
+
+    # get doc and its revisions
+    q = '''function(doc) {
+    if ((doc._id == '%(id)s') && (doc.type == 'snippet')) {
+        map([doc._id,0], doc);
+    } else if ((doc.type == 'revision') && (doc.parent == '%(id)s')) {
+        map([doc.parent, 1, doc.updated], doc);
+    }
+}''' % { 'id': id }
+
     db = local.application.db
-    s = Snippet.load(db, id)
+    res = list(db.query(q))
+
+    # get snippet object
+    data = res[0].value
+    data['_id'] = res[0].id
+    s = Snippet.wrap(data)
+
+    # set revisions
+    revisions = res[1:]
+    revisions.reverse()
+    for rev in revisions:
+        print "%s, %s" % (rev.value['revid'], rev.value['updated'])
+
+
     form = PasteForm(request.form, prefix='paste', **{
         'title': s.title,
         'snippet': s.snippet,
         'language': str(s.language)
     })
-    
-    revisions = s.get_revisions(db)
+
+
     theme = request.cookies.get('theme', 'default')
     highlight_css = "%s/css/%s.css" % (SHARED_DATA, theme)
     if not os.path.exists(highlight_css):

templates/paste/view.html

     <div>
         
     </div>
-    <div id="info">Revision <a href="/{{ snippet.id }}/revs">{{ snippet.rev }}</a> ({{ snippet.updated|timesince }} ago)<br />Link to this snippet : <a href="/{{ snippet.id }}">http://friendpaste.com/{{ snippet.id  }}</a></div>
+    <div id="info">Revision <a href="/{{ snippet.id }}/revs">{{ revisions[0].value['revid'] }}</a> ({{ snippet.updated|timesince }} ago)<br />Link to this snippet : <a href="/{{ snippet.id }}">http://friendpaste.com/{{ snippet.id  }}</a></div>
 
         <div id="actions">
             <a href="/{{ snippet.id }}/edit" class="e">Edit paste</a>