Kiln » TortoiseHg » TortoiseHg
Clone URL:  
Pushed to one repository · View In Graph Contained in 1.9.1, 1.9.2, and 1.9.3

hgqt: branch, tag, bookmark APIs are all in local encoding

Reviewed all code under hgqt and verified all uses of UTF-8 are now valid.

Changeset 7b2980a423b1

Parent b77c00662719

by Steve Borho

Changes to 7 files · Browse files at 7b2980a423b1 Showing diff from parent b77c00662719 Diff from another changeset...

 
142
143
144
145
146
 
 
147
148
149
 
161
162
163
164
 
165
166
167
 
179
180
181
182
183
 
 
184
185
186
 
188
189
190
191
 
192
193
194
 
197
198
199
200
201
 
 
202
203
204
205
206
207
 
208
209
210
 
214
215
216
217
 
218
219
220
221
 
 
222
223
224
225
 
226
227
228
229
230
231
232
233
 
 
234
235
236
 
142
143
144
 
 
145
146
147
148
149
 
161
162
163
 
164
165
166
167
 
179
180
181
 
 
182
183
184
185
186
 
188
189
190
 
191
192
193
194
 
197
198
199
 
 
200
201
202
203
204
205
206
 
207
208
209
210
 
214
215
216
 
217
218
219
 
 
220
221
222
223
224
 
225
226
227
228
229
230
231
 
 
232
233
234
235
236
@@ -142,8 +142,8 @@
    def toggle_new_bookmark(self):   bookmark = self.bookmark_combo.currentText() - bookmarkutf = unicode(bookmark).encode('utf-8') - is_new = bookmarkutf not in self.repo.bookmarks + bookmarklocal = hglib.fromunicode(bookmark) + is_new = bookmarklocal not in self.repo.bookmarks   self.add_btn.setVisible(is_new)   self.add_btn.setDisabled(not is_new)   self.remove_btn.setVisible(not is_new) @@ -161,7 +161,7 @@
    try:   # check if valid revision, tag, or branch - self.repo[unicode(revstr, 'utf-8')] + self.repo[hglib.fromunicode(revstr)]   except (error.LookupError, error.RepoLookupError, error.RepoError):   self.add_btn.setDisabled(True)   self.remove_btn.setDisabled(True) @@ -179,8 +179,8 @@
    def add_bookmark(self):   bookmark = self.bookmark_combo.currentText() - bookmarkutf = unicode(bookmark).encode('utf-8') - if bookmarkutf in self.repo.bookmarks: + bookmarklocal = hglib.fromunicode(bookmark) + if bookmarklocal in self.repo.bookmarks:   self.set_status(_('A bookmark named "%s" already exists') %   bookmark, False)   return @@ -188,7 +188,7 @@
  bookmarks.bookmark(ui=self.repo.ui,   repo=self.repo,   rev=self.initial_rev, - mark=bookmarkutf) + mark=bookmarklocal)     self.bookmark_combo.addItem(bookmark)   self.set_status(_("Bookmark '%s' has been added") % bookmark, True) @@ -197,14 +197,14 @@
    def remove_bookmark(self):   bookmark = self.bookmark_combo.currentText() - bookmarkutf = unicode(bookmark).encode('utf-8') - if not bookmarkutf in self.repo.bookmarks: + bookmarklocal = hglib.fromunicode(bookmark) + if not bookmarklocal in self.repo.bookmarks:   self.set_status(_("Bookmark '%s' does not exist") % bookmark, False)   return     bookmarks.bookmark(ui=self.repo.ui,   repo=self.repo, - mark=bookmarkutf, + mark=bookmarklocal,   delete=True)     self.bookmark_combo.removeItem(self.bookmark_combo.currentIndex()) @@ -214,23 +214,23 @@
    def rename_bookmark(self):   name = self.bookmark_combo.currentText() - nameutf = unicode(name).encode('utf-8') + bookmarklocal = hglib.fromunicode(bookmark)     newname = self.new_name_text.text() - newnameutf = unicode(newname).encode('utf-8') - if not nameutf in self.repo.bookmarks: + newnamelocal = hglib.fromunicode(newname) + if not bookmarklocal in self.repo.bookmarks:   self.set_status(_("Bookmark '%s' does not exist") % name, False)   return   - if newnameutf in self.repo.bookmarks: + if newnamelocal in self.repo.bookmarks:   self.set_status(_('A bookmark named "%s" already exists') %   newname, False)   return     bookmarks.bookmark(ui=self.repo.ui,   repo=self.repo, - mark=newnameutf, - rename=nameutf) + mark=newnamelocal, + rename=namelocal)     self.bookmark_combo.removeItem(self.bookmark_combo.currentIndex())   self.bookmark_combo.addItem(newname)
 
