Kiln » TortoiseHg » TortoiseHg
Clone URL:  
Pushed to one repository · View In Graph Contained in 0.8, 0.8.1, and 0.8.2

merge with crew

Changeset 944173cd38df

Parents 8a6772ddbf11

Parents 73165e662498

by Simon Heimberg

Changes to 8 files · Browse files at 944173cd38df Showing diff from parent 8a6772ddbf11 73165e662498 Diff from another changeset...

Change 1 of 2 Show Entire File hggtk/​commit.py Stacked
 
111
112
113
 
114
115
116
 
248
249
250
251
252
253
 
 
 
254
255
256
 
111
112
113
114
115
116
117
 
249
250
251
 
 
 
252
253
254
255
256
257
@@ -111,6 +111,7 @@
  response = Confirm('Discard Message', [], self,   'Discard current commit message?').run()   if response != gtk.RESPONSE_YES: + combobox.set_active(-1)   return   buf.set_text(model[index][1])   @@ -248,9 +249,9 @@
    # pre-fill commit message   self.text.get_buffer().set_text('merge') - else: - self.selectlabel.set_text( - _('toggle change hunks to leave them out of commit')) + #else: + # self.selectlabel.set_text( + # _('toggle change hunks to leave them out of commit'))      
Change 1 of 1 Show Entire File hggtk/​gdialog.py Stacked
 
65
66
67
 
 
 
 
 
 
 
68
69
70
 
65
66
67
68
69
70
71
72
73
74
75
76
77
@@ -65,6 +65,13 @@
  message += ' ...\n'   break   self.format_secondary_text(toutf(message)) + accel_group = gtk.AccelGroup() + self.add_accel_group(accel_group) + buttons = self.get_children()[0].get_children()[1].get_children() + buttons[1].add_accelerator("clicked", accel_group, ord("y"), + 0, gtk.ACCEL_VISIBLE) + buttons[0].add_accelerator("clicked", accel_group, ord("n"), + 0, gtk.ACCEL_VISIBLE)      class GDialog(gtk.Window):
Change 1 of 1 Show Entire File hggtk/​hgignore.py Stacked
 
149
150
151
152
 
 
153
154
155
 
149
150
151
 
152
153
154
155
156
@@ -149,7 +149,8 @@
  try: repo = hg.repository(ui.ui(), path=self.root)   except: gtk.main_quit()   matcher = match.always(repo.root, repo.root) - changes = repo.dirstate.status(matcher, unknown=True) + changes = repo.dirstate.status(matcher, ignored=False, clean=False, + unknown=True)   (lookup, modified, added, removed,   deleted, unknown, ignored, clean) = changes   self.unkmodel.clear()
Change 1 of 1 Show Entire File hggtk/​hgshelve.py Stacked
 
96
97
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
100
101
 
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
@@ -96,6 +96,32 @@
  if h.startswith('index '):   return True   + def selpretty(self, selected): + str = '' + for h in self.header: + if h.startswith('index '): + str += _('this modifies a binary file (all or nothing)\n') + break + if self.pretty_re.match(h): + str += h + if self.binary(): + str += _('this is a binary file\n') + break + if h.startswith('---'): + hunks = len(self.hunks) + shunks, lines, slines = 0, 0, 0 + for i, h in enumerate(self.hunks): + lines += h.added + h.removed + if selected(i): + shunks += 1 + slines += h.added + h.removed + str += _('total: %d hunks (%d changed lines); ' + 'selected: %d hunks (%d changed lines)') % (hunks, + lines, shunks, slines) + break + str += h + return str +   def pretty(self, fp):   for h in self.header:   if h.startswith('index '):
Change 1 of 12 Show Entire File hggtk/​status.py Stacked
 
169
170
171
172
 
 
 
 
 
173
174
175
 
270
271
272
273
274
 
275
276
277
 
371
372
373
374
375
376
377
378
379
380
381
 
 
 
 
 
 
 
 
382
383
384
 
501
502
503
 
 
 
 
 
 
504
505
506
 
