Merge lp:~maria-captains/bzr-gtk/gcommit-fixes into lp:bzr-gtk/gtk2
- gcommit-fixes
- Merge into gtk2
Status: | Work in progress |
---|---|
Proposed branch: | lp:~maria-captains/bzr-gtk/gcommit-fixes |
Merge into: | lp:bzr-gtk/gtk2 |
Diff against target: |
261 lines (+128/-5) 3 files modified
NEWS (+4/-0) bugtrackerex.py (+47/-0) commit.py (+77/-5) |
To merge this branch: | bzr merge lp:~maria-captains/bzr-gtk/gcommit-fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jelmer Vernooij (community) | Needs Fixing | ||
Review via email: mp+48206@code.launchpad.net |
Commit message
Description of the change
Sergei Golubchik (sergii) wrote : | # |
Hi, Jelmer!
On Feb 01, Jelmer Vernooij wrote:
> Thanks for working on this! :)
>
> I don't understand why bugtrackerex.py is necessary. If the existing
> code in bzrlib.bugtracker isn't sufficient, please extend it rather
> than duplicating it here.
I wanted to stay within bzr-gtk.
How to do that otherwise - you want me to submit a merge request to bzr
tree with this change (extending bzrlib.bugtracker), and when it's
accepted do another one for bzr-gtk ?
That would be the right way, I agree. Although I afraid that bzr, as a
bigger project with more developers will be slower to accept a patch.
But I could try, by all means.
> Is there any particular reason why you've added a configuration
> option, rather than always allowing users to specify the bug # ? I
> think it'd be reasonable to enable this functionality unconditionally.
I copied this from per-file comments. It also has a configuration
option.
I got an idea (from the comments in the code) that it was done
to have more screen space dedicated to diff and changeset comment and
not waste it on per-file comments, when user does not want them.
So, I figured out that it applies as well to "bugs" input field.
If you'd like I can remove it, sure.
Regards,
Sergei
Jelmer Vernooij (jelmer) wrote : | # |
Hi Sergei,
On Tue, Feb 01, 2011 at 09:36:45PM -0000, Sergei wrote:
> On Feb 01, Jelmer Vernooij wrote:
> > Thanks for working on this! :)
> >
> > I don't understand why bugtrackerex.py is necessary. If the existing
> > code in bzrlib.bugtracker isn't sufficient, please extend it rather
> > than duplicating it here.
> I wanted to stay within bzr-gtk.
>
> How to do that otherwise - you want me to submit a merge request to bzr
> tree with this change (extending bzrlib.bugtracker), and when it's
> accepted do another one for bzr-gtk ?
Yeah, that'd be great. That way others can also take advantage of your
improvements.
> That would be the right way, I agree. Although I afraid that bzr, as a
> bigger project with more developers will be slower to accept a patch.
>
> But I could try, by all means.
Bazaar has higher quality standards for new code, in particular requiring unit
tests for new code. On the other hand, Bazaar has a dedicated patch pilot
who helps community members land finish and land patches. If there's anything I can
help with, please ping me on email or IRC (#bzr).
> > Is there any particular reason why you've added a configuration
> > option, rather than always allowing users to specify the bug # ? I
> > think it'd be reasonable to enable this functionality unconditionally.
> I copied this from per-file comments. It also has a configuration
> option.
per file commit comments is a feature that's really just a hack in bzr-gtk at
the moment, unlike bugs which is supported by bzr core. IIUC it was mainly
added because a particular project needed it, and so they have the chance to
enable it if they want to.
> I got an idea (from the comments in the code) that it was done
> to have more screen space dedicated to diff and changeset comment and
> not waste it on per-file comments, when user does not want them.
>
> So, I figured out that it applies as well to "bugs" input field.
>
> If you'd like I can remove it, sure.
Please do, I think this is useful enough to be enabled by default rather
than just for those people who happen to know about the magic option.
Cheers,
Jelmer
Sergei Golubchik (sergii) wrote : | # |
Hi, Jelmer!
On Feb 01, Jelmer Vernooij wrote:
> > >
> > > I don't understand why bugtrackerex.py is necessary. If the
> > > existing code in bzrlib.bugtracker isn't sufficient, please extend
> > > it rather than duplicating it here.
You see, the functionality I added to bugtrackerex is not needed for bzr
core.
Let me explain how bugs work in bzr.
bzr commit --fixes takes a list of bug ids in the form of
[tracker]:[id]. Then it converts them into urls, e.g. lp:123 is
converted into https:/
It generates a string, something like this
'\n'.join([url + ' fixes' for url in bug_url_list])
which then gets stored with the changeset.
All tools that show bugs, say, bzr log or bzr uncommit, get this string,
split on '\n', take the first word, ignore the second (yes!), and show
urls.
It certainly looks like whoever did that planned to have more complex
feature, where instead of "fixes" there could be different words
describing the relation of the bug number to the changeset. For example,
"fixes", "tests", etc. But it was not implemented.
Anyway, my point is - for 'bzr uncommit' to work in bzr-gtk, it needs to
save bug ids in the lp:123 form (to be able to show them in
gcommit). And to do that, it needs to *reverse engineer* bug urls back
into [tracker]:[id]. That's what bugtrackerex.py is doing.
But bzr core does not need that at all. It never needs to convert bug
urls back into bug ids.
You still want me to submit a merge request to bzr core?
Regards,
Sergei
Jelmer Vernooij (jelmer) wrote : | # |
Setting this back to work-in-progress for the moment so it doesn't show up in the review queue. Please set back to needs-review when it uses the new bugtracker infrastructure in bzrlib.
Unmerged revisions
- 708. By Sergei Golubchik
-
Added support for bugs (as in "bzr commit --fixes") to gcommit.
This includes reverse-engineering of bug urls by extending the core
bzr classes. Because bzr does that to bugs :(Only lp: gnome: and debian: urls are supported by this changeset.
Preview Diff
1 | === modified file 'NEWS' | |||
2 | --- NEWS 2011-01-16 18:55:13 +0000 | |||
3 | +++ NEWS 2011-02-01 17:50:14 +0000 | |||
4 | @@ -1,5 +1,9 @@ | |||
5 | 1 | 0.100.0 UNRELEASED | 1 | 0.100.0 UNRELEASED |
6 | 2 | 2 | ||
7 | 3 | FEATURES | ||
8 | 4 | |||
9 | 5 | * Added support for bugs (as in "bzr commit --fixes") to gcommit. | ||
10 | 6 | |||
11 | 3 | BUG FIXES | 7 | BUG FIXES |
12 | 4 | 8 | ||
13 | 5 | * Clarify 'visualise' help about the multiple branches feature | 9 | * Clarify 'visualise' help about the multiple branches feature |
14 | 6 | 10 | ||
15 | === added file 'bugtrackerex.py' | |||
16 | --- bugtrackerex.py 1970-01-01 00:00:00 +0000 | |||
17 | +++ bugtrackerex.py 2011-02-01 17:50:14 +0000 | |||
18 | @@ -0,0 +1,47 @@ | |||
19 | 1 | from bzrlib.bugtracker import * | ||
20 | 2 | from bzrlib import errors | ||
21 | 3 | |||
22 | 4 | def _iter_bug_fix_urls(fixes, branch): | ||
23 | 5 | # Configure the properties for bug fixing attributes. | ||
24 | 6 | for fixed_bug in fixes: | ||
25 | 7 | tokens = fixed_bug.split(':') | ||
26 | 8 | if len(tokens) != 2: | ||
27 | 9 | raise errors.BzrCommandError( | ||
28 | 10 | "Invalid bug %s. Must be in the form of 'tracker:id'. " | ||
29 | 11 | "See \"bzr help bugs\" for more information on this " | ||
30 | 12 | "feature.\nCommit refused." % fixed_bug) | ||
31 | 13 | tag, bug_id = tokens | ||
32 | 14 | try: | ||
33 | 15 | yield get_bug_url(tag, branch, bug_id) | ||
34 | 16 | except errors.UnknownBugTrackerAbbreviation: | ||
35 | 17 | raise errors.BzrCommandError( | ||
36 | 18 | 'Unrecognized bug %s. Commit refused.' % fixed_bug) | ||
37 | 19 | except errors.MalformedBugIdentifier, e: | ||
38 | 20 | raise errors.BzrCommandError( | ||
39 | 21 | "%s\nCommit refused." % (str(e),)) | ||
40 | 22 | |||
41 | 23 | def encode_fixes_bug_ids(fixes, branch): | ||
42 | 24 | return encode_fixes_bug_urls(_iter_bug_fix_urls(fixes, branch)) | ||
43 | 25 | |||
44 | 26 | def get_bugtracker_and_bug_id(url, branch): | ||
45 | 27 | """this is the reverse of get_bug_url - return an | ||
46 | 28 | abbreviated_bugtracker_name and bug_id when given a full bug url | ||
47 | 29 | """ | ||
48 | 30 | for tracker_name in tracker_registry.keys(): | ||
49 | 31 | tracker = tracker_registry.get(tracker_name) | ||
50 | 32 | if hasattr(tracker, 'reverse_engineer'): | ||
51 | 33 | abbreviation, bug_id = tracker.reverse_engineer(url, branch) | ||
52 | 34 | if bug_id is not None: | ||
53 | 35 | return abbreviation, bug_id | ||
54 | 36 | # raising an error here corrupts the tree in a way that | ||
55 | 37 | # is not obvious to recover from. As it's only a value to help | ||
56 | 38 | # the user to fill in the bug number on the next commit, don't | ||
57 | 39 | # abort if it cannot be reversed. | ||
58 | 40 | return 'UNRECOGNIZED', url | ||
59 | 41 | |||
60 | 42 | def _UniqueIntegerBugTracker_reverse_engineer(self, url, branch): | ||
61 | 43 | if url.startswith(self.base_url): | ||
62 | 44 | return self.abbreviation, url[len(self.base_url):] | ||
63 | 45 | return None, None | ||
64 | 46 | |||
65 | 47 | UniqueIntegerBugTracker.reverse_engineer = _UniqueIntegerBugTracker_reverse_engineer | ||
66 | 0 | 48 | ||
67 | === modified file 'commit.py' | |||
68 | --- commit.py 2010-07-21 20:21:17 +0000 | |||
69 | +++ commit.py 2011-02-01 17:50:14 +0000 | |||
70 | @@ -125,6 +125,7 @@ | |||
71 | 125 | # It used to set all changes but this one to False | 125 | # It used to set all changes but this one to False |
72 | 126 | self._selected = selected | 126 | self._selected = selected |
73 | 127 | self._enable_per_file_commits = True | 127 | self._enable_per_file_commits = True |
74 | 128 | self._enable_bugs_fixed = True | ||
75 | 128 | self._commit_all_changes = True | 129 | self._commit_all_changes = True |
76 | 129 | self.committed_revision_id = None # Nothing has been committed yet | 130 | self.committed_revision_id = None # Nothing has been committed yet |
77 | 130 | self._saved_commit_messages_manager = SavedCommitMessagesManager(self._wt, self._wt.branch) | 131 | self._saved_commit_messages_manager = SavedCommitMessagesManager(self._wt, self._wt.branch) |
78 | @@ -148,6 +149,7 @@ | |||
79 | 148 | self._fill_in_files() | 149 | self._fill_in_files() |
80 | 149 | self._fill_in_checkout() | 150 | self._fill_in_checkout() |
81 | 150 | self._fill_in_per_file_info() | 151 | self._fill_in_per_file_info() |
82 | 152 | self._fill_in_bug_info() | ||
83 | 151 | 153 | ||
84 | 152 | def _fill_in_pending(self): | 154 | def _fill_in_pending(self): |
85 | 153 | if not self._pending: | 155 | if not self._pending: |
86 | @@ -279,6 +281,18 @@ | |||
87 | 279 | self._file_message_expander.hide() | 281 | self._file_message_expander.hide() |
88 | 280 | self._global_message_label.set_markup(_i18n('<b>Commit Message</b>')) | 282 | self._global_message_label.set_markup(_i18n('<b>Commit Message</b>')) |
89 | 281 | 283 | ||
90 | 284 | def _fill_in_bug_info(self): | ||
91 | 285 | config = self._wt.branch.get_config() | ||
92 | 286 | enable_bugs_fixed = config.get_user_option('bugs_fixed') | ||
93 | 287 | if (enable_bugs_fixed is None | ||
94 | 288 | or enable_bugs_fixed.lower() | ||
95 | 289 | not in ('y', 'yes', 'on', 'enable', '1', 't', 'true')): | ||
96 | 290 | self._enable_bugs_fixed = False | ||
97 | 291 | else: | ||
98 | 292 | self._enable_bugs_fixed = True | ||
99 | 293 | if not self._enable_bugs_fixed: | ||
100 | 294 | self._bugs_fixed_expander.hide() | ||
101 | 295 | |||
102 | 282 | def _compute_delta(self): | 296 | def _compute_delta(self): |
103 | 283 | self._delta = self._wt.changes_from(self._basis_tree) | 297 | self._delta = self._wt.changes_from(self._basis_tree) |
104 | 284 | 298 | ||
105 | @@ -350,6 +364,7 @@ | |||
106 | 350 | self._right_pane_table.set_col_spacings(5) | 364 | self._right_pane_table.set_col_spacings(5) |
107 | 351 | self._right_pane_table_row = 0 | 365 | self._right_pane_table_row = 0 |
108 | 352 | self._construct_diff_view() | 366 | self._construct_diff_view() |
109 | 367 | self._construct_bugs_fixed() | ||
110 | 353 | self._construct_file_message() | 368 | self._construct_file_message() |
111 | 354 | self._construct_global_message() | 369 | self._construct_global_message() |
112 | 355 | 370 | ||
113 | @@ -528,6 +543,27 @@ | |||
114 | 528 | self._add_to_right_table(self._diff_view, 4, True) | 543 | self._add_to_right_table(self._diff_view, 4, True) |
115 | 529 | self._diff_view.show() | 544 | self._diff_view.show() |
116 | 530 | 545 | ||
117 | 546 | def _construct_bugs_fixed(self): | ||
118 | 547 | scroller = gtk.ScrolledWindow() | ||
119 | 548 | scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | ||
120 | 549 | |||
121 | 550 | self._bugs_fixed_text_view = gtk.TextView() | ||
122 | 551 | scroller.add(self._bugs_fixed_text_view) | ||
123 | 552 | scroller.set_shadow_type(gtk.SHADOW_IN) | ||
124 | 553 | scroller.show() | ||
125 | 554 | |||
126 | 555 | self._bugs_fixed_text_view.modify_font(pango.FontDescription("Monospace")) | ||
127 | 556 | self._bugs_fixed_text_view.set_wrap_mode(gtk.WRAP_WORD) | ||
128 | 557 | self._bugs_fixed_text_view.set_accepts_tab(False) | ||
129 | 558 | self._bugs_fixed_text_view.show() | ||
130 | 559 | |||
131 | 560 | self._bugs_fixed_expander = gtk.Expander(_i18n('Bugs fixed')) | ||
132 | 561 | self._bugs_fixed_expander.set_expanded(False) | ||
133 | 562 | self._bugs_fixed_expander.add(scroller) | ||
134 | 563 | self._add_to_right_table(self._bugs_fixed_expander, 1, False) | ||
135 | 564 | self._set_bugs_fixed_list(self._saved_commit_messages_manager.get()[2]) | ||
136 | 565 | self._bugs_fixed_expander.show() | ||
137 | 566 | |||
138 | 531 | def _construct_file_message(self): | 567 | def _construct_file_message(self): |
139 | 532 | scroller = gtk.ScrolledWindow() | 568 | scroller = gtk.ScrolledWindow() |
140 | 533 | scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | 569 | scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) |
141 | @@ -683,7 +719,8 @@ | |||
142 | 683 | mgr = SavedCommitMessagesManager() | 719 | mgr = SavedCommitMessagesManager() |
143 | 684 | self._saved_commit_messages_manager = mgr | 720 | self._saved_commit_messages_manager = mgr |
144 | 685 | mgr.insert(self._get_global_commit_message(), | 721 | mgr.insert(self._get_global_commit_message(), |
146 | 686 | self._get_specific_files()[1]) | 722 | self._get_specific_files()[1], |
147 | 723 | self._get_bugs_fixed_list()) | ||
148 | 687 | if mgr.is_not_empty(): # maybe worth saving | 724 | if mgr.is_not_empty(): # maybe worth saving |
149 | 688 | response = self._question_dialog( | 725 | response = self._question_dialog( |
150 | 689 | _i18n('Commit cancelled'), | 726 | _i18n('Commit cancelled'), |
151 | @@ -702,6 +739,7 @@ | |||
152 | 702 | 739 | ||
153 | 703 | def _do_commit(self): | 740 | def _do_commit(self): |
154 | 704 | message = self._get_global_commit_message() | 741 | message = self._get_global_commit_message() |
155 | 742 | bugs_fixed = self._get_bugs_fixed_list() | ||
156 | 705 | 743 | ||
157 | 706 | if message == '': | 744 | if message == '': |
158 | 707 | response = self._question_dialog( | 745 | response = self._question_dialog( |
159 | @@ -738,6 +776,12 @@ | |||
160 | 738 | revprops = {} | 776 | revprops = {} |
161 | 739 | if file_info: | 777 | if file_info: |
162 | 740 | revprops['file-info'] = bencode.bencode(file_info).decode('UTF-8') | 778 | revprops['file-info'] = bencode.bencode(file_info).decode('UTF-8') |
163 | 779 | if bugs_fixed: | ||
164 | 780 | from bzrlib.plugins.gtk import bugtrackerex | ||
165 | 781 | fixes = bugs_fixed.split() | ||
166 | 782 | bug_property = bugtrackerex.encode_fixes_bug_ids(fixes, self._wt.branch) | ||
167 | 783 | if bug_property: | ||
168 | 784 | revprops['bugs'] = bug_property | ||
169 | 741 | try: | 785 | try: |
170 | 742 | rev_id = self._wt.commit(message, | 786 | rev_id = self._wt.commit(message, |
171 | 743 | allow_pointless=False, | 787 | allow_pointless=False, |
172 | @@ -769,12 +813,26 @@ | |||
173 | 769 | text = buf.get_text(start, end) | 813 | text = buf.get_text(start, end) |
174 | 770 | return _sanitize_and_decode_message(text) | 814 | return _sanitize_and_decode_message(text) |
175 | 771 | 815 | ||
176 | 816 | def _get_bugs_fixed_list(self): | ||
177 | 817 | buf = self._bugs_fixed_text_view.get_buffer() | ||
178 | 818 | start, end = buf.get_bounds() | ||
179 | 819 | text = buf.get_text(start, end) | ||
180 | 820 | return _sanitize_and_decode_message(text) | ||
181 | 821 | |||
182 | 772 | def _set_global_commit_message(self, message): | 822 | def _set_global_commit_message(self, message): |
183 | 773 | """Just a helper for the test suite.""" | 823 | """Just a helper for the test suite.""" |
184 | 774 | if isinstance(message, unicode): | 824 | if isinstance(message, unicode): |
185 | 775 | message = message.encode('UTF-8') | 825 | message = message.encode('UTF-8') |
186 | 776 | self._global_message_text_view.get_buffer().set_text(message) | 826 | self._global_message_text_view.get_buffer().set_text(message) |
187 | 777 | 827 | ||
188 | 828 | def _set_bugs_fixed_list(self, message): | ||
189 | 829 | """Just a helper for the test suite.""" | ||
190 | 830 | if isinstance(message, unicode): | ||
191 | 831 | message = message.encode('UTF-8') | ||
192 | 832 | if len(message) > 0: | ||
193 | 833 | self._bugs_fixed_text_view.get_buffer().set_text(message) | ||
194 | 834 | self._bugs_fixed_expander.set_expanded(True) | ||
195 | 835 | |||
196 | 778 | def _set_file_commit_message(self, message): | 836 | def _set_file_commit_message(self, message): |
197 | 779 | """Helper for the test suite.""" | 837 | """Helper for the test suite.""" |
198 | 780 | if isinstance(message, unicode): | 838 | if isinstance(message, unicode): |
199 | @@ -809,6 +867,7 @@ | |||
200 | 809 | if branch is None: | 867 | if branch is None: |
201 | 810 | self.global_message = u'' | 868 | self.global_message = u'' |
202 | 811 | self.file_messages = {} | 869 | self.file_messages = {} |
203 | 870 | self.bugs_fixed = u'' | ||
204 | 812 | else: | 871 | else: |
205 | 813 | config = branch.get_config() | 872 | config = branch.get_config() |
206 | 814 | self.global_message = config.get_user_option( | 873 | self.global_message = config.get_user_option( |
207 | @@ -821,14 +880,17 @@ | |||
208 | 821 | file_messages.encode('UTF-8')) | 880 | file_messages.encode('UTF-8')) |
209 | 822 | else: | 881 | else: |
210 | 823 | self.file_messages = {} | 882 | self.file_messages = {} |
211 | 883 | self.bugs_fixed = config.get_user_option('gtk_bugs_fixed_list') | ||
212 | 884 | if self.bugs_fixed is None: | ||
213 | 885 | self.bugs_fixed = u'' | ||
214 | 824 | 886 | ||
215 | 825 | def get(self): | 887 | def get(self): |
217 | 826 | return self.global_message, self.file_messages | 888 | return self.global_message, self.file_messages, self.bugs_fixed |
218 | 827 | 889 | ||
219 | 828 | def is_not_empty(self): | 890 | def is_not_empty(self): |
221 | 829 | return bool(self.global_message or self.file_messages) | 891 | return bool(self.global_message or self.file_messages or self.bugs_fixed) |
222 | 830 | 892 | ||
224 | 831 | def insert(self, global_message, file_info): | 893 | def insert(self, global_message, file_info, bugs_fixed): |
225 | 832 | """Formats per-file commit messages (list of dictionaries, one per file) | 894 | """Formats per-file commit messages (list of dictionaries, one per file) |
226 | 833 | into one utf-8 file_id->message dictionary and merges this with | 895 | into one utf-8 file_id->message dictionary and merges this with |
227 | 834 | previously existing dictionary. Merges global commit message too.""" | 896 | previously existing dictionary. Merges global commit message too.""" |
228 | @@ -847,6 +909,10 @@ | |||
229 | 847 | + self.global_message | 909 | + self.global_message |
230 | 848 | else: | 910 | else: |
231 | 849 | self.global_message = global_message | 911 | self.global_message = global_message |
232 | 912 | if self.bugs_fixed: | ||
233 | 913 | self.bugs_fixed = bugs_fixed + ' ' + self.bugs_fixed | ||
234 | 914 | else: | ||
235 | 915 | self.bugs_fixed = bugs_fixed | ||
236 | 850 | 916 | ||
237 | 851 | def save(self, tree, branch): | 917 | def save(self, tree, branch): |
238 | 852 | # We store in branch's config, which can be a problem if two gcommit | 918 | # We store in branch's config, which can be a problem if two gcommit |
239 | @@ -863,6 +929,7 @@ | |||
240 | 863 | config.set_user_option( | 929 | config.set_user_option( |
241 | 864 | 'gtk_file_commit_messages', | 930 | 'gtk_file_commit_messages', |
242 | 865 | bencode.bencode(self.file_messages).decode('UTF-8')) | 931 | bencode.bencode(self.file_messages).decode('UTF-8')) |
243 | 932 | config.set_user_option('gtk_bugs_fixed_list', self.bugs_fixed) | ||
244 | 866 | 933 | ||
245 | 867 | 934 | ||
246 | 868 | def save_commit_messages(local, master, old_revno, old_revid, | 935 | def save_commit_messages(local, master, old_revno, old_revid, |
247 | @@ -886,8 +953,13 @@ | |||
248 | 886 | else: | 953 | else: |
249 | 887 | file_info = bencode.bdecode(file_info.encode('UTF-8')) | 954 | file_info = bencode.bdecode(file_info.encode('UTF-8')) |
250 | 888 | global_message = osutils.safe_unicode(rev.message) | 955 | global_message = osutils.safe_unicode(rev.message) |
251 | 956 | |||
252 | 957 | from bzrlib.plugins.gtk import bugtrackerex | ||
253 | 958 | bugs_fixed = ' '.join('%s:%s' % bugtrackerex.get_bugtracker_and_bug_id(url, b) | ||
254 | 959 | for url,status in rev.iter_bugs()) | ||
255 | 960 | |||
256 | 889 | # Concatenate comment of the uncommitted revision | 961 | # Concatenate comment of the uncommitted revision |
258 | 890 | mgr.insert(global_message, file_info) | 962 | mgr.insert(global_message, file_info, bugs_fixed) |
259 | 891 | 963 | ||
260 | 892 | parents = graph.get_parent_map([rev_id]).get(rev_id, None) | 964 | parents = graph.get_parent_map([rev_id]).get(rev_id, None) |
261 | 893 | if not parents: | 965 | if not parents: |
Thanks for working on this! :)
I don't understand why bugtrackerex.py is necessary. If the existing code in bzrlib.bugtracker isn't sufficient, please extend it rather than duplicating it here.
Is there any particular reason why you've added a configuration option, rather than always allowing users to specify the bug # ? I think it'd be reasonable to enable this functionality unconditionally.