249
250
251
252
 
253
254
255
 
520
521
522
523
524
525
526
 
 
527
528
 
529
530
531
 
532
533
534
 
544
545
546
547
 
548
549
550
 
249
250
251
 
252
253
254
255
 
520
521
522
 
 
 
 
523
524
525
 
526
527
528
 
529
530
531
532
 
542
543
544
 
545
546
547
548
@@ -249,7 +249,7 @@
  self.msgcombo.reset(self.msghistory)     # Update branch operation button - branchu = unicode(self.repo[None].branch(), 'utf-8') + branchu = hglib.tounicode(self.repo[None].branch())   if self.branchop is None:   title = _('Branch: ') + branchu   elif self.branchop == False: @@ -520,15 +520,13 @@
  brcmd = ['--close-branch']   else:   brcmd = [] - # self.branchop - new branch name in QString (unicode) - # branchutf - new branch name in UTF8 - branchutf = unicode(self.branchop).encode('utf-8') - if branchutf in repo.branchtags(): + branch = hglib.fromunicode(self.branchop) + if branch in repo.branchtags():   # response: 0=Yes, 1=No, 2=Cancel - if branchutf in [p.branch() for p in repo.parents()]: + if branch in [p.branch() for p in repo.parents()]:   resp = 0   else: - rev = repo[branchutf].rev() + rev = repo[branch].rev()   resp = qtlib.CustomPrompt(_('Confirm Branch Change'),   _('Named branch "%s" already exists, '   'last used in revision %d\n' @@ -544,7 +542,7 @@
  'Cancel\t- Cancel this commit') % self.branchop,   self, (_('&Yes'), _('&No'), _('Cancel')), 2, 2).run()   if resp == 0: - repo.dirstate.setbranch(branchutf) + repo.dirstate.setbranch(branch)   elif resp == 2:   return   files = self.stwidget.getChecked('MAR?!S')
 
53
54
55
56
 
57
58
 
59
60
61
 
53
54
55
 
56
57
 
58
59
60
61
@@ -53,9 +53,9 @@
  os.chdir(self.root)   fname = util.normpath(fname)   if target: - target = hglib.toutf(util.normpath(target)) + target = hglib.tounicode(util.normpath(target))   else: - target = hglib.toutf(fname) + target = hglib.tounicode(fname)   return (fname, target)     def init_view(self, src, dest):
 
463
464
465
466
 
467
468
469
470
471
472
 
473
474
475
 
492
493
494
495
 
496
497
498
 
509
510
511
512
513
 
514
515
516
 
463
464
465
 
466
467
468
469
470
471
 
472
473
474
475
 
492
493
494
 
495
496
497
498
 
509
510
511
 
 
512
513
514
515
@@ -463,13 +463,13 @@
  self.layoutChanged.emit()     def getbranch(self, ctx, gnode): - return unicode(ctx.branch(), 'utf-8') + return hglib.tounicode(ctx.branch())     def gettags(self, ctx, gnode):   if ctx.rev() is None:   return ''   tags = [t for t in ctx.tags() if t not in self._mqtags] - return unicode(','.join(tags), 'utf-8') + return hglib.tounicode(','.join(tags))     def getauthor(self, ctx, gnode):   try: @@ -492,7 +492,7 @@
    parts = []   if ctx.thgbranchhead(): - branchu = unicode(ctx.branch(), 'utf-8') + branchu = hglib.tounicode(ctx.branch())   effects = qtlib.geteffect('log.branch')   parts.append(qtlib.applyeffects(u' %s ' % branchu, effects))   @@ -509,8 +509,7 @@
  style = 'log.bookmark'   else:   style = 'log.tag' - # tag is in UTF-8, we need it in unicode with style effects - tagu = unicode(tag, 'utf-8') + tagu = hglib.tounicode(tag)   effects = qtlib.geteffect(style)   parts.append(qtlib.applyeffects(u' %s ' % tagu, effects))  
 
859
860
861
862
 
863
864
865
 
859
860
861
 
862
863
864
865
@@ -859,7 +859,7 @@
  """output version and copyright information"""   ui.write(_('TortoiseHg Dialogs (version %s), '   'Mercurial (version %s)\n') % - (hglib.fromutf(thgversion.version()), hglib.hgversion)) + (thgversion.version(), hglib.hgversion))   if not ui.quiet:   ui.write(shortlicense)  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
 
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
 
