[PATCH python-hglib v2] Add feature to allow hglib user to get call backs for prompts, output

Yuya Nishihara yuya at tcha.org
Sun Oct 23 05:53:26 EDT 2016


On Sat, 22 Oct 2016 18:37:07 +0100, Barry A. Scott wrote:
> # HG changeset patch
> # User Barry A. Scott <barry at barrys-emacs.org>
> # Date 1477157573 -3600
> #      Sat Oct 22 18:32:53 2016 +0100
> # Node ID 12c96b1d8dfff261f91ed010cc59ce57bfa63b4f
> # Parent  6f15cb7cc9cb4427f35c60080f85dbf4ca5abd10
> Add feature to allow hglib user to get call backs for prompts, output
> and errors.

"topic: short summary line with no trailing period"

https://www.mercurial-scm.org/wiki/ContributingChanges#Patch_descriptions

> setcbout(cbout), setcberr(cberr) and setcbprompt(cbprompt) are used to
> set the call back function used by the hgclient class. cb stands for
> call back.
> 
> cbout is a function that will be called with the stdout data of the
> command as it runs. cbout is called with output as it is made available,
> which can be as partial lines or multiple lines.
> 
> cberr is a function that will be called with the stderr data of the
> command as it runs. cberr is called with output as it is made available,
> which can be as partial lines or multiple lines.
> 
> Command that make remote connects can prompt for username and password
> for HTTP/HTTPS connections.
> 
> cbprompt is called when hgclient need a response to a prompt from the
> server. It receives the max number of bytes to return and the contents
> of stdout received so far. The last text sent to either cbout or cberr
> will contain the prompt text itself.
> 
> init() has been added to hgclient to allow use of setcbXXX functions
> with init(). The init() code is based on the version in __init__.py.

So this patch contains 3 different things. Can you send them as separate
patches?

 - add callbacks
 - change clone() behavior (which seems wrong)
 - add init()

> +    def setcbout(self, cbout):
> +        """
> +        cbout is a function that will be called with the stdout data of
> +         the command as it runs. Call with None to stop getting call backs.
> +        """
> +        self._cbout = cbout
> +
> +    def setcberr(self, cberr):
> +        """
> +        cberr is a function that will be called with the stderr data of
> +         the command as it runs.Call with None to stop getting call backs.
> +        """
> +        self._cberr = cberr
> +
> +    def setcbprompt(self, cbprompt):
> +        """
> +        cbprompt is used to reply to prompts by the server
> +         It receives the max number of bytes to return and the
> +         contents of stdout received so far.
> +
> +        Call with None to stop getting call backs.
> +
> +        cbprompt is never called from merge() or import_()
> +        which already handle the prompt.
> +        """
> +        self._cbprompt = cbprompt

Nit: The "cb" prefix doesn't make sense here because there's little possibility
of name conflicts.

And I think your setprotocoltrace() covers setcbout/err. Do we still need them?

>      def clone(self, source=b('.'), dest=None, branch=None, updaterev=None,
> -              revrange=None):
> +              revrange=None, pull=False, uncompressed=False, ssh=None,
> +              remotecmd=None, insecure=False, encoding=None, configs=None):
>          """
>          Create a copy of an existing repository specified by source in a new
>          directory dest.
> @@ -536,9 +584,30 @@
>          revrange - include the specified changeset
>          """
>          args = cmdbuilder(b('clone'), source, dest, b=branch,
> -                          u=updaterev, r=revrange)
> +                          u=updaterev, r=revrange, pull=pull,
> +                          uncompresses=uncompressed, e=ssh,
> +                          remotecmd=remotecmd, insecure=insecure)
>          self.rawcommand(args)
>  
> +        if self._path is None:
> +            self._path = dest
> +            # become the client for the cloned hg repo
> +            self.close()
> +            self._args += ['-R', dest]
> +            self.open()

This changes the behavior of clone(), but hglib should provide a stable API.

Also, dest may be a remote (ssh) path.

> +    def init(self, dest, ssh=None, remotecmd=None, insecure=False,
> +             encoding=None, configs=None):
> +        args = util.cmdbuilder(b'init', dest, e=ssh, remotecmd=remotecmd,
> +                               insecure=insecure)
> +        self.rawcommand(args)
> +
> +        # become the client for this new hg repo
> +        self._path = dest
> +        self.close()
> +        self._args += ['-R', dest]
> +        self.open()

Same here, dest may be a remote path.

IMHO, methods of hgclient shouldn't have such magic. Instead, we can provide
a utility function on top of plain init(), e.g.

  client = client.hgclient()
  client.init(dest)
  return open(dest)

Maybe we can provide it as a replacement for hglib.init().

  def init():
      try:
          _initbyhgclient()
      except 'exception raised if command server failed to start':
          falls back to the original init()


More information about the Mercurial-devel mailing list