From 0521d8b2e26242fa3a161df50b3f61b9a05ae0dd Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 9 Sep 2008 17:26:38 +1000 Subject: [PATCH] Hook-up hashing infrastructure Signed-off-by: Jeremy Kerr --- apps/patchwork/bin/rehash.py | 28 +++++++++++++++++ apps/patchwork/models.py | 9 ++++-- apps/patchwork/parser.py | 61 ++++++++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 5 deletions(-) create mode 100755 apps/patchwork/bin/rehash.py diff --git a/apps/patchwork/bin/rehash.py b/apps/patchwork/bin/rehash.py new file mode 100755 index 0000000..1b3e3e9 --- /dev/null +++ b/apps/patchwork/bin/rehash.py @@ -0,0 +1,28 @@ +#!/usr/bin/python +# +# Patchwork - automated patch tracking system +# Copyright (C) 2008 Jeremy Kerr +# +# This file is part of the Patchwork package. +# +# Patchwork is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Patchwork is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Patchwork; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from patchwork.models import Patch + +if __name__ == '__main__': + for patch in Patch.objects.all(): + print patch.id, patch.name + patch.hash = None + patch.save() diff --git a/apps/patchwork/models.py b/apps/patchwork/models.py index fb2ccc7..f354acb 100644 --- a/apps/patchwork/models.py +++ b/apps/patchwork/models.py @@ -22,6 +22,7 @@ from django.contrib.auth.models import User 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 @@ -223,7 +224,7 @@ class Patch(models.Model): 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) def __str__(self): return self.name @@ -236,8 +237,10 @@ class Patch(models.Model): 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).digest() + super(Patch, self).save() def is_editable(self, user): diff --git a/apps/patchwork/parser.py b/apps/patchwork/parser.py index 16d1de4..8ed36cc 100644 --- a/apps/patchwork/parser.py +++ b/apps/patchwork/parser.py @@ -22,6 +22,16 @@ import re +try: + import hashlib + sha1_hash = hashlib.sha1 +except ImportError: + import sha + sha1_hash = sha.sha + +_hunk_re = re.compile('^\@\@ -\d+(?:,(\d+))? \+\d+(?:,(\d+))? \@\@') +_filename_re = re.compile('^(---|\+\+\+) (\S+)') + def parse_patch(text): patchbuf = '' commentbuf = '' @@ -53,7 +63,6 @@ def parse_patch(text): lc = (0, 0) hunk = 0 - hunk_re = re.compile('^\@\@ -\d+(?:,(\d+))? \+\d+(?:,(\d+))? \@\@') for line in text.split('\n'): line += '\n' @@ -91,7 +100,7 @@ def parse_patch(text): buf = '' elif state == 3: - match = hunk_re.match(line) + match = _hunk_re.match(line) if match: def fn(x): @@ -149,10 +158,58 @@ def parse_patch(text): return (patchbuf, commentbuf) +def hash_patch(str): + # normalise spaces + str = str.replace('\r', '') + str = str.strip() + '\n' + + prefixes = ['-', '+', ' '] + hash = sha1_hash() + + for line in str.split('\n'): + + if len(line) <= 0: + continue + + hunk_match = _hunk_re.match(line) + filename_match = _filename_re.match(line) + + if filename_match: + # normalise -p1 top-directories + if filename_match.group(1) == '---': + filename = 'a/' + else: + filename = 'b/' + filename += '/'.join(filename_match.group(2).split('/')[1:]) + + line = filename_match.group(1) + ' ' + filename + + elif hunk_match: + # remove line numbers, but leave line counts + def fn(x): + if not x: + return 1 + return int(x) + line_nos = map(fn, hunk_match.groups()) + line = '@@ -%d +%d @@' % tuple(line_nos) + + elif line[0] in prefixes: + # if we have a +, - or context line, leave as-is + pass + + else: + # other lines are ignored + continue + + hash.update(line.encode('utf-8') + '\n') + + return hash + if __name__ == '__main__': import sys (patch, comment) = parse_patch(sys.stdin.read()) if patch: print "Patch: ------\n" + patch + print "hash: %s" % hash_patch(patch).hexdigest() if comment: print "Comment: ----\n" + comment -- 2.39.2