531
532
533
534
535
536
537
538
539
 
617
618
619
 
 
 
 
620
621
622
623
624
 
625
626
 
627
628
629
 
631
632
633
 
 
 
 
 
 
 
 
 
 
 
634
635
636
 
797
798
799
800
 
801
802
803
 
842
843
844
845
 
846
847
848
849
850
 
851
852
853
 
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
 
873
874
875
 
919
920
921
922
923
924
925
926
927
 
 
928
929
930
 
931
932
933
934
 
 
 
 
935
936
937
 
993
994
995
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
996
997
998
 
169
170
171
 
172
173
174
175
176
177
178
179
 
274
275
276
 
 
277
278
279
280
 
374
375
376
 
 
 
 
 
 
 
 
377
378
379
380
381
382
383
384
385
386
387
 
504
505
506
507
508
509
510
511
512
513
514
515
 
540
541
542
 
 
 
543
544
545
 
623
624
625
626
627
628
629
630
 
 
 
 
631
632
 
633
634
635
636
 
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
 
815
816
817
 
818
819
820
821
 
860
861
862
 
863
864
865
866
867
 
868
869
870
871
 
874
875
876
 
877
878
879
 
 
 
 
 
 
 
 
 
 
880
881
882
883
 
927
928
929
 
 
 
 
 
 
930
931
932
933
 