239
240
241
242
243
244
245
246
 
247
248
249
250
251
252
253
 
254
255
256
257
258
 
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
 
274
275
276
277
278
279
 
280
281
282
283
284
285
286
287
288
 
289
290
291
292
 
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
 
239
240
241
242
243
244
245
246
 
247
248
249
250
251
252
253
 
254
255
256
257
258
 
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
 
274
275
276
277
278
279
 
280
281
282
283
284
285
286
287
288
 
289
290
291
292
 
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
 # tag.py - Tag dialog for TortoiseHg  #  # Copyright 2010 Yuki KODAMA <endflow.net@gmail.com>  #  # This software may be used and distributed according to the terms of the  # GNU General Public License version 2, incorporated herein by reference.    import os    from PyQt4.QtCore import *  from PyQt4.QtGui import *    from mercurial import error    from tortoisehg.util import hglib, i18n  from tortoisehg.hgqt.i18n import _  from tortoisehg.hgqt import qtlib    # TODO: Use cmdui.Runner, emit output statements for dock log widget    keep = i18n.keepgettext()    class TagDialog(QDialog):     localTagChanged = pyqtSignal()   showMessage = pyqtSignal(unicode)     def __init__(self, repo, tag='', rev='tip', parent=None, opts={}):   super(TagDialog, self).__init__(parent) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) + self.setWindowFlags(self.windowFlags() & \ + ~Qt.WindowContextHelpButtonHint)     self.repo = repo     if not tag and rev and rev != 'tip':   bmarks = repo.bookmarks.keys()   for t in repo.nodetags(repo[rev].node()):   if t != 'tip' \   and ((not bmarks) or (bmarks and t not in bmarks)):   tag = t   break   else:   tag = ''     # base layout box   base = QVBoxLayout()   base.setSpacing(0)   base.setContentsMargins(*(0,)*4)     # main layout box   box = QVBoxLayout()   box.setSpacing(6)   box.setContentsMargins(*(6,)*4)   base.addLayout(box)     ## main layout grid   grid = QGridLayout()   grid.setSpacing(6)   box.addLayout(grid)     ### tag combo   self.tag_combo = QComboBox()   self.tag_combo.setEditable(True)   self.tag_combo.setMinimumWidth(180)   self.tag_combo.setEditText(tag)   self.tag_combo.editTextChanged.connect(self.tag_changed)   grid.addWidget(QLabel(_('Tag:')), 0, 0)   grid.addWidget(self.tag_combo, 0, 1)     ### revision input   self.initial_rev = rev   self.rev_text = QLineEdit()   self.rev_text.setMaximumWidth(100)   self.rev_text.setText(rev)   self.rev_text.textEdited.connect(self.update_sensitives)   grid.addWidget(QLabel(_('Revision:')), 1, 0)   grid.addWidget(self.rev_text, 1, 1)     ### options   expander = qtlib.ExpanderLabel(_('Options'), False)   expander.expanded.connect(self.show_options)   grid.addWidget(expander, 2, 0, 1, 2, Qt.AlignLeft | Qt.AlignTop)     optbox = QVBoxLayout()   optbox.setSpacing(6)   grid.addLayout(optbox, 3, 0, 1, 2)     hbox = QHBoxLayout()   hbox.setSpacing(0)   optbox.addLayout(hbox)     self.local_chk = QCheckBox(_('Local tag'))   self.local_chk.toggled.connect(self.local_toggled)   self.replace_chk = QCheckBox(_('Replace existing tag (-f/--force)'))   self.replace_chk.toggled.connect(self.update_sensitives)   optbox.addWidget(self.local_chk)   optbox.addWidget(self.replace_chk)     self.eng_chk = QCheckBox(_('Use English commit message'))   engmsg = repo.ui.configbool('tortoisehg', 'engmsg', False)   self.eng_chk.setChecked(engmsg)   optbox.addWidget(self.eng_chk)     self.custom_chk = QCheckBox(_('Use custom commit message:'))   self.custom_chk.toggled.connect(   lambda e: self.toggle_enabled(e, self.custom_text))   self.custom_text = QLineEdit()   optbox.addWidget(self.custom_chk)   optbox.addWidget(self.custom_text)     ## bottom buttons   buttons = QDialogButtonBox()   self.close_btn = buttons.addButton(QDialogButtonBox.Close)   self.close_btn.clicked.connect(self.reject)   self.add_btn = buttons.addButton(_('&Add'),   QDialogButtonBox.ActionRole)   self.add_btn.clicked.connect(self.add_tag)   self.remove_btn = buttons.addButton(_('&Remove'),   QDialogButtonBox.ActionRole)   self.remove_btn.clicked.connect(self.remove_tag)   box.addWidget(buttons)     ## horizontal separator   self.sep = QFrame()   self.sep.setFrameShadow(QFrame.Sunken)   self.sep.setFrameShape(QFrame.HLine)   base.addWidget(self.sep)     ## status line   self.status = qtlib.StatusLabel()   self.status.setContentsMargins(4, 2, 4, 4)   base.addWidget(self.status)     # dialog setting   self.setLayout(base)   self.layout().setSizeConstraint(QLayout.SetFixedSize)   self.setWindowTitle(_('Tag - %s') % repo.displayname)   self.setWindowIcon(qtlib.geticon('tag'))     # prepare to show   self.custom_text.setDisabled(True)   self.clear_statue()   self.update_tagcombo(clear=False)   self.update_sensitives(affectlocal=True)   self.show_options(False)   self.tag_combo.setFocus()     self.replace_chk.setChecked(bool(opts.get('force')))   self.local_chk.setChecked(bool(opts.get('local')))   if not opts.get('local') and opts.get('message'):   self.custom_chk.setChecked(True)   self.custom_text.setText(opts.get('message', ''))     ### Private Methods ###     def update_tagcombo(self, clear=True):   """ update display on dialog with recent repo data """   tag_name = self.tag_combo.currentText()   self.tag_combo.clear()     # add tags to drop-down list   tags = list(self.repo.tags())   tags.sort()   tags.reverse()   for tag in tags:   if tag == 'tip':   continue   self.tag_combo.addItem(hglib.tounicode(tag))   self.tag_combo.clearEditText()     # restore tag name   if not clear and tag_name:   self.tag_combo.setEditText(tag_name)     @pyqtSlot()   def update_sensitives(self, affectlocal=False):   """ update bottom button sensitives based on rev and tag """   tag = self.tag_combo.currentText()   rev = self.rev_text.text()   if not rev or not tag:   self.add_btn.setDisabled(True)   self.remove_btn.setDisabled(True)   return     # check if valid revision   try:   self.repo[hglib.fromunicode(rev)]   except (error.LookupError, error.RepoLookupError, error.RepoError):   self.add_btn.setDisabled(True)   self.remove_btn.setDisabled(True)   return     # check tag existence   force = self.replace_chk.isChecked()   is_exist = hglib.fromunicode(tag) in self.repo.tags()   self.add_btn.setEnabled(not is_exist or force)   self.remove_btn.setEnabled(is_exist)     # check if local   is_local = self.repo.tagtype(hglib.fromunicode(tag))   if affectlocal and is_local is not None:   self.local_chk.setChecked(is_local == 'local')   self.update_revision()     def update_revision(self):   """ update revision entry based on tag """   tagmap = self.repo.tags()   tag = self.tag_combo.currentText()   replace = self.replace_chk.isChecked()   if not tag or hglib.fromunicode(tag) not in tagmap or replace:   if self.initial_rev:   self.rev_text.setText(self.initial_rev)   return     node = tagmap[hglib.fromunicode(tag)]   ctx = self.repo[node]   self.rev_text.setText(unicode(ctx.rev()))     def show_options(self, visible):   self.local_chk.setVisible(visible)   self.replace_chk.setVisible(visible)   self.eng_chk.setVisible(visible)   self.custom_chk.setVisible(visible)   self.custom_text.setVisible(visible)     def set_status(self, text, icon=None):   self.status.setShown(True)   self.sep.setShown(True)   self.status.set_status(text, icon)   self.showMessage.emit(text)     def clear_statue(self):   self.status.setHidden(True)   self.sep.setHidden(True)     def add_tag(self):   local = self.local_chk.isChecked()   name = self.tag_combo.currentText() - nameutf = unicode(name).encode('utf-8') + namelocal = hglib.fromunicode(name)   rev = hglib.fromunicode(self.rev_text.text())   force = self.replace_chk.isChecked()   english = self.eng_chk.isChecked()   message = self.custom_text.text()     try:   # tagging - if nameutf in self.repo.tags() and not force: + if namelocal in self.repo.tags() and not force:   raise util.Abort(_("Tag '%s' already exist") % name)   ctx = self.repo[rev]   node = ctx.node()   if not message:   msgset = keep._('Added tag %s for changeset %s')   message = (english and msgset['id'] or msgset['str']) \ - % (name, str(ctx)) + % (namelocal, str(ctx))   if not isinstance(message, str):   message = hglib.fromunicode(message)     self.repo.incrementBusyCount() - self.repo.tag(nameutf, node, message, local, None, None) + self.repo.tag(namelocal, node, message, local, None, None)   self.repo.decrementBusyCount()   if local:   self.localTagChanged.emit()     # update UI   self.set_status(_("Tag '%s' has been added") % name, True)   self.update_tagcombo()   self.close_btn.setFocus()   except:   self.set_status(_('Error in tagging'), False)     def remove_tag(self):   local = self.local_chk.isChecked()   name = self.tag_combo.currentText() - nameutf = unicode(name).encode('utf-8') + namelocal = hglib.fromunicode(name)   english = self.eng_chk.isChecked()   message = hglib.fromunicode(self.custom_text.text())     try:   # tagging - tagtype = self.repo.tagtype(nameutf) + tagtype = self.repo.tagtype(namelocal)   if local:   if tagtype != 'local':   raise util.Abort(_('tag \'%s\' is not a local tag') % name)   else:   if tagtype != 'global':   raise util.Abort(_('tag \'%s\' is not a global tag') % name)   if not message:   msgset = keep._('Removed tag %s') - message = (english and msgset['id'] or msgset['str']) % name + message = (english and msgset['id'] or msgset['str']) % namelocal     self.repo.incrementBusyCount()   node = self.repo[-1].node() - self.repo.tag(nameutf, node, message, local, None, None) + self.repo.tag(namelocal, node, message, local, None, None)   self.repo.decrementBusyCount()   if local:   self.localTagChanged.emit()     # update UI   self.set_status(_("Tag '%s' has been removed") % name, True)   self.update_tagcombo()   self.close_btn.setFocus()   except:   self.set_status(_('Error in tagging'), False)     ### Signal Handlers ###     def local_toggled(self, checked):   self.eng_chk.setEnabled(not checked)   self.custom_chk.setEnabled(not checked)   custom = self.custom_chk.isChecked()   self.custom_text.setEnabled(not checked and custom)     def tag_changed(self, combo):   self.update_revision()   self.update_sensitives(True)     def toggle_enabled(self, checked, target):   target.setEnabled(checked)   if checked:   target.setFocus()    def run(ui, *pats, **opts):   kargs = {}   tag = len(pats) > 0 and pats[0] or None   if tag:   kargs['tag'] = tag   rev = opts.get('rev')   if rev:   kargs['rev'] = rev   from tortoisehg.util import paths   from tortoisehg.hgqt import thgrepo   repo = thgrepo.repository(ui, path=paths.find_root())   return TagDialog(repo, opts=opts, **kargs)
 
