Merge lp:~jelmer/bzr/2.1-feature-flags into lp:bzr/2.1
- 2.1-feature-flags
- Merge into 2.1
Status: | Merged |
---|---|
Approved by: | Vincent Ladeuil |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4883 |
Proposed branch: | lp:~jelmer/bzr/2.1-feature-flags |
Merge into: | lp:bzr/2.1 |
Diff against target: |
156 lines (+78/-1) 7 files modified
NEWS (+4/-0) bzrlib/branch.py (+2/-1) bzrlib/bzrdir.py (+28/-0) bzrlib/errors.py (+20/-0) bzrlib/repository.py (+1/-0) bzrlib/tests/test_bzrdir.py (+22/-0) bzrlib/workingtree.py (+1/-0) |
To merge this branch: | bzr merge lp:~jelmer/bzr/2.1-feature-flags |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Vincent Ladeuil | Approve | ||
Review via email: mp+97636@code.launchpad.net |
Commit message
Add basic support for feature flags.
Description of the change
Add basic support for feature flags to the 2.1 release series.
This does the bare minimum to:
* ignore optional feature flags
* raise an appropriate error (non-confusing) for any other feature flags
Vincent Ladeuil (vila) wrote : | # |
I failed to mention: I've dreamed for a looong time of being able to review some code by just adding failing tests... raising the S/N ratio to a factual question.
Thanks for making a proposal focused and well tested allowing my dream to come true ;-)
Vincent Ladeuil (vila) wrote : | # |
One more thing: how did you test this ?
For the review purpose I tried './bzr selftest -s bt.test_
Still, not being able to run the tests for a supported release makes it harder to release or review (not unrelated to the ML thread about selftest ;). So please enlight me :) Some lucid chroot ?
Jelmer Vernooij (jelmer) wrote : | # |
> I'm unclear about how this diverges from implementation in 2.5 though, can you
> elaborate ?
It doesn't actually allow users to register features or use them. It just makes bzr 2.1 ignore optional features and raise an appropriate error when non-optional features are encountered. This is why the branch is so simple.
> This seems to special-case for branch, why is that ? Repo and wt relies on
> bzrdir but not branch ? Is this also true for 2.2 and up ?
I'm not sure I follow; It doesn't special case branch, updating branch is a single line change just like working tree, bzrdir and repository. Can you elaborate perhaps?
>
> Also, the following tests fails:
>
> === modified file 'bzrlib/
> --- bzrlib/
> +++ bzrlib/
> @@ -1386,3 +1386,11 @@
> self.assertRais
> bzrdir.
> "requiredfoo\n")
> +
> + def test_with_
> + self.assertRais
> + bzrdir.
> +
> + def test_with_
> + self.assertRais
> + bzrdir.
>
> Again, I'm not sure if this diverges from the *actual* behavior but since the
> format file is modified when a feature is added/removed, I'd like us to be
> paranoid about *new* potential failures. I.e. if the actual implementation
> does not raise ParseFormatError for these tests, fine, otherwise, please
> consider adding them anf fixing the fallouts ;)
The actual implementation doesn't have extract_
> Finally, I don't quite understand why you 4 proposals instead of just this
> one. If they are all the same, no need for 4 reviews, once this one is
> approved, just merge up to trunk.
They aren't the same, there are differences to the format infrastructure for each branch that would otherwise cause conflicts.
Vincent Ladeuil (vila) wrote : | # |
> > I'm unclear about how this diverges from implementation in 2.5 though, can
> you
> > elaborate ?
> It doesn't actually allow users to register features or use them. It just
> makes bzr 2.1 ignore optional features and raise an appropriate error when
> non-optional features are encountered. This is why the branch is so simple.
Right. I was slightly confused that I couldn't find extract_
>
> > This seems to special-case for branch, why is that ? Repo and wt relies on
> > bzrdir but not branch ? Is this also true for 2.2 and up ?
> I'm not sure I follow; It doesn't special case branch, updating branch is a
> single line change just like working tree, bzrdir and repository. Can you
> elaborate perhaps?
Hmm, yeah, gimme a minute to turn sober....
...
ha, indeed, I missed the single line change in wt and repo, please forgive me ;)
> The actual implementation doesn't have extract_
> apply there (it has a more complex parsing function).
Ok, so you will remove extract_
> I'll look into the
> failures.
Cool.
>
> > Finally, I don't quite understand why you 4 proposals instead of just this
> > one. If they are all the same, no need for 4 reviews, once this one is
> > approved, just merge up to trunk.
> They aren't the same, there are differences to the format infrastructure for
> each branch that would otherwise cause conflicts.
:-/ Let's hope we don't need to fix bugs there then. Maintaining the same feature in 5 (or 6 ?) different forms *for* a dvcs tool sounds like a good way to become insane ;)
Jelmer Vernooij (jelmer) wrote : | # |
> > The actual implementation doesn't have extract_
> doesn't
> > apply there (it has a more complex parsing function).
> Ok, so you will remove extract_
> hoping we could keep it and add the needed features instead to keep a single
> place to maintain, but no big deal as long as we can keep the tests ?
Yep.
> > I'll look into the
> > failures.
> Cool.
Fixed now.
> > > Finally, I don't quite understand why you 4 proposals instead of just this
> > > one. If they are all the same, no need for 4 reviews, once this one is
> > > approved, just merge up to trunk.
> > They aren't the same, there are differences to the format infrastructure for
> > each branch that would otherwise cause conflicts.
> :-/ Let's hope we don't need to fix bugs there then. Maintaining the same
> feature in 5 (or 6 ?) different forms *for* a dvcs tool sounds like a good way
> to become insane ;
It's not radically different, but simply upmerging triggers conflicts.
I've tested this in a lucid chroot, as 2.1's testsuite indeed doesn't run on precise.
Cheers,
Jelmer
Vincent Ladeuil (vila) wrote : | # |
> > > The actual implementation doesn't have extract_
> > doesn't
> > > apply there (it has a more complex parsing function).
> > Ok, so you will remove extract_
> > hoping we could keep it and add the needed features instead to keep a single
> > place to maintain, but no big deal as long as we can keep the tests ?
> Yep.
Great.
>
> > > I'll look into the
> > > failures.
> > Cool.
> Fixed now.
Thanks.
>
> > > > Finally, I don't quite understand why you 4 proposals instead of just
> this
> > > > one. If they are all the same, no need for 4 reviews, once this one is
> > > > approved, just merge up to trunk.
> > > They aren't the same, there are differences to the format infrastructure
> for
> > > each branch that would otherwise cause conflicts.
> > :-/ Let's hope we don't need to fix bugs there then. Maintaining the same
> > feature in 5 (or 6 ?) different forms *for* a dvcs tool sounds like a good
> way
> > to become insane ;
> It's not radically different, but simply upmerging triggers conflicts.
>
:-/
> I've tested this in a lucid chroot, as 2.1's testsuite indeed doesn't run on
> precise.
>
Ok.
Vincent Ladeuil (vila) wrote : | # |
Unless you encounter issues or want more feedback for your other related proposals, just merge up the tests and land them too.
Jelmer Vernooij (jelmer) wrote : | # |
sent to pqm by email
Jelmer Vernooij (jelmer) wrote : | # |
sent to pqm by email
Jelmer Vernooij (jelmer) wrote : | # |
sent to pqm by email
Jelmer Vernooij (jelmer) wrote : | # |
sent to pqm by email
Preview Diff
1 | === modified file 'NEWS' |
2 | --- NEWS 2011-08-19 12:49:28 +0000 |
3 | +++ NEWS 2012-03-18 19:06:24 +0000 |
4 | @@ -47,6 +47,10 @@ |
5 | Improvements |
6 | ************ |
7 | |
8 | + * When opening formats with feature flags, optional features are |
9 | + ignored and an improved error is printed for non-optional features. |
10 | + (Jelmer Vernooij) |
11 | + |
12 | Documentation |
13 | ************* |
14 | |
15 | |
16 | === modified file 'bzrlib/branch.py' |
17 | --- bzrlib/branch.py 2010-02-17 17:11:16 +0000 |
18 | +++ bzrlib/branch.py 2012-03-18 19:06:24 +0000 |
19 | @@ -1438,7 +1438,8 @@ |
20 | """Return the format for the branch object in a_bzrdir.""" |
21 | try: |
22 | transport = a_bzrdir.get_branch_transport(None) |
23 | - format_string = transport.get_bytes("format") |
24 | + format_string = bzrdir.extract_format_string( |
25 | + transport.get_bytes("format")) |
26 | return klass._formats[format_string] |
27 | except errors.NoSuchFile: |
28 | raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir) |
29 | |
30 | === modified file 'bzrlib/bzrdir.py' |
31 | --- bzrlib/bzrdir.py 2010-11-26 18:10:01 +0000 |
32 | +++ bzrlib/bzrdir.py 2012-03-18 19:06:24 +0000 |
33 | @@ -87,6 +87,32 @@ |
34 | ) |
35 | |
36 | |
37 | +def extract_format_string(text): |
38 | + """Read a format string from a file. |
39 | + |
40 | + The first line is returned. The other lines can contain |
41 | + optional features. An exception is raised when a |
42 | + required feature is present. |
43 | + """ |
44 | + lines = text.splitlines(True) |
45 | + try: |
46 | + firstline = lines.pop(0) |
47 | + except IndexError: |
48 | + raise errors.UnknownFormatError(format=text, kind='') |
49 | + for lineno, line in enumerate(lines): |
50 | + try: |
51 | + (necessity, feature) = line.split(" ", 1) |
52 | + except ValueError: |
53 | + raise errors.ParseFormatError(lineno=lineno+2, |
54 | + line=line, text=text) |
55 | + else: |
56 | + if necessity == "optional": |
57 | + mutter("Ignoring optional feature %s", feature) |
58 | + else: |
59 | + raise errors.MissingFeature(feature) |
60 | + return firstline |
61 | + |
62 | + |
63 | class BzrDir(object): |
64 | """A .bzr control diretory. |
65 | |
66 | @@ -1829,6 +1855,8 @@ |
67 | except errors.NoSuchFile: |
68 | raise errors.NotBranchError(path=transport.base) |
69 | |
70 | + format_string = extract_format_string(format_string) |
71 | + |
72 | try: |
73 | return klass._formats[format_string] |
74 | except KeyError: |
75 | |
76 | === modified file 'bzrlib/errors.py' |
77 | --- bzrlib/errors.py 2010-09-10 05:13:57 +0000 |
78 | +++ bzrlib/errors.py 2012-03-18 19:06:24 +0000 |
79 | @@ -3136,3 +3136,23 @@ |
80 | |
81 | def __init__(self, path): |
82 | self.path = path |
83 | + |
84 | + |
85 | +class MissingFeature(BzrError): |
86 | + |
87 | + _fmt = ("Missing feature %(feature)s not provided by this " |
88 | + "version of Bazaar or any plugin.") |
89 | + |
90 | + def __init__(self, feature): |
91 | + self.feature = feature |
92 | + |
93 | + |
94 | +class ParseFormatError(BzrError): |
95 | + |
96 | + _fmt = "Parse error on line %(lineno)d of format name: %(line)s" |
97 | + |
98 | + def __init__(self, lineno, line, text): |
99 | + BzrError.__init__(self) |
100 | + self.lineno = lineno |
101 | + self.line = line |
102 | + self.text = text |
103 | |
104 | === modified file 'bzrlib/repository.py' |
105 | --- bzrlib/repository.py 2010-11-30 20:42:42 +0000 |
106 | +++ bzrlib/repository.py 2012-03-18 19:06:24 +0000 |
107 | @@ -3107,6 +3107,7 @@ |
108 | try: |
109 | transport = a_bzrdir.get_repository_transport(None) |
110 | format_string = transport.get_bytes("format") |
111 | + format_string = bzrdir.extract_format_string(format_string) |
112 | return format_registry.get(format_string) |
113 | except errors.NoSuchFile: |
114 | raise errors.NoRepositoryPresent(a_bzrdir) |
115 | |
116 | === modified file 'bzrlib/tests/test_bzrdir.py' |
117 | --- bzrlib/tests/test_bzrdir.py 2010-02-17 17:11:16 +0000 |
118 | +++ bzrlib/tests/test_bzrdir.py 2012-03-18 19:06:24 +0000 |
119 | @@ -1333,3 +1333,25 @@ |
120 | url = transport.base |
121 | err = self.assertRaises(errors.BzrError, bzrdir.BzrDir.open, url) |
122 | self.assertEqual('fail', err._preformatted_string) |
123 | + |
124 | + |
125 | +class ExtractFormatStringTests(TestCase): |
126 | + |
127 | + def test_normal(self): |
128 | + self.assertEquals("Bazaar-NG branch, format 0.0.4\n", |
129 | + bzrdir.extract_format_string("Bazaar-NG branch, format 0.0.4\n")) |
130 | + |
131 | + def test_with_optional_feature(self): |
132 | + self.assertEquals("Bazaar-NG branch, format 0.0.4\n", |
133 | + bzrdir.extract_format_string("Bazaar-NG branch, format 0.0.4\n" |
134 | + "optional feature foo\n")) |
135 | + |
136 | + def test_with_required_feature(self): |
137 | + self.assertRaises(errors.MissingFeature, |
138 | + bzrdir.extract_format_string, "Bazaar-NG branch, format 0.0.4\n" |
139 | + "required feature foo\n") |
140 | + |
141 | + def test_with_invalid_line(self): |
142 | + self.assertRaises(errors.ParseFormatError, |
143 | + bzrdir.extract_format_string, "Bazaar-NG branch, format 0.0.4\n" |
144 | + "requiredfoo\n") |
145 | |
146 | === modified file 'bzrlib/workingtree.py' |
147 | --- bzrlib/workingtree.py 2010-01-21 17:54:58 +0000 |
148 | +++ bzrlib/workingtree.py 2012-03-18 19:06:24 +0000 |
149 | @@ -2799,6 +2799,7 @@ |
150 | try: |
151 | transport = a_bzrdir.get_workingtree_transport(None) |
152 | format_string = transport.get_bytes("format") |
153 | + format_string = bzrdir.extract_format_string(format_string) |
154 | return klass._formats[format_string] |
155 | except errors.NoSuchFile: |
156 | raise errors.NoWorkingTree(base=transport.base) |
Looks mostly fine :)
I'm unclear about how this diverges from implementation in 2.5 though, can you elaborate ?
This seems to special-case for branch, why is that ? Repo and wt relies on bzrdir but not branch ? Is this also true for 2.2 and up ?
Also, the following tests fails:
=== modified file 'bzrlib/ tests/test_ bzrdir. py' tests/test_ bzrdir. py 2012-03-15 14:54:05 +0000 tests/test_ bzrdir. py 2012-03-16 08:27:13 +0000
self. assertRaises( errors. ParseFormatErro r,
bzrdir. extract_ format_ string, "Bazaar-NG branch, format 0.0.4\n"
"requiredfoo\ n") empty_file( self): es(errors. ParseFormatErro r, extract_ format_ string, "") corrupted_ file(self) : es(errors. ParseFormatErro r, extract_ format_ string, "Bazaar-NG branch")
--- bzrlib/
+++ bzrlib/
@@ -1386,3 +1386,11 @@
+
+ def test_with_
+ self.assertRais
+ bzrdir.
+
+ def test_with_
+ self.assertRais
+ bzrdir.
Again, I'm not sure if this diverges from the *actual* behavior but since the format file is modified when a feature is added/removed, I'd like us to be paranoid about *new* potential failures. I.e. if the actual implementation does not raise ParseFormatError for these tests, fine, otherwise, please consider adding them anf fixing the fallouts ;)
Finally, I don't quite understand why you 4 proposals instead of just this one. If they are all the same, no need for 4 reviews, once this one is approved, just merge up to trunk.