Merge lp:~abentley/bzr/appenddir into lp:bzr

Proposed by Aaron Bentley
Status: Work in progress
Proposed branch: lp:~abentley/bzr/appenddir
Merge into: lp:bzr
Diff against target: 158 lines (+43/-14)
5 files modified
bzrlib/config.py (+12/-9)
bzrlib/help_topics/en/configuration.txt (+17/-1)
bzrlib/tests/test_config.py (+7/-1)
doc/developers/contribution-quickstart.txt (+2/-2)
doc/en/release-notes/bzr-2.4.txt (+5/-1)
To merge this branch: bzr merge lp:~abentley/bzr/appenddir
Reviewer Review Type Date Requested Status
Vincent Ladeuil Abstain
Review via email: mp+50060@code.launchpad.net

Commit message

Support appenddir configuration policy. (Aaron Bentley)

Description of the change

Hi all,

This branch introduces a new configuration policy, "appenddir". This new
policy is similar to appendpath, except that it appends only the last path
element to the value. Here's an example configuration:

[/home/abentley/bzr]
public_branch = lp:~abentley/bzr
public_branch:policy = appenddir

This means that the public branch for "/home/abentley/bzr/foo" will be
"lp:~abentley/bzr/foo", as with appendpath. But the public branch of
"/home/abentley/bzr/bar/foo" will *also* be "lp:~abentley/bzr/foo", whereas
appendpath would make it "lp:~abentley/bzr/bar/foo". While the appendpath
behaviour may be useful for some, it produces too-long branch names in many
cases.

My motivating case is "bzr-pipeline". When a pipeline is created with
"reconfigure-pipeline", the branch is converted into a lightweight checkout,
with branches at ".bzr/pipes/". If the push location had been set with
appendpath, a push location of "lp:~abentley/bzr/foo" would become
"lp:~abentley/bzr/.bzr/pipes/foo", which is undesirable. With appenddir, it
would retain the value "lp:~abentley/bzr/foo". I believe bzr-colo has the same
issue.

While the new policy is syntactically compatible with existing config files,
current versions of bzr treat unknown configuration policies as internal
errors:
*** Bazaar has encountered an internal error. This probably indicates a
    bug in Bazaar. You can help us fix it by filing a bug report at
        https://bugs.launchpad.net/bzr/+filebug
    including this traceback and a description of the problem.

I would be happy to create a bugfix for earlier bzrs so that they emit a
user-friendly error when they encounter unknown configuration policies.

To post a comment you must log in.
Revision history for this message
Vincent Ladeuil (vila) wrote :

Thanks for working on this, this is clearly a sore point in out config handling.

I've got a couple of questions about the implementation:

- are you aware of the work in progress documented in configuration.txt in the lp:~bzr/bzr/devnotes ? The interpolation part especially may provide a more scalable means to achieve the same result.

- why did you chose 'appendir' instead of say 'nick' ? I'm well aware that they may not match but the later would also work for looms,

27 STORE_LOCATION = POLICY_NONE
28 STORE_LOCATION_NORECURSE = POLICY_NORECURSE
29 STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
30 STORE_BRANCH = 3
31 STORE_GLOBAL = 4
32 +STORE_LOCATION_APPENDDIR = POLICY_APPENDDIR

The overlapping between STORE_* and POLICY_* is already a concern in the current implementation, could you think of a better way to articulate their relationship ?

This shows even more in:

51 - if store not in [STORE_LOCATION,
52 - STORE_LOCATION_NORECURSE,
53 - STORE_LOCATION_APPENDPATH]:
54 + if store not in _policy_name:

Err, wait, checking 'store' in '_policy_name' ? This at least requires a comment...

review: Needs Information
Revision history for this message
Aaron Bentley (abentley) wrote :
Download full text (3.2 KiB)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 11-02-17 04:47 AM, Vincent Ladeuil wrote:
> Review: Needs Information
> Thanks for working on this, this is clearly a sore point in out config handling.
>
> I've got a couple of questions about the implementation:
>
> - are you aware of the work in progress documented in configuration.txt in the lp:~bzr/bzr/devnotes ?

No. I'm glad that serious re-thinking is going on. I would rather not
have to wait for a ground-up rewrite, unless it is immanent.

> The interpolation part especially may provide a more scalable means to achieve the same result.
>
> - why did you chose 'appendir' instead of say 'nick' ?

Initially, I did choose 'nick', but locations.conf is not branch-aware,
and in fact is sometimes used without a branch. So making it
branch-aware didn't seem like a good fit.

> I'm well aware that they may not match but the later would also work for looms,

Supporting looms would be nice, but holds little value for me. I
haven't used looms since I wrote bzr-pipeline.

> 27 STORE_LOCATION = POLICY_NONE
> 28 STORE_LOCATION_NORECURSE = POLICY_NORECURSE
> 29 STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
> 30 STORE_BRANCH = 3
> 31 STORE_GLOBAL = 4
> 32 +STORE_LOCATION_APPENDDIR = POLICY_APPENDDIR
>
> The overlapping between STORE_* and POLICY_* is already a concern in the current implementation, could you think of a better way to articulate their relationship ?

