Basic in that it only handles the main inventory file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | ### Models
from django.db import models
from docutils.core import publish_parts
from jellyroll.models import Item
def restructuredtext(source):
"""
Use reStructuredText to format the given source text.
"""
parts = publish_parts(source=source, writer_name='html4css1')
return parts['html_body']
class DarcsRepository(models.Model):
"""
A darcs repository that you may commit patches to.
"""
name = models.CharField(maxlength=100)
slug = models.SlugField(prepopulate_from=('name',))
username = models.CharField(maxlength=100, blank=True, help_text='Your username - if provided, it will be used to filter patches.')
url = models.URLField(help_text='Don\'t include the <code>_darcs</code> folder.')
description = models.TextField(blank=True, help_text='Use <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">reStructuredText</a>')
description_html = models.TextField(editable=False, blank=True)
class Meta:
verbose_name_plural = 'darcs repositories'
class Admin:
list_display = ('name', 'url', 'username')
def __unicode__(self):
return self.name
def save(self):
if self.description:
self.description = self.description.strip()
self.description_html = restructuredtext(self.description).strip()
super(DarcsRepository, self).save()
class DarcsPatch(models.Model):
"""
A darcs patch.
"""
repository = models.ForeignKey(DarcsRepository, related_name='patches')
name = models.TextField()
author = models.CharField(maxlength=150)
timestamp = models.DateTimeField()
comment = models.TextField(blank=True)
inverted = models.BooleanField(default=False)
class Meta:
verbose_name_plural ='darcs patches'
ordering = ['-timestamp']
class Admin:
list_display = ('name', 'author', 'timestamp', 'repository')
list_filter = ('repository',)
search_fields = ('name', 'comment')
def __unicode__(self):
return self.name
# Register item objects to be "followed"
Item.objects.follow_model(DarcsPatch)
### Provider
import datetime
import logging
import re
import time
import urlparse
from django.db import transaction
from django.encoding import smart_unicode
from jellyroll.models import Item
from jellyroll.providers import utils
from somewhere.models import DarcsPatch, DarcsRepository
PATCH_DATE_FORMAT = '%Y%m%d%H%M%S'
patch_pattern = r"""
\[ # Patch start indicator
(?P<name>[^\n]+)\n # Patch name (rest of same line)
(?P<author>[^\*]+) # Patch author
\* # Author/date separator
(?P<inverted>[-\*]) # Inverted patch indicator
(?P<date>\d{14}) # Patch date
(?:\n(?P<comment>(?:^\ [^\n]*\n)+))? # Optional long comment
\] # Patch end indicator
"""
patch_re = re.compile(patch_pattern, re.VERBOSE | re.MULTILINE)
tidy_comment_re = re.compile(r'^ ', re.MULTILINE)
class Patch:
"""
Patch details, as defined in a darcs inventory file.
Attribute names match those generated by the
``darcs changes --xml-output`` command.
"""
def __init__(self, name, author, date, inverted, comment=None):
self.name = smart_unicode(name)
self.author = smart_unicode(author)
self.date = datetime(*time.strptime(date, PATCH_DATE_FORMAT)[:6])
self.inverted = inverted
self.comment = smart_unicode(comment)
def __str__(self):
return self.name
log = logging.getLogger('newsite.providers.darcs')
#
# Public API
#
def enabled():
return True # No dependencies
def update():
for repository in DarcsRepository.objects.all():
_update_repository(repository)
#
# Private API
#
def _update_repository(repository):
source_identifier = '%s:%s' % (__name__, repository.url)
last_update_date = Item.objects.get_last_update_of_model(DarcsPatch, source=source_identifier)
log.info(u'Updating changes from %s since %s', repository.url, last_update_date)
inventory = utils.fetch_resource(urlparse.urljoin(repository.url, '_darcs/inventory'))
for patch in reversed(list(_parse_inventory(inventory))):
if patch.date < last_update_date:
log.debug(u'Hit an old patch (commited %s; last update was %s); stopping.', patch.date, last_update_date)
break
if repository.username is None or repository.username in patch.author:
_handle_patch(repository, patch)
def _parse_inventory(inventory):
"""
Given the contents of a darcs inventory file, generates ``Patch``
objects representing contained patch details.
"""
for match in patch_re.finditer(inventory):
attrs = match.groupdict(None)
attrs['inverted'] = (attrs['inverted'] == '-')
if attrs['comment'] is not None:
attrs['comment'] = tidy_comment_re.sub('', attrs['comment']).strip()
yield Patch(**attrs)
@transaction.commit_on_success
def _handle_patch(repository, patch):
log.debug(u'Handling "%s" from %s' % (patch.name, repository.url))
ci, created = DarcsPatch.objects.get_or_create(
repository = repository,
author = patch.author,
name = patch.name,
timestamp = patch.date,
inverted = patch.inverted,
defaults = {'comment': patch.comment}
)
return Item.objects.create_or_update(
instance = ci,
timestamp = patch.date,
source = u'%s:%s' % (__name__, repository.url),
)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.