/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: Jelmer Vernooij
  • Date: 2020-04-05 19:11:34 UTC
  • mto: (7490.7.16 work)
  • mto: This revision was merged to the branch mainline in revision 7501.
  • Revision ID: jelmer@jelmer.uk-20200405191134-0aebh8ikiwygxma5
Populate the .gitignore file.

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
import patiencediff
 
22
 
 
23
from ... import bugtracker, osutils
 
24
import re
 
25
 
 
26
_BUG_MATCH = re.compile(r'lp:(\d+)')
 
27
 
 
28
 
 
29
class CommitTemplate(object):
 
30
 
 
31
    def __init__(self, commit, message, filespec):
 
32
        """Create a commit template for commit with initial message message.
 
33
 
 
34
        :param commit: A Commit object for the in progress commit.
 
35
        :param message: The current message (which may be None).
 
36
        :param filespec: List of files to match
 
37
        """
 
38
        self.commit = commit
 
39
        self.message = message
 
40
        self.filespec = filespec
 
41
 
 
42
    def make(self):
 
43
        """Make the template.
 
44
 
 
45
        If NEWS is missing or not not modified, the original template is
 
46
        returned unaltered. Otherwise the changes from NEWS are concatenated
 
47
        with whatever message was provided to __init__.
 
48
        """
 
49
        delta = self.commit.builder.get_basis_delta()
 
50
        found_old_path = None
 
51
        found_entry = None
 
52
        for old_path, new_path, fileid, entry in delta:
 
53
            if new_path in self.filespec:
 
54
                found_entry = entry
 
55
                found_old_path = old_path
 
56
                break
 
57
        if not found_entry:
 
58
            return self.message
 
59
        if found_old_path is None:
 
60
            # New file
 
61
            _, new_chunks = list(
 
62
                self.commit.builder.repository.iter_files_bytes(
 
63
                    [(found_entry.file_id, found_entry.revision, None)]))[0]
 
64
            content = b''.join(new_chunks).decode('utf-8')
 
65
            return self.merge_message(content)
 
66
        else:
 
67
            # Get a diff. XXX Is this hookable? I thought it was, can't find it
 
68
            # though.... add DiffTree.diff_factories. Sadly thats not at the
 
69
            # right level: we want to identify the changed lines, not have the
 
70
            # final diff: because we want to grab the sections for regions
 
71
            # changed in new version of the file. So for now a direct diff
 
72
            # using patiencediff is done.
 
73
            old_revision = self.commit.basis_tree.get_file_revision(old_path)
 
74
            needed = [(found_entry.file_id, found_entry.revision, 'new'),
 
75
                      (found_entry.file_id, old_revision, 'old')]
 
76
            contents = self.commit.builder.repository.iter_files_bytes(needed)
 
77
            lines = {}
 
78
            for name, chunks in contents:
 
79
                lines[name] = osutils.chunks_to_lines(chunks)
 
80
            new = lines['new']
 
81
            sequence_matcher = patiencediff.PatienceSequenceMatcher(
 
82
                None, lines['old'], new)
 
83
            new_lines = []
 
84
            for group in sequence_matcher.get_opcodes():
 
85
                tag, i1, i2, j1, j2 = group
 
86
                if tag == 'equal':
 
87
                    continue
 
88
                if tag == 'delete':
 
89
                    continue
 
90
                new_lines.extend([l.decode('utf-8') for l in new[j1:j2]])
 
91
            if not self.commit.revprops.get('bugs'):
 
92
                # TODO: Allow the user to configure the bug tracker to use
 
93
                # rather than hardcoding Launchpad.
 
94
                bt = bugtracker.tracker_registry.get('launchpad')
 
95
                bugids = []
 
96
                for line in new_lines:
 
97
                    bugids.extend(_BUG_MATCH.findall(line))
 
98
                self.commit.revprops['bugs'] = \
 
99
                    bugtracker.encode_fixes_bug_urls(
 
100
                        [(bt.get_bug_url(bugid), bugtracker.FIXED)
 
101
                         for bugid in bugids])
 
102
            return self.merge_message(''.join(new_lines))
 
103
 
 
104
    def merge_message(self, new_message):
 
105
        """Merge new_message with self.message.
 
106
 
 
107
        :param new_message: A string message to merge with self.message.
 
108
        :return: A string with the merged messages.
 
109
        """
 
110
        if self.message is None:
 
111
            return new_message
 
112
        return self.message + new_message