Kiln » TortoiseHg » TortoiseHg
Clone URL:  
Pushed to one repository · View In Graph Contained in 1.0.1, 1.0.2, and 1.0.3

stable protect filenames in command lines

Filenames that start with '--' cause trouble when used as positional
arguments on the command line since they are seen as a command line
flag. So

hg clone foo --foobar

fails and result in questions like this:

http://stackoverflow.com/questions/2523080/

There is a standard way to indicate that the following command line
arguments should be interpreted literally, namely by giving an
argument of '--'. So

hg clone -- foo --foobar

works as expected.

Changeset 829f55c1ae49

Parent 1e847daf480b

by Martin Geisler

Changes to 10 files · Browse files at 829f55c1ae49 Showing diff from parent 1e847daf480b Diff from another changeset...

 
226
227
228
 
229
230
231
 
226
227
228
229
230
231
232
@@ -226,6 +226,7 @@
  cmdline.append(rev)   cmdline.append('-t')   cmdline.append(type) + cmdline.append('--')   cmdline.append(hglib.fromutf(dest))     # start archiving
 
1007
1008
1009
1010
 
1011
1012
1013
 
1007
1008
1009
 
1010
1011
1012
1013
@@ -1007,7 +1007,7 @@
  (self.curfile, rev))   if dialog.run() == gtk.RESPONSE_NO:   return - cmdline = ['hg', 'revert', '--verbose', '--rev', str(rev), self.curfile] + cmdline = ['hg', 'revert', '--verbose', '--rev', str(rev), '--', self.curfile]   dlg = hgcmd.CmdDialog(cmdline)   dlg.run()   dlg.hide()
 
331
332
333
 
334
335
336
 
331
332
333
334
335
336
337
@@ -331,6 +331,7 @@
  cmdline.append('--verbose')   cmdline.append(hglib.fromutf(src))   if dest: + cmdline.append('--')   cmdline.append(hglib.fromutf(dest))     # start cloning
 
1017
1018
1019
1020
 
1021
1022
1023
 
1146
1147
1148
 
1149
1150
1151
 
1017
1018
1019
 
1020
1021
1022
1023
 
1146
1147
1148
1149
1150
1151
1152
@@ -1017,7 +1017,7 @@
  # prompts). Problem?   self.opts['addremove'] = True   if self.qnew or self.qheader is not None: - cmdline = ['hg', 'addremove', '--verbose'] + cmdline = ['hg', 'addremove', '--verbose', '--']   cmdline += [self.repo.wjoin(x) for x in files]   self.execute_command(cmdline, force=True)   return True @@ -1146,6 +1146,7 @@
  cmdline += ['--message', hglib.fromutf(self.opts['message'])]   if self.qnew:   cmdline += [hglib.fromutf(self.get_qnew_name())] + cmdline.append('--')   cmdline += files   if autopush:   cmdline = (cmdline, ['hg', 'push'])
 
1660
1661
1662
1663
 
1664
1665
1666
 
1856
1857
1858
1859
 
1860
1861
1862
 
1941
1942
1943
1944
 
1945
1946
1947
 
2285
2286
2287
 
2288
2289
2290
 
2526
2527
2528
2529
 
2530
2531
 
2532
2533
2534
 
2557
2558
2559
2560
 
2561
2562
2563
 
1660
1661
1662
 
1663
1664
1665
1666
 
1856
1857
1858
 
1859
1860
1861
1862
 
1941
1942
1943
 
1944
1945
1946
1947
 
2285
2286
2287
2288
2289
2290
2291
 
2527
2528
2529
 
2530
2531
2532
2533
2534
2535
2536
 
2559
2560
2561
 