934
935
936
937
938
939
940
941
942
943
944
945
 
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
@@ -169,7 +169,11 @@
  self._refresh_clicked, tip='refresh'),   gtk.SeparatorToolItem()]   - if self.count_revs() < 2: + if self.count_revs() == 2: + tbuttons += [ + self.make_toolbutton(gtk.STOCK_SAVE_AS, 'Save As', + self._save_clicked, tip='Save selected changes')] + else:   tbuttons += [   self.make_toolbutton(gtk.STOCK_MEDIA_REWIND, 'Re_vert',   self._revert_clicked, tip='revert'), @@ -270,8 +274,7 @@
  stat_cell = gtk.CellRendererText()     self.selcb = None - ismerge = len(self.repo.changectx(None).parents()) == 2 - if self.count_revs() < 2 and not ismerge: + if len(self.repo.changectx(None).parents()) != 2:   # show file selection checkboxes only when applicable   col0 = gtk.TreeViewColumn('', toggle_cell)   col0.add_attribute(toggle_cell, 'active', FM_CHECKED) @@ -371,14 +374,14 @@
  self._tree_selection_changed, False)   scroller.add(self.diff_tree)   - vbox = gtk.VBox() - self.selectlabel = gtk.Label() - hbox = gtk.HBox() - hbox.pack_start(self.selectlabel, False, False, 2) - vbox.pack_start(hbox, False, False, 2) - vbox.pack_start(scroller, True, True, 2) - - diff_frame.add(vbox) + #vbox = gtk.VBox() + #self.selectlabel = gtk.Label() + #hbox = gtk.HBox() + #hbox.pack_start(self.selectlabel, False, False, 2) + #vbox.pack_start(hbox, False, False, 2) + #vbox.pack_start(scroller, True, True, 2) + #diff_frame.add(vbox) + diff_frame.add(scroller)     if self.diffbottom:   self._diffpane = gtk.VPaned() @@ -501,6 +504,12 @@
  self._diffpane_moved(self._diffpane)   return False   + def auto_check(self): + if self.opts.get('rev'): + for entry in self.filemodel: + entry[FM_CHECKED] = True + self._update_check_count() +   ### End of overrides ###     def _do_reload_status(self): @@ -531,9 +540,6 @@
  (modified, added, removed, deleted, unknown, ignored, clean) = status   self.modified = modified   - if not self.opts.get('rev') and deleted and unknown: - print "Suggest to detect copies or renames" -   changetypes = (('modified', 'M', modified),   ('added', 'A', added),   ('removed', 'R', removed), @@ -617,13 +623,14 @@
  '''Update chunk toggle state to match file toggle state'''   wfile = util.pconvert(entry[FM_PATH])   if wfile not in self._filechunks: return + selected = entry[FM_CHECKED] + for n in self._filechunks[wfile][1:]: + self.diff_model[n][DM_REJECTED] = not selected + self._update_diff_hunk(self.diff_model[n])   entry[FM_PARTIAL_SELECTED] = False - self._update_partial(self.diff_model, wfile, False) - for n in self._filechunks[wfile][1:]: - self.diff_model[n][DM_REJECTED] = not entry[FM_CHECKED] - self._update_diff_model_row(self.diff_model[n]) + self._update_diff_header(self.diff_model, wfile, selected)   - def _update_diff_model_row(self, row): + def _update_diff_hunk(self, row):   if row[DM_REJECTED]:   row[DM_FONT] = self.rejfont   row[DM_DISPLAYED] = row[DM_TEXT] @@ -631,6 +638,17 @@
  row[DM_FONT] = self.difffont   row[DM_DISPLAYED] = row[DM_MARKUP]   + def _update_diff_header(self, dmodel, wfile, selected): + hc = self._filechunks[wfile][0] + row = dmodel[hc] + displayed = row[DM_DISPLAYED] + sel = lambda x: not dmodel[hc+x+1][DM_REJECTED] + newtext = self._shelve_chunks[row[DM_CHUNK_ID]].selpretty(sel) + row[DM_DISPLAYED] = newtext + if selected: + row[DM_FONT] = self.headerfont + else: + row[DM_FONT] = self.rejfont     def _show_toggle(self, check, toggletype):   self.opts[toggletype] = check.get_active() @@ -797,7 +815,7 @@
  line = diffexpand(line)   buf.insert(bufiter, line)   - self.merge_diff_text.set_buffer(buffer) + self.merge_diff_text.set_buffer(buf)     if self.showdiff_toggle.get_active():   sel = self.filetree.get_selection().get_selected_rows()[1] @@ -842,12 +860,12 @@
  if row[DM_IS_HEADER]:   for n in fchunks:   dmodel[n][DM_REJECTED] = fr[FM_CHECKED] - self._update_diff_model_row(dmodel[n]) + self._update_diff_hunk(dmodel[n])   newvalue = not fr[FM_CHECKED]   partial = False   else:   row[DM_REJECTED] = not row[DM_REJECTED] - self._update_diff_model_row(row) + self._update_diff_hunk(row)   rej = [ n for n in fchunks if dmodel[n][DM_REJECTED] ]   nonrej = [ n for n in fchunks if not dmodel[n][DM_REJECTED] ]   newvalue = nonrej and True or False @@ -856,20 +874,10 @@
  # Update file's check status   if fr[FM_PARTIAL_SELECTED] != partial:   fr[FM_PARTIAL_SELECTED] = partial - self._update_partial(dmodel, wfile, partial)   if fr[FM_CHECKED] != newvalue:   fr[FM_CHECKED] = newvalue   self._update_check_count() - - def _update_partial(self, dmodel, wfile, partial): - hc = self._filechunks[wfile][0] - row = dmodel[hc] - displayed = row[DM_DISPLAYED] - tag = ' ** Partial **' - if partial and not displayed.endswith(tag): - row[DM_DISPLAYED] = displayed + tag - elif not partial and displayed.endswith(tag): - row[DM_DISPLAYED] = displayed[0:-len(tag)] + self._update_diff_header(dmodel, wfile, newvalue)     def _show_diff_hunks(self, files):   ''' Update the diff text ''' @@ -919,19 +927,19 @@
  self._filechunks = {}   skip = False   for n, chunk in enumerate(self._shelve_chunks): - fp = cStringIO.StringIO() - chunk.pretty(fp) - markedup = markup(fp) - text = unmarkup(fp) - isheader = isinstance(chunk, hgshelve.header) - if isheader: + if isinstance(chunk, hgshelve.header): + text = chunk.selpretty(lambda x: True)   for f in chunk.files():   self._filechunks[f] = [len(self.diff_model)] - row = [False, markedup, text, markedup, + row = [False, text, text, text,   True, n, self.headerfont]   self.diff_model.append(row)   skip = chunk.special()   elif not skip: + fp = cStringIO.StringIO() + chunk.pretty(fp) + markedup = markup(fp) + text = unmarkup(fp)   f = chunk.filename()   self._filechunks[f].append(len(self.diff_model))   row = [False, markedup, text, markedup, @@ -993,6 +1001,33 @@
  self.reload_status()   return True   + def _save_clicked(self, toolbutton, data=None): + 'Write selected diff hunks to a patch file' + revrange = self.opts.get('rev')[0] + filename = "%s.patch" % revrange.replace(':', '_to_') + fd = NativeSaveFileDialogWrapper(Title = "Save patch to", + InitialDir=self.repo.root, + FileName=filename) + result = fd.run() + if not result: + return + + cids = [] + dmodel = self.diff_model + for row in self.filemodel: + if row[FM_CHECKED]: + wfile = util.pconvert(row[FM_PATH]) + fc = self._filechunks[wfile] + cids.append(fc[0]) + cids += [dmodel[r][DM_CHUNK_ID] for r in fc[1:] if not dmodel[r][DM_REJECTED]] + try: + fp = open(result, "w") + for cid in cids: + self._shelve_chunks[cid].write(fp) + except OSError: + pass + finally: + fp.close()     def _revert_clicked(self, toolbutton, data=None):   revert_list = self._relevant_files('MAR!')
 
85
86
87
88
89
 
 
90
91
92
 
211
212
213
214
 
215
216
217
 
85
86
87
 
 
88
89
90
91
92
 
211
212
213
 
214
215
216
217
@@ -85,8 +85,8 @@
  self._vpaned.set_position(self._setting_vpos)   self._activate_shelve_buttons(True)   - self.selectlabel.set_text( - _('toggle change hunks to leave them in your working directory')) + #self.selectlabel.set_text( + # _('toggle change hunks to leave them in your working directory'))   return self._vpaned     @@ -211,7 +211,7 @@
  cmdoptions = {   'user':'', 'date':'',   'modified':True, 'added':True, 'removed':True, 'deleted':True, - 'unknown':True, 'ignored':False, + 'unknown':False, 'ignored':False,   'exclude':[], 'include':[],   'check': True, 'git':False, 'logfile':'', 'addremove':False,   }
 
349
350
351
352
353
 
354
355
356
 
349
350
351
 
 
352
353
354
355
@@ -349,8 +349,7 @@
  open_dialog('rename', cmdopts, cwd=cwd, filelist=[src])     def _guess_rename(self, parent_window): - root = self._folder - open_dialog('rename --detect', None, root) + self._run_dialog('rename --detect')     def _status(self, parent_window):   self._run_dialog('status')
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
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
 # Published under the GNU GPL, v2 or later.  # Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>  # Copyright (C) 2007 Henry Ludemann <misc@hl.id.au>  # Copyright (C) 2007 TK Soh <teekaysoh@gmail.com>    import os  #import tempfile  from mercurial import hg  from thgutil import *  from mercurial import ui  from mercurial.i18n import _    try:   from mercurial.error import RepoError  except ImportError:   from mercurial.repo import RepoError      class TortoiseMenu(object):     def __init__(self, menutext, helptext, handler, icon=None, state=True):   self.menutext = menutext   self.helptext = helptext   self.handler = handler   self.state = state   self.icon = icon     def isSubmenu(self):   return False     def isSep(self):   return False      class TortoiseSubmenu(TortoiseMenu):     def __init__(self, menutext, helptext, menus=[], icon=None):   TortoiseMenu.__init__(self, menutext, helptext, None, icon)   self.menus = menus[:]     def add_menu(self, menutext, helptext, handler, icon=None, state=True):   self.menus.append(TortoiseMenu(menutext, helptext,   handler, icon, state))     def add_sep(self):   self.menus.append(TortoiseMenuSep())     def get_menus(self):   return self.menus     def append(self, entry):   self.menus.append(entry)     def isSubmenu(self):   return True      class TortoiseMenuSep(object):     def isSubmenu(self):   return False     def isSep(self):   return True      def open_repo(path):   root = find_root(path)   if root:   try:   repo = hg.repository(ui.ui(), path=root)   return repo   except RepoError:   pass     return None      class menuThg:   """shell extension that adds context menu items"""     def __init__(self):   self.handlers = self   self.name = "TortoiseHG"     def get_commands_dragdrop(self, srcfiles, destfolder):   """   Get a list of commands valid for the current selection.     Commands are instances of TortoiseMenu, TortoiseMenuSep or TortoiseMenu   """     try:   print "_get_commands_dragdrop() on %s" % ", ".join(files)   except:   print "_get_commands_dragdrop() on some files"     # we can only accept dropping one item   if len(srcfiles) > 1:   return []     # open repo   drag_repo = None   drop_repo = None     print "drag = %s" % self.srcfiles[0]   print "drop = %s" % self.destfolder     drag_path = self.srcfiles[0]   drag_repo = open_repo(drag_path)   if not drag_repo:   return []   if drag_repo and drag_repo.root != drag_path:   return [] # dragged item must be a hg repo root directory     drop_repo = open_repo(self._folder)     thgmenu = []   thgmenu.append(TortoiseMenu(_("Create Clone"),   _("Create clone here from source"),   self.handlers._clone_here, icon="menuclone.ico"))     if drop_repo:   thgmenu.append(TortoiseMenu(_("Synchronize"),   _("Synchronize with dragged repository"),   self.handlers._synch_here, icon="menusynch.py"))   return thgmenu     def get_commands(self, files):   """   Get a list of commands valid for the current selection.     Commands are instances of TortoiseMenu, TortoiseMenuSep or TortoiseMenu   """   try:   print "_get_commands() on %s" % ", ".join(files)   except:   print "_get_commands() on some files"     # open repo   if type(files) != list:   files = [files]   if not files:   return []   rpath = files[0]   repo = open_repo(rpath)     thgmenu = []     if repo:   thgmenu.append(TortoiseMenu(_("HG Commit..."),   _("Commit changes in repository"),   self.handlers._commit, icon="menucommit.ico"))     menu = TortoiseSubmenu(self.name, "Mercurial", [], icon="hg.ico")     if repo is None:   menu.append(TortoiseMenu(_("Clone a Repository"),   _("clone a repository"),   self.handlers._clone, icon="menuclone.ico"))   menu.append(TortoiseMenu(_("Create Repository Here"),   _("create a new repository in this directory"),   self.handlers._init, icon="menucreaterepos.ico",   state=os.path.isdir(rpath)))   else:     for f in files:   if f.endswith('.hgignore'): - menu.append(TortoiseMenu(_("Modify ignore filter"), - _("Modify repository ignore filter"), + menu.append(TortoiseMenu(_("Edit Ignore Filter"), + _("Edit repository ignore filter"),   self.handlers._hgignore, icon="general.ico")) # needs ico   break     menu.append(TortoiseMenu(_("View File Status"),   _("Repository status"),   self.handlers._status, icon="menushowchanged.ico"))   - menu.append(TortoiseMenu(_("(Un)Shelve Changes"), - _("Shelve repository changes"), + menu.append(TortoiseMenu(_("Shelve Changes"), + _("Shelve or unshelve repository changes"),   self.handlers._shelve, icon="general.ico")) # needs ico     # Visual Diff (any extdiff command)   has_vdiff = repo.ui.config('tortoisehg', 'vdiff', '') != ''   menu.append(TortoiseMenu(_("Visual Diff"),   _("View changes using GUI diff tool"),   self.handlers._vdiff, icon="TortoiseMerge.ico",   state=has_vdiff))     if len(files) == 0:   menu.append(TortoiseMenu(_("Guess Renames"),   _("Detect renames and copies"),   self.handlers._guess_rename, icon="general.ico")) # needs ico   elif len(files) == 1: - menu.append(TortoiseMenu(_("Rename file"), + menu.append(TortoiseMenu(_("Rename File"),   _("Rename file or directory"),   self.handlers._rename, icon="general.ico")) # needs ico     menu.append(TortoiseMenu(_("Add Files"),   _("Add files to Hg repository"),   self.handlers._add, icon="menuadd.ico"))   menu.append(TortoiseMenu(_("Remove Files"),   _("Remove selected files on the next commit"),   self.handlers._remove, icon="menudelete.ico"))   menu.append(TortoiseMenu(_("Undo Changes"),   _("Revert selected files"),   self.handlers._revert, icon="menurevert.ico"))     # we can only annotate file but not directories   annotatible = len(files) > 0   for f in files:   if not os.path.isfile(f):   annotatible = False   break   menu.append(TortoiseMenu(_("Annotate Files"),   _("show changeset information per file line"),   self.handlers._annotate, icon="menublame.ico",   state=annotatible))     menu.append(TortoiseMenuSep())   menu.append(TortoiseMenu(_("Update To Revision"),   _("update working directory"),   self.handlers._update, icon="menucheckout.ico"))     can_merge = len(repo.heads()) > 1 and \   len(repo.changectx(None).parents()) < 2   menu.append(TortoiseMenu(_("Merge Revisions"),   _("merge working directory with another revision"),   self.handlers._merge, icon="menumerge.ico",   state=can_merge))     in_merge = len(repo.changectx(None).parents()) > 1   menu.append(TortoiseMenu(_("Undo Merge"),   _("Undo merge by updating to revision"),   self.handlers._merge, icon="menuunmerge.ico",   state=in_merge))     menu.append(TortoiseMenuSep())     menu.append(TortoiseMenu(_("View Changelog"),   _("View revision history"),   self.handlers._history, icon="menulog.ico"))     menu.append(TortoiseMenu(_("Search Repository"),   _("Search revisions of files for a text pattern"),   self.handlers._grep, icon="menurepobrowse.ico"))     if repo.ui.config('tortoisehg', 'view'):   menu.append(TortoiseMenu(_("Revision Graph"),   _("View history with DAG graph"),   self.handlers._view, icon="menurevisiongraph.ico"))     menu.append(TortoiseMenuSep())     menu.append(TortoiseMenu(_("Synchronize..."),   _("Synchronize with remote repository"),   self.handlers._synch, icon="menusynch.ico"))   menu.append(TortoiseMenu(_("Recovery..."),   _("General repair and recovery of repository"),   self.handlers._recovery, icon="general.ico"))   menu.append(TortoiseMenu(_("Web Server"),   _("start web server for this repository"),   self.handlers._serve, icon="proxy.ico"))     menu.append(TortoiseMenuSep())   menu.append(TortoiseMenu(_("Create Clone"),   _("Clone a repository here"),   self.handlers._clone, icon="menuclone.ico"))   can_init = repo.root != rpath and os.path.isdir(rpath)   menu.append(TortoiseMenu(_("Create Repository Here"),   _("create a new repository in this directory"),   self.handlers._init, icon="menucreaterepos.ico",   state=can_init))     # config settings menu   menu.append(TortoiseMenuSep())   optmenu = TortoiseSubmenu(_("Settings"), '',   icon="menusettings.ico")   optmenu.add_menu(_("Global"),   _("Configure user wide settings"),   self.handlers._config_user, icon="settings_user.ico")   if repo:   optmenu.add_menu(_("Repository"),   _("Configure settings local to this repository"),   self.handlers._config_repo,   icon="settings_repo.ico")   menu.append(optmenu)     # add common menu items   menu.append(TortoiseMenuSep())   menu.append(TortoiseMenu(_("About"), _("About TortoiseHg"),   self.handlers._about, icon="menuabout.ico"))     thgmenu.append(menu)   thgmenu.append(TortoiseMenuSep())   return thgmenu