~qbzr-dev/qbzr/show-merge-depth

« back to all changes in this revision

Viewing changes to lib/commit_data.py

  • Committer: Gary van der Merwe
  • Date: 2009-08-19 12:41:14 UTC
  • mfrom: (677.1.243 trunk)
  • Revision ID: garyvdm@gmail.com-20090819124114-jz8zf4o4dlcl0a4r
Merge Trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
#
 
3
# QBzr - Qt frontend to Bazaar commands
 
4
# Copyright (C) 2009 Alexander Belchenko
 
5
#
 
6
# This program is free software; you can redistribute it and/or
 
7
# modify it under the terms of the GNU General Public License
 
8
# as published by the Free Software Foundation; either version 2
 
9
# of the License, or (at your option) any later version.
 
10
#
 
11
# This program is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with this program; if not, write to the Free Software
 
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
19
 
 
20
"""Commit data save/restore support."""
 
21
 
 
22
 
 
23
class CommitData(object):
 
24
    """Class to manipulate with commit data.
 
25
 
 
26
    Hold the data as dictionary and provide dict-like interface.
 
27
    All strings saved internally as unicode.
 
28
 
 
29
    Known items for data dict:
 
30
        message: main commit message.
 
31
        bugs: string with space separated fixed bugs ids
 
32
            in the form 'id:number'
 
33
        authors: string with name(s) of patch author(s)
 
34
        file_message: dict for per-file commit messages (used e.g. in MySQL),
 
35
            keys in this dict are filenames/fileids,
 
36
            values are specific commit messages.
 
37
        old_revid: old tip revid (before uncommit)
 
38
        new_revid: new tip revid (after uncommit)
 
39
 
 
40
    Pair of revision ids (old_revid and new_revid) could be used
 
41
    to get all revision messages from uncommitted chain.
 
42
    XXX provide some helper API to get uncommitted chain of revisions
 
43
    and/or graph and/or revisions data.
 
44
 
 
45
    [bialix 20090812] Data saved in branch.conf in [commit_data] section
 
46
    as plain dict.
 
47
    """
 
48
 
 
49
    def __init__(self, branch=None, tree=None, data=None):
 
50
        """Initialize data object attached to some tree.
 
51
        @param tree: working tree object for commit/uncommit.
 
52
        @param branch: branch object for commit/uncommit.
 
53
        @param data: initial data values (dictionary).
 
54
        """
 
55
        self._tree = tree
 
56
        self._branch = branch
 
57
        self._data = {}
 
58
        if data:
 
59
            self._data.update(data)
 
60
 
 
61
    def _filtered_data(self):
 
62
        """Return copy of internal data dictionary without
 
63
        keys with "empty" values (i.e. those equal to empty
 
64
        string or None).
 
65
        """
 
66
        d = {}
 
67
        for k,v in self._data.iteritems():
 
68
            if v not in (None, ''):
 
69
                d[k] = v
 
70
        return d
 
71
 
 
72
    def __nonzero__(self):
 
73
        """Check if there is some data actually.
 
74
        @return: True if data dictionary is not empty.
 
75
        """
 
76
        return bool(self._filtered_data())
 
77
 
 
78
    def __getitem__(self, key):
 
79
        """Read the value of specified key via dict-like interface, e.g. a[key].
 
80
        @param key: key in data dictionary.
 
81
        @return: value or None if there is no such key.
 
82
        """
 
83
        return self._data.get(key)
 
84
 
 
85
    def __setitem__(self, key, value):
 
86
        """Set new value for specified key."""
 
87
        self._data[key] = value
 
88
 
 
89
    def __delitem__(self, key):
 
90
        """Delete key from dictionary."""
 
91
        del self._data[key]
 
92
 
 
93
    def keys(self):
 
94
        """Return keys of internal dict."""
 
95
        return self._data.keys()
 
96
 
 
97
    def as_dict(self):
 
98
        return self._data.copy()
 
99
 
 
100
    def set_data(self, data=None, **kw):
 
101
        """Set new data to dictionary (e.g. to save data from commit dialog).
 
102
        @param data: dictionary with new data.
 
103
        @param kw: pairs name=value to insert.
 
104
        """
 
105
        if data:
 
106
            self._data.update(data)
 
107
        for key, value in kw.iteritems():
 
108
            self._data[key] = value
 