It looks like inheritance to me-- All STORE values indicate which file
to store the value in, while the STORE_LOCATION ones also indicate a
policy. If I was doing a radical rewrite, I'd probably make them
classes with static/classmethods, e.g.

class ValueScope:

    @classmethod
    def store_value(cls, name, value):
        config = cls.get_config()
        cls._set_value(config, name, value)

    @staticmethod
    def _set_value(config, name, value)
        config.set_value(name, value)

class GlobalScope(ValueScope):

    @staticmethod
    def get_config():
        return GlobalConfig

class PlainLocationScope(ValueScope):

    @staticmethod
    def get_config():
        return LocationConfig

class AppendPathScope(PlainLocationScope):

    @staticmethod
    def _set_value(config, name, value):
        config.set_value(name, value, policy='appendpath')

A less-radical rewrite would be to make the STORE values tuples of
config, POLICY:

STORE_BRANCH = ('branch', POLICY_NONE)
STORE_LOCATION_APPENDPATH = ('location', POLICY_APPENDPATH)

No matter what, I don't think assigning integers to these things is
doing us any good. I'd love to see "STORE_BRANCH = 'branch'". That
would make debugging easier.

> This shows even more in:
>
> 51 - if store not in [STORE_LOCATION,
> 52 - STORE_LOCATION_NORECURSE,
> 53 - STORE_LOCATION_APPENDPATH]:
> 54 + if store not in _policy_name:
>
> Err, wait, checking 'store' in '_policy_name' ? This at least requires a comment...

Yesterday, it looked like a nice way to avoid repeating ourselves.
Today, it looks a bit broken.

Aaron
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk1dR4MACgkQ0F+nu1YWqI1IoA...

Read more...

lp:~abentley/bzr/appenddir updated
5668. By Aaron Bentley

Saner checking for valid store locations.

Revision history for this message
Vincent Ladeuil (vila) wrote :

So, I've been working on this from a different angle:
- http://doc.bazaar.canonical.com/devnotes/configuration.html
- lp:~vila/bzr/new-config

This is a work in progress which still doesn't provide a working solution in core.

So basically I can't disapprove this proposal until I'm able to point to a working implementation but on the other hand, this proposal use a feature I'd like to get rid of (option and store policies) so approving it means I'll have to deprecate it in the future and provide a migration path.

On the third hand, I will need to provide a migration path for the existing policies which will require a yet *unknown* amount of work ;)

That being said:
- option expansion is (now) available and using {nickname} is very close to the 'appendir' policy,
- 'appenddir' fooled me (twice) as a policy name: it really add the *basename* of the branch/wt which indeed is a dir but I tend to think in terms of os.path API and read 'appenddir' as 'os.path.dirname'

Regarding policies, the plan is to define them once and only once for a given option, that means *outside* of the config files. This is my main issue with the current implementation.

review: Abstain
Revision history for this message
Vincent Ladeuil (vila) wrote :

Also, aren't there cases where 'appendir' would be empty and led to confusing errors ?

