TiddlyWiki.org

Changeset 4997

Show
Ignore:
Timestamp:
16/05/08 17:33:13 (2 months ago)
Author:
cdent
Message:

tiddlyweb - add support for store and presenting revisions of tiddlers
through tiddlyweb.

Nothing is done as yet on the client side to support handling revisions,
and nothing is done on the server to support contention mgt. That's to
come.

The fundamental change here is to the text storage system. Now instead
of a flat textfilefor storing a tiddler, we have a directory. In that
directory are files with numbers for the name. The number is the revision.
It starts at 1 and goes up.

The store API has only one change: list_tiddler_revisions(tiddler) lists the
revisions of the provided tiddler. Access to a specific revision of a tiddler
is done by creating a new Tiddler object, setting the revision attribute and
doing store.get(tiddler). The store is expected to look at the revision field
and respect it if it is there. Otherwise, we desire the most recent revision.
This was deemed to be the most straightforward way to maintain a clean store
API that can easily be duplicated into other storage systems.

PUTting a tiddler always involves creating a new revision.

There are four new URLs on which a GET may be performed:

/recipes/{recipe_name}/tiddlers/{tiddler_name}/revisions
/recipes/{recipe_name}/tiddlers/{tiddler_name}/revisions/{revision_id}
/bags/{bag_name}/tiddlers/{tiddler_name}/revisions
/bags/{bag_name}/tiddlers/{tiddler_name}/revisions/{revision_id}

Next:

* Experiment with TiddlyWebAdaptorPlugin? to support revisions

