/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/plugins/commitfromnews/committemplate.py

  • Committer: Richard Wilbur
  • Date: 2016-02-04 19:07:28 UTC
  • mto: This revision was merged to the branch mainline in revision 6618.
  • Revision ID: richard.wilbur@gmail.com-20160204190728-p0zvfii6zase0fw7
Update COPYING.txt from the original http://www.gnu.org/licenses/gpl-2.0.txt  (Only differences were in whitespace.)  Thanks to Petr Stodulka for pointing out the discrepancy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2010 Canonical Ltd
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
"""Logic to create commit templates."""
18
 
 
19
 
from __future__ import absolute_import
20
 
 
21
 
from ... import bugtracker, osutils, patiencediff
22
 
import re
23
 
 
24
 
_BUG_MATCH = re.compile(r'lp:(\d+)')
25
 
 
26
 
 
27
 
class CommitTemplate(object):
28
 
 
29
 
    def __init__(self, commit, message, filespec):
30
 
        """Create a commit template for commit with initial message message.
31
 
 
32
 
        :param commit: A Commit object for the in progress commit.
33
 
        :param message: The current message (which may be None).
34
 
        :param filespec: List of files to match
35
 
        """
36
 
        self.commit = commit
37
 
        self.message = message
38
 
        self.filespec = filespec
39
 
 
40
 
    def make(self):
41
 
        """Make the template.
42
 
 
43
 
        If NEWS is missing or not not modified, the original template is
44
 
        returned unaltered. Otherwise the changes from NEWS are concatenated
45
 
        with whatever message was provided to __init__.
46
 
        """
47
 
        delta = self.commit.builder.get_basis_delta()
48
 
        found_old_path = None
49
 
        found_entry = None
50
 
        for old_path, new_path, fileid, entry in delta:
51
 
            if new_path in self.filespec:
52
 
                found_entry = entry
53
 
                found_old_path = old_path
54
 
                break
55
 
        if not found_entry:
56
 
            return self.message
57
 
        if found_old_path is None:
58
 
            # New file
59
 
            _, new_chunks = list(
60
 
                self.commit.builder.repository.iter_files_bytes(
61
 
                    [(found_entry.file_id, found_entry.revision, None)]))[0]
62
 
            content = ''.join(new_chunks)
63
 
            return self.merge_message(content)
64
 
        else:
65
 
            # Get a diff. XXX Is this hookable? I thought it was, can't find it
66
 
            # though.... add DiffTree.diff_factories. Sadly thats not at the 
67
 
            # right level: we want to identify the changed lines, not have the
68
 
            # final diff: because we want to grab the sections for regions 
69
 
            # changed in new version of the file. So for now a direct diff
70
 
            # using patiencediff is done.
71
 
            old_revision = self.commit.basis_tree.get_file_revision(
72
 
                old_path, found_entry.file_id)
73
 
            needed = [(found_entry.file_id, found_entry.revision, 'new'),
74
 
                      (found_entry.file_id, old_revision, 'old')]
75
 
            contents = self.commit.builder.repository.iter_files_bytes(needed)
76
 
            lines = {}
77
 
            for name, chunks in contents:
78
 
                lines[name] = osutils.chunks_to_lines(chunks)
79
 
            new = lines['new']
80
 
            sequence_matcher = patiencediff.PatienceSequenceMatcher(
81
 
                None, lines['old'], new)
82
 
            new_lines = []
83
 
            for group in sequence_matcher.get_opcodes():
84
 
                tag, i1, i2, j1, j2 = group
85
 
                if tag == 'equal':
86
 
                    continue
87
 
                if tag == 'delete':
88
 
                    continue
89
 
                new_lines.extend(new[j1:j2])
90
 
            if not self.commit.revprops.get('bugs'):
91
 
                # TODO: Allow the user to configure the bug tracker to use
92
 
                # rather than hardcoding Launchpad.
93
 
                bt = bugtracker.tracker_registry.get('launchpad')
94
 
                bugids = []
95
 
                for line in new_lines:
96
 
                    bugids.extend(_BUG_MATCH.findall(line))
97
 
                self.commit.revprops['bugs'] = \
98
 
                    bugtracker.encode_fixes_bug_urls(
99
 
                        [bt.get_bug_url(bugid) for bugid in bugids])
100
 
            return self.merge_message(''.join(new_lines))
101
 
 
102
 
    def merge_message(self, new_message):
103
 
        """Merge new_message with self.message.
104
 
 
105
 
        :param new_message: A string message to merge with self.message.
106
 
        :return: A string with the merged messages.
107
 
        """
108
 
        if self.message is None:
109
 
            return new_message
110
 
        return self.message + new_message