109
 
 
110
    def set_data_on_uncommit(self, old_revid, new_revid):
 
111
        """Set data from post_uncommit hook.
 
112
        @param old_revid: old tip revid (before uncommit)
 
113
        @param new_revid: new tip revid (after uncommit). Could be None.
 
114
        """
 
115
        from bzrlib.plugins.qbzr.lib.bugs import bug_urls_to_ids
 
116
        branch = self._get_branch()
 
117
        revision = branch.repository.get_revision(old_revid)
 
118
        # remember revids
 
119
        self._data['old_revid'] = old_revid
 
120
        if new_revid is None:
 
121
            from bzrlib.revision import NULL_REVISION
 
122
            new_revid = NULL_REVISION
 
123
        self._data['new_revid'] = new_revid
 
124
        # set data from revision
 
125
        self._data['message'] = revision.message or ''
 
126
        bug_urls = revision.properties.get('bugs', None)
 
127
        if bug_urls:
 
128
            self._data['bugs'] = ' '.join(bug_urls_to_ids(bug_urls.split('\n')))
 
129
 
 
130
    def compare_data(self, other, all_keys=True):
 
131
        """Compare this data with other data.
 
132
        @return:    True if data equals.
 
133
        @param other: other object (dict or instance of CommitData).
 
134
        @param all_keys: if True all keys in both objects
 
135
            are compared. If False then only keys in this
 
136
            instance compared with corresponding keys in other
 
137
            instance.
 
138
        """
 
139
        try:
 
140
            for k,v in self._data.iteritems():
 
141
                if v != other[k]:
 
142
                    return False
 
143
        except KeyError:
 
144
            return False
 
145
        if all_keys:
 
146
            if set(self._data.keys()) != set(other.keys()):
 
147
                return False
 
148
        return True
 
149
 
 
150
    def _load_old_data(self):
 
151
        """Load saved data in old format."""
 
152
        return
 
153
 
 
154
    def load(self):
 
155
        """Load saved data from branch/tree."""
 
156
        config = self._get_branch_config()
 
157
        data = config.get_user_option('commit_data')
 
158
        if data:
 
159
            self.set_data(data)
 
160
        else:
 
161
            # for backward compatibility
 
162
            self._load_old_data()
 
163
 
 
164
    def save(self):
 
165
        """Save data to the branch/tree."""
 
166
        # XXX save should wipe if self._data is empty
 
167
        config = self._get_branch_config()
 
168
        config.set_user_option('commit_data', self._filtered_data())
 
169
        # clear old data
 
170
        self._wipe_old_data()
 
171
 
 
172
    def _wipe_old_data(self):
 
173
        """Wipe saved data in old format."""
 
174
        return
 
175
 
 
176
    def wipe(self):
 
177
        """Delete saved data from branch/tree config."""
 
178
        config = self._get_branch_config()
 
179
        config.set_user_option('commit_data', {})
 
180
        # clear old data
 
181
        self._wipe_old_data()
 
182
 
 
183
    def _get_branch(self):
 
184
        """Return branch object if either branch or tree was specified on init.
 
185
        Raise BzrInternalError otherwise.
 
186
        """
 
187
        if self._branch:
 
188
            return self._branch
 
189
        if self._tree:
 
190
            return self._tree.branch
 
191
        # too bad
 
192
        from bzrlib import errors
 
193
        raise errors.BzrInternalError("CommitData has no saved branch or tree.")
 
194
 
 
195
    def _get_branch_config(self):
 
196
        return self._get_branch().get_config()
 
197
 
 
198
 
 
199
class QBzrCommitData(CommitData):
 
200
    """CommitData variant with backward compatibility support.
 
201
    This class knows about old data saved as qbzr_commit_message
 
202
    and can provide automatic migration of data.
 
203
    """
 
204
 
 
205
    def _load_old_data(self):
 
206
        config = self._get_branch_config()
 
207
        old_data = config.get_user_option('qbzr_commit_message')
 
208
        if old_data:
 
209
            self.set_data(message=old_data)
 
210
 
 
211
    def _wipe_old_data(self):
 
212
        config = self._get_branch_config()
 
213
        if config.get_user_option('qbzr_commit_message'):
 
214
            config.set_user_option('qbzr_commit_message', '')
 
215
 
 
216
 
 
217
# in similar way to QBzrCommitData it's possible to implement
 
218
# class for bzr-gtk.