2562
2563
2564
2565
@@ -1660,7 +1660,7 @@
  # load the rebase extension explicitly   hglib.loadextension(self.ui, 'rebase')   - cmdline = ['hg'] + cmd + [self.bfile] + cmdline = ['hg'] + cmd + ['--', self.bfile]     def callback(return_code, *args):   self.remove_overlay('--rebase' in cmd) @@ -1856,7 +1856,7 @@
  self).run()   self.pathentry.grab_focus()   return - cmdline = ['hg'] + cmd + self.get_proxy_args() + [remote_path] + cmdline = ['hg'] + cmd + self.get_proxy_args() + ['--', remote_path]     def callback(return_code, *args):   if return_code == 0: @@ -1941,7 +1941,7 @@
  cmdline = ['hg', 'push'] + self.get_proxy_args()   if self.forcepush:   cmdline += ['--force'] - cmdline += [remote_path] + cmdline += ['--', remote_path]     def callback(return_code, *args):   if return_code == 0: @@ -2285,6 +2285,7 @@
  status = _('Bundling from %(base)s to %(rev)s...') % data   else:   status = _('Bundling from %(base)s to tip...') % data + cmdline.append('--')   cmdline.append(result)     def callback(return_code, *args): @@ -2526,9 +2527,10 @@
    node = self.repo[self.currevid].node()   rev = str(self.currevid) - cmdline = ['hg', 'push', '--rev', rev, remote_path] + cmdline = ['hg', 'push', '--rev', rev]   if self.forcepush:   cmdline += ['--force'] + cmdline += ['--', remote_path]     def callback(return_code, *args):   if return_code == 0: @@ -2557,7 +2559,7 @@
    def pull_to(self, menuitem):   rev = str(self.currevid) - cmdline = ['hg', 'pull', '--rev', rev, self.bfile] + cmdline = ['hg', 'pull', '--rev', rev, '--', self.bfile]     def callback(return_code, *args):   if return_code == 0:
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
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
 # quickop.py - TortoiseHg's dialog for quick dirstate operations  #  # Copyright 2009 Steve Borho <steve@borho.org>  #  # 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  import gtk  import pango    from mercurial import cmdutil, util    from tortoisehg.util.i18n import _  from tortoisehg.util import hglib, shlib    from tortoisehg.hgtk import gtklib, gdialog    LABELS = { 'add': (_('Select files to add'), _('Add')),   'forget': (_('Select files to forget'), _('Forget')),   'revert': (_('Select files to revert'), _('Revert')),   'remove': (_('Select files to remove'), _('Remove')),}    class QuickOpDialog(gdialog.GDialog):   """ Dialog for performing quick dirstate operations """   def __init__(self, command, pats):   gdialog.GDialog.__init__(self, resizable=True)   self.pats = pats     # Handle rm alias   if command == 'rm':   command = 'remove'   self.command = command     # show minimize/maximize buttons   self.realize()   if self.window:   self.window.set_decorations(gtk.gdk.DECOR_ALL)     ### Start of Overriding Section ###     def get_title(self, reponame):   return reponame + ' - hg ' + self.command     def get_icon(self):   return 'hg.ico'     def get_defsize(self):   return (450, 300)     def get_body(self, vbox):   os.chdir(self.repo.root)     # wrap box   wrapbox = gtk.VBox()   wrapbox.set_border_width(5)   vbox.pack_start(wrapbox, True, True)   self.wrapbox = wrapbox     lbl = gtk.Label(LABELS[self.command][0])   lbl.set_alignment(0, 0)   wrapbox.pack_start(lbl, False, False)     def keypressed(tree, event):   'Make spacebar toggle selected rows'   if event.keyval != 32:   return False   def toggler(model, path, bufiter):   model[path][0] = not model[path][0]   selection = tree.get_selection()   selection.selected_foreach(toggler)   return True     # add file list treeview   fm = gtk.ListStore(bool, # Checked   str, # Path   str, # Path-UTF8   str) # Status   self.filetree = gtk.TreeView(fm)   self.filetree.connect('key-press-event', keypressed)   self.filetree.set_headers_clickable(True)   self.filetree.set_reorderable(False)   if hasattr(self.filetree, 'set_rubber_banding'):   self.filetree.set_rubber_banding(True)   fontlist = hglib.getfontconfig()['fontlist']   self.filetree.modify_font(pango.FontDescription(fontlist))     def select_toggle(cell, path):   fm[path][0] = not fm[path][0]     # file selection checkboxes   toggle_cell = gtk.CellRendererToggle()   toggle_cell.connect('toggled', select_toggle)   toggle_cell.set_property('activatable', True)     col = gtk.TreeViewColumn('', toggle_cell, active=0)   col.set_resizable(False)   self.filetree.append_column(col)     col = gtk.TreeViewColumn(_('status'), gtk.CellRendererText(), text=3)   self.filetree.append_column(col)     col = gtk.TreeViewColumn(_('path'), gtk.CellRendererText(), text=2)   self.filetree.append_column(col)     scroller = gtk.ScrolledWindow()   scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)   scroller.set_shadow_type(gtk.SHADOW_ETCHED_IN)   scroller.add(self.filetree)   wrapbox.pack_start(scroller, True, True, 6)     def toggleall(button):   for row in self.filetree.get_model():   row[0] = not row[0]     # extra box   self.extrabox = hbox = gtk.HBox()   wrapbox.pack_start(hbox, False, False)     ## toggle button   tb = gtk.Button(_('Toggle all selections'))   tb.connect('pressed', toggleall)   hbox.pack_start(tb, False, False)     if self.command == 'revert':   ## no backup checkbox   chk = gtk.CheckButton(_('Do not save backup files (*.orig)'))   hbox.pack_start(chk, False, False, 6)   self.nobackup = chk     ## padding   hbox.pack_start(gtk.Label())     types = { 'add' : 'I?',   'forget' : 'MAR!C',   'revert' : 'MAR!',   'remove' : 'MAR!CI?',   }   filetypes = types[self.command]     try:   matcher = cmdutil.match(self.repo, self.pats)   status = self.repo.status(match=matcher,   clean='C' in filetypes,   ignored='I' in filetypes,   unknown='?' in filetypes)   except (IOError, util.Abort), e:   gdialog.Prompt(_('Unable to determine repository status'),   str(e), self).run()   self.earlyout=True   self.hide()   return     (modified, added, removed, deleted, unknown, ignored, clean) = status   if 'M' in filetypes:   for f in modified:   fm.append([True, f, hglib.toutf(f), _('modified')])   if 'A' in filetypes:   for f in added:   fm.append([True, f, hglib.toutf(f), _('added')])   if 'R' in filetypes:   for f in removed:   fm.append([True, f, hglib.toutf(f), _('removed')])   if '!' in filetypes:   for f in deleted:   fm.append([True, f, hglib.toutf(f), _('missing')])   if '?' in filetypes:   for f in unknown:   fm.append([True, f, hglib.toutf(f), _('unknown')])   if 'I' in filetypes:   for f in ignored:   if self.command == 'remove' or f in self.pats:   fm.append([True, f, hglib.toutf(f), _('ignored')])   if 'C' in filetypes:   for f in clean:   if self.command == 'remove' or f in self.pats:   fm.append([True, f, hglib.toutf(f), _('clean')])     if not len(fm):   gdialog.Prompt(_('No appropriate files'),   _('No files found for this operation'), self).run()   self.earlyout=True   self.hide()     def get_buttons(self):   return [('go', LABELS[self.command][1], gtk.RESPONSE_OK),   ('cancel', gtk.STOCK_CANCEL, gtk.RESPONSE_CLOSE)]     def get_default_button(self):   return 'go'     def get_action_map(self):   return {gtk.RESPONSE_OK: self.operation}     def switch_to(self, normal, working, cmd):   self.wrapbox.set_sensitive(normal)   self.buttons['go'].set_property('visible', normal)   self.buttons['cancel'].set_property('visible', normal)   if normal:   self.buttons['cancel'].grab_focus()     def command_done(self, returncode, useraborted, list):   if returncode == 0:   shlib.shell_notify(list)   self.cmd.set_result(_('Successfully'), style='ok')   elif useraborted:   self.cmd.set_result(_('Canceled'), style='error')   else:   self.cmd.set_result(_('Failed'), style='error')     ### End of Overriding Section ###     def operation(self):   fm = self.filetree.get_model()   deleting = self.command == 'remove'   list, dellist = [], []   for row in fm:   if not row[0]: continue   if deleting and row[3] in (_('unknown'), _('ignored')):   dellist.append(row[1])   else:   list.append(row[1])     if not (list or dellist):   gdialog.Prompt(_('No files selected'),   _('No operation to perform'), self).run()   return     for file in dellist:   try:   os.unlink(file)   except IOError:   pass     if not list:   gtklib.idle_add_single_call(self.response, gtk.RESPONSE_CLOSE)   return     # prepare command line - cmdline = ['hg', self.command, '--verbose'] + list + cmdline = ['hg', self.command, '--verbose']   if hasattr(self, 'nobackup') and self.nobackup.get_active():   cmdline.append('--no-backup') + cmdline.append('--') + cmdline += list     # execute command   self.execute_command(cmdline, list)    def run(ui, *pats, **opts):   pats = hglib.canonpaths(pats)   if opts.get('canonpats'):   pats = list(pats) + opts['canonpats']   return QuickOpDialog(opts.get('alias'), pats)
 