I also want to add that I *like* the feature even if I frown upon the implementation (while understanding that's the only one available ;).

Revision history for this message
Vincent Ladeuil (vila) wrote :

@Aaron: What's the status on this ? I'll mark it wip to clear the queue but I'm open to discussion and don't want to mark it rejected (or should it be just abandoned ?).

Unmerged revisions

5668. By Aaron Bentley

Saner checking for valid store locations.

5667. By Aaron Bentley

Support appenddir configuration policy.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/config.py'
2--- bzrlib/config.py 2011-01-20 04:44:14 +0000
3+++ bzrlib/config.py 2011-02-17 16:40:48 +0000
4@@ -109,25 +109,23 @@
5 POLICY_NONE = 0
6 POLICY_NORECURSE = 1
7 POLICY_APPENDPATH = 2
8+POLICY_APPENDDIR = 5
9
10 _policy_name = {
11 POLICY_NONE: None,
12 POLICY_NORECURSE: 'norecurse',
13 POLICY_APPENDPATH: 'appendpath',
14- }
15-_policy_value = {
16- None: POLICY_NONE,
17- 'none': POLICY_NONE,
18- 'norecurse': POLICY_NORECURSE,
19- 'appendpath': POLICY_APPENDPATH,
20- }
21-
22+ POLICY_APPENDDIR: 'appenddir',
23+ }
24+_policy_value = dict((v, k) for k, v in _policy_name.iteritems())
25+_policy_value['none'] = POLICY_NONE
26
27 STORE_LOCATION = POLICY_NONE
28 STORE_LOCATION_NORECURSE = POLICY_NORECURSE
29 STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
30 STORE_BRANCH = 3
31 STORE_GLOBAL = 4
32+STORE_LOCATION_APPENDDIR = POLICY_APPENDDIR
33
34 _ConfigObj = None
35 def ConfigObj(*args, **kwargs):
36@@ -561,6 +559,10 @@
37 if extra_path:
38 value = urlutils.join(value, extra_path)
39 return value
40+ elif policy == POLICY_APPENDDIR:
41+ if extra_path:
42+ value = urlutils.join(value, urlutils.basename(extra_path))
43+ return value
44 else:
45 raise AssertionError('Unexpected config policy %r' % policy)
46 else:
47@@ -931,7 +933,8 @@
48 """Save option and its value in the configuration."""
49 if store not in [STORE_LOCATION,
50 STORE_LOCATION_NORECURSE,
51- STORE_LOCATION_APPENDPATH]:
52+ STORE_LOCATION_APPENDPATH,
53+ STORE_LOCATION_APPENDDIR]:
54 raise ValueError('bad storage policy %r for %r' %
55 (store, option))
56 self.reload()
57
58=== modified file 'bzrlib/help_topics/en/configuration.txt'
59--- bzrlib/help_topics/en/configuration.txt 2011-01-16 01:12:01 +0000
60+++ bzrlib/help_topics/en/configuration.txt 2011-02-17 16:40:48 +0000
61@@ -276,6 +276,8 @@
62 appendpath:
63 for contained locations, any additional path components are
64 appended to the value.
65+ appenddir:
66+ for contained locations, the last path component is appended to the value.
67
68 Policies are specified by keys with names of the form "$var:policy".
69 For example, to define the push location for a tree of branches, the
70@@ -286,7 +288,21 @@
71 push_location:policy = appendpath
72
73 With this configuration, the push location for ``/top/location/branch1``
74-would be ``sftp://example.com/location/branch1``.
75+would be ``sftp://example.com/location/branch1``, and the push location for
76+``top/location/subdir/branch2`` would be
77+``sftp://example.com/location/subdir/branch2``.
78+
79+If we want to avoid including subdirectories, we can use the appenddir policy
80+instead::
81+
82+ [/top/location]
83+ push_location = sftp://example.com/location
84+ push_location:policy = appenddir
85+
86+With this configuration, the push location for ``/top/location/branch1``
87+would be ``sftp://example.com/location/branch1``, and the push location for
88+``top/location/subdir/branch2`` would be
89+``sftp://example.com/location/branch2``.
90
91
92 The main configuration file, bazaar.conf
93
94=== modified file 'bzrlib/tests/test_config.py'
95--- bzrlib/tests/test_config.py 2011-01-20 04:44:14 +0000
96+++ bzrlib/tests/test_config.py 2011-02-17 16:40:48 +0000
97@@ -33,7 +33,6 @@
98 errors,
99 osutils,
100 mail_client,
101- mergetools,
102 ui,
103 urlutils,
104 tests,
105@@ -1216,6 +1215,13 @@
106 self.assertEqual('normal',
107 self.my_config.get_user_option('appendpath_option'))
108
109+ def test_get_user_option_appenddir(self):
110+ foo_config = config.LocationConfig('/foo')
111+ foo_config.set_user_option('bar', 'baz',
112+ config.STORE_LOCATION_APPENDDIR)
113+ qux_config = config.LocationConfig('/foo/bar/qux')
114+ self.assertEqual('baz/qux', qux_config.get_user_option('bar'))
115+
116 def test_get_user_option_norecurse(self):
117 self.get_branch_config('http://www.example.com')
118 self.assertEqual('norecurse',
119
120=== modified file 'doc/developers/contribution-quickstart.txt'
121--- doc/developers/contribution-quickstart.txt 2010-12-02 10:41:05 +0000
122+++ doc/developers/contribution-quickstart.txt 2011-02-17 16:40:48 +0000
123@@ -58,9 +58,9 @@
124
125 [/home/USER/bzr]
126 push_location = lp:~LAUNCHPAD_USER/bzr/
127- push_location:policy = appendpath
128+ push_location:policy = appenddir
129 public_branch = http://bazaar.launchpad.net/~LAUNCHPAD_USER/bzr/
130- public_branch:policy = appendpath
131+ public_branch:policy = appenddir
132
133 with your local and Launchpad usernames inserted.
134
135
136=== modified file 'doc/en/release-notes/bzr-2.4.txt'
137--- doc/en/release-notes/bzr-2.4.txt 2011-02-16 17:20:10 +0000
138+++ doc/en/release-notes/bzr-2.4.txt 2011-02-17 16:40:48 +0000
139@@ -26,6 +26,10 @@
140 * External merge tools can now be configured in bazaar.conf. See
141 ``bzr help configuration`` for more information. (Gordon Tyler, #489915)
142
143+* New "appenddir" configuration policy appends only the last path element to a
144+ config value, providing better support for colocated branches and
145+ bzr-pipeline. (Aaron Bentley)
146+
147 Improvements
148 ************
149
150@@ -38,7 +42,7 @@
151
152 * Branching, merging and pulling a branch now copies revisions named in
153 tags, not just the tag metadata. (Andrew Bennetts, #309682)
154-
155+
156 * ``bzr cat-revision`` no longer requires a working tree. (Jelmer Vernooij, #704405)
157
158 Bug Fixes