from django.core.urlresolvers import reverse
from django.contrib.sites.models import Site
from django.conf import settings
+from patchwork.parser import hash_patch
import django.oldforms as oldforms
import re
person.save()
else:
for person in people:
- person.user = self.user
+ person.link_to_user(self.user)
person.save()
def __str__(self):
return self.name()
-def _confirm_key():
- allowedchars = string.ascii_lowercase + string.digits
- str = ''
- for i in range(1, 32):
- str += random.choice(allowedchars)
- return str;
-
-class UserPersonConfirmation(models.Model):
- user = models.ForeignKey(User)
- email = models.CharField(max_length = 200)
- key = models.CharField(max_length = 32, default = _confirm_key)
- date = models.DateTimeField(default=datetime.datetime.now)
- active = models.BooleanField(default = True)
-
- def confirm(self):
- if not self.active:
- return
- person = None
- try:
- person = Person.objects.get(email = self.email)
- except Exception:
- pass
- if not person:
- person = Person(email = self.email)
-
- person.link_to_user(self.user)
- person.save()
- self.active = False
-
class State(models.Model):
name = models.CharField(max_length = 100)
ordering = models.IntegerField(unique = True)
class Meta:
ordering = ['ordering']
-class HashField(models.Field):
+class HashField(models.CharField):
__metaclass__ = models.SubfieldBase
def __init__(self, algorithm = 'sha1', *args, **kwargs):
self.algorithm = algorithm
try:
import hashlib
- self.hashlib = True
+ def _construct(string = ''):
+ return hashlib.new(self.algorithm, string)
+ self.construct = _construct
+ self.n_bytes = len(hashlib.new(self.algorithm).hexdigest())
except ImportError:
- self.hashlib = False
- if algorithm == 'sha1':
- import sha
- self.hash_constructor = sha.new
- elif algorithm == 'md5':
- import md5
- self.hash_constructor = md5.new
- else:
+ modules = { 'sha1': 'sha', 'md5': 'md5'}
+
+ if algorithm not in modules.keys():
raise NameError("Unknown algorithm '%s'" % algorithm)
-
- super(HashField, self).__init__(*args, **kwargs)
- def db_type(self):
- if self.hashlib:
- n_bytes = len(hashlib.new(self.algorithm).digest())
- else:
- n_bytes = len(self.hash_constructor().digest())
- if settings.DATABASE_ENGINE == 'postgresql':
- return 'bytea'
- elif settings.DATABASE_ENGINE == 'mysql':
- return 'binary(%d)' % n_bytes
+ self.construct = __import__(modules[algorithm]).new
- def to_python(self, value):
- return value
+ self.n_bytes = len(self.construct().hexdigest())
- def get_db_prep_save(self, value):
- return ''.join(map(lambda x: '\\%03o' % ord(x), value))
+ kwargs['max_length'] = self.n_bytes
+ super(HashField, self).__init__(*args, **kwargs)
- def get_manipulator_field_objs(self):
- return [oldforms.TextField]
+ def db_type(self):
+ return 'char(%d)' % self.n_bytes
class Patch(models.Model):
project = models.ForeignKey(Project)
headers = models.TextField(blank = True)
content = models.TextField()
commit_ref = models.CharField(max_length=255, null = True, blank = True)
- hash = HashField()
+ hash = HashField(null = True, db_index = True)
def __str__(self):
return self.name
s = self.state
except:
self.state = State.objects.get(ordering = 0)
- if hash is None:
- print "no hash"
+
+ if self.hash is None:
+ self.hash = hash_patch(self.content).hexdigest()
+
super(Patch, self).save()
def is_editable(self, user):
def mbox(self):
comment = None
try:
- comment = Comment.objects.get(msgid = self.msgid)
+ comment = Comment.objects.get(patch = self, msgid = self.msgid)
except Exception:
pass
body = ''
if comment:
- body = comment.content.strip() + "\n\n"
+ body = comment.content.strip() + "\n"
+
+ responses = False
+ for comment in Comment.objects.filter(patch = self) \
+ .exclude(msgid = self.msgid):
+ body += comment.patch_responses()
+
+ if body:
+ body += '\n'
+
body += self.content
- mail = MIMEText(body)
+ mail = MIMEText(body, _charset = 'utf-8')
mail['Subject'] = self.name
mail['Date'] = email.utils.formatdate(
time.mktime(self.date.utctimetuple()))
headers = models.TextField(blank = True)
content = models.TextField()
+ response_re = re.compile('^(Acked|Signed-off|Nacked)-by: .*$', re.M)
+
+ def patch_responses(self):
+ return ''.join([ match.group(0) + '\n' for match in \
+ self.response_re.finditer(self.content)])
+
class Meta:
ordering = ['date']
return '\n'.join([p.mbox().as_string(True) \
for p in self.patches.all()])
+class UserPersonConfirmation(models.Model):
+ user = models.ForeignKey(User)
+ email = models.CharField(max_length = 200)
+ key = HashField()
+ date = models.DateTimeField(default=datetime.datetime.now)
+ active = models.BooleanField(default = True)
+
+ def confirm(self):
+ if not self.active:
+ return
+ person = None
+ try:
+ person = Person.objects.get(email = self.email)
+ except Exception:
+ pass
+ if not person:
+ person = Person(email = self.email)
+
+ person.link_to_user(self.user)
+ person.save()
+ self.active = False
+ self.save()
+
+ def save(self):
+ max = 1 << 32
+ if self.key == '':
+ str = '%s%s%d' % (self.user, self.email, random.randint(0, max))
+ self.key = self._meta.get_field('key').construct(str).hexdigest()
+ super(UserPersonConfirmation, self).save()
+
+