553
554
555
556
 
557
558
559
 
553
554
555
 
556
557
558
559
@@ -553,7 +553,7 @@
  cmdline += ['--verbose']   if proxy_host and not use_proxy:   cmdline += ["--config", "http_proxy.host="] - cmdline += [remote_path] + cmdline += ['--', remote_path]   self.lastcmd = cmdline     # show command to be executed
 
937
938
939
940
 
941
942
943
 
937
938
939
 
940
941
942
943
@@ -937,7 +937,7 @@
  return   if testpath[0] == '~':   testpath = os.path.expanduser(testpath) - cmdline = ['hg', 'incoming', '--verbose', testpath] + cmdline = ['hg', 'incoming', '--verbose', '--', testpath]   dlg = hgcmd.CmdDialog(cmdline, text='hg incoming')   dlg.run()   dlg.hide()
 
341
342
343
344
 
345
346
347
 
341
342
343
 
344
345
346
347
@@ -341,7 +341,7 @@
  raise _('unexpected destination name: %s') % dest     # prepare command line - cmdline = ['hg', cmd, '--verbose'] + cmdline = ['hg', cmd, '--verbose', '--']   cmdline.extend(files)     # start importing
 
298
299
300
301
 
302
303
304
 
358
359
360
361
 
362
363
 
 
364
365
366
 
