1
# -*- coding: utf-8 -*-
3
# QBzr - Qt frontend to Bazaar commands
4
# Copyright (C) 2009 Alexander Belchenko
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.
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.
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.
20
"""Commit data save/restore support."""
23
class CommitData(object):
24
"""Class to manipulate with commit data.
26
Hold the data as dictionary and provide dict-like interface.
27
All strings saved internally as unicode.
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)
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.
45
[bialix 20090812] Data saved in branch.conf in [commit_data] section
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).
59
self._data.update(data)
61
def _filtered_data(self):
62
"""Return copy of internal data dictionary without
63
keys with "empty" values (i.e. those equal to empty
67
for k,v in self._data.iteritems():
68
if v not in (None, ''):
72
def __nonzero__(self):
73
"""Check if there is some data actually.
74
@return: True if data dictionary is not empty.
76
return bool(self._filtered_data())
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.
83
return self._data.get(key)
85
def __setitem__(self, key, value):
86
"""Set new value for specified key."""
87
self._data[key] = value
89
def __delitem__(self, key):
90
"""Delete key from dictionary."""
94
"""Return keys of internal dict."""
95
return self._data.keys()
98
return self._data.copy()
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.
106
self._data.update(data)
107
for key, value in kw.iteritems():
108
self._data[key] = value
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.
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)
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)
128
self._data['bugs'] = ' '.join(bug_urls_to_ids(bug_urls.split('\n')))
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
140
for k,v in self._data.iteritems():
146
if set(self._data.keys()) != set(other.keys()):
150
def _load_old_data(self):
151
"""Load saved data in old format."""
155
"""Load saved data from branch/tree."""
156
config = self._get_branch_config()
157
data = config.get_user_option('commit_data')
161
# for backward compatibility
162
self._load_old_data()
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())
170
self._wipe_old_data()
172
def _wipe_old_data(self):
173
"""Wipe saved data in old format."""
177
"""Delete saved data from branch/tree config."""
178
config = self._get_branch_config()
179
config.set_user_option('commit_data', {})
181
self._wipe_old_data()
183
def _get_branch(self):
184
"""Return branch object if either branch or tree was specified on init.
185
Raise BzrInternalError otherwise.
190
return self._tree.branch
192
from bzrlib import errors
193
raise errors.BzrInternalError("CommitData has no saved branch or tree.")
195
def _get_branch_config(self):
196
return self._get_branch().get_config()
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.
205
def _load_old_data(self):
206
config = self._get_branch_config()
207
old_data = config.get_user_option('qbzr_commit_message')
209
self.set_data(message=old_data)
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', '')
217
# in similar way to QBzrCommitData it's possible to implement