228
229
230
231
232
233
 
234
235
236
 
344
345
346
347
348
349
 
350
351
352
 
483
484
485
486
 
487
488
489
 
595
596
597
598
 
599
600
601
 
 
602
603
604
 
228
229
230
 
231
 
232
233
234
235
 
343
344
345
 
346
 
347
348
349
350
 
481
482
483
 
484
485
486
487
 
593
594
595
 
596
597
 
 
598
599
600
601
602
@@ -228,9 +228,8 @@
    @propertycache   def _thghiddentags(self): - # Assume Mercurial.ini file is in local encoding, need UTF-8   ht = self.ui.config('tortoisehg', 'hidetags', '') - return [hglib.toutf(t).strip() for t in ht.split()] + return [t.strip() for t in ht.split()]     @propertycache   def thgmqunappliedpatches(self): @@ -344,9 +343,8 @@
    @propertycache   def deadbranches(self): - # Assume Mercurial.ini file is in local encoding, need UTF-8   db = self.ui.config('tortoisehg', 'deadbranch', '') - return [hglib.toutf(b).strip() for b in db.split(',')] + return [b.strip() for b in db.split(',')]     @propertycache   def displayname(self): @@ -483,7 +481,7 @@
 def _extendchangectx(changectx):   class thgchangectx(changectx.__class__):   def thgtags(self): - '''Returns all unhidden tags for self in UTF-8''' + '''Returns all unhidden tags for self'''   htlist = self._repo._thghiddentags   return [tag for tag in self.tags() if tag not in htlist]   @@ -595,10 +593,10 @@
  if msg:   msg = '\n'.join(msg)   self._node = node - self._user = user and hglib.tounicode(user) or '' + self._user = user or ''   self._date = date and util.parsedate(date) or util.makedate() - self._desc = msg and msg or '' - self._branch = branch and hglib.tounicode(branch) or '' + self._desc = msg or '' + self._branch = branch or ''   self._parents = []   self._rev = rev   for p in (p1, p2):