On Monday, 24 October 2016 22:30:08 BST Yuya Nishihara wrote:
> On Mon, 24 Oct 2016 11:04:39 +0100, Barry Scott wrote:
> > > So this patch contains 3 different things. Can you send them as separate
> > > patches?
> > > 
> > > - add callbacks
> > > - change clone() behavior (which seems wrong)
> > > - add init()
> > 
> > Yes and no. Both clone and init cannot be used with the call backs with
> > these changes.
> > 
> > I can package as 3 patches that build on each other. But in my mind these
> > are linked.
> > 
> > I will do as you advise, please confirm 3 patches required.
> 
> https://www.mercurial-scm.org/wiki/ContributingChanges#Submission_checklist
> 
> "6. patch does just one thing (if you need a bullet list, split your patch)"
> 
> I would split clone/init changes since they solve separate issues on top of
> the new callback API.
> 
> > >> +    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.
> > 
> > True but it is descriptive.
> 
> Hmm, but it introduces new naming style, right? I have no strong opinion
> about this, but "prompt" seems just fine because we already have one.

prompt is not part of the public API.

> 
> > > And I think your setprotocoltrace() covers setcbout/err. Do we still
> > > need them?> 
> > They solve two distinct problems.
> > 
> > protocol tracing provides a way to see the low level, almost unprocessed
> > messages between client and server. Its purpose is to allow inspection
> > and debugging of the protocol.
> > 
> > cbout and cderr provide a user of hglib with the post processed output and
> > error information.
> > 
> > In production my GUI will use cdout and cderr often, but never protocol
> > trace. But when I cannot figure out what is happening I turn on protocol
> > trace to get an insight into how hglib works. That is, for example, how I
> > found that password: is sent on the ā€˜eā€™ channel.
> > 
> > Conclusion yes we need both.
> 
> Okay, I don't think they are required, but I agree they are semantically
> different from setprotocoltrace().
> 
> Another option is to provide an interface to set a single callback object
> that handles o/e/I/L channels altogether, so we could provide a helper class
> to translate o+L and e+L sequences to .prompt() and .password()
> respectively.

I've assumed that its better to leave the hglib patch simple.

As we talked about before a getcredentials call back would be great.
But That needs hg itself to change. I sugest that we stay with this API
until that is possible.

> 
> TortoiseHg handles user interaction in that way:
> https://bitbucket.org/tortoisehg/thg/src/3.9.2/tortoisehg/hgqt/cmdcore.py#cm
> dcore.py-44
> 
> BTW, is hglib usable in GUI? I think its synchronous I/O will behave pretty
> bad in GUI environment.

With these patches its usable :-)

I run any long running hg operation in a background thread.

> > >>     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.> 
> > It is a backward compatible extension of the API by adding what hglib
> > provided in the __init__.py version of clone.
> 
> No.
> 
>   client = hglib.open()
>   client.root()
>   client.clone('.', 'somewhere')
>   client.root()
> 
> Here clone() shouldn't reopen the client. Be aware that hglib.open() opens
> the repository found in cwd by default.

What I wanted was to be able to create the hgclient() object,
setup call backs then do the init() or the clone() with the call backs being 
called as required.

If I drop the reopenning that avoids your objects to semantic changhed.

Indeed in my GUI code I do not use the hgclient() object that I do the clone()
of init() on. I use a new object.

> Maybe you can get some errors by running the test.
> 
>   $ python test.py --with-doctest --with-hg path/to/hg

Will do.

> 
> > > Also, dest may be a remote (ssh) path.
> > 
> > I do not see how my patch breaks things in that case. I do not assume the
> > dest is a local path.
> 
> If dest isn't a local path, open() with ['-R', dest] would fail.

I'll drop the reopen code.

> 
> > >> +    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)
> > 
> > That is semantically identical to my patch.
> > 
> > See __init__.py:11 and client.py:49 of the unpatched source.
> > 
> > However that does not work for the call back case. Here is how I use init.
> > 
> >    c = hglib.open( None )
> >    c.setcbout(cbout)
> >    c.setcberr(cbout)
> >    c.init(b'path/for/new/repo')
> >    c.status() # works on new repo
> > 
> > This works for the local path case. And this for clone:
> >    c = hglib.open( None )
> >    c.setcbout(cbout)
> >    c.setcberr(cbout)
> >    c.setcbprompt(cbprompt)
> >    c.clone(b'http://example.com/hgrepo', b'path/for/new/repo
> >    <http://example.com/hgrepo',%20b'path/for/new/repo>') c.status() #
> >    works on new repo
> > > 
> > > 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()
> > 
> > I choose to leave the hglib.init and hglib.clone code untouched for as its
> > uses of it cannot care about call backs.
> 
> Maybe they could take a callback as an argument?

You will recall that where I started and you pointed out that it should be set 
once as state of hgclient().

I'll genreate a new set of patches for this and post once I see that test.py
is happy.

Barry

_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Reply via email to