374
375
376
377
 
378
379
380
 
448
449
450
451
 
452
453
454
 
298
299
300
 
301
302
303
304
 
358
359
360
 
361
362
363
364
365
366
367
368
 
376
377
378
 
379
380
381
382
 
450
451
452
 
453
454
455
456
@@ -298,7 +298,7 @@
  """   if not self.is_operable():   return - cmdline = ['hg', 'qgoto', patch] + cmdline = ['hg', 'qgoto', '--', patch]   self.cmd.execute(cmdline, self.cmd_done)     def qpop(self, all=False): @@ -358,9 +358,11 @@
  keep = True   else:   return - cmdline = ['hg', 'qdelete'] + unapplied + cmdline = ['hg', 'qdelete']   if keep:   cmdline.append('--keep') + cmdline.append('--') + cmdline.extned(unapplied)   self.cmd.execute(cmdline, self.cmd_done, noemit=True)     def qrename(self, name, patch='qtip'): @@ -374,7 +376,7 @@
  """   if not name or not self.has_patch():   return - cmdline = ['hg', 'qrename', patch, name] + cmdline = ['hg', 'qrename', '--', patch, name]   self.cmd.execute(cmdline, self.cmd_done)     def qrename_ui(self, patch='qtip'): @@ -448,7 +450,7 @@
  " into the current patch '%(qtip)s'?") % data).run()   if ret != gtk.RESPONSE_YES:   return - cmdline = ['hg', 'qfold'] + unapplied + cmdline = ['hg', 'qfold', '--'] + unapplied   self.cmd.execute(cmdline, self.cmd_done)     def qreorder(self, patch, op):