/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 committemplate.py

Created plugin, basic functionality of looking for NEWS and including the
NEWS diff.

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 bzrlib.lazy_import import lazy_import
 
20
lazy_import(globals(), """
 
21
from bzrlib import osutils, patiencediff
 
22
""")
 
23
 
 
24
class CommitTemplate(object):
 
25
 
 
26
    def __init__(self, commit, message):
 
27
        """Create a commit template for commit with initial message message.
 
28
 
 
29
        :param commit: A Commit object for the in progress commit.
 
30
        :param message: The current message (which may be None).
 
31
        """
 
32
        self.commit = commit
 
33
        self.message = message
 
34
 
 
35
    def make(self):
 
36
        """Make the template.
 
37
 
 
38
        If NEWS is missing or not not modified, the original template is
 
39
        returned unaltered. Otherwise the changes from NEWS are concatenated
 
40
        with whatever message was provided to __init__.
 
41
        """
 
42
        try:
 
43
            delta = self.commit.builder.get_basis_delta()
 
44
        except AssertionError:
 
45
            # Not 2a, someone can write a slow-format code path if they want
 
46
            # to.
 
47
            return self.messsage
 
48
        found_old_path = None
 
49
        found_entry = None
 
50
        for old_path, new_path, fileid, entry in delta:
 
51
            if new_path == 'NEWS':
 
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(self.commit.builder.repository.iter_files_bytes(
 
60
                [(found_entry.file_id, found_entry.revision, None)]))[0]
 
61
            content = ''.join(new_chunks)
 
62
            return self.merge_message(content)
 
63
        else:
 
64
            # Get a diff. XXX Is this hookable? I thought it was, can't find it
 
65
            # though.... add DiffTree.diff_factories. Sadly thats not at the 
 
66
            # right level: we want to identify the changed lines, not have the
 
67
            # final diff: because we want to grab the sections for regions 
 
68
            # changed in new version of the file. So for now a direct diff
 
69
            # using patiencediff is done.
 
70
            old_entry = self.commit.basis_tree.inventory[found_entry.file_id]
 
71
            needed = [(found_entry.file_id, found_entry.revision, 'new'),
 
72
                (old_entry.file_id, old_entry.revision, 'old')]
 
73
            contents = self.commit.builder.repository.iter_files_bytes(needed)
 
74
            lines = {}
 
75
            for name, chunks in contents:
 
76
                lines[name] = osutils.chunks_to_lines(chunks)
 
77
            new = lines['new']
 
78
            sequence_matcher = patiencediff.PatienceSequenceMatcher(
 
79
                None, lines['old'], new)
 
80
            new_lines = []
 
81
            for group in sequence_matcher.get_opcodes():
 
82
                tag, i1, i2, j1, j2 = group
 
83
                if tag == 'equal':
 
84
                    continue
 
85
                if tag == 'delete':
 
86
                    continue
 
87
                new_lines.extend(new[j1:j2])
 
88
            return ''.join(new_lines)
 
89
 
 
90
    def merge_message(self, new_message):
 
91
        """Merge new_message with self.message.
 
92
        
 
93
        :param new_message: A string message to merge with self.message.
 
94
        :return: A string with the merged messages.
 
95
        """
 
96
        if self.message is None:
 
97
            return new_message
 
98
        return self.message + new_message