##// END OF EJS Templates
hidden: add support to explicitly access hidden changesets with SSH peers...
Manuel Jacob -
r51316:45c7bada default
parent child Browse files
Show More
@@ -69,6 +69,7 b' from . import ('
69 )
69 )
70 from .utils import (
70 from .utils import (
71 dateutil,
71 dateutil,
72 procutil,
72 stringutil,
73 stringutil,
73 urlutil,
74 urlutil,
74 )
75 )
@@ -6672,7 +6673,25 b' def serve(ui, repo, **opts):'
6672 raise error.RepoError(
6673 raise error.RepoError(
6673 _(b"there is no Mercurial repository here (.hg not found)")
6674 _(b"there is no Mercurial repository here (.hg not found)")
6674 )
6675 )
6675 s = wireprotoserver.sshserver(ui, repo)
6676 accesshidden = False
6677 if repo.filtername is None:
6678 allow = ui.configlist(
6679 b'experimental', b'server.allow-hidden-access'
6680 )
6681 user = procutil.getuser()
6682 if allow and scmutil.ismember(ui, user, allow):
6683 accesshidden = True
6684 else:
6685 msg = (
6686 _(
6687 b'ignoring request to access hidden changeset by '
6688 b'unauthorized user: %s\n'
6689 )
6690 % user
6691 )
6692 ui.warn(msg)
6693
6694 s = wireprotoserver.sshserver(ui, repo, accesshidden=accesshidden)
6676 s.serve_forever()
6695 s.serve_forever()
6677 return
6696 return
6678
6697
@@ -177,7 +177,9 b' def _cleanuppipes(ui, pipei, pipeo, pipe'
177 ui.develwarn(b'missing close on SSH connection created at:\n%s' % warn)
177 ui.develwarn(b'missing close on SSH connection created at:\n%s' % warn)
178
178
179
179
180 def _makeconnection(ui, sshcmd, args, remotecmd, path, sshenv=None):
180 def _makeconnection(
181 ui, sshcmd, args, remotecmd, path, sshenv=None, remotehidden=False
182 ):
181 """Create an SSH connection to a server.
183 """Create an SSH connection to a server.
182
184
183 Returns a tuple of (process, stdin, stdout, stderr) for the
185 Returns a tuple of (process, stdin, stdout, stderr) for the
@@ -187,8 +189,12 b' def _makeconnection(ui, sshcmd, args, re'
187 sshcmd,
189 sshcmd,
188 args,
190 args,
189 procutil.shellquote(
191 procutil.shellquote(
190 b'%s -R %s serve --stdio'
192 b'%s -R %s serve --stdio%s'
191 % (_serverquote(remotecmd), _serverquote(path))
193 % (
194 _serverquote(remotecmd),
195 _serverquote(path),
196 b' --hidden' if remotehidden else b'',
197 )
192 ),
198 ),
193 )
199 )
194
200
@@ -393,13 +399,6 b' class sshv1peer(wireprotov1peer.wirepeer'
393 stderr and to forward its output.
399 stderr and to forward its output.
394 """
400 """
395 super().__init__(ui, path=path, remotehidden=remotehidden)
401 super().__init__(ui, path=path, remotehidden=remotehidden)
396 if remotehidden:
397 msg = _(
398 b"ignoring `--remote-hidden` request\n"
399 b"(access to hidden changeset for ssh peers not supported "
400 b"yet)\n"
401 )
402 ui.warn(msg)
403 # self._subprocess is unused. Keeping a handle on the process
402 # self._subprocess is unused. Keeping a handle on the process
404 # holds a reference and prevents it from being garbage collected.
403 # holds a reference and prevents it from being garbage collected.
405 self._subprocess = proc
404 self._subprocess = proc
@@ -416,6 +415,7 b' class sshv1peer(wireprotov1peer.wirepeer'
416 self._caps = caps
415 self._caps = caps
417 self._autoreadstderr = autoreadstderr
416 self._autoreadstderr = autoreadstderr
418 self._initstack = b''.join(util.getstackframes(1))
417 self._initstack = b''.join(util.getstackframes(1))
418 self._remotehidden = remotehidden
419
419
420 # Commands that have a "framed" response where the first line of the
420 # Commands that have a "framed" response where the first line of the
421 # response contains the length of that response.
421 # response contains the length of that response.
@@ -683,7 +683,13 b' def make_peer('
683 raise error.RepoError(_(b'could not create remote repo'))
683 raise error.RepoError(_(b'could not create remote repo'))
684
684
685 proc, stdin, stdout, stderr = _makeconnection(
685 proc, stdin, stdout, stderr = _makeconnection(
686 ui, sshcmd, args, remotecmd, remotepath, sshenv
686 ui,
687 sshcmd,
688 args,
689 remotecmd,
690 remotepath,
691 sshenv,
692 remotehidden=remotehidden,
687 )
693 )
688
694
689 peer = _make_peer(
695 peer = _make_peer(
@@ -446,7 +446,7 b' class sshv1protocolhandler:'
446 pass
446 pass
447
447
448
448
449 def _runsshserver(ui, repo, fin, fout, ev):
449 def _runsshserver(ui, repo, fin, fout, ev, accesshidden=False):
450 # This function operates like a state machine of sorts. The following
450 # This function operates like a state machine of sorts. The following
451 # states are defined:
451 # states are defined:
452 #
452 #
@@ -487,7 +487,9 b' def _runsshserver(ui, repo, fin, fout, e'
487 _sshv1respondbytes(fout, b'')
487 _sshv1respondbytes(fout, b'')
488 continue
488 continue
489
489
490 rsp = wireprotov1server.dispatch(repo, proto, request)
490 rsp = wireprotov1server.dispatch(
491 repo, proto, request, accesshidden=accesshidden
492 )
491 repo.ui.fout.flush()
493 repo.ui.fout.flush()
492 repo.ui.ferr.flush()
494 repo.ui.ferr.flush()
493
495
@@ -522,10 +524,11 b' def _runsshserver(ui, repo, fin, fout, e'
522
524
523
525
524 class sshserver:
526 class sshserver:
525 def __init__(self, ui, repo, logfh=None):
527 def __init__(self, ui, repo, logfh=None, accesshidden=False):
526 self._ui = ui
528 self._ui = ui
527 self._repo = repo
529 self._repo = repo
528 self._fin, self._fout = ui.protectfinout()
530 self._fin, self._fout = ui.protectfinout()
531 self._accesshidden = accesshidden
529
532
530 # Log write I/O to stdout and stderr if configured.
533 # Log write I/O to stdout and stderr if configured.
531 if logfh:
534 if logfh:
@@ -542,4 +545,6 b' class sshserver:'
542
545
543 def serveuntil(self, ev):
546 def serveuntil(self, ev):
544 """Serve until a threading.Event is set."""
547 """Serve until a threading.Event is set."""
545 _runsshserver(self._ui, self._repo, self._fin, self._fout, ev)
548 _runsshserver(
549 self._ui, self._repo, self._fin, self._fout, ev, self._accesshidden
550 )
@@ -6,6 +6,8 b' Test the ability to access a hidden revi'
6
6
7 $ . $TESTDIR/testlib/obsmarker-common.sh
7 $ . $TESTDIR/testlib/obsmarker-common.sh
8 $ cat >> $HGRCPATH << EOF
8 $ cat >> $HGRCPATH << EOF
9 > [ui]
10 > ssh = "$PYTHON" "$RUNTESTDIR/dummyssh"
9 > [phases]
11 > [phases]
10 > # public changeset are not obsolete
12 > # public changeset are not obsolete
11 > publish=false
13 > publish=false
@@ -305,6 +307,98 b' pulling an hidden changeset with --remot'
305 abort: filtered revision 'be215fbb8c50' (not in 'served' subset)
307 abort: filtered revision 'be215fbb8c50' (not in 'served' subset)
306 [255]
308 [255]
307
309
310 Test --remote-hidden for ssh peer
311 ----------------------------------
312
313 $ hg clone --pull ssh://user@dummy/repo-with-hidden client-ssh
314 requesting all changes
315 adding changesets
316 adding manifests
317 adding file changes
318 added 2 changesets with 2 changes to 1 files
319 2 new obsolescence markers
320 new changesets 5f354f46e585:c33affeb3f6b (1 drafts)
321 updating to branch default
322 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
323 $ hg -R client-ssh log -G --hidden -v
324 @ 1:c33affeb3f6b c_Amend_New [draft]
325 |
326 o 0:5f354f46e585 c_Public [public]
327
328
329 Check on a server that do not allow hidden access:
330 ``````````````````````````````````````````````````
331
332 pulling an hidden changeset should fail:
333
334 $ hg -R client-ssh pull -r be215fbb8c50
335 pulling from ssh://user@dummy/repo-with-hidden
336 abort: filtered revision 'be215fbb8c50' (not in 'served' subset)
337 [255]
338
339 pulling an hidden changeset with --remote-hidden should succeed:
340
341 $ hg -R client-ssh pull --remote-hidden -r be215fbb8c50
342 pulling from ssh://user@dummy/repo-with-hidden
343 remote: ignoring request to access hidden changeset by unauthorized user: * (glob)
344 abort: filtered revision 'be215fbb8c50' (not in 'served' subset)
345 [255]
346 $ hg -R client-ssh log -G --hidden -v
347 @ 1:c33affeb3f6b c_Amend_New [draft]
348 |
349 o 0:5f354f46e585 c_Public [public]
350
351
352 Check on a server that do allow hidden access:
353 ``````````````````````````````````````````````
354
355 $ cat << EOF >> repo-with-hidden/.hg/hgrc
356 > [experimental]
357 > server.allow-hidden-access=*
358 > EOF
359
360 pulling an hidden changeset should fail:
361
362 $ hg -R client-ssh pull -r be215fbb8c50
363 pulling from ssh://user@dummy/repo-with-hidden
364 abort: filtered revision 'be215fbb8c50' (not in 'served' subset)
365 [255]
366
367 pulling an hidden changeset with --remote-hidden should succeed:
368
369 $ hg -R client-ssh pull --remote-hidden -r be215fbb8c50
370 pulling from ssh://user@dummy/repo-with-hidden
371 searching for changes
372 adding changesets
373 adding manifests
374 adding file changes
375 added 1 changesets with 1 changes to 1 files (+1 heads)
376 (1 other changesets obsolete on arrival)
377 (run 'hg heads' to see heads)
378 $ hg -R client-ssh log -G --hidden -v
379 x 2:be215fbb8c50 c_Amend_Old [draft]
380 |
381 | @ 1:c33affeb3f6b c_Amend_New [draft]
382 |/
383 o 0:5f354f46e585 c_Public [public]
384
385
386 Pulling a secret changeset is still forbidden:
387
388 secret visible:
389
390 $ hg -R client-ssh pull --remote-hidden -r 8d28cbe335f3
391 pulling from ssh://user@dummy/repo-with-hidden
392 abort: filtered revision '8d28cbe335f3' (not in 'served.hidden' subset)
393 [255]
394
395 secret hidden:
396
397 $ hg -R client-ssh pull --remote-hidden -r 1c6afd79eb66
398 pulling from ssh://user@dummy/repo-with-hidden
399 abort: filtered revision '1c6afd79eb66' (not in 'served.hidden' subset)
400 [255]
401
308 =============
402 =============
309 Final cleanup
403 Final cleanup
310 =============
404 =============
General Comments 0
You need to be logged in to leave comments. Login now