and collisions. This will likely require some server side
changes in the HTTP response realm.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • Trunk/contributors/ChrisDent/experimental/TiddlyWeb/tiddlyweb/bag.py

    r4995 r4997  
    1414 
    1515class Bag(dict): 
     16    """ 
     17    XXX: We should subclass for tmpbag and revbag. 
     18    """ 
    1619 
    17     def __init__(self, name, policy=default_policy, tmpbag=False): 
     20    def __init__(self, name, policy=default_policy, tmpbag=False, revbag=False): 
    1821        dict.__init__(self) 
    1922        self.name = name 
    2023        self.policy = policy 
    2124        self.tmpbag = tmpbag 
     25        self.revbag = revbag 
    2226        self.order = [] 
    2327        # reference to the store which 'got' us 
  • Trunk/contributors/ChrisDent/experimental/TiddlyWeb/tiddlyweb/serializers/html.py

    r4957 r4997  
    5959    lines = [] 
    6060    output = '<ul>\n' 
    61 # XXX we are encoding an absolute url here, which is not such a good thing 
    6261    for tiddler in bag.list_tiddlers(): 
    63         line = '<li><a href="/bags/%s/tiddlers/%s">%s</a></li>' % (urllib.quote(tiddler.bag), urllib.quote(tiddler.title), tiddler.title) 
     62        if bag.revbag: 
     63            line = '<li><a href="/bags/%s/tiddlers/%s/revisions/%s">%s:%s</a></li>' % (urllib.quote(tiddler.bag), urllib.quote(tiddler.title), tiddler.revision, tiddler.title, tiddler.revision) 
     64        else: 
     65            line = '<li><a href="/bags/%s/tiddlers/%s">%s</a></li>' % (urllib.quote(tiddler.bag), urllib.quote(tiddler.title), tiddler.title) 
    6466        lines.append(line) 
    6567    output += "\n".join(lines) 
  • Trunk/contributors/ChrisDent/experimental/TiddlyWeb/tiddlyweb/serializers/json.py

    r4957 r4997  
    3232    """ 
    3333    List the tiddlers in a bag as text. 
     34    We will likely want to expand this someday. 
    3435    """ 
    35     return simplejson.dumps([tiddler.title for tiddler in bag.list_tiddlers()]) 
     36    if bag.revbag: 
     37        return simplejson.dumps([(tiddler.title, tiddler.revision) for tiddler in bag.list_tiddlers()]) 
     38    else: 
     39        return simplejson.dumps([tiddler.title for tiddler in bag.list_tiddlers()]) 
    3640 
    3741def as_bag(bag, input): 
  • Trunk/contributors/ChrisDent/experimental/TiddlyWeb/tiddlyweb/serializers/text.py

    r4109 r4997  
    5252    List the tiddlers in a bag as text. 
    5353    """ 
    54     return "\n".join([tiddler.title for tiddler in bag.list_tiddlers()]) 
     54    if bag.revbag: 
     55        return "\n".join(["%s:%s" % (tiddler.title, tiddler.revision) for tiddler in bag.list_tiddlers()]) 
     56    else: 
     57        return "\n".join([tiddler.title for tiddler in bag.list_tiddlers()]) 
    5558 
    5659def as_bag(bag, input): 
  • Trunk/contributors/ChrisDent/experimental/TiddlyWeb/tiddlyweb/web/tiddler.py

    r4981 r4997  
    22from tiddlyweb.tiddler import Tiddler 
    33from tiddlyweb.recipe import Recipe 
     4from tiddlyweb.bag import Bag 
    45from tiddlyweb.store import Store, NoTiddlerError, NoBagError 
    56from tiddlyweb.serializer import Serializer, TiddlerFormatError 
     
    1718 
    1819def _send_tiddler_revisions(environ, start_response, tiddler): 
    19     content = 'no done' 
    20     start_response("200 OK", 
    21             [('Content-Type', mime_type)]) 
     20    store = environ['tiddlyweb.store'] 
    2221 
    23     return [content] 
     22    tmp_bag = Bag('tmp', tmpbag=True, revbag=True) 
     23    for revision in store.list_tiddler_revisions(tiddler): 
     24        tmp_tiddler = Tiddler(title=tiddler.title, revision=revision, bag=tiddler.bag) 
     25        try: 
     26            store.get(tmp_tiddler) 
     27        except NoTiddlerError, e: 
     28            raise HTTP404, 'tiddler %s at revision % not found, %s' % (tiddler.title, revision, e) 
     29        tmp_bag.add_tiddler(tmp_tiddler) 
     30 
     31    serialize_type, mime_type = web.get_serialize_type(environ) 
     32    serializer = Serializer(serialize_type) 
     33    serializer.object = tmp_bag 
     34 
     35    start_response("200 OK", [('Content-Type', mime_type), 
     36             ('Set-Cookie', 'chkHttpReadOnly=false')]) 
     37    return [serializer.to_string()] 
    2438 
    2539def _send_tiddler(environ, start_response, tiddler): 
  • Trunk/contributors/ChrisDent/experimental/TiddlyWeb/urls.map

    r4957 r4997  
    5454#   text/x-tiddlywiki: this tiddler wrapped up as a TiddlyWiki 
    5555/recipes/{recipe_name:segment}/tiddlers/{tiddler_name:segment} 
    56     GET tiddlyweb.web.tiddler:get_by_recipe 
    57     PUT tiddlyweb.web.tiddler:put_by_recipe 
     56    GET tiddlyweb.web.tiddler:get 
     57    PUT tiddlyweb.web.tiddler:put 
    5858 
    5959/recipes/{recipe_name:segment}/tiddlers/{tiddler_name:segment}/revisions/{revision:segment} 
    60     GET tiddlyweb.web.tiddler:get_by_recipe 
     60    GET tiddlyweb.web.tiddler:get 
     61 
     62/recipes/{recipe_name:segment}/tiddlers/{tiddler_name:segment}/revisions[.{format}] 
     63    GET tiddlyweb.web.tiddler:get_revisions 
    6164 
    6265# list of bags 
     
    111114    GET tiddlyweb.web.tiddler:get 
    112115 
     116/bags/{bag_name:segment}/tiddlers/{tiddler_name:segment}/revisions[.{format}] 
     117    GET tiddlyweb.web.tiddler:get_revisions 
     118 
     119