Release testing and the relationship between 'bzr selftest' and plugins

Alexander Belchenko bialix at
Fri Mar 16 17:03:53 UTC 2012

Jelmer Vernooij пишет:
> Am 15/03/12 16:29, schrieb Alexander Belchenko:
>> Vincent Ladeuil пишет:
>>>>>>>> Jelmer Vernooij <jelmer at> writes:
>>> <snip/>
>>>     > The API versioning infrastructure doesn't work
>>>     > ----------------------------------------------
>>> Sad but true.
>> I think the problem is in the fact that bzrlib is too big and has very
>> big public API: a lot of classes and methods. Multiply it to the
>> possible changes in algorithms or main ideas behind those classes.
>> E.g. whether some code should use Inventory or it shouldn't.
>> The main source of frustration is in the fact that changes in ideas
>> behind classes are backward incompatible, so that breaks plugins.
>> Changes in API itself are lesser evil for me, but it's often annoying,
>> e.g. when some public method gets new non-optional argument.
> <snip/>
>> I remember sometimes in the past, when we had forced to update QBzr or
>> some other plugins because of small but annoying changes in bzrlib, I
>> wished to have an intermediate proxy on top of bzrlib API that could
>> adapt to minor API changes in bzrlib and provide a consistent
>> interface to bzrlib internals required by QBzr needs.
> Why does it have to be a proxy? Is there any particular reason we
> shouldn't just make the changes in bzrlib itself more robust by e.g. not
> adding non-optional arguments?

What's about deprecating/deleting some code from bzrlib? Like 
deprecation of tree_files in I'm sure there was a reason 
behind this deprecation, but qbzr for example only uses it as 
tree_files(selected_list) with all optional arguments in their default 
state. The change itself is small enough, just to change 
builtins.tree_files to WorkingTree.open_containing_paths, and all other 
semantics stay the same. In the end I wondered why such rename needed 
from the POV of plugins.

Proxy should hide such minor changes in bzrlib API from plugins, IIUC.

>> If you look at QBzr internals you could see that only small amount of
>> q-commands works with bzrlib API directly, and all those commands are
>> in fact "browsers/viewers" (browse log, working tree/revision tree
>> browser, diff viewer, annotations viewer).
>> Most of q-commands provided by QBzr are just front-ends to construct
>> valid bzr command line and execute `bzr blah...` as subprocess. This
>> approach has proved to be very successful - we cover most of the bzr
>> CLI required by bzr-explorer without any effort from our side to keep
>> compatibility with bzrlib internals.
> Is the relatively low number of issues you've seen with qbzr due to the
> fact that the command line interface is used, though? bzr-gtk uses
> roughly the same functionality as qbzr but through the bzrlib API and it
> also hasn't seen as many issues. I think for the majority of plugins
> which use the well-known stable APIs we haven't seen many issues. It's
> the somewhat lower level APIs that are more prone to changes that are
> problematic.
>> So, maybe reducing the amount of public bzrlib API will help here? Or
>> provide some consistent set of methods as an adaptor between plugins
>> needs and bzrlib internals? Of course plugins authors should
>> understand what they need from such interface. Of course plugins like
>> bzr-svn or bzr-git won't need such adaptor, they have to dive deep
>> into bzrlib.
>> Maybe such adaptor could be a core plugin? I'm not quite sure.
>> But such adaptor should be very conservative to able to operate with
>> old versions of plugins. Maybe such adaptor could provide new bzrlib
>> features by new names, so plugins could get benefits of using newer
>> features if they are aware of it.

> Is there a particular reason this has to be a features dictionary,
> rather than e.g. an object in a module the plugins could look for ? This
> is how bzr-svn/bzr-git/bzr-hg do most of their compatibility checking.

If we talks about qbzr's FEATURE dictionary, then yes, I wanted one 
standard place to look. That place should be always in the same place to 
keep backward compatibility.

For the qignore case described above: bzr-explorer don't use qignore as 
python object directly, but run `bzr qignore` as subprocess. So checking 
of particular object in particular module is too much for bzr-explorer. 
I don't want bzr-explorer to know too much about qbzr internals if it 
can live without that. Python code tends to be too much open for 
inspection that it's hard to draw a line between internal API and API 
specifically designed to use from outside.

More information about the bazaar mailing list