Merge lp:~vila/bzr/389648-hook-calls-base into lp:~bzr/bzr/trunk-old
- 389648-hook-calls-base
- Merge into trunk-old
Status: | Merged |
---|---|
Approved by: | John A Meinel |
Approved revision: | no longer in the source branch. |
Merge reported by: | Vincent Ladeuil |
Merged at revision: | not available |
Proposed branch: | lp:~vila/bzr/389648-hook-calls-base |
Merge into: | lp:~bzr/bzr/trunk-old |
Diff against target: |
29287 lines 0 files modified
|
To merge this branch: | bzr merge lp:~vila/bzr/389648-hook-calls-base |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
John A Meinel | Approve | ||
Review via email: mp+14347@code.launchpad.net |
Commit message
Description of the change
Vincent Ladeuil (vila) wrote : | # |
Alexander Belchenko (bialix) wrote : | # |
Something wrong with the diff.
Aaron Bentley (abentley) wrote : | # |
> Something wrong with the diff.
I think you want to propose against lp:~bzr-pqm/bzr/bzr.dev, not lp:~bzr/bzr/trunk, which is a 1.9-format mirror from before the 2a upgrade.
John A Meinel (jameinel) wrote : | # |
As mentioned above, the target was wrong, it should be 'lp:bzr' which is ~bzr-pqm/
Anyway, I did the review locally. It was still a bit hard to follow, because a lot of 'formatting' updates. Stuff like:
-class TestHook(TestCase):
+class TestHook(
I wonder if this wouldn't be like the whitespace fixes, and we should have "one big patch" across the codebase to fix them, rather than getting them piecemeal. Then again, the same arguments apply for and against that were present for the whitespace updates...
Anyway, I think the basic fix here was:
1) Add
+ super(InfoHooks, self).__init__()
To a couple of the hook instances
2) Add
+ self.assertEqua
To the tests to ensure that the internal dictionary is created and able to return a value for an unnamed hook.
Which seems just fine.
I should comment that using "super()" is not always correct anymore. To start with, it only matters when you have multiple inheritance. But even more importantly, python 2.6 'broke' super(.
Anyway, IMO super().__init__() was broken in 2.6, though certainly someone thought it was the right thing to do.
Vincent Ladeuil (vila) wrote : | # |
>>>>> "jam" == John A Meinel <email address hidden> writes:
jam> Review: Approve
jam> As mentioned above, the target was wrong, it should be 'lp:bzr'
jam> which is ~bzr-pqm/
Amazing, obviously I clicked the wrong button... no idea why nor
when... that wasn't intended anyway.
jam> Anyway, I did the review locally. It was still a bit hard to
jam> follow, because a lot of 'formatting' updates. Stuff like:
jam> -class TestHook(TestCase):
jam> +class TestHook(
Yeah :-(
In the past I've sent these trivial updates directly without
review, but then you commented that may be I should at least send
them so that people know about them even without waiting for an
approval.
I tried a middle term approach here, because I thought there was
only a few of them (but you call them 'a lot' :-)...
I don't mind fixing them as I encounter them, I don't want to
make the reviews harder than they have to either, but I'd like a
minimal effort workflow to get these fixes landed too.
jam> I wonder if this wouldn't be like the whitespace fixes, and we
jam> should have "one big patch" across the codebase to fix them,
jam> rather than getting them piecemeal. Then again, the same
jam> arguments apply for and against that were present for the
jam> whitespace updates...
Yeah, exactly the same arguments. But again, I feel that I spend
less energy fixing them that discussing how to fix them all,
so...
jam> Anyway, I think the basic fix here was:
You're right.
<snip/>
jam> Which seems just fine.
Ok.
jam> I should comment that using "super()" is not always
jam> correct anymore.
jam> To start with, it only matters when you have multiple
jam> inheritance. But even more importantly, python 2.6
jam> 'broke' super(.
jam> arguments.
I disagree. python-2.6 is just stricter and catch bogus calls.
jam> Because object.__init__() no longer allows
jam> arguments. (So as near as I can tell, there is no way to
jam> safely __init__ a multiple inheritance structure that
jam> wants arguments passed as part of init.
Yes there is, you handle arguments where they are expected and
you don't pass them where they are not.
The cases I had to fix when I addressed python-2.6 compatibility
weren't that complex once I understood what was going on.
And as I remember the only case that seemed controversial at the
time was indeed an abuse.
<snip/>
jam> Anyway, IMO super().__init__() was broken in 2.6, though
jam> certainly someone thought it was the right thing to do.
Well, it would be good to agree on that and decide whether we
want to use super() or not.
I refrained to fix all calls to Hooks.__init__ because I
considered it was slightly out of scope for this patch but only
slightly.
If you can provide examples in the actual code base where calling
super().__init__ will be bogus, I'll be happy to revise my
opinion.
Vincent
John A Meinel (jameinel) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
...
>
> jam> I should comment that using "super()" is not always
> jam> correct anymore.
>
>
> jam> To start with, it only matters when you have multiple
> jam> inheritance. But even more importantly, python 2.6
> jam> 'broke' super(.
> jam> arguments.
>
> I disagree. python-2.6 is just stricter and catch bogus calls.
>
> jam> Because object.__init__() no longer allows
> jam> arguments. (So as near as I can tell, there is no way to
> jam> safely __init__ a multiple inheritance structure that
> jam> wants arguments passed as part of init.
>
> Yes there is, you handle arguments where they are expected and
> you don't pass them where they are not.
>
> The cases I had to fix when I addressed python-2.6 compatibility
> weren't that complex once I understood what was going on.
>
> And as I remember the only case that seemed controversial at the
> time was indeed an abuse.
By the way, don't block landing this on us resolving super() issues. I'm
moving the super() discussion over to the regular mailing list.
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAkr
q1MAoM5oqOsF0jX
=uKqH
-----END PGP SIGNATURE-----
John A Meinel (jameinel) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I'm trying to split up a few discussion points into different emails.
Sorry if things get a bit broken. Thunderbird isn't as nice as 'bzr
shelve' :)
Vincent Ladeuil wrote:
>>>>>> "jam" == John A Meinel <email address hidden> writes:
>
> jam> Review: Approve
> jam> As mentioned above, the target was wrong, it should be 'lp:bzr'
> jam> which is ~bzr-pqm/
>
> Amazing, obviously I clicked the wrong button... no idea why nor
> when... that wasn't intended anyway.
>
> jam> Anyway, I did the review locally. It was still a bit hard to
> jam> follow, because a lot of 'formatting' updates. Stuff like:
>
> jam> -class TestHook(TestCase):
> jam> +class TestHook(
>
> Yeah :-(
>
> In the past I've sent these trivial updates directly without
> review, but then you commented that may be I should at least send
> them so that people know about them even without waiting for an
> approval.
>
> I tried a middle term approach here, because I thought there was
> only a few of them (but you call them 'a lot' :-)...
Your fix was about 2 lines long, and it was about 10 lines of
'tests.TestCase' changes.
so not many, but *more* of those trivial changes than there were actual
content changes.
>
> I don't mind fixing them as I encounter them, I don't want to
> make the reviews harder than they have to either, but I'd like a
> minimal effort workflow to get these fixes landed too.
>
> jam> I wonder if this wouldn't be like the whitespace fixes, and we
> jam> should have "one big patch" across the codebase to fix them,
> jam> rather than getting them piecemeal. Then again, the same
> jam> arguments apply for and against that were present for the
> jam> whitespace updates...
>
> Yeah, exactly the same arguments. But again, I feel that I spend
> less energy fixing them that discussing how to fix them all,
> so...
Style patches are always a bit contentious. Far to easy for people to
bikeshed on. Which is why we say "PEP 8" but even that doesn't cover all
the cases of things you want to do.
Similarly stripping the whitespace from all files is trivially easy to
do. (We now have about 300? files that have trailing whitespace again.)
I'd like to say just land trivial cleanups. But on the flip side, your
'trivial cleanups' may cause merge conflicts in any pending work people
are doing. However, we don't want to hold cleaning up the code hostage
for work that may land in the future either.
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAkr
QooAnRk6sP/
=OUbh
-----END PGP SIGNATURE-----
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2009-07-31 19:56:19 +0000 |
3 | +++ .bzrignore 2009-11-03 09:40:55 +0000 |
4 | @@ -5,10 +5,21 @@ |
5 | ./.bzr.log |
6 | # Generated files |
7 | CHANGELOG |
8 | +# generated documents |
9 | bzr.1 |
10 | ./doc/*.html |
11 | -./doc/_build/ |
12 | +./doc/*/_build/ |
13 | +./doc/*/Makefile |
14 | +./doc/*/make.bat |
15 | ./tutorial.html |
16 | +./build_doc_website |
17 | +./html_docs |
18 | +./pretty_docs |
19 | +./api |
20 | +./doc/**/*.html |
21 | +./doc/developers/performance.png |
22 | +./doc/en/user-reference/*.txt |
23 | +./doc/en/release-notes/*.txt |
24 | BRANCH-INFO |
25 | # setup.py working directory |
26 | ./build |
27 | @@ -35,11 +46,7 @@ |
28 | ./dist |
29 | # performance history data file |
30 | ./.perf_history |
31 | -./html_docs |
32 | -./pretty_docs |
33 | -./api |
34 | -doc/**/*.html |
35 | -doc/developers/performance.png |
36 | +# Pyrex |
37 | bzrlib/_annotator_pyx.c |
38 | bzrlib/_bencode_pyx.c |
39 | bzrlib/_btree_serializer_pyx.c |
40 | @@ -51,16 +58,12 @@ |
41 | bzrlib/_known_graph_pyx.c |
42 | bzrlib/_readdir_pyx.c |
43 | bzrlib/_rio_pyx.c |
44 | +bzrlib/_simple_set_pyx.c |
45 | +bzrlib/_simple_set_pyx.h |
46 | +bzrlib/_simple_set_pyx_api.h |
47 | bzrlib/_walkdirs_win32.c |
48 | -doc/en/release-notes/NEWS.txt |
49 | -doc/en/developer-guide/HACKING.txt |
50 | -doc/en/user-reference/bzr_man.txt |
51 | # built extension modules |
52 | bzrlib/_*.dll |
53 | bzrlib/_*.so |
54 | bzrlib/_*.pyd |
55 | -# generated help topics |
56 | -doc/en/user-reference/*.txt |
57 | -./doc/en/user-guide/latex_prepared |
58 | -./doc/en/user-guide/*.pdf |
59 | ./.ccache |
60 | |
61 | === modified file 'Makefile' |
62 | --- Makefile 2009-08-27 00:53:27 +0000 |
63 | +++ Makefile 2009-11-03 09:40:55 +0000 |
64 | @@ -75,44 +75,161 @@ |
65 | # these are treated as phony so they'll always be rebuilt - it's pretty quick |
66 | .PHONY: TAGS tags |
67 | |
68 | + |
69 | ### Documentation ### |
70 | |
71 | -# set PRETTY to get docs that look like the Bazaar web site |
72 | -ifdef PRETTY |
73 | -rst2html := $(PYTHON) tools/rst2prettyhtml.py doc/bazaar-vcs.org.kid |
74 | -else |
75 | -rst2html := $(PYTHON) tools/rst2html.py --link-stylesheet --footnote-references=superscript --halt=warning |
76 | -endif |
77 | +# Default to plain documentation for maximum backwards compatibility. |
78 | +# (Post 2.0, the defaults will most likely be Sphinx-style instead.) |
79 | + |
80 | +docs: docs-plain |
81 | + |
82 | +clean-docs: clean-plain |
83 | + |
84 | +html-docs: html-plain |
85 | + |
86 | + |
87 | +### Man-page Documentation ### |
88 | + |
89 | +MAN_DEPENDENCIES = bzrlib/builtins.py \ |
90 | + $(wildcard bzrlib/*.py) \ |
91 | + $(wildcard bzrlib/*/*.py) \ |
92 | + tools/generate_docs.py \ |
93 | + $(wildcard $(addsuffix /*.txt, bzrlib/help_topics/en)) |
94 | + |
95 | +MAN_PAGES = man1/bzr.1 |
96 | +man1/bzr.1: $(MAN_DEPENDENCIES) |
97 | + $(PYTHON) tools/generate_docs.py -o $@ man |
98 | + |
99 | + |
100 | +### Sphinx-style Documentation ### |
101 | + |
102 | +# Build the documentation. To keep the dependencies down to a minimum |
103 | +# for distro packagers, we only build the html documentation by default. |
104 | +# Sphinx 0.6 or later is preferred for the best rendering, though |
105 | +# Sphinx 0.4 or later should work. See http://sphinx.pocoo.org/index.html |
106 | +# for installation instructions. |
107 | +docs-sphinx: html-sphinx |
108 | + |
109 | +# Clean out generated documentation |
110 | +clean-sphinx: |
111 | + cd doc/en && make clean |
112 | + cd doc/es && make clean |
113 | + cd doc/ru && make clean |
114 | + cd doc/developers && make clean |
115 | + |
116 | +SPHINX_DEPENDENCIES = \ |
117 | + doc/en/release-notes/index.txt \ |
118 | + doc/en/user-reference/index.txt \ |
119 | + doc/es/Makefile \ |
120 | + doc/es/make.bat \ |
121 | + doc/ru/Makefile \ |
122 | + doc/ru/make.bat \ |
123 | + doc/developers/Makefile \ |
124 | + doc/developers/make.bat |
125 | + |
126 | +doc/en/user-reference/index.txt: $(MAN_DEPENDENCIES) |
127 | + $(PYTHON) tools/generate_docs.py -o $@ rstx |
128 | + |
129 | +doc/en/release-notes/index.txt: NEWS tools/generate_release_notes.py |
130 | + $(PYTHON) tools/generate_release_notes.py NEWS $@ |
131 | + |
132 | +doc/%/Makefile: doc/en/Makefile |
133 | + $(PYTHON) -c "import shutil; shutil.copyfile('$<', '$@')" |
134 | + |
135 | +doc/%/make.bat: doc/en/make.bat |
136 | + $(PYTHON) -c "import shutil; shutil.copyfile('$<', '$@')" |
137 | + |
138 | +# Build the html docs using Sphinx. |
139 | +html-sphinx: $(SPHINX_DEPENDENCIES) |
140 | + cd doc/en && make html |
141 | + cd doc/es && make html |
142 | + cd doc/ru && make html |
143 | + cd doc/developers && make html |
144 | + |
145 | +# Build the PDF docs using Sphinx. This requires numerous LaTeX |
146 | +# packages. See http://sphinx.pocoo.org/builders.html for details. |
147 | +# Note: We don't currently build PDFs for the Russian docs because |
148 | +# they require additional packages to be installed (to handle |
149 | +# Russian hyphenation rules, etc.) |
150 | +pdf-sphinx: $(SPHINX_DEPENDENCIES) |
151 | + cd doc/en && make latex |
152 | + cd doc/es && make latex |
153 | + cd doc/developers && make latex |
154 | + cd doc/en/_build/latex && make all-pdf |
155 | + cd doc/es/_build/latex && make all-pdf |
156 | + cd doc/developers/_build/latex && make all-pdf |
157 | + |
158 | +# Build the CHM (Windows Help) docs using Sphinx. |
159 | +# Note: HtmlHelp Workshop needs to be used on the generated hhp files |
160 | +# to generate the final chm files. |
161 | +chm-sphinx: $(SPHINX_DEPENDENCIES) |
162 | + cd doc/en && make htmlhelp |
163 | + cd doc/es && make htmlhelp |
164 | + cd doc/ru && make htmlhelp |
165 | + cd doc/developers && make htmlhelp |
166 | + |
167 | + |
168 | +### Documentation Website ### |
169 | + |
170 | +# Where to build the website |
171 | +DOC_WEBSITE_BUILD = build_doc_website |
172 | + |
173 | +# Build and package docs into a website, complete with downloads. |
174 | +doc-website: html-sphinx pdf-sphinx |
175 | + $(PYTHON) tools/package_docs.py doc/en $(DOC_WEBSITE_BUILD) |
176 | + $(PYTHON) tools/package_docs.py doc/es $(DOC_WEBSITE_BUILD) |
177 | + $(PYTHON) tools/package_docs.py doc/ru $(DOC_WEBSITE_BUILD) |
178 | + $(PYTHON) tools/package_docs.py doc/developers $(DOC_WEBSITE_BUILD) |
179 | + |
180 | + |
181 | +### Plain Documentation ### |
182 | + |
183 | +# While Sphinx is the preferred tool for building documentation, we still |
184 | +# support our "plain" html documentation so that Sphinx is not a hard |
185 | +# dependency for packagers on older platforms. |
186 | + |
187 | +rst2html = $(PYTHON) tools/rst2html.py --link-stylesheet --footnote-references=superscript --halt=warning |
188 | |
189 | # translate txt docs to html |
190 | -derived_txt_files := \ |
191 | +derived_txt_files = \ |
192 | doc/en/user-reference/bzr_man.txt \ |
193 | doc/en/release-notes/NEWS.txt |
194 | -txt_files := \ |
195 | +txt_all = \ |
196 | doc/en/tutorials/tutorial.txt \ |
197 | doc/en/tutorials/using_bazaar_with_launchpad.txt \ |
198 | doc/en/tutorials/centralized_workflow.txt \ |
199 | + $(wildcard doc/es/tutorials/*.txt) \ |
200 | $(wildcard doc/ru/tutorials/*.txt) \ |
201 | $(wildcard doc/*/mini-tutorial/index.txt) \ |
202 | - $(wildcard doc/*/user-guide/index.txt) \ |
203 | + $(wildcard doc/*/user-guide/index-plain.txt) \ |
204 | + $(wildcard doc/es/guia-usario/*.txt) \ |
205 | $(derived_txt_files) \ |
206 | - doc/en/developer-guide/HACKING.txt \ |
207 | doc/en/upgrade-guide/index.txt \ |
208 | - $(wildcard doc/es/guia-usario/*.txt) \ |
209 | - doc/es/mini-tutorial/index.txt \ |
210 | doc/index.txt \ |
211 | $(wildcard doc/index.*.txt) |
212 | -non_txt_files := \ |
213 | +txt_nohtml = \ |
214 | + doc/en/user-guide/index.txt \ |
215 | + doc/es/user-guide/index.txt \ |
216 | + doc/ru/user-guide/index.txt |
217 | +txt_files = $(filter-out $(txt_nohtml), $(txt_all)) |
218 | +htm_files = $(patsubst %.txt, %.html, $(txt_files)) |
219 | + |
220 | +non_txt_files = \ |
221 | doc/default.css \ |
222 | - $(wildcard doc/*/quick-reference/bzr-quick-reference.svg) \ |
223 | - $(wildcard doc/*/quick-reference/bzr-quick-reference.png) \ |
224 | - $(wildcard doc/*/quick-reference/bzr-quick-reference.pdf) \ |
225 | + $(wildcard doc/*/bzr-en-quick-reference.svg) \ |
226 | + $(wildcard doc/*/bzr-en-quick-reference.png) \ |
227 | + $(wildcard doc/*/bzr-en-quick-reference.pdf) \ |
228 | + $(wildcard doc/*/bzr-es-quick-reference.svg) \ |
229 | + $(wildcard doc/*/bzr-es-quick-reference.png) \ |
230 | + $(wildcard doc/*/bzr-es-quick-reference.pdf) \ |
231 | + $(wildcard doc/*/bzr-ru-quick-reference.svg) \ |
232 | + $(wildcard doc/*/bzr-ru-quick-reference.png) \ |
233 | + $(wildcard doc/*/bzr-ru-quick-reference.pdf) \ |
234 | $(wildcard doc/*/user-guide/images/*.png) |
235 | -htm_files := $(patsubst %.txt, %.html, $(txt_files)) |
236 | |
237 | # doc/developers/*.txt files that should *not* be individually |
238 | # converted to HTML |
239 | -dev_txt_nohtml := \ |
240 | +dev_txt_nohtml = \ |
241 | doc/developers/add.txt \ |
242 | doc/developers/annotate.txt \ |
243 | doc/developers/bundle-creation.txt \ |
244 | @@ -120,46 +237,37 @@ |
245 | doc/developers/diff.txt \ |
246 | doc/developers/directory-fingerprints.txt \ |
247 | doc/developers/gc.txt \ |
248 | + doc/developers/implementation-notes.txt \ |
249 | doc/developers/incremental-push-pull.txt \ |
250 | + doc/developers/index.txt \ |
251 | doc/developers/initial-push-pull.txt \ |
252 | doc/developers/merge-scaling.txt \ |
253 | + doc/developers/miscellaneous-notes.txt \ |
254 | doc/developers/missing.txt \ |
255 | doc/developers/performance-roadmap-rationale.txt \ |
256 | doc/developers/performance-use-case-analysis.txt \ |
257 | doc/developers/planned-change-integration.txt \ |
258 | doc/developers/planned-performance-changes.txt \ |
259 | + doc/developers/plans.txt \ |
260 | + doc/developers/process.txt \ |
261 | doc/developers/revert.txt \ |
262 | + doc/developers/specifications.txt \ |
263 | doc/developers/status.txt \ |
264 | doc/developers/uncommit.txt |
265 | |
266 | -dev_txt_all := $(wildcard $(addsuffix /*.txt, doc/developers)) |
267 | -dev_txt_files := $(filter-out $(dev_txt_nohtml), $(dev_txt_all)) |
268 | -dev_htm_files := $(patsubst %.txt, %.html, $(dev_txt_files)) |
269 | - |
270 | -doc/%/user-guide/index.html: $(wildcard $(addsuffix /*.txt, doc/%/user-guide)) |
271 | - $(rst2html) --stylesheet=../../default.css $(dir $@)index.txt $@ |
272 | - |
273 | -# Set the paper size for PDF files. |
274 | -# Options: 'a4' (ISO A4 size), 'letter' (US Letter size) |
275 | -PAPERSIZE = a4 |
276 | -# TODO: Add generation for Russian PDF |
277 | -PDF_DOCS := doc/en/user-guide/user-guide.$(PAPERSIZE).pdf |
278 | - |
279 | -# Copy and modify the RST sources, and convert SVG images to PDF |
280 | -# files for use a images in the LaTeX-generated PDF. |
281 | -# Then generate the PDF output from the modified RST sources. |
282 | -doc/en/user-guide/user-guide.$(PAPERSIZE).pdf: $(wildcard $(addsuffix /*.txt, doc/en/user-guide)) |
283 | - mkdir -p doc/en/user-guide/latex_prepared |
284 | - $(PYTHON) tools/prepare_for_latex.py \ |
285 | - --out-dir=doc/en/user-guide/latex_prepared \ |
286 | - --in-dir=doc/en/user-guide |
287 | - cd doc/en/user-guide/latex_prepared && \ |
288 | - $(PYTHON) ../../../../tools/rst2pdf.py \ |
289 | - --documentoptions=10pt,$(PAPERSIZE)paper \ |
290 | - --input-encoding=UTF-8:strict --output-encoding=UTF-8:strict \ |
291 | - --strict --title="Bazaar User Guide" \ |
292 | - index.txt ../user-guide.$(PAPERSIZE).pdf |
293 | - |
294 | +dev_txt_all = $(wildcard $(addsuffix /*.txt, doc/developers)) |
295 | +dev_txt_files = $(filter-out $(dev_txt_nohtml), $(dev_txt_all)) |
296 | +dev_htm_files = $(patsubst %.txt, %.html, $(dev_txt_files)) |
297 | + |
298 | +doc/en/user-guide/index-plain.html: $(wildcard $(addsuffix /*.txt, doc/en/user-guide)) |
299 | + $(rst2html) --stylesheet=../../default.css $(dir $@)index-plain.txt $@ |
300 | + |
301 | +#doc/es/user-guide/index.html: $(wildcard $(addsuffix /*.txt, doc/es/user-guide)) |
302 | +# $(rst2html) --stylesheet=../../default.css $(dir $@)index.txt $@ |
303 | +# |
304 | +#doc/ru/user-guide/index.html: $(wildcard $(addsuffix /*.txt, doc/ru/user-guide)) |
305 | +# $(rst2html) --stylesheet=../../default.css $(dir $@)index.txt $@ |
306 | +# |
307 | doc/developers/%.html: doc/developers/%.txt |
308 | $(rst2html) --stylesheet=../default.css $< $@ |
309 | |
310 | @@ -172,55 +280,42 @@ |
311 | %.html: %.txt |
312 | $(rst2html) --stylesheet=../../default.css $< $@ |
313 | |
314 | -MAN_DEPENDENCIES = bzrlib/builtins.py \ |
315 | - $(wildcard bzrlib/*.py) \ |
316 | - $(wildcard bzrlib/*/*.py) \ |
317 | - tools/generate_docs.py \ |
318 | - $(wildcard $(addsuffix /*.txt, bzrlib/help_topics/en)) |
319 | - |
320 | doc/en/user-reference/bzr_man.txt: $(MAN_DEPENDENCIES) |
321 | $(PYTHON) tools/generate_docs.py -o $@ rstx |
322 | |
323 | doc/en/release-notes/NEWS.txt: NEWS |
324 | $(PYTHON) -c "import shutil; shutil.copyfile('$<', '$@')" |
325 | |
326 | -MAN_PAGES = man1/bzr.1 |
327 | -man1/bzr.1: $(MAN_DEPENDENCIES) |
328 | - $(PYTHON) tools/generate_docs.py -o $@ man |
329 | - |
330 | upgrade_guide_dependencies = $(wildcard $(addsuffix /*.txt, doc/en/upgrade-guide)) |
331 | |
332 | doc/en/upgrade-guide/index.html: $(upgrade_guide_dependencies) |
333 | $(rst2html) --stylesheet=../../default.css $(dir $@)index.txt $@ |
334 | |
335 | -# build a png of our performance task list |
336 | -# |
337 | -# this is no longer built by default; you can build it if you want to look at it |
338 | -doc/developers/performance.png: doc/developers/performance.dot |
339 | - @echo Generating $@ |
340 | - @dot -Tpng $< -o$@ || echo "Dot not installed; skipping generation of $@" |
341 | - |
342 | derived_web_docs = $(htm_files) $(dev_htm_files) |
343 | WEB_DOCS = $(derived_web_docs) $(non_txt_files) |
344 | ALL_DOCS = $(derived_web_docs) $(MAN_PAGES) |
345 | |
346 | # the main target to build all the docs |
347 | -docs: $(ALL_DOCS) |
348 | +docs-plain: $(ALL_DOCS) |
349 | |
350 | # produce a tree containing just the final docs, ready for uploading to the web |
351 | -HTMLDIR := html_docs |
352 | -html-docs: docs |
353 | +HTMLDIR = html_docs |
354 | +html-plain: docs-plain |
355 | $(PYTHON) tools/win32/ostools.py copytree $(WEB_DOCS) $(HTMLDIR) |
356 | |
357 | -# Produce PDF documents. Requires pdfLaTeX, rubber, and Inkscape. |
358 | -pdf-docs: $(PDF_DOCS) |
359 | - |
360 | # clean produced docs |
361 | -clean-docs: |
362 | +clean-plain: |
363 | $(PYTHON) tools/win32/ostools.py remove $(ALL_DOCS) \ |
364 | $(HTMLDIR) $(derived_txt_files) |
365 | - rm -f doc/*/user-guide/*.pdf |
366 | - rm -rf doc/*/user-guide/latex_prepared |
367 | + |
368 | + |
369 | +### Miscellaneous Documentation Targets ### |
370 | + |
371 | +# build a png of our performance task list |
372 | +# this is no longer built by default; you can build it if you want to look at it |
373 | +doc/developers/performance.png: doc/developers/performance.dot |
374 | + @echo Generating $@ |
375 | + @dot -Tpng $< -o$@ || echo "Dot not installed; skipping generation of $@" |
376 | |
377 | |
378 | ### Windows Support ### |
379 | @@ -230,7 +325,7 @@ |
380 | # These are files that need to be copied into the build location to boostrap |
381 | # the build process. |
382 | # Note that the path is relative to tools/win32 |
383 | -BUILDOUT_FILES := buildout.cfg \ |
384 | +BUILDOUT_FILES = buildout.cfg \ |
385 | buildout-templates/bin/build-installer.bat.in \ |
386 | ostools.py bootstrap.py |
387 | |
388 | @@ -296,9 +391,12 @@ |
389 | $(PYTHON) tools/win32/ostools.py remove bzr-*win32.exe |
390 | $(PYTHON) tools/win32/ostools.py remove dist |
391 | |
392 | + |
393 | +### Packaging Targets ### |
394 | + |
395 | .PHONY: dist dist-upload-escudero check-dist-tarball |
396 | |
397 | -# build a distribution tarball and zip file. |
398 | +# build a distribution source tarball |
399 | # |
400 | # this method of copying the pyrex generated files is a bit ugly; it would be |
401 | # nicer to generate it from distutils. |
402 | @@ -308,15 +406,12 @@ |
403 | expbasedir=`mktemp -t -d tmp_bzr_dist.XXXXXXXXXX` && \ |
404 | expdir=$$expbasedir/bzr-$$version && \ |
405 | tarball=$$PWD/../bzr-$$version.tar.gz && \ |
406 | - zipball=$$PWD/../bzr-$$version.zip && \ |
407 | $(MAKE) clean && \ |
408 | $(MAKE) && \ |
409 | bzr export $$expdir && \ |
410 | - cp bzrlib/*.c $$expdir/bzrlib/. && \ |
411 | + cp bzrlib/*.c bzrlib/*.h $$expdir/bzrlib/. && \ |
412 | tar cfz $$tarball -C $$expbasedir bzr-$$version && \ |
413 | - (cd $$expbasedir && zip -r $$zipball bzr-$$version) && \ |
414 | gpg --detach-sign $$tarball && \ |
415 | - gpg --detach-sign $$zipball && \ |
416 | rm -rf $$expbasedir |
417 | |
418 | # run all tests in a previously built tarball |
419 | @@ -334,15 +429,10 @@ |
420 | dist-upload-escudero: |
421 | version=`./bzr version --short` && \ |
422 | tarball=../bzr-$$version.tar.gz && \ |
423 | - zipball=../bzr-$$version.zip && \ |
424 | - scp $$zipball $$zipball.sig $$tarball $$tarball.sig \ |
425 | + scp $$tarball $$tarball.sig \ |
426 | escudero.ubuntu.com:/srv/bazaar.canonical.com/www/releases/src \ |
427 | && \ |
428 | echo verifying over http... && \ |
429 | - curl http://bazaar-vcs.org/releases/src/bzr-$$version.zip \ |
430 | - | diff -s - $$zipball && \ |
431 | - curl http://bazaar-vcs.org/releases/src/bzr-$$version.zip.sig \ |
432 | - | diff -s - $$zipball.sig |
433 | curl http://bazaar-vcs.org/releases/src/bzr-$$version.tar.gz \ |
434 | | diff -s - $$tarball && \ |
435 | curl http://bazaar-vcs.org/releases/src/bzr-$$version.tar.gz.sig \ |
436 | |
437 | === modified file 'NEWS' |
438 | --- NEWS 2009-09-02 18:07:58 +0000 |
439 | +++ NEWS 2009-11-03 09:40:55 +0000 |
440 | @@ -2,44 +2,409 @@ |
441 | Bazaar Release Notes |
442 | #################### |
443 | |
444 | - |
445 | .. contents:: List of Releases |
446 | :depth: 1 |
447 | |
448 | -In Development |
449 | -############## |
450 | - |
451 | -Compatibility Breaks |
452 | -******************** |
453 | - |
454 | -New Features |
455 | -************ |
456 | - |
457 | -Bug Fixes |
458 | -********* |
459 | - |
460 | -* ``bzr check`` in pack-0.92, 1.6 and 1.9 format repositories will no |
461 | - longer report incorrect errors about ``Missing inventory ('TREE_ROOT', ...)`` |
462 | - (Robert Collins, #416732) |
463 | + |
464 | +bzr 2.1.0b3 (not released yet) |
465 | +############################## |
466 | + |
467 | +:Codename: |
468 | +:2.1.0b3: ??? |
469 | + |
470 | +Compatibility Breaks |
471 | +******************** |
472 | + |
473 | +New Features |
474 | +************ |
475 | + |
476 | +Bug Fixes |
477 | +********* |
478 | + |
479 | +* Hooks daughter classes should always call the base constructor. |
480 | + (Alexander Belchenko, Vincent Ladeuil, #389648) |
481 | + |
482 | +Improvements |
483 | +************ |
484 | + |
485 | +Documentation |
486 | +************* |
487 | + |
488 | +API Changes |
489 | +*********** |
490 | + |
491 | +Internals |
492 | +********* |
493 | + |
494 | +Testing |
495 | +******* |
496 | + |
497 | +* KnownFailure is now signalled to ``ExtendedTestResult`` using the same |
498 | + method that Python 2.7 uses - ``addExpectedFailure``. (Robert Collins) |
499 | + |
500 | +* TestNotApplicable is now handled within the TestCase.run method rather |
501 | + than being looked for within ``ExtendedTestResult.addError``. This |
502 | + provides better handling with other ``TestResult`` objects, degrading to |
503 | + sucess rather than error. (Robert Collins) |
504 | + |
505 | +* The private method ``_testConcluded`` on ``ExtendedTestResult`` has been |
506 | + removed - it was empty and unused. (Robert Collins) |
507 | + |
508 | +* UnavailableFeature is now handled within the TestCase.run method rather |
509 | + than being looked for within addError. If the Result object does not |
510 | + have an addNotSupported method, addSkip is attempted instead, and |
511 | + failing that addSuccess. (Robert Collins) |
512 | + |
513 | +* When a TestResult does not have an addSkip method, skipped tests are now |
514 | + reported as successful tests, rather than as errors. This change is |
515 | + to make it possible to get a clean test run with a less capable |
516 | + TestResult. (Robert Collins) |
517 | + |
518 | + |
519 | + |
520 | +bzr 2.0.3 (not released yet) |
521 | +############################ |
522 | + |
523 | +:Codename: template |
524 | +:2.0.3: ??? |
525 | + |
526 | +Compatibility Breaks |
527 | +******************** |
528 | + |
529 | +New Features |
530 | +************ |
531 | + |
532 | +Bug Fixes |
533 | +********* |
534 | + |
535 | +Improvements |
536 | +************ |
537 | + |
538 | +Documentation |
539 | +************* |
540 | + |
541 | +API Changes |
542 | +*********** |
543 | + |
544 | +Internals |
545 | +********* |
546 | + |
547 | +Testing |
548 | +******* |
549 | + |
550 | + |
551 | +bzr 2.1.0b2 |
552 | +########### |
553 | + |
554 | +:Codename: a load off my mind |
555 | +:2.1.0b2: 2009-11-02 |
556 | + |
557 | +This is our second feature-filled release since 2.0, pushing us down the |
558 | +path to a 2.1.0. Once again, all bugfixes in 2.0.2 are present in 2.1.0b2. |
559 | + |
560 | +Key highlights in this release are: improved handling of |
561 | +failures-during-cleanup for commit, fixing a long-standing bug with |
562 | +``bzr+http`` and shared repositories, and a new StaticTuple datatype, |
563 | +allowing us to reduce memory consumption (50%) and garbage collector |
564 | +overhead (40% faster) for many operations. |
565 | + |
566 | +Bug Fixes |
567 | +********* |
568 | + |
569 | +* ``bzr+http`` servers no longer give spurious jail break errors when |
570 | + serving branches inside a shared repository. (Andrew Bennetts, #348308) |
571 | + |
572 | +* Errors during commit are handled more robustly so that knock-on errors |
573 | + are less likely to occur, and will not obscure the original error if |
574 | + they do occur. This fixes some causes of ``TooManyConcurrentRequests`` |
575 | + and similar errors. (Andrew Bennetts, #429747, #243391) |
576 | + |
577 | +* TreeTransform.adjust_path updates the limbo paths of descendants of adjusted |
578 | + files. (Aaron Bentley) |
579 | + |
580 | +* Unicode paths are now handled correctly and consistently by the smart |
581 | + server. (Andrew Bennetts, Michael Hudson, #458762) |
582 | + |
583 | +Improvements |
584 | +************ |
585 | + |
586 | +* When reading index files, we now use a ``StaticTuple`` rather than a |
587 | + plain ``tuple`` object. This generally gives a 20% decrease in peak |
588 | + memory, and can give a performance boost up to 40% on large projects. |
589 | + (John Arbash Meinel) |
590 | + |
591 | +* Peak memory under certain operations has been reduced significantly. |
592 | + (eg, 'bzr branch launchpad standalone' is cut in half) |
593 | + (John Arbash Meinel) |
594 | + |
595 | +Documentation |
596 | +************* |
597 | + |
598 | +* Filtered views user documentation upgraded to refer to format 2a |
599 | + instead of pre-2.0 formats. (Ian Clatworthy) |
600 | + |
601 | +API Changes |
602 | +*********** |
603 | + |
604 | +* Remove deprecated ``CLIUIFactory``. (Martin Pool) |
605 | + |
606 | +* ``UIFactory`` now has new ``show_error``, ``show_message`` and |
607 | + ``show_warning`` methods, which can be hooked by non-text UIs. |
608 | + (Martin Pool) |
609 | + |
610 | +Internals |
611 | +********* |
612 | + |
613 | +* Added ``bzrlib._simple_set_pyx``. This is a hybrid between a Set and a |
614 | + Dict (it only holds keys, but you can lookup the object located at a |
615 | + given key). It has significantly reduced memory consumption versus the |
616 | + builtin objects (1/2 the size of Set, 1/3rd the size of Dict). This is |
617 | + used as the interning structure for StaticTuple objects. |
618 | + (John Arbash Meinel) |
619 | + |
620 | +* ``bzrlib._static_tuple_c.StaticTuple`` is now available and used by |
621 | + the btree index parser and the chk map parser. This class functions |
622 | + similarly to ``tuple`` objects. However, it can only point to a limited |
623 | + collection of types. (Currently StaticTuple, str, unicode, None, bool, |
624 | + int, long, float, but not subclasses). This allows us to remove it from |
625 | + the garbage collector (it cannot be in a cycle), it also allows us to |
626 | + intern the objects. In testing, this can reduce peak memory by 20-40%, |
627 | + and significantly improve performance by removing objects from being |
628 | + inspected by the garbage collector. (John Arbash Meinel) |
629 | + |
630 | +* ``GroupCompressBlock._ensure_content()`` will now release the |
631 | + ``zlib.decompressobj()`` when the first request is for all of the |
632 | + content. (Previously it would only be released if you made a request for |
633 | + part of the content, and then all of it later.) This turns out to be a |
634 | + significant memory savings, as a ``zstream`` carries around approx 260kB |
635 | + of internal state and buffers. (For branching bzr.dev this drops peak |
636 | + memory from 382MB => 345MB.) (John Arbash Meinel) |
637 | + |
638 | +* When streaming content between ``2a`` format repositories, we now clear |
639 | + caches from earlier versioned files. (So 'revisions' is cleared when we |
640 | + start reading 'inventories', etc.) This can have a significant impact on |
641 | + peak memory for initial copies (~200MB). (John Arbash Meinel) |
642 | + |
643 | + |
644 | +bzr 2.0.2 |
645 | +######### |
646 | + |
647 | +:Codename: after the scare |
648 | +:2.0.2: 2009-11-02 |
649 | + |
650 | +The second in our "let's keep the stable bugfixes flowing" series. As |
651 | +expected this has a few (~9) bugfixes relative to 2.0.1, and no major api |
652 | +changes or features. |
653 | + |
654 | +Bug Fixes |
655 | +********* |
656 | + |
657 | +* Avoid "NoneType has no attribute st_mode" error when files disappear |
658 | + from a directory while it's being read. (Martin Pool, #446033) |
659 | + |
660 | +* Content filters are now applied correctly after revert. |
661 | + (Ian Clatworthy) |
662 | + |
663 | +* Diff parsing handles "Binary files differ" hunks. (Aaron Bentley, #436325) |
664 | + |
665 | +* Fetching from stacked pre-2a repository via a smart server no longer |
666 | + fails intermittently with "second push failed to complete". |
667 | + (Andrew Bennetts, #437626) |
668 | + |
669 | +* Fix typos left after test_selftest refactoring. |
670 | + (Vincent Ladeuil, Matt Nordhoff, #461149) |
671 | + |
672 | +* Fixed ``ObjectNotLocked`` errors during ``bzr log -r NNN somefile``. |
673 | + (Andrew Bennetts, #445171) |
674 | + |
675 | +* PreviewTree file names are not limited by the encoding of the temp |
676 | + directory's filesystem. (Aaron Bentley, #436794) |
677 | + |
678 | +Improvements |
679 | +************ |
680 | + |
681 | +* ``bzr log`` now read-locks branches exactly once, so makes better use of |
682 | + data caches. (Andrew Bennetts) |
683 | + |
684 | +Documentation |
685 | +************* |
686 | + |
687 | +* Filtered views user documentation upgraded to refer to format 2a |
688 | + instead of pre-2.0 formats. (Ian Clatworthy) |
689 | + |
690 | + |
691 | +bzr 2.1.0b1 |
692 | +########### |
693 | + |
694 | +:Codename: While the cat is away |
695 | +:2.1.0b1: 2009-10-14 |
696 | + |
697 | +This is the first development release in the new split "stable" and |
698 | +"development" series. As such, the release is a snapshot of bzr.dev |
699 | +without creating a release candidate first. This release includes a |
700 | +fair amount of internal changes, with deprecated code being removed, |
701 | +and several new feature developments. People looking for a stable code |
702 | +base with only bugfixes should focus on the 2.0.1 release. All bugfixes |
703 | +present in 2.0.1 are present in 2.1.0b1. |
704 | + |
705 | +Highlights include support for ``bzr+ssh://host/~/homedir`` style urls, |
706 | +finer control over the plugin search path via extended BZR_PLUGIN_PATH |
707 | +syntax, visible warnings when extension modules fail to load, and improved |
708 | +error handling during unlocking. |
709 | + |
710 | + |
711 | +New Features |
712 | +************ |
713 | + |
714 | +* Bazaar can now send mail through Apple OS X Mail.app. |
715 | + (Brian de Alwis) |
716 | + |
717 | +* ``bzr+ssh`` and ``bzr`` paths can now be relative to home directories |
718 | + specified in the URL. Paths starting with a path segment of ``~`` are |
719 | + relative to the home directory of the user running the server, and paths |
720 | + starting with ``~user`` are relative to the home directory of the named |
721 | + user. For example, for a user "bob" with a home directory of |
722 | + ``/home/bob``, these URLs are all equivalent: |
723 | + |
724 | + * ``bzr+ssh://bob@host/~/repo`` |
725 | + * ``bzr+ssh://bob@host/~bob/repo`` |
726 | + * ``bzr+ssh://bob@host/home/bob/repo`` |
727 | + |
728 | + If ``bzr serve`` was invoked with a ``--directory`` argument, then no |
729 | + home directories outside that directory will be accessible via this |
730 | + method. |
731 | + |
732 | + This is a feature of ``bzr serve``, so pre-2.1 clients will |
733 | + automatically benefit from this feature when ``bzr`` on the server is |
734 | + upgraded. (Andrew Bennetts, #109143) |
735 | + |
736 | +* Extensions can now be compiled if either Cython or Pyrex is available. |
737 | + Currently Pyrex is preferred, but that may change in the future. |
738 | + (Arkanes) |
739 | + |
740 | +* Give more control on BZR_PLUGIN_PATH by providing a way to refer to or |
741 | + disable the user, site and core plugin directories. |
742 | + (Vincent Ladeuil, #412930, #316192, #145612) |
743 | + |
744 | +Bug Fixes |
745 | +********* |
746 | + |
747 | +* Bazaar's native protocol code now correctly handles EINTR, which most |
748 | + noticeably occurs if you break in to the debugger while connected to a |
749 | + bzr+ssh server. You can now can continue from the debugger (by typing |
750 | + 'c') and the process continues. However, note that pressing C-\ in the |
751 | + shell may still kill the SSH process, which is bug 162509, so you must |
752 | + sent a signal to the bzr process specifically, for example by typing |
753 | + ``kill -QUIT PID`` in another shell. (Martin Pool, #341535) |
754 | + |
755 | +* ``bzr add`` in a tree that has files with ``\r`` or ``\n`` in the |
756 | + filename will issue a warning and skip over those files. |
757 | + (Robert Collins, #3918) |
758 | + |
759 | +* ``bzr dpush`` now aborts if uncommitted changes (including pending merges) |
760 | + are present in the working tree. The configuration option ``dpush_strict`` |
761 | + can be used to set the default for this behavior. |
762 | + (Vincent Ladeuil, #438158) |
763 | + |
764 | +* ``bzr merge`` and ``bzr remove-tree`` now requires --force if pending |
765 | + merges are present in the working tree. |
766 | + (Vincent Ladeuil, #426344) |
767 | + |
768 | +* Clearer message when Bazaar runs out of memory, instead of a ``MemoryError`` |
769 | + traceback. (Martin Pool, #109115) |
770 | + |
771 | +* Don't give a warning on Windows when failing to import ``_readdir_pyx`` |
772 | + as it is never built. (John Arbash Meinel, #430645) |
773 | |
774 | * Don't restrict the command name used to run the test suite. |
775 | (Vincent Ladeuil, #419950) |
776 | |
777 | +* ftp transports were built differently when the kerberos python module was |
778 | + present leading to obscure failures related to ASCII/BINARY modes. |
779 | + (Vincent Ladeuil, #443041) |
780 | + |
781 | +* Network streams now decode adjacent records of the same type into a |
782 | + single stream, reducing layering churn. (Robert Collins) |
783 | + |
784 | +* PreviewTree behaves correctly when get_file_mtime is invoked on an unmodified |
785 | + file. (Aaron Bentley, #251532) |
786 | + |
787 | +* Registry objects should not use iteritems() when asked to use items(). |
788 | + (Vincent Ladeuil, #430510) |
789 | + |
790 | +* Weave based repositories couldn't be cloned when committers were using |
791 | + domains or user ids embedding '.sig'. Now they can. |
792 | + (Matthew Fuller, Vincent Ladeuil, #430868) |
793 | + |
794 | Improvements |
795 | ************ |
796 | |
797 | +* Revision specifiers can now be given in a more DWIM form, without |
798 | + needing explicit prefixes for specifiers like tags or revision id's. |
799 | + See ``bzr help revisionspec`` for full details. (Matthew Fuller) |
800 | + |
801 | +* Bazaar gives a warning before exiting, and writes into ``.bzr.log``, if |
802 | + compiled extensions can't be loaded. This typically indicates a |
803 | + packaging or installation problem. In this case Bazaar will keep |
804 | + running using pure-Python versions, but this may be substantially |
805 | + slower. The warning can be disabled by setting |
806 | + ``ignore_missing_extensions = True`` in ``bazaar.conf``. |
807 | + See also <https://answers.launchpad.net/bzr/+faq/703>. |
808 | + (Martin Pool, #406113, #430529) |
809 | + |
810 | +* Secondary errors that occur during Branch.unlock and Repository.unlock |
811 | + no longer obscure the original error. These methods now use a new |
812 | + decorator, ``only_raises``. This fixes many causes of |
813 | + ``TooManyConcurrentRequests`` and similar errors. |
814 | + (Andrew Bennetts, #429747) |
815 | + |
816 | Documentation |
817 | ************* |
818 | |
819 | +* Describe the new shell-like test feature. (Vincent Ladeuil) |
820 | + |
821 | +* Help on hooks no longer says 'Not deprecated' for hooks that are |
822 | + currently supported. (Ian Clatworthy, #422415) |
823 | + |
824 | API Changes |
825 | *********** |
826 | |
827 | +* ``bzrlib.user_encoding`` has been removed; use |
828 | + ``bzrlib.osutils.get_user_encoding`` instead. (Martin Pool) |
829 | + |
830 | * ``bzrlib.tests`` now uses ``stopTestRun`` for its ``TestResult`` |
831 | subclasses - the same as python's unittest module. (Robert Collins) |
832 | + |
833 | +* ``diff._get_trees_to_diff`` has been renamed to |
834 | + ``diff.get_trees_and_branches_to_diff``. It is now a public API, and it |
835 | + returns the old and new branches. (Gary van der Merwe) |
836 | + |
837 | +* ``bzrlib.trace.log_error``, ``error`` and ``info`` have been deprecated. |
838 | + (Martin Pool) |
839 | + |
840 | +* ``MutableTree.has_changes()`` does not require a tree parameter anymore. It |
841 | + now defaults to comparing to the basis tree. It now checks for pending |
842 | + merges too. ``Merger.check_basis`` has been deprecated and replaced by the |
843 | + corresponding has_changes() calls. ``Merge.compare_basis``, |
844 | + ``Merger.file_revisions`` and ``Merger.ensure_revision_trees`` have also |
845 | + been deprecated. |
846 | + (Vincent Ladeuil, #440631) |
847 | + |
848 | +* ``ProgressTask.note`` is deprecated. |
849 | + (Martin Pool) |
850 | |
851 | Internals |
852 | ********* |
853 | |
854 | +* Added ``-Drelock`` debug flag. It will ``note`` a message every time a |
855 | + repository or branch object is unlocked then relocked the same way. |
856 | + (Andrew Bennetts) |
857 | + |
858 | +* ``BTreeLeafParser.extract_key`` has been tweaked slightly to reduce |
859 | + mallocs while parsing the index (approx 3=>1 mallocs per key read). |
860 | + This results in a 10% speedup while reading an index. |
861 | + (John Arbash Meinel) |
862 | + |
863 | * The ``bzrlib.lsprof`` module has a new class ``BzrProfiler`` which makes |
864 | profiling in some situations like callbacks and generators easier. |
865 | (Robert Collins) |
866 | @@ -50,27 +415,195 @@ |
867 | * Passing ``--lsprof-tests -v`` to bzr selftest will cause lsprof output to |
868 | be output for every test. Note that this is very verbose! (Robert Collins) |
869 | |
870 | +* Setting ``BZR_TEST_PDB=1`` when running selftest will cause a pdb |
871 | + post_mortem to be triggered when a test failure occurs. (Robert Collins) |
872 | + |
873 | +* Shell-like tests can now be written. Code in ``bzrlib/tests/script.py`` , |
874 | + documentation in ``developers/testing.txt`` for details. |
875 | + (Vincent Ladeuil) |
876 | + |
877 | +* Some tests could end up with the same id, that was dormant for |
878 | + a long time. |
879 | + (Vincent Ladeuil, #442980) |
880 | + |
881 | +* Stop showing the number of tests due to missing features in the test |
882 | + progress bar. (Martin Pool) |
883 | + |
884 | * Test parameterisation now does a shallow copy, not a deep copy of the test |
885 | to be parameterised. This is not expected to break external use of test |
886 | parameterisation, and is substantially faster. (Robert Collins) |
887 | |
888 | - |
889 | -bzr 2.0rc2 |
890 | -########## |
891 | - |
892 | -Bug Fixes |
893 | -********* |
894 | +* Tests that try to open a bzr dir on an arbitrary transport will now |
895 | + fail unless they have explicitly permitted the transport via |
896 | + ``self.permit_url``. The standard test factories such as ``self.get_url`` |
897 | + will permit the urls they provide automatically, so only exceptional |
898 | + tests should need to do this. (Robert Collins) |
899 | + |
900 | +* The break-in test no longer cares about clean shutdown of the child, |
901 | + instead it is happy if the debugger starts up. (Robert Collins) |
902 | + |
903 | +* The full test suite is expected to pass when the C extensions are not |
904 | + present. (Vincent Ladeuil, #430749) |
905 | + |
906 | + |
907 | +bzr 2.0.1 |
908 | +######### |
909 | + |
910 | +:Codename: Stability First |
911 | +:2.0.1: 2009-10-14 |
912 | + |
913 | +The first of our new ongoing bugfix-only stable releases has arrived. It |
914 | +includes a collection of 12 bugfixes applied to bzr 2.0.0, but does not |
915 | +include any of the feature development in the 2.1.0 series. |
916 | + |
917 | + |
918 | +Bug Fixes |
919 | +********* |
920 | + |
921 | +* ``bzr add`` in a tree that has files with ``\r`` or ``\n`` in the |
922 | + filename will issue a warning and skip over those files. |
923 | + (Robert Collins, #3918) |
924 | + |
925 | +* bzr will attempt to authenticate with SSH servers that support |
926 | + ``keyboard-interactive`` auth but not ``password`` auth when using |
927 | + Paramiko. (Andrew Bennetts, #433846) |
928 | + |
929 | +* Fixed fetches from a stacked branch on a smart server that were failing |
930 | + with some combinations of remote and local formats. This was causing |
931 | + "unknown object type identifier 60" errors. (Andrew Bennetts, #427736) |
932 | + |
933 | +* Fixed ``ObjectNotLocked`` errors when doing some log and diff operations |
934 | + on branches via a smart server. (Andrew Bennetts, #389413) |
935 | + |
936 | +* Handle things like ``bzr add foo`` and ``bzr rm foo`` when the tree is |
937 | + at the root of a drive. ``osutils._cicp_canonical_relpath`` always |
938 | + assumed that ``abspath()`` returned a path that did not have a trailing |
939 | + ``/``, but that is not true when working at the root of the filesystem. |
940 | + (John Arbash Meinel, Jason Spashett, #322807) |
941 | + |
942 | +* Hide deprecation warnings for 'final' releases for python2.6. |
943 | + (John Arbash Meinel, #440062) |
944 | + |
945 | +* Improve the time for ``bzr log DIR`` for 2a format repositories. |
946 | + We had been using the same code path as for <2a formats, which required |
947 | + iterating over all objects in all revisions. |
948 | + (John Arbash Meinel, #374730) |
949 | + |
950 | +* Make sure that we unlock the tree if we fail to create a TreeTransform |
951 | + object when doing a merge, and there is limbo, or pending-deletions |
952 | + directory. (Gary van der Merwe, #427773) |
953 | + |
954 | +* Occasional IndexError on renamed files have been fixed. Operations that |
955 | + set a full inventory in the working tree will now go via the |
956 | + apply_inventory_delta code path which is simpler and easier to |
957 | + understand than dirstates set_state_from_inventory method. This may |
958 | + have a small performance impact on operations built on _write_inventory, |
959 | + but such operations are already doing full tree scans, so no radical |
960 | + performance change should be observed. (Robert Collins, #403322) |
961 | + |
962 | +* Retrieving file text or mtime from a _PreviewTree has good performance when |
963 | + there are many changes. (Aaron Bentley) |
964 | + |
965 | +* The CHK index pages now use an unlimited cache size. With a limited |
966 | + cache and a large project, the random access of chk pages could cause us |
967 | + to download the entire cix file many times. |
968 | + (John Arbash Meinel, #402623) |
969 | + |
970 | +* When a file kind becomes unversionable after being added, a sensible |
971 | + error will be shown instead of a traceback. (Robert Collins, #438569) |
972 | + |
973 | +Documentation |
974 | +************* |
975 | + |
976 | +* Improved README. (Ian Clatworthy) |
977 | + |
978 | +* Improved upgrade documentation for Launchpad branches. |
979 | + (Barry Warsaw) |
980 | + |
981 | + |
982 | +bzr 2.0.0 |
983 | +######### |
984 | + |
985 | +:2.0.0: 2009-09-22 |
986 | +:Codename: Instant Karma |
987 | + |
988 | +This release of Bazaar makes the 2a (previously 'brisbane-core') format |
989 | +the default when new branches or repositories are created. This format is |
990 | +substantially smaller and faster for many operations. Most of the work in |
991 | +this release focuses on bug fixes and stabilization, covering both 2a and |
992 | +previous formats. (See the Upgrade Guide for information on migrating |
993 | +existing projects.) |
994 | + |
995 | +This release also improves the documentation content and presentation, |
996 | +including adding Windows HtmlHelp manuals. |
997 | + |
998 | +The Bazaar team decided that 2.0 will be a long-term supported release, |
999 | +with bugfix-only 2.0.x releases based on it, continuing for at least six |
1000 | +months or until the following stable release. |
1001 | + |
1002 | +Changes from 2.0.0rc2 to final |
1003 | +****************************** |
1004 | + |
1005 | +* Officially branded as 2.0.0 rather than 2.0 to clarify between things |
1006 | + that "want to happen on the 2.0.x stable series" versus things that want |
1007 | + to "land in 2.0.0". (Changes how bzrlib._format_version_tuple() handles |
1008 | + micro = 0.) (John Arbash Meinel) |
1009 | + |
1010 | + |
1011 | +bzr 2.0.0rc2 |
1012 | +############ |
1013 | + |
1014 | +:2.0.0rc2: 2009-09-10 |
1015 | + |
1016 | +New Features |
1017 | +************ |
1018 | + |
1019 | +* Added post_commit hook for mutable trees. This allows the keywords |
1020 | + plugin to expand keywords on files changed by the commit. |
1021 | + (Ian Clatworthy, #408841) |
1022 | + |
1023 | +Bug Fixes |
1024 | +********* |
1025 | + |
1026 | +* Bazaar's native protocol code now correctly handles EINTR, which most |
1027 | + noticeably occurs if you break in to the debugger while connected to a |
1028 | + bzr+ssh server. You can now can continue from the debugger (by typing |
1029 | + 'c') and the process continues. However, note that pressing C-\ in the |
1030 | + shell may still kill the SSH process, which is bug 162509, so you must |
1031 | + sent a signal to the bzr process specifically, for example by typing |
1032 | + ``kill -QUIT PID`` in another shell. (Martin Pool, #341535) |
1033 | |
1034 | * ``bzr check`` in pack-0.92, 1.6 and 1.9 format repositories will no |
1035 | longer report incorrect errors about ``Missing inventory ('TREE_ROOT', ...)`` |
1036 | (Robert Collins, #416732) |
1037 | |
1038 | +* ``bzr info -v`` on a 2a format still claimed that it was a "Development |
1039 | + format" (John Arbash Meinel, #424392) |
1040 | + |
1041 | * ``bzr log stacked-branch`` shows the full log including |
1042 | revisions that are in the fallback repository. (Regressed in 2.0rc1). |
1043 | (John Arbash Meinel, #419241) |
1044 | |
1045 | -* Fix a segmentation fault when computing the ``merge_sort`` of a graph |
1046 | - that has a ghost in the mainline ancestry. |
1047 | +* Clearer message when Bazaar runs out of memory, instead of a ``MemoryError`` |
1048 | + traceback. (Martin Pool, #109115) |
1049 | + |
1050 | +* Conversion to 2a will create a single pack for all the new revisions (as |
1051 | + long as it ran without interruption). This improves both ``bzr upgrade`` |
1052 | + and ``bzr pull`` or ``bzr merge`` from local branches in older formats. |
1053 | + The autopack logic that occurs every 100 revisions during local |
1054 | + conversions was not returning that pack's identifier, which resulted in |
1055 | + the partial packs created during the conversion not being consolidated |
1056 | + at the end of the conversion process. (Robert Collins, #423818) |
1057 | + |
1058 | +* Fetches from 2a to 2a are now again requested in 'groupcompress' order. |
1059 | + Groups that are seen as 'underutilized' will be repacked on-the-fly. |
1060 | + This means that when the source is fully packed, there is minimal |
1061 | + overhead during the fetch, but if the source is poorly packed the result |
1062 | + is a fairly well packed repository (not as good as 'bzr pack' but |
1063 | + good-enough.) (Robert Collins, John Arbash Meinel, #402652) |
1064 | + |
1065 | +* Fix a potential segmentation fault when doing 'log' of a branch that had |
1066 | + ghosts in its mainline. (Evaluating None as a tuple is bad.) |
1067 | (John Arbash Meinel, #419241) |
1068 | |
1069 | * ``groupcompress`` sort order is now more stable, rather than relying on |
1070 | @@ -81,28 +614,41 @@ |
1071 | bugfix vs 2.0rc1, and all 2.0rc1 users should upgrade to 2.0rc2 before |
1072 | converting repositories. (Robert Collins, #422849) |
1073 | |
1074 | +* Network streams now decode adjacent records of the same type into a |
1075 | + single stream, reducing layering churn. (Robert Collins) |
1076 | + |
1077 | +* Prevent some kinds of incomplete data from being committed to a 2a |
1078 | + repository, such as revisions without inventories, a missing chk_bytes |
1079 | + record for an inventory, or a missing text referenced by an inventory. |
1080 | + (Andrew Bennetts, #423506, #406687) |
1081 | + |
1082 | Documentation |
1083 | ************* |
1084 | |
1085 | +* Fix assertion error about "_remember_remote_is_before" when pushing to |
1086 | + older smart servers. |
1087 | + (Andrew Bennetts, #418931) |
1088 | + |
1089 | +* Help on hooks no longer says 'Not deprecated' for hooks that are |
1090 | + currently supported. (Ian Clatworthy, #422415) |
1091 | + |
1092 | +* PDF and CHM (Windows HtmlHelp) formats are now supported for the |
1093 | + user documentation. The HTML documentation is better broken up into |
1094 | + topics. (Ian Clatworthy) |
1095 | + |
1096 | +* The developer and foreign language documents are now separated |
1097 | + out so that searching in the HTML and CHM files produces more |
1098 | + useful results. (Ian Clatworthy) |
1099 | + |
1100 | * The main table of contents now provides links to the new Migration Docs |
1101 | and Plugins Guide. (Ian Clatworthy) |
1102 | |
1103 | |
1104 | -bzr 2.0rc1 |
1105 | -########## |
1106 | - |
1107 | +bzr 2.0.0rc1 |
1108 | +############ |
1109 | |
1110 | :Codename: no worries |
1111 | -:2.0rc1: 2009-08-26 |
1112 | - |
1113 | -This release of Bazaar makes 2a 'brisbane-core' format the |
1114 | -default. Most of the work in this release now focuses on bug |
1115 | -fixes and stabilization, covering both 2a and previous formats. |
1116 | - |
1117 | -The Bazaar team decided that 2.0 will be a long-term supported |
1118 | -release, with bugfix-only releases based on it continuing for at |
1119 | -least six months or until the following stable release (we said |
1120 | -that previously, but that's worth repeating). |
1121 | +:2.0.0rc1: 2009-08-26 |
1122 | |
1123 | Compatibility Breaks |
1124 | ******************** |
1125 | @@ -110,7 +656,7 @@ |
1126 | * The default format for bzr is now ``2a``. This format brings many |
1127 | significant performance and size improvements. bzr can pull from |
1128 | any existing repository into a ``2a`` one, but can only transfer |
1129 | - into ``rich-root`` repositories from ``2a``. The Upgrade guide |
1130 | + from ``2a`` into ``rich-root`` repositories. The Upgrade guide |
1131 | has more information about this change. (Robert Collins) |
1132 | |
1133 | * On Windows auto-detection of Putty's plink.exe is disabled. |
1134 | @@ -175,7 +721,7 @@ |
1135 | * ``bzr shelve`` and ``bzr unshelve`` now work on windows. |
1136 | (Robert Collins, #305006) |
1137 | |
1138 | -* Commit of specific files no longer prevents using the the iter_changes |
1139 | +* Commit of specific files no longer prevents using the iter_changes |
1140 | codepath. On 2a repositories, commit of specific files should now be as |
1141 | fast, or slightly faster, than a full commit. (Robert Collins) |
1142 | |
1143 | @@ -202,8 +748,17 @@ |
1144 | Testing |
1145 | ******* |
1146 | |
1147 | -bzr 1.18.1 NOT RELEASED YET |
1148 | -########################### |
1149 | +bzr 1.18.1 |
1150 | +########## |
1151 | + |
1152 | +:Codename: nein nein nein! |
1153 | +:1.18.1: 2009-09-09 |
1154 | + |
1155 | +This release fixes two small but worthwhile bugs relevant to users on |
1156 | +Microsoft Windows: some commands that failed on with locking errors will |
1157 | +now work, and a bug that caused poor performance after committing a file |
1158 | +with line-ending conversion has now been fixed. It also fixes a bug in |
1159 | +pushing to older servers. |
1160 | |
1161 | Bug Fixes |
1162 | ********* |
1163 | @@ -212,13 +767,17 @@ |
1164 | conversion will commit too many copies a file. |
1165 | (Martin Pool, #415508) |
1166 | |
1167 | +* Fix assertion error about ``_remember_remote_is_before`` in |
1168 | + ``set_tags_bytes`` when pushing to older smart servers. |
1169 | + (Andrew Bennetts, Alexander Belchenko, #418931) |
1170 | + |
1171 | Improvements |
1172 | ************ |
1173 | |
1174 | -* ``bzr push`` locally on windows will no longer give a locking error with |
1175 | +* ``bzr push`` locally on Windows will no longer give a locking error with |
1176 | dirstate based formats. (Robert Collins) |
1177 | |
1178 | -* ``bzr shelve`` and ``bzr unshelve`` now work on windows. |
1179 | +* ``bzr shelve`` and ``bzr unshelve`` now work on Windows. |
1180 | (Robert Collins, #305006) |
1181 | |
1182 | API Changes |
1183 | @@ -583,8 +1142,8 @@ |
1184 | knit format repositories. (Andrew Bennetts, #405653) |
1185 | |
1186 | |
1187 | -bzr 1.17 "So late it's brunch" 2009-07-20 |
1188 | -######################################### |
1189 | +bzr 1.17 |
1190 | +######## |
1191 | :Codename: so-late-its-brunch |
1192 | :1.17rc1: 2009-07-13 |
1193 | :1.17: 2009-07-20 |
1194 | @@ -833,8 +1392,10 @@ |
1195 | this class and the UI. (Martin Pool) |
1196 | |
1197 | |
1198 | -bzr 1.16.1 2009-06-26 |
1199 | -##################### |
1200 | +bzr 1.16.1 |
1201 | +########## |
1202 | + |
1203 | +:Released: 2009-06-26 |
1204 | |
1205 | End user testing of the 2a format revealed two serious bugs. The first, |
1206 | #365615, caused bzr to raise AbsentContentFactory errors when autopacking. |
1207 | @@ -889,8 +1450,8 @@ |
1208 | (Robert Collins, #376748) |
1209 | |
1210 | |
1211 | -bzr 1.16 "It's yesterday in California" 2009-06-18 |
1212 | -################################################## |
1213 | +bzr 1.16 |
1214 | +######## |
1215 | :Codename: yesterday-in-california |
1216 | :1.16rc1: 2009-06-11 |
1217 | :1.16: 2009-06-18 |
1218 | @@ -929,7 +1490,7 @@ |
1219 | ************ |
1220 | |
1221 | * A new repository format ``2a`` has been added. This is a beta release |
1222 | - of the the brisbane-core (aka group-compress) project. This format now |
1223 | + of the brisbane-core (aka group-compress) project. This format now |
1224 | suitable for wider testing by advanced users willing to deal with some |
1225 | bugs. We would appreciate test reports, either positive or negative. |
1226 | Format 2a is substantially smaller and faster for many operations on |
1227 | @@ -1658,7 +2219,7 @@ |
1228 | |
1229 | * Added ``bzrlib.inventory_delta`` module. This will be used for |
1230 | serializing and deserializing inventory deltas for more efficient |
1231 | - streaming on the the network. (Robert Collins, Andrew Bennetts) |
1232 | + streaming on the network. (Robert Collins, Andrew Bennetts) |
1233 | |
1234 | * ``Branch._get_config`` has been added, which splits out access to the |
1235 | specific config file from the branch. This is used to let RemoteBranch |
1236 | @@ -2367,8 +2928,11 @@ |
1237 | (Vincent Ladeuil) |
1238 | |
1239 | |
1240 | -bzr 1.11 "Eyes up!" 2009-01-19 |
1241 | -############################## |
1242 | +bzr 1.11 |
1243 | +######## |
1244 | + |
1245 | +:Codename: "Eyes up!" |
1246 | +:Released: 2009-01-19 |
1247 | |
1248 | This first monthly release of Bazaar for 2009 improves Bazaar's operation |
1249 | in Windows, Mac OS X, and other situations where file names are matched |
1250 | @@ -2394,8 +2958,11 @@ |
1251 | |
1252 | |
1253 | |
1254 | -bzr 1.11rc1 "Eyes up!" 2009-01-09 |
1255 | -################################# |
1256 | +bzr 1.11rc1 |
1257 | +########### |
1258 | + |
1259 | +:Codename: "Eyes up!" |
1260 | +:Released: 2009-01-09 |
1261 | |
1262 | Changes |
1263 | ******* |
1264 | @@ -2631,8 +3198,10 @@ |
1265 | |
1266 | |
1267 | |
1268 | -bzr 1.10 2008-12-05 |
1269 | -################### |
1270 | +bzr 1.10 |
1271 | +######## |
1272 | + |
1273 | +:Released: 2008-12-05 |
1274 | |
1275 | Bazaar 1.10 has several performance improvements for copying revisions |
1276 | (especially for small updates to large projects). There has also been a |
1277 | @@ -2657,8 +3226,10 @@ |
1278 | topologically. (John Arbash Meinel, #304841) |
1279 | |
1280 | |
1281 | -bzr 1.10rc1 2008-11-28 |
1282 | -###################### |
1283 | +bzr 1.10rc1 |
1284 | +########### |
1285 | + |
1286 | +:Released: 2008-11-28 |
1287 | |
1288 | This release of Bazaar focuses on performance improvements when pushing |
1289 | and pulling revisions, both locally and to remote networks. The popular |
1290 | @@ -2778,8 +3349,10 @@ |
1291 | * Doctests now only report the first failure. (Martin Pool) |
1292 | |
1293 | |
1294 | -bzr 1.9 2008-11-07 |
1295 | -################## |
1296 | +bzr 1.9 |
1297 | +####### |
1298 | + |
1299 | +:Released: 2008-11-07 |
1300 | |
1301 | This release of Bazaar adds a new repository format, ``1.9``, with smaller |
1302 | and more efficient index files. This format can be specified when |
1303 | @@ -2801,8 +3374,10 @@ |
1304 | (John Arbash Meinel, #293746) |
1305 | |
1306 | |
1307 | -bzr 1.9rc1 2008-10-31 |
1308 | -##################### |
1309 | +bzr 1.9rc1 |
1310 | +########## |
1311 | + |
1312 | +:Released: 2008-10-31 |
1313 | |
1314 | New Features |
1315 | ************ |
1316 | @@ -2919,8 +3494,10 @@ |
1317 | configuration of authetication credentials. |
1318 | |
1319 | |
1320 | -bzr 1.8 2008-10-16 |
1321 | -################## |
1322 | +bzr 1.8 |
1323 | +####### |
1324 | + |
1325 | +:Released: 2008-10-16 |
1326 | |
1327 | Bazaar 1.8 includes several fixes that improve working tree performance, |
1328 | display of revision logs, and merges. The bzr testsuite now passes on OS |
1329 | @@ -2941,8 +3518,10 @@ |
1330 | that platform. (Alexander Belchenko, Martin Pool, #277481) |
1331 | |
1332 | |
1333 | -bzr 1.8rc1 2008-10-07 |
1334 | -##################### |
1335 | +bzr 1.8rc1 |
1336 | +########## |
1337 | + |
1338 | +:Released: 2008-10-07 |
1339 | |
1340 | Changes |
1341 | ******* |
1342 | @@ -3140,14 +3719,18 @@ |
1343 | (Vincent Ladeuil) |
1344 | |
1345 | |
1346 | -bzr 1.7.1 2008-10-01 |
1347 | -#################### |
1348 | +bzr 1.7.1 |
1349 | +######### |
1350 | + |
1351 | +:Released: 2008-10-01 |
1352 | |
1353 | No changes from 1.7.1rc1. |
1354 | |
1355 | |
1356 | -bzr 1.7.1rc1 2008-09-24 |
1357 | -####################### |
1358 | +bzr 1.7.1rc1 |
1359 | +############ |
1360 | + |
1361 | +:Released: 2008-09-24 |
1362 | |
1363 | This release just includes an update to how the merge algorithm handles |
1364 | file paths when we encounter complex history. |
1365 | @@ -3162,8 +3745,10 @@ |
1366 | (John Arbash Meinel) |
1367 | |
1368 | |
1369 | -bzr 1.7 2008-09-23 |
1370 | -################## |
1371 | +bzr 1.7 |
1372 | +####### |
1373 | + |
1374 | +:Released: 2008-09-23 |
1375 | |
1376 | This release includes many bug fixes and a few performance and feature |
1377 | improvements. ``bzr rm`` will now scan for missing files and remove them, |
1378 | @@ -3180,8 +3765,10 @@ |
1379 | packaging qbzr. (Mark Hammond) |
1380 | |
1381 | |
1382 | -bzr 1.7rc2 2008-09-17 |
1383 | -##################### |
1384 | +bzr 1.7rc2 |
1385 | +########## |
1386 | + |
1387 | +:Released: 2008-09-17 |
1388 | |
1389 | A few bug fixes from 1.7rc1. The biggest change is a new |
1390 | ``RemoteBranch.get_stacked_on_url`` rpc. This allows clients that are |
1391 | @@ -3205,8 +3792,10 @@ |
1392 | (Andrew Bennetts) |
1393 | |
1394 | |
1395 | -bzr 1.7rc1 2008-09-09 |
1396 | -##################### |
1397 | +bzr 1.7rc1 |
1398 | +########## |
1399 | + |
1400 | +:Released: 2008-09-09 |
1401 | |
1402 | This release candidate for bzr 1.7 has several bug fixes and a few |
1403 | performance and feature improvements. ``bzr rm`` will now scan for |
1404 | @@ -3403,16 +3992,20 @@ |
1405 | clients now use this mechanism. (Neil Martinsen-Burrell) |
1406 | |
1407 | |
1408 | -bzr 1.6.1 2008-09-05 |
1409 | -#################### |
1410 | +bzr 1.6.1 |
1411 | +######### |
1412 | + |
1413 | +:Released: 2008-09-05 |
1414 | |
1415 | A couple regressions were found in the 1.6 release. There was a |
1416 | performance issue when using ``bzr+ssh`` to branch large repositories, |
1417 | and some problems with stacking and ``rich-root`` capable repositories. |
1418 | |
1419 | |
1420 | -bzr 1.6.1rc2 2008-09-03 |
1421 | -####################### |
1422 | +bzr 1.6.1rc2 |
1423 | +############ |
1424 | + |
1425 | +:Released: 2008-09-03 |
1426 | |
1427 | Bug Fixes |
1428 | ********* |
1429 | @@ -3423,8 +4016,10 @@ |
1430 | (John Arbash Meinel, #264321) |
1431 | |
1432 | |
1433 | -bzr 1.6.1rc1 2008-08-29 |
1434 | -####################### |
1435 | +bzr 1.6.1rc1 |
1436 | +############ |
1437 | + |
1438 | +:Released: 2008-08-29 |
1439 | |
1440 | This release fixes a few regressions found in the 1.6 client. Fetching |
1441 | changes was using an O(N^2) buffering algorithm, so for large projects it |
1442 | @@ -3464,8 +4059,10 @@ |
1443 | (John Arbash Meinel, #262333) |
1444 | |
1445 | |
1446 | -bzr 1.6 2008-08-25 |
1447 | -################## |
1448 | +bzr 1.6 |
1449 | +####### |
1450 | + |
1451 | +:Released: 2008-08-25 |
1452 | |
1453 | Finally, the long awaited bzr 1.6 has been released. This release includes |
1454 | new features like Stacked Branches, improved weave merge, and an updated |
1455 | @@ -3478,8 +4075,10 @@ |
1456 | TortoiseBzr in the standalone Windows installer. |
1457 | |
1458 | |
1459 | -bzr 1.6rc5 2008-08-19 |
1460 | -##################### |
1461 | +bzr 1.6rc5 |
1462 | +########## |
1463 | + |
1464 | +:Released: 2008-08-19 |
1465 | |
1466 | Bug Fixes |
1467 | ********* |
1468 | @@ -3491,8 +4090,10 @@ |
1469 | (This change was reverted when merged to bzr.dev) |
1470 | |
1471 | |
1472 | -bzr 1.6rc4 2008-08-18 |
1473 | -##################### |
1474 | +bzr 1.6rc4 |
1475 | +########## |
1476 | + |
1477 | +:Released: 2008-08-18 |
1478 | |
1479 | Bug Fixes |
1480 | ********* |
1481 | @@ -3502,8 +4103,10 @@ |
1482 | rather than preserving deltas. (John Arbash Meinel, #256757) |
1483 | |
1484 | |
1485 | -bzr 1.6rc3 2008-08-14 |
1486 | -##################### |
1487 | +bzr 1.6rc3 |
1488 | +########## |
1489 | + |
1490 | +:Released: 2008-08-14 |
1491 | |
1492 | Changes |
1493 | ******* |
1494 | @@ -3536,8 +4139,10 @@ |
1495 | development which is substantially faster. (Robert Collins) |
1496 | |
1497 | |
1498 | -bzr 1.6rc2 2008-08-13 |
1499 | -##################### |
1500 | +bzr 1.6rc2 |
1501 | +########## |
1502 | + |
1503 | +:Released: 2008-08-13 |
1504 | |
1505 | This release candidate has a few minor bug fixes, and some regression |
1506 | fixes for Windows. |
1507 | @@ -3575,8 +4180,10 @@ |
1508 | will get the same results. (John Arbash Meinel, #232188) |
1509 | |
1510 | |
1511 | -bzr 1.6rc1 2008-08-06 |
1512 | -##################### |
1513 | +bzr 1.6rc1 |
1514 | +########## |
1515 | + |
1516 | +:Released: 2008-08-06 |
1517 | |
1518 | This release candidate for bzr 1.6 solidifies the new branch stacking |
1519 | feature. Bazaar now recommends that users upgrade all knit repositories, |
1520 | @@ -3712,8 +4319,10 @@ |
1521 | (Ian Clatworthy) |
1522 | |
1523 | |
1524 | -bzr 1.6beta3 2008-07-17 |
1525 | -####################### |
1526 | +bzr 1.6beta3 |
1527 | +############ |
1528 | + |
1529 | +:Released: 2008-07-17 |
1530 | |
1531 | This release adds a new 'stacked branches' feature allowing branches to |
1532 | share storage without being in the same repository or on the same machine. |
1533 | @@ -3885,8 +4494,10 @@ |
1534 | (Robert Collins) |
1535 | |
1536 | |
1537 | -bzr 1.6beta2 2008-06-10 |
1538 | -####################### |
1539 | +bzr 1.6beta2 |
1540 | +############ |
1541 | + |
1542 | +:Released: 2008-06-10 |
1543 | |
1544 | This release contains further progress towards our 1.6 goals of shallow |
1545 | repositories, and contains a fix for some user-affecting bugs in the |
1546 | @@ -3969,9 +4580,10 @@ |
1547 | * Knit record serialisation is now stricter on what it will accept, to |
1548 | guard against potential internal bugs, or broken input. (Robert Collins) |
1549 | |
1550 | -bzr 1.6beta1 2008-06-02 |
1551 | -####################### |
1552 | +bzr 1.6beta1 |
1553 | +############ |
1554 | |
1555 | +:Released: 2008-06-02 |
1556 | |
1557 | Commands that work on the revision history such as push, pull, missing, |
1558 | uncommit and log are now substantially faster. This release adds a |
1559 | @@ -4189,8 +4801,10 @@ |
1560 | (Martin Pool) |
1561 | |
1562 | |
1563 | -bzr 1.5 2008-05-16 |
1564 | -################## |
1565 | +bzr 1.5 |
1566 | +####### |
1567 | + |
1568 | +:Released: 2008-05-16 |
1569 | |
1570 | This release of Bazaar includes several updates to the documentation, and fixes |
1571 | to prepare for making rich root support the default format. Many bugs have been |
1572 | @@ -4211,8 +4825,10 @@ |
1573 | (Ian Clatworthy) |
1574 | |
1575 | |
1576 | -bzr 1.5rc1 2008-05-09 |
1577 | -##################### |
1578 | +bzr 1.5rc1 |
1579 | +########## |
1580 | + |
1581 | +:Released: 2008-05-09 |
1582 | |
1583 | Changes |
1584 | ******* |
1585 | @@ -4327,7 +4943,7 @@ |
1586 | exception. (Andrew Bennetts) |
1587 | |
1588 | * New ``--debugflag``/``-E`` option to ``bzr selftest`` for setting |
1589 | - options for debugging tests, these are complementary to the the -D |
1590 | + options for debugging tests, these are complementary to the -D |
1591 | options. The ``-Dselftest_debug`` global option has been replaced by the |
1592 | ``-E=allow_debug`` option for selftest. (Andrew Bennetts) |
1593 | |
1594 | @@ -4382,8 +4998,10 @@ |
1595 | (Martin Pool) |
1596 | |
1597 | |
1598 | -bzr 1.4 2008-04-28 |
1599 | -################## |
1600 | +bzr 1.4 |
1601 | +####### |
1602 | + |
1603 | +:Released: 2008-04-28 |
1604 | |
1605 | This release of Bazaar includes handy improvements to the speed of log and |
1606 | status, new options for several commands, improved documentation, and better |
1607 | @@ -4402,8 +5020,10 @@ |
1608 | (John Arbash Meinel, Andrew Bennetts, #214894) |
1609 | |
1610 | |
1611 | -bzr 1.4rc2 2008-04-21 |
1612 | -##################### |
1613 | +bzr 1.4rc2 |
1614 | +########## |
1615 | + |
1616 | +:Released: 2008-04-21 |
1617 | |
1618 | Bug Fixes |
1619 | ********* |
1620 | @@ -4426,8 +5046,10 @@ |
1621 | (Robert Collins, John Arbash Meinel) |
1622 | |
1623 | |
1624 | -bzr 1.4rc1 2008-04-11 |
1625 | -##################### |
1626 | +bzr 1.4rc1 |
1627 | +########## |
1628 | + |
1629 | +:Released: 2008-04-11 |
1630 | |
1631 | Changes |
1632 | ******* |
1633 | @@ -4714,14 +5336,18 @@ |
1634 | ``Graph.get_parent_map`` returns a dict of key:parents. (Robert Collins) |
1635 | |
1636 | |
1637 | -bzr 1.3.1 2008-04-09 |
1638 | -#################### |
1639 | +bzr 1.3.1 |
1640 | +######### |
1641 | + |
1642 | +:Released: 2008-04-09 |
1643 | |
1644 | No changes from 1.3.1rc1. |
1645 | |
1646 | |
1647 | -bzr 1.3.1rc1 2008-04-04 |
1648 | -####################### |
1649 | +bzr 1.3.1rc1 |
1650 | +############ |
1651 | + |
1652 | +:Released: 2008-04-04 |
1653 | |
1654 | Bug Fixes |
1655 | ********* |
1656 | @@ -4732,8 +5358,10 @@ |
1657 | (#208418, Andrew Bennetts, Martin Pool, Robert Collins) |
1658 | |
1659 | |
1660 | -bzr 1.3 2008-03-20 |
1661 | -################## |
1662 | +bzr 1.3 |
1663 | +####### |
1664 | + |
1665 | +:Released: 2008-03-20 |
1666 | |
1667 | Bazaar has become part of the GNU project <http://www.gnu.org> |
1668 | |
1669 | @@ -4749,8 +5377,10 @@ |
1670 | (#202778, Martin Pool) |
1671 | |
1672 | |
1673 | -bzr 1.3rc1 2008-03-16 |
1674 | -##################### |
1675 | +bzr 1.3rc1 |
1676 | +########## |
1677 | + |
1678 | +:Released: 2008-03-16 |
1679 | |
1680 | Notes When Upgrading |
1681 | ******************** |
1682 | @@ -4936,8 +5566,10 @@ |
1683 | format. (Robert Collins) |
1684 | |
1685 | |
1686 | -bzr 1.2 2008-02-15 |
1687 | -################## |
1688 | +bzr 1.2 |
1689 | +####### |
1690 | + |
1691 | +:Released: 2008-02-15 |
1692 | |
1693 | Bug Fixes |
1694 | ********* |
1695 | @@ -4945,8 +5577,10 @@ |
1696 | * Fix failing test in Launchpad plugin. (Martin Pool) |
1697 | |
1698 | |
1699 | -bzr 1.2rc1 2008-02-13 |
1700 | -##################### |
1701 | +bzr 1.2rc1 |
1702 | +########## |
1703 | + |
1704 | +:Released: 2008-02-13 |
1705 | |
1706 | Notes When Upgrading |
1707 | ******************** |
1708 | @@ -5147,13 +5781,17 @@ |
1709 | revision names etc. (Robert Collins) |
1710 | |
1711 | |
1712 | -bzr 1.1 2008-01-15 |
1713 | -################## |
1714 | +bzr 1.1 |
1715 | +####### |
1716 | + |
1717 | +:Released: 2008-01-15 |
1718 | |
1719 | (no changes from 1.1rc1) |
1720 | |
1721 | -bzr 1.1rc1 2008-01-05 |
1722 | -##################### |
1723 | +bzr 1.1rc1 |
1724 | +########## |
1725 | + |
1726 | +:Released: 2008-01-05 |
1727 | |
1728 | Changes |
1729 | ******* |
1730 | @@ -5363,8 +6001,10 @@ |
1731 | replaced by the new helper methods added in this release. (Robert Collins) |
1732 | |
1733 | |
1734 | -bzr 1.0 2007-12-14 |
1735 | -################## |
1736 | +bzr 1.0 |
1737 | +####### |
1738 | + |
1739 | +:Released: 2007-12-14 |
1740 | |
1741 | Documentation |
1742 | ************* |
1743 | @@ -5381,8 +6021,10 @@ |
1744 | (Ian Clatworthy) |
1745 | |
1746 | |
1747 | -bzr 1.0rc3 2007-12-11 |
1748 | -##################### |
1749 | +bzr 1.0rc3 |
1750 | +########## |
1751 | + |
1752 | +:Released: 2007-12-11 |
1753 | |
1754 | Changes |
1755 | ******* |
1756 | @@ -5423,8 +6065,10 @@ |
1757 | (Vincent Ladeuil) |
1758 | |
1759 | |
1760 | -bzr 1.0rc2 2007-12-07 |
1761 | -##################### |
1762 | +bzr 1.0rc2 |
1763 | +########## |
1764 | + |
1765 | +:Released: 2007-12-07 |
1766 | |
1767 | Improvements |
1768 | ************ |
1769 | @@ -5498,8 +6142,10 @@ |
1770 | ``started`` methods. (Matt Nordhoff) |
1771 | |
1772 | |
1773 | -bzr 1.0rc1 2007-11-30 |
1774 | -##################### |
1775 | +bzr 1.0rc1 |
1776 | +########## |
1777 | + |
1778 | +:Released: 2007-11-30 |
1779 | |
1780 | Notes When Upgrading |
1781 | ******************** |
1782 | @@ -5775,8 +6421,10 @@ |
1783 | * InventoryEntry.diff is now deprecated. Please use diff.DiffTree instead. |
1784 | |
1785 | |
1786 | -bzr 0.92 2007-11-05 |
1787 | -################### |
1788 | +bzr 0.92 |
1789 | +######## |
1790 | + |
1791 | +:Released: 2007-11-05 |
1792 | |
1793 | Changes |
1794 | ******* |
1795 | @@ -5784,8 +6432,10 @@ |
1796 | * New uninstaller on Win32. (Alexander Belchenko) |
1797 | |
1798 | |
1799 | -bzr 0.92rc1 2007-10-29 |
1800 | -###################### |
1801 | +bzr 0.92rc1 |
1802 | +########### |
1803 | + |
1804 | +:Released: 2007-10-29 |
1805 | |
1806 | Changes |
1807 | ******* |
1808 | @@ -6104,8 +6754,10 @@ |
1809 | raises a Python warning. (Martin Pool) |
1810 | |
1811 | |
1812 | -bzr 0.91 2007-09-26 |
1813 | -################### |
1814 | +bzr 0.91 |
1815 | +######## |
1816 | + |
1817 | +:Released: 2007-09-26 |
1818 | |
1819 | Bug Fixes |
1820 | ********* |
1821 | @@ -6126,15 +6778,19 @@ |
1822 | (Andrew Bennetts) |
1823 | |
1824 | |
1825 | -bzr 0.91rc2 2007-09-11 |
1826 | -###################### |
1827 | +bzr 0.91rc2 |
1828 | +########### |
1829 | + |
1830 | +:Released: 2007-09-11 |
1831 | |
1832 | * Replaced incorrect tarball for previous release; a debug statement was left |
1833 | in bzrlib/remote.py. |
1834 | |
1835 | |
1836 | -bzr 0.91rc1 2007-09-11 |
1837 | -###################### |
1838 | +bzr 0.91rc1 |
1839 | +########### |
1840 | + |
1841 | +:Released: 2007-09-11 |
1842 | |
1843 | Changes |
1844 | ******* |
1845 | @@ -6461,8 +7117,10 @@ |
1846 | [] to revert all files is deprecated. (Aaron Bentley) |
1847 | |
1848 | |
1849 | -bzr 0.90 2007-08-28 |
1850 | -################### |
1851 | +bzr 0.90 |
1852 | +######## |
1853 | + |
1854 | +:Released: 2007-08-28 |
1855 | |
1856 | Improvements |
1857 | ************ |
1858 | @@ -6485,8 +7143,10 @@ |
1859 | and call ``create_repository`` on that. (Martin Pool) |
1860 | |
1861 | |
1862 | -bzr 0.90rc1 2007-08-14 |
1863 | -###################### |
1864 | +bzr 0.90rc1 |
1865 | +########### |
1866 | + |
1867 | +:Released: 2007-08-14 |
1868 | |
1869 | Bugfixes |
1870 | ******** |
1871 | @@ -6758,8 +7418,10 @@ |
1872 | parameter. Varargs-style parameters are deprecated. (Aaron Bentley) |
1873 | |
1874 | |
1875 | -bzr 0.18 2007-07-17 |
1876 | -#################### |
1877 | +bzr 0.18 |
1878 | +######## |
1879 | + |
1880 | +:Released: 2007-07-17 |
1881 | |
1882 | Bugfixes |
1883 | ******** |
1884 | @@ -6767,8 +7429,10 @@ |
1885 | * Fix 'bzr add' crash under Win32 (Kuno Meyer) |
1886 | |
1887 | |
1888 | -bzr 0.18rc1 2007-07-10 |
1889 | -####################### |
1890 | +bzr 0.18rc1 |
1891 | +########### |
1892 | + |
1893 | +:Released: 2007-07-10 |
1894 | |
1895 | Bugfixes |
1896 | ******** |
1897 | @@ -7019,8 +7683,10 @@ |
1898 | (Vincent Ladeuil, #110448) |
1899 | |
1900 | |
1901 | -bzr 0.17 2007-06-18 |
1902 | -#################### |
1903 | +bzr 0.17 |
1904 | +######## |
1905 | + |
1906 | +:Released: 2007-06-18 |
1907 | |
1908 | Bugfixes |
1909 | ******** |
1910 | @@ -7032,8 +7698,10 @@ |
1911 | (Aaron Bentley, Ian Clatworthy, #120930) |
1912 | |
1913 | |
1914 | -bzr 0.17rc1 2007-06-12 |
1915 | -####################### |
1916 | +bzr 0.17rc1 |
1917 | +########### |
1918 | + |
1919 | +:Released: 2007-06-12 |
1920 | |
1921 | Notes When Upgrading |
1922 | ******************** |
1923 | @@ -7134,8 +7802,10 @@ |
1924 | your repository. (Previously Branch6 only supported revisions in your |
1925 | mainline). (John Arbash Meinel, #115343) |
1926 | |
1927 | -bzr 0.16 2007-05-07 |
1928 | -#################### |
1929 | +bzr 0.16 |
1930 | +######## |
1931 | + |
1932 | +:Released: 2007-05-07 |
1933 | |
1934 | Bugfixes |
1935 | ******** |
1936 | @@ -7165,8 +7835,10 @@ |
1937 | diff`` and ``bzr status`` significantly improving the speed of |
1938 | both. (John Arbash Meinel) |
1939 | |
1940 | -bzr 0.16rc2 2007-04-30 |
1941 | -####################### |
1942 | +bzr 0.16rc2 |
1943 | +########### |
1944 | + |
1945 | +:Released: 2007-04-30 |
1946 | |
1947 | Bugfixes |
1948 | ******** |
1949 | @@ -7189,8 +7861,10 @@ |
1950 | * ``WorkingTree4._iter_changes`` should not descend into unversioned |
1951 | directories. (John Arbash Meinel, #110399) |
1952 | |
1953 | -bzr 0.16rc1 2007-04-26 |
1954 | -####################### |
1955 | +bzr 0.16rc1 |
1956 | +########### |
1957 | + |
1958 | +:Released: 2007-04-26 |
1959 | |
1960 | Notes When Upgrading |
1961 | ******************** |
1962 | @@ -7497,8 +8171,10 @@ |
1963 | implementation of new auth schemes for both http and proxy. |
1964 | (Vincent Ladeuil) |
1965 | |
1966 | -bzr 0.15 2007-04-01 |
1967 | -################### |
1968 | +bzr 0.15 |
1969 | +######## |
1970 | + |
1971 | +:Released: 2007-04-01 |
1972 | |
1973 | Bugfixes |
1974 | ******** |
1975 | @@ -7510,8 +8186,10 @@ |
1976 | checking out a branch that contains an old-format working tree. |
1977 | (Martin Pool) |
1978 | |
1979 | -bzr 0.15rc3 2007-03-26 |
1980 | -####################### |
1981 | +bzr 0.15rc3 |
1982 | +########### |
1983 | + |
1984 | +:Released: 2007-03-26 |
1985 | |
1986 | Changes |
1987 | ******* |
1988 | @@ -7586,8 +8264,10 @@ |
1989 | * Correctly handles mutiple permanent http redirections. |
1990 | (vila, #88780) |
1991 | |
1992 | -bzr 0.15rc2 2007-03-14 |
1993 | -####################### |
1994 | +bzr 0.15rc2 |
1995 | +########### |
1996 | + |
1997 | +:Released: 2007-03-14 |
1998 | |
1999 | Notes When Upgrading |
2000 | ******************** |
2001 | @@ -7640,8 +8320,10 @@ |
2002 | (Wouter van Heyst, #53483) |
2003 | |
2004 | |
2005 | -bzr 0.15rc1 2007-03-07 |
2006 | -####################### |
2007 | +bzr 0.15rc1 |
2008 | +########### |
2009 | + |
2010 | +:Released: 2007-03-07 |
2011 | |
2012 | Surprises |
2013 | ********* |
2014 | @@ -7871,8 +8553,10 @@ |
2015 | before the rest of the suite. (Martin Pool) |
2016 | |
2017 | |
2018 | -bzr 0.14 2007-01-23 |
2019 | -#################### |
2020 | +bzr 0.14 |
2021 | +######## |
2022 | + |
2023 | +:Released: 2007-01-23 |
2024 | |
2025 | Improvements |
2026 | ************ |
2027 | @@ -7891,8 +8575,10 @@ |
2028 | it is in is below a repository. (James Westby, #77306) |
2029 | |
2030 | |
2031 | -bzr 0.14rc1 2007-01-16 |
2032 | -####################### |
2033 | +bzr 0.14rc1 |
2034 | +########### |
2035 | + |
2036 | +:Released: 2007-01-16 |
2037 | |
2038 | Improvements |
2039 | ************ |
2040 | @@ -8026,14 +8712,18 @@ |
2041 | (Alexander Belchenko, #68124) |
2042 | |
2043 | |
2044 | -bzr 0.13 2006-12-05 |
2045 | -#################### |
2046 | +bzr 0.13 |
2047 | +######## |
2048 | + |
2049 | +:Released: 2006-12-05 |
2050 | |
2051 | No changes from 0.13rc |
2052 | |
2053 | |
2054 | -bzr 0.13rc1 2006-11-27 |
2055 | -####################### |
2056 | +bzr 0.13rc1 |
2057 | +########### |
2058 | + |
2059 | +:Released: 2006-11-27 |
2060 | |
2061 | Improvements |
2062 | ************ |
2063 | @@ -8158,8 +8848,10 @@ |
2064 | * TestingHTTPRequestHandler really handles the Range header |
2065 | (previously it was ignoring it and returning the whole file,). |
2066 | |
2067 | -bzr 0.12 2006-10-30 |
2068 | -#################### |
2069 | +bzr 0.12 |
2070 | +######## |
2071 | + |
2072 | +:Released: 2006-10-30 |
2073 | |
2074 | Internals |
2075 | ********* |
2076 | @@ -8168,8 +8860,10 @@ |
2077 | and remove benchmarks that take longer than 10min to run. |
2078 | (John Arbash Meinel) |
2079 | |
2080 | -bzr 0.12rc1 2006-10-23 |
2081 | -####################### |
2082 | +bzr 0.12rc1 |
2083 | +########### |
2084 | + |
2085 | +:Released: 2006-10-23 |
2086 | |
2087 | Improvements |
2088 | ************ |
2089 | @@ -8290,13 +8984,17 @@ |
2090 | option to set the BzrDir, Repository and Branch formats of the |
2091 | created objects. (Robert Collins, John Arbash Meinel) |
2092 | |
2093 | -bzr 0.11 2006-10-02 |
2094 | -#################### |
2095 | +bzr 0.11 |
2096 | +######## |
2097 | + |
2098 | +:Released: 2006-10-02 |
2099 | |
2100 | * Smart server transport test failures on windows fixed. (Lukáš Lalinský). |
2101 | |
2102 | -bzr 0.11rc2 2006-09-27 |
2103 | -####################### |
2104 | +bzr 0.11rc2 |
2105 | +########### |
2106 | + |
2107 | +:Released: 2006-09-27 |
2108 | |
2109 | Bug Fixes |
2110 | ********* |
2111 | @@ -8306,8 +9004,10 @@ |
2112 | * Commit performance regression fixed. (Aaron Bentley, Robert Collins, John |
2113 | Arbash Meinel). |
2114 | |
2115 | -bzr 0.11rc1 2006-09-25 |
2116 | -####################### |
2117 | +bzr 0.11rc1 |
2118 | +########### |
2119 | + |
2120 | +:Released: 2006-09-25 |
2121 | |
2122 | Improvements |
2123 | ************ |
2124 | @@ -8500,8 +9200,10 @@ |
2125 | allow upgrades to a richer interface than the VFS one provided by |
2126 | Transport. (Andrew Bennetts, Martin Pool) |
2127 | |
2128 | -bzr 0.10 2006-08-29 |
2129 | -#################### |
2130 | +bzr 0.10 |
2131 | +######## |
2132 | + |
2133 | +:Released: 2006-08-29 |
2134 | |
2135 | Improvements |
2136 | ************ |
2137 | @@ -8578,8 +9280,10 @@ |
2138 | need to be installed. This should help make the life of packagers |
2139 | easier. (John Arbash Meinel) |
2140 | |
2141 | -bzr 0.9.0 2006-08-11 |
2142 | -##################### |
2143 | +bzr 0.9.0 |
2144 | +######### |
2145 | + |
2146 | +:Released: 2006-08-11 |
2147 | |
2148 | Surprises |
2149 | ********* |
2150 | @@ -8846,16 +9550,20 @@ |
2151 | |
2152 | * "RevisionTree" is now in bzrlib/revisiontree.py. (Robert Collins) |
2153 | |
2154 | -bzr 0.8.2 2006-05-17 |
2155 | -##################### |
2156 | +bzr 0.8.2 |
2157 | +######### |
2158 | + |
2159 | +:Released: 2006-05-17 |
2160 | |
2161 | Bug Fixes |
2162 | ********* |
2163 | |
2164 | * setup.py failed to install launchpad plugin. (Martin Pool) |
2165 | |
2166 | -bzr 0.8.1 2006-05-16 |
2167 | -##################### |
2168 | +bzr 0.8.1 |
2169 | +######### |
2170 | + |
2171 | +:Released: 2006-05-16 |
2172 | |
2173 | Bug Fixes |
2174 | ********* |
2175 | @@ -8908,8 +9616,10 @@ |
2176 | * Fix test case for bzr info in upgrading a standalone branch to metadir, |
2177 | uses bzrlib api now. (Olaf Conradi) |
2178 | |
2179 | -bzr 0.8 2006-05-08 |
2180 | -################### |
2181 | +bzr 0.8 |
2182 | +####### |
2183 | + |
2184 | +:Released: 2006-05-08 |
2185 | |
2186 | Notes When Upgrading |
2187 | ******************** |
2188 | @@ -9170,8 +9880,10 @@ |
2189 | * ``run_bzr`` and ``run_bzr_captured`` now accept a 'stdin="foo"' |
2190 | parameter which will provide String("foo") to the command as its stdin. |
2191 | |
2192 | -bzr 0.7 2006-01-09 |
2193 | -################## |
2194 | +bzr 0.7 |
2195 | +####### |
2196 | + |
2197 | +:Released: 2006-01-09 |
2198 | |
2199 | Changes |
2200 | ******* |
2201 | @@ -9466,8 +10178,10 @@ |
2202 | * ``bzrlib.osutils.safe_unicode`` now exists to provide parameter coercion |
2203 | for functions that need unicode strings. (Robert Collins) |
2204 | |
2205 | -bzr 0.6 2005-10-28 |
2206 | -################## |
2207 | +bzr 0.6 |
2208 | +####### |
2209 | + |
2210 | +:Released: 2005-10-28 |
2211 | |
2212 | Improvements |
2213 | ************ |
2214 | @@ -9682,8 +10396,10 @@ |
2215 | [-1] in the revision-history. (Andres Salomon) |
2216 | |
2217 | |
2218 | -bzr 0.1.1 2005-10-12 |
2219 | -#################### |
2220 | +bzr 0.1.1 |
2221 | +######### |
2222 | + |
2223 | +:Released: 2005-10-12 |
2224 | |
2225 | Bug Fixes |
2226 | ********* |
2227 | @@ -9700,8 +10416,10 @@ |
2228 | * Avoid some unnecessary http operations in branch and pull. |
2229 | |
2230 | |
2231 | -bzr 0.1 2005-10-11 |
2232 | -################## |
2233 | +bzr 0.1 |
2234 | +####### |
2235 | + |
2236 | +:Released: 2005-10-11 |
2237 | |
2238 | Notes |
2239 | ***** |
2240 | @@ -9830,8 +10548,10 @@ |
2241 | of tests to run, e.g. ``bzr selftest test_weave`` |
2242 | |
2243 | |
2244 | -bzr 0.0.9 2005-09-23 |
2245 | -#################### |
2246 | +bzr 0.0.9 |
2247 | +######### |
2248 | + |
2249 | +:Released: 2005-09-23 |
2250 | |
2251 | Bug Fixes |
2252 | ********* |
2253 | @@ -9872,8 +10592,11 @@ |
2254 | another (used by pull, merged, etc.) |
2255 | |
2256 | |
2257 | -bzr 0.0.8 2005-09-20 |
2258 | -#################### |
2259 | +bzr 0.0.8 |
2260 | +######### |
2261 | + |
2262 | +:Released: 2005-09-20 |
2263 | + |
2264 | |
2265 | Improvements |
2266 | ************ |
2267 | @@ -9923,8 +10646,10 @@ |
2268 | * Quieten warnings about locking; patch from Matt Lavin. |
2269 | |
2270 | |
2271 | -bzr-0.0.7 2005-09-02 |
2272 | -#################### |
2273 | +bzr-0.0.7 |
2274 | +######### |
2275 | + |
2276 | +:Released: 2005-09-02 |
2277 | |
2278 | New Features |
2279 | ************ |
2280 | @@ -9978,8 +10703,10 @@ |
2281 | |
2282 | |
2283 | |
2284 | -bzr-0.0.6 2005-08-18 |
2285 | -#################### |
2286 | +bzr-0.0.6 |
2287 | +######### |
2288 | + |
2289 | +:Released: 2005-08-18 |
2290 | |
2291 | New Features |
2292 | ************ |
2293 | @@ -10064,8 +10791,10 @@ |
2294 | * Fix bugs in committing only selected files or within a subdirectory. |
2295 | |
2296 | |
2297 | -bzr-0.0.5 2005-06-15 |
2298 | -##################### |
2299 | +bzr-0.0.5 |
2300 | +######### |
2301 | + |
2302 | +:Released: 2005-06-15 |
2303 | |
2304 | Changes |
2305 | ******* |
2306 | @@ -10206,8 +10935,10 @@ |
2307 | 2.4 is now only recommended. |
2308 | |
2309 | |
2310 | -bzr-0.0.4 2005-04-22 |
2311 | -##################### |
2312 | +bzr-0.0.4 |
2313 | +######### |
2314 | + |
2315 | +:Released: 2005-04-22 |
2316 | |
2317 | Enhancements |
2318 | ************ |
2319 | @@ -10275,8 +11006,10 @@ |
2320 | from QuantumG. |
2321 | |
2322 | |
2323 | -bzr-0.0.3 2005-04-06 |
2324 | -##################### |
2325 | +bzr-0.0.3 |
2326 | +######### |
2327 | + |
2328 | +:Released: 2005-04-06 |
2329 | |
2330 | Enhancements |
2331 | ************ |
2332 | @@ -10330,8 +11063,11 @@ |
2333 | * Win32 fixes from Steve Brown. |
2334 | |
2335 | |
2336 | -bzr-0.0.2 "black cube" 2005-03-31 |
2337 | -################################### |
2338 | +bzr-0.0.2 |
2339 | +######### |
2340 | + |
2341 | +:Codename: "black cube" |
2342 | +:Released: 2005-03-31 |
2343 | |
2344 | Enhancements |
2345 | ************ |
2346 | @@ -10359,8 +11095,10 @@ |
2347 | the root directory only. |
2348 | |
2349 | |
2350 | -bzr-0.0.1 2005-03-26 |
2351 | -##################### |
2352 | +bzr-0.0.1 |
2353 | +######### |
2354 | + |
2355 | +:Released: 2005-03-26 |
2356 | |
2357 | Enhancements |
2358 | ************ |
2359 | @@ -10389,8 +11127,10 @@ |
2360 | supported). |
2361 | |
2362 | |
2363 | -bzr-0.0.0.69 2005-03-22 |
2364 | -######################## |
2365 | +bzr-0.0.0.69 |
2366 | +############ |
2367 | + |
2368 | +:Released: 2005-03-22 |
2369 | |
2370 | Enhancements |
2371 | ************ |
2372 | @@ -10400,5 +11140,38 @@ |
2373 | * Storage of local versions: init, add, remove, rm, info, log, |
2374 | diff, status, etc. |
2375 | |
2376 | + |
2377 | +bzr ?.?.? (not released yet) |
2378 | +############################ |
2379 | + |
2380 | +:Codename: template |
2381 | +:2.0.2: ??? |
2382 | + |
2383 | +Compatibility Breaks |
2384 | +******************** |
2385 | + |
2386 | +New Features |
2387 | +************ |
2388 | + |
2389 | +Bug Fixes |
2390 | +********* |
2391 | + |
2392 | +Improvements |
2393 | +************ |
2394 | + |
2395 | +Documentation |
2396 | +************* |
2397 | + |
2398 | +API Changes |
2399 | +*********** |
2400 | + |
2401 | +Internals |
2402 | +********* |
2403 | + |
2404 | +Testing |
2405 | +******* |
2406 | + |
2407 | + |
2408 | + |
2409 | .. |
2410 | vim: tw=74 ft=rst ff=unix |
2411 | |
2412 | === modified file 'README' |
2413 | --- README 2008-03-16 14:01:20 +0000 |
2414 | +++ README 2009-11-03 09:40:55 +0000 |
2415 | @@ -3,72 +3,44 @@ |
2416 | ================= |
2417 | |
2418 | Bazaar (``bzr``) is a decentralized revision control system, designed to be |
2419 | -easy for developers and end users alike. Bazaar is part of the GNU project to |
2420 | -develop a complete free operating system. |
2421 | - |
2422 | -To install Bazaar from source, follow the instructions in the INSTALL |
2423 | -file. Otherwise, you may want to check your distribution package manager |
2424 | -for ready-to-install packages, or http://bazaar-vcs.org/DistroDownloads. |
2425 | - |
2426 | -To learn how to use Bazaar, check the documentation in the doc/ directory. |
2427 | -Once installed, you can also run 'bzr help'. An always up-to-date and more |
2428 | -complete set of documents can be found in the Bazaar website, at: |
2429 | - |
2430 | - http://bazaar-vcs.org/Documentation |
2431 | +easy for developers and end users alike. Bazaar is part of the GNU project |
2432 | +to develop a complete free operating system. |
2433 | + |
2434 | +To install Bazaar, follow the instructions given at |
2435 | +http://bazaar-vcs.org/Download. Ready-to-install packages are available |
2436 | +for most popular operating systems or you can install from source. |
2437 | + |
2438 | +To learn how to use Bazaar, see the official documentation at: |
2439 | + |
2440 | + http://doc.bazaar-vcs.org/en/ |
2441 | + |
2442 | +For additional training materials including screencasts and slides, |
2443 | +visit our community wiki documentation page at: |
2444 | + |
2445 | + http://bazaar-vcs.org/Documentation/ |
2446 | |
2447 | Bazaar is written in Python, and is sponsored by Canonical Limited, the |
2448 | founders of Ubuntu and Launchpad. Bazaar is Free Software, and is released |
2449 | under the GNU General Public License. |
2450 | |
2451 | -Bazaar was formerly known as Bazaar-NG. It's the successor to ``baz``, a fork |
2452 | -of GNU arch, but shares no code. (To upgrade from Baz, use the ``baz-import`` |
2453 | -command in the bzrtools plugin.) |
2454 | - |
2455 | Bazaar highlights |
2456 | ================= |
2457 | |
2458 | -* Easy to use and intuitive. |
2459 | - |
2460 | - Only five commands are needed to do all basic operations, and all |
2461 | - commands have documentation accessible via 'bzr help command'. |
2462 | - Bazaar's interface is also easy to learn for CVS and Subversion users. |
2463 | - |
2464 | -* Robust and reliable. |
2465 | - |
2466 | - Bazaar is developed under an extensive test suite. Branches can be |
2467 | - checked and verified for integrity at any time, and revisions can be |
2468 | - signed with PGP/GnuPG. |
2469 | - |
2470 | -* Publish branches with HTTP. |
2471 | - |
2472 | - Branches can be hosted on an HTTP server with no need for special |
2473 | - software on the server side. Branches can be uploaded by bzr itself |
2474 | - over SSH (SFTP), or with rsync. |
2475 | - |
2476 | -* Adapts to multiple environments. |
2477 | - |
2478 | - Bazaar runs on Linux and Windows, fully supports Unicode filenames, |
2479 | - and suits different development models, including centralized. |
2480 | - |
2481 | -* Easily extended and customized. |
2482 | - |
2483 | - A rich Python interface is provided for extending and embedding, |
2484 | - including a plugin interface. There are already many available plugins, |
2485 | - most of them registered at http://bazaar-vcs.org/PluginRegistry. |
2486 | - |
2487 | -* Smart merging. |
2488 | - |
2489 | - Changes will never be merged more than once, conflicts will be |
2490 | - minimized, and identical changes are dealt with well. |
2491 | - |
2492 | -* Vibrant and active community. |
2493 | - |
2494 | - Help with Bazaar is obtained easily, via the mailing list, or the IRC |
2495 | - channel. |
2496 | - |
2497 | - |
2498 | -Registration and Feedback |
2499 | -========================= |
2500 | +Bazaar directly supports both central version control (like cvs/svn) and |
2501 | +distributed version control (like git/hg). Developers can organize their |
2502 | +workspace in whichever way they want on a per project basis including: |
2503 | + |
2504 | +* checkouts (like svn) |
2505 | +* feature branches (like hg) |
2506 | +* shared working tree (like git). |
2507 | + |
2508 | +It also directly supports and encourages a large number of development best |
2509 | +practices like refactoring and pre-commit regression testing. Users can |
2510 | +choose between our command line tool and our cross-platform GUI application. |
2511 | +For further details, see our website at http://bazaar-vcs.org/en. |
2512 | + |
2513 | +Feedback |
2514 | +======== |
2515 | |
2516 | If you encounter any problems with Bazaar, need help understanding it, or would |
2517 | like to offer suggestions or feedback, please get in touch with us: |
2518 | @@ -76,7 +48,7 @@ |
2519 | * Ask a question through our web support interface, at |
2520 | https://answers.launchpad.net/bzr/ |
2521 | |
2522 | -* Report bugs at https://bugs.edge.launchpad.net/bzr/+filebug |
2523 | +* Report bugs at https://bugs.launchpad.net/bzr/+filebug |
2524 | |
2525 | * Write to us at bazaar@lists.canonical.com |
2526 | You can join the list at <https://lists.ubuntu.com/mailman/listinfo/bazaar>. |
2527 | @@ -85,12 +57,8 @@ |
2528 | |
2529 | * Talk to us in irc://irc.ubuntu.com/bzr |
2530 | |
2531 | -* And see http://bazaar-vcs.org/BzrSupport for more. |
2532 | - |
2533 | -If you would like to help us improve Bazaar by telling us about yourself and |
2534 | -what we could do better, please register and complete the online survey here: |
2535 | -http://www.surveymonkey.com/s.aspx?sm=L94RvLswhKdktrxiHWiX3g_3d_3d. |
2536 | -Registration is completely optional. |
2537 | - |
2538 | -Enjoy, |
2539 | +Our mission is to make a version control tool that developers LOVE to use |
2540 | +and that casual contributors feel confident with. Please let us know how |
2541 | +we're going. |
2542 | + |
2543 | The Bazaar Team |
2544 | |
2545 | === modified file 'bzrlib/__init__.py' |
2546 | --- bzrlib/__init__.py 2009-08-30 21:34:42 +0000 |
2547 | +++ bzrlib/__init__.py 2009-11-03 09:40:55 +0000 |
2548 | @@ -31,16 +31,10 @@ |
2549 | import bzrlib.lazy_regex |
2550 | bzrlib.lazy_regex.install_lazy_compile() |
2551 | |
2552 | -from bzrlib.osutils import get_user_encoding |
2553 | - |
2554 | |
2555 | IGNORE_FILENAME = ".bzrignore" |
2556 | |
2557 | |
2558 | -# XXX: Deprecated as of bzr-1.17 use osutils.get_user_encoding() directly |
2559 | -user_encoding = get_user_encoding() |
2560 | - |
2561 | - |
2562 | __copyright__ = "Copyright 2005, 2006, 2007, 2008, 2009 Canonical Ltd." |
2563 | |
2564 | # same format as sys.version_info: "A tuple containing the five components of |
2565 | @@ -50,10 +44,11 @@ |
2566 | # Python version 2.0 is (2, 0, 0, 'final', 0)." Additionally we use a |
2567 | # releaselevel of 'dev' for unreleased under-development code. |
2568 | |
2569 | -version_info = (2, 1, 0, 'dev', 0) |
2570 | +version_info = (2, 1, 0, 'dev', 3) |
2571 | |
2572 | # API compatibility version: bzrlib is currently API compatible with 1.15. |
2573 | -api_minimum_version = (1, 17, 0) |
2574 | +api_minimum_version = (2, 1, 0) |
2575 | + |
2576 | |
2577 | def _format_version_tuple(version_info): |
2578 | """Turn a version number 2, 3 or 5-tuple into a short string. |
2579 | @@ -65,23 +60,29 @@ |
2580 | zero for final releases. |
2581 | |
2582 | >>> print _format_version_tuple((1, 0, 0, 'final', 0)) |
2583 | - 1.0 |
2584 | + 1.0.0 |
2585 | >>> print _format_version_tuple((1, 2, 0, 'dev', 0)) |
2586 | - 1.2dev |
2587 | + 1.2.0dev |
2588 | + >>> print bzrlib._format_version_tuple((1, 2, 0, 'dev', 1)) |
2589 | + 1.2.0dev1 |
2590 | >>> print _format_version_tuple((1, 1, 1, 'candidate', 2)) |
2591 | 1.1.1rc2 |
2592 | >>> print bzrlib._format_version_tuple((2, 1, 0, 'beta', 1)) |
2593 | - 2.1b1 |
2594 | + 2.1.0b1 |
2595 | >>> print _format_version_tuple((1, 4, 0)) |
2596 | - 1.4 |
2597 | + 1.4.0 |
2598 | >>> print _format_version_tuple((1, 4)) |
2599 | 1.4 |
2600 | + >>> print bzrlib._format_version_tuple((2, 1, 0, 'final', 1)) |
2601 | + Traceback (most recent call last): |
2602 | + ... |
2603 | + ValueError: version_info (2, 1, 0, 'final', 1) not valid |
2604 | >>> print _format_version_tuple((1, 4, 0, 'wibble', 0)) |
2605 | Traceback (most recent call last): |
2606 | ... |
2607 | ValueError: version_info (1, 4, 0, 'wibble', 0) not valid |
2608 | """ |
2609 | - if len(version_info) == 2 or version_info[2] == 0: |
2610 | + if len(version_info) == 2: |
2611 | main_version = '%d.%d' % version_info[:2] |
2612 | else: |
2613 | main_version = '%d.%d.%d' % version_info[:3] |
2614 | @@ -96,6 +97,8 @@ |
2615 | sub_string = '' |
2616 | elif release_type == 'dev' and sub == 0: |
2617 | sub_string = 'dev' |
2618 | + elif release_type == 'dev': |
2619 | + sub_string = 'dev' + str(sub) |
2620 | elif release_type in ('alpha', 'beta'): |
2621 | sub_string = release_type[0] + str(sub) |
2622 | elif release_type == 'candidate': |
2623 | @@ -103,7 +106,6 @@ |
2624 | else: |
2625 | raise ValueError("version_info %r not valid" % (version_info,)) |
2626 | |
2627 | - version_string = '%d.%d.%d.%s.%d' % tuple(version_info) |
2628 | return main_version + sub_string |
2629 | |
2630 | |
2631 | |
2632 | === modified file 'bzrlib/_bencode_pyx.pyx' |
2633 | --- bzrlib/_bencode_pyx.pyx 2009-06-05 01:48:32 +0000 |
2634 | +++ bzrlib/_bencode_pyx.pyx 2009-11-03 09:40:55 +0000 |
2635 | @@ -58,6 +58,13 @@ |
2636 | void D_UPDATE_TAIL(Decoder, int n) |
2637 | void E_UPDATE_TAIL(Encoder, int n) |
2638 | |
2639 | +# To maintain compatibility with older versions of pyrex, we have to use the |
2640 | +# relative import here, rather than 'bzrlib._static_tuple_c' |
2641 | +from _static_tuple_c cimport StaticTuple, StaticTuple_CheckExact, \ |
2642 | + import_static_tuple_c |
2643 | + |
2644 | +import_static_tuple_c() |
2645 | + |
2646 | |
2647 | cdef class Decoder: |
2648 | """Bencode decoder""" |
2649 | @@ -371,7 +378,8 @@ |
2650 | self._encode_int(x) |
2651 | elif PyLong_CheckExact(x): |
2652 | self._encode_long(x) |
2653 | - elif PyList_CheckExact(x) or PyTuple_CheckExact(x): |
2654 | + elif (PyList_CheckExact(x) or PyTuple_CheckExact(x) |
2655 | + or StaticTuple_CheckExact(x)): |
2656 | self._encode_list(x) |
2657 | elif PyDict_CheckExact(x): |
2658 | self._encode_dict(x) |
2659 | |
2660 | === modified file 'bzrlib/_btree_serializer_pyx.pyx' |
2661 | --- bzrlib/_btree_serializer_pyx.pyx 2009-06-22 12:52:39 +0000 |
2662 | +++ bzrlib/_btree_serializer_pyx.pyx 2009-11-03 09:40:55 +0000 |
2663 | @@ -1,4 +1,4 @@ |
2664 | -# Copyright (C) 2008 Canonical Ltd |
2665 | +# Copyright (C) 2008, 2009 Canonical Ltd |
2666 | # |
2667 | # This program is free software; you can redistribute it and/or modify |
2668 | # it under the terms of the GNU General Public License as published by |
2669 | @@ -38,11 +38,16 @@ |
2670 | Py_ssize_t PyString_Size(object p) |
2671 | Py_ssize_t PyString_GET_SIZE_ptr "PyString_GET_SIZE" (PyObject *) |
2672 | char * PyString_AS_STRING_ptr "PyString_AS_STRING" (PyObject *) |
2673 | + char * PyString_AS_STRING(object) |
2674 | + Py_ssize_t PyString_GET_SIZE(object) |
2675 | int PyString_AsStringAndSize_ptr(PyObject *, char **buf, Py_ssize_t *len) |
2676 | void PyString_InternInPlace(PyObject **) |
2677 | int PyTuple_CheckExact(object t) |
2678 | + object PyTuple_New(Py_ssize_t n_entries) |
2679 | + void PyTuple_SET_ITEM(object, Py_ssize_t offset, object) # steals the ref |
2680 | Py_ssize_t PyTuple_GET_SIZE(object t) |
2681 | PyObject *PyTuple_GET_ITEM_ptr_object "PyTuple_GET_ITEM" (object tpl, int index) |
2682 | + void Py_INCREF(object) |
2683 | void Py_DECREF_ptr "Py_DECREF" (PyObject *) |
2684 | |
2685 | cdef extern from "string.h": |
2686 | @@ -52,6 +57,12 @@ |
2687 | # void *memrchr(void *s, int c, size_t n) |
2688 | int strncmp(char *s1, char *s2, size_t n) |
2689 | |
2690 | +# It seems we need to import the definitions so that the pyrex compiler has |
2691 | +# local names to access them. |
2692 | +from _static_tuple_c cimport StaticTuple, \ |
2693 | + import_static_tuple_c, StaticTuple_New, \ |
2694 | + StaticTuple_Intern, StaticTuple_SET_ITEM, StaticTuple_CheckExact |
2695 | + |
2696 | |
2697 | # TODO: Find some way to import this from _dirstate_helpers |
2698 | cdef void* _my_memrchr(void *s, int c, size_t n): |
2699 | @@ -68,6 +79,7 @@ |
2700 | pos = pos - 1 |
2701 | return NULL |
2702 | |
2703 | + |
2704 | # TODO: Import this from _dirstate_helpers when it is merged |
2705 | cdef object safe_string_from_size(char *s, Py_ssize_t size): |
2706 | if size < 0: |
2707 | @@ -91,6 +103,10 @@ |
2708 | Py_DECREF_ptr(py_str) |
2709 | return result |
2710 | |
2711 | +from bzrlib import _static_tuple_c |
2712 | +# This sets up the StaticTuple C_API functionality |
2713 | +import_static_tuple_c() |
2714 | + |
2715 | |
2716 | cdef class BTreeLeafParser: |
2717 | """Parse the leaf nodes of a BTree index. |
2718 | @@ -130,6 +146,7 @@ |
2719 | self._cur_str = NULL |
2720 | self._end_str = NULL |
2721 | self._header_found = 0 |
2722 | + # keys are tuples |
2723 | |
2724 | cdef extract_key(self, char * last): |
2725 | """Extract a key. |
2726 | @@ -139,15 +156,14 @@ |
2727 | """ |
2728 | cdef char *temp_ptr |
2729 | cdef int loop_counter |
2730 | - # keys are tuples |
2731 | - loop_counter = 0 |
2732 | - key_segments = [] |
2733 | - while loop_counter < self.key_length: |
2734 | - loop_counter = loop_counter + 1 |
2735 | + cdef StaticTuple key |
2736 | + |
2737 | + key = StaticTuple_New(self.key_length) |
2738 | + for loop_counter from 0 <= loop_counter < self.key_length: |
2739 | # grab a key segment |
2740 | temp_ptr = <char*>memchr(self._start, c'\0', last - self._start) |
2741 | if temp_ptr == NULL: |
2742 | - if loop_counter == self.key_length: |
2743 | + if loop_counter + 1 == self.key_length: |
2744 | # capture to last |
2745 | temp_ptr = last |
2746 | else: |
2747 | @@ -157,15 +173,20 @@ |
2748 | last - self._start))) |
2749 | raise AssertionError(failure_string) |
2750 | # capture the key string |
2751 | - # TODO: Consider using PyIntern_FromString, the only caveat is that |
2752 | - # it assumes a NULL-terminated string, so we have to check if |
2753 | - # temp_ptr[0] == c'\0' or some other char. |
2754 | - key_element = safe_interned_string_from_size(self._start, |
2755 | + if (self.key_length == 1 |
2756 | + and (temp_ptr - self._start) == 45 |
2757 | + and strncmp(self._start, 'sha1:', 5) == 0): |
2758 | + key_element = safe_string_from_size(self._start, |
2759 | + temp_ptr - self._start) |
2760 | + else: |
2761 | + key_element = safe_interned_string_from_size(self._start, |
2762 | temp_ptr - self._start) |
2763 | # advance our pointer |
2764 | self._start = temp_ptr + 1 |
2765 | - PyList_Append(key_segments, key_element) |
2766 | - return tuple(key_segments) |
2767 | + Py_INCREF(key_element) |
2768 | + StaticTuple_SET_ITEM(key, loop_counter, key_element) |
2769 | + key = StaticTuple_Intern(key) |
2770 | + return key |
2771 | |
2772 | cdef int process_line(self) except -1: |
2773 | """Process a line in the bytes.""" |
2774 | @@ -174,6 +195,7 @@ |
2775 | cdef char *ref_ptr |
2776 | cdef char *next_start |
2777 | cdef int loop_counter |
2778 | + cdef Py_ssize_t str_len |
2779 | |
2780 | self._start = self._cur_str |
2781 | # Find the next newline |
2782 | @@ -186,14 +208,13 @@ |
2783 | # And the next string is right after it |
2784 | self._cur_str = last + 1 |
2785 | # The last character is right before the '\n' |
2786 | - last = last |
2787 | |
2788 | if last == self._start: |
2789 | # parsed it all. |
2790 | return 0 |
2791 | if last < self._start: |
2792 | # Unexpected error condition - fail |
2793 | - return -1 |
2794 | + raise AssertionError("last < self._start") |
2795 | if 0 == self._header_found: |
2796 | # The first line in a leaf node is the header "type=leaf\n" |
2797 | if strncmp("type=leaf", self._start, last - self._start) == 0: |
2798 | @@ -202,36 +223,48 @@ |
2799 | else: |
2800 | raise AssertionError('Node did not start with "type=leaf": %r' |
2801 | % (safe_string_from_size(self._start, last - self._start))) |
2802 | - return -1 |
2803 | |
2804 | key = self.extract_key(last) |
2805 | # find the value area |
2806 | temp_ptr = <char*>_my_memrchr(self._start, c'\0', last - self._start) |
2807 | if temp_ptr == NULL: |
2808 | # Invalid line |
2809 | - return -1 |
2810 | + raise AssertionError("Failed to find the value area") |
2811 | else: |
2812 | - # capture the value string |
2813 | - value = safe_string_from_size(temp_ptr + 1, last - temp_ptr - 1) |
2814 | + # Because of how conversions were done, we ended up with *lots* of |
2815 | + # values that are identical. These are all of the 0-length nodes |
2816 | + # that are referred to by the TREE_ROOT (and likely some other |
2817 | + # directory nodes.) For example, bzr has 25k references to |
2818 | + # something like '12607215 328306 0 0', which ends up consuming 1MB |
2819 | + # of memory, just for those strings. |
2820 | + str_len = last - temp_ptr - 1 |
2821 | + if (str_len > 4 |
2822 | + and strncmp(" 0 0", last - 4, 4) == 0): |
2823 | + # This drops peak mem for bzr.dev from 87.4MB => 86.2MB |
2824 | + # For Launchpad 236MB => 232MB |
2825 | + value = safe_interned_string_from_size(temp_ptr + 1, str_len) |
2826 | + else: |
2827 | + value = safe_string_from_size(temp_ptr + 1, str_len) |
2828 | # shrink the references end point |
2829 | last = temp_ptr |
2830 | + |
2831 | if self.ref_list_length: |
2832 | - ref_lists = [] |
2833 | + ref_lists = StaticTuple_New(self.ref_list_length) |
2834 | loop_counter = 0 |
2835 | while loop_counter < self.ref_list_length: |
2836 | ref_list = [] |
2837 | # extract a reference list |
2838 | loop_counter = loop_counter + 1 |
2839 | if last < self._start: |
2840 | - return -1 |
2841 | + raise AssertionError("last < self._start") |
2842 | # find the next reference list end point: |
2843 | temp_ptr = <char*>memchr(self._start, c'\t', last - self._start) |
2844 | if temp_ptr == NULL: |
2845 | # Only valid for the last list |
2846 | if loop_counter != self.ref_list_length: |
2847 | # Invalid line |
2848 | - return -1 |
2849 | - raise AssertionError("invalid key") |
2850 | + raise AssertionError( |
2851 | + "invalid key, loop_counter != self.ref_list_length") |
2852 | else: |
2853 | # scan to the end of the ref list area |
2854 | ref_ptr = last |
2855 | @@ -248,18 +281,20 @@ |
2856 | if temp_ptr == NULL: |
2857 | # key runs to the end |
2858 | temp_ptr = ref_ptr |
2859 | + |
2860 | PyList_Append(ref_list, self.extract_key(temp_ptr)) |
2861 | - PyList_Append(ref_lists, tuple(ref_list)) |
2862 | + ref_list = StaticTuple_Intern(StaticTuple(*ref_list)) |
2863 | + Py_INCREF(ref_list) |
2864 | + StaticTuple_SET_ITEM(ref_lists, loop_counter - 1, ref_list) |
2865 | # prepare for the next reference list |
2866 | self._start = next_start |
2867 | - ref_lists = tuple(ref_lists) |
2868 | - node_value = (value, ref_lists) |
2869 | + node_value = StaticTuple(value, ref_lists) |
2870 | else: |
2871 | if last != self._start: |
2872 | # unexpected reference data present |
2873 | - return -1 |
2874 | - node_value = (value, ()) |
2875 | - PyList_Append(self.keys, (key, node_value)) |
2876 | + raise AssertionError("unexpected reference data present") |
2877 | + node_value = StaticTuple(value, StaticTuple()) |
2878 | + PyList_Append(self.keys, StaticTuple(key, node_value)) |
2879 | return 0 |
2880 | |
2881 | def parse(self): |
2882 | @@ -294,7 +329,6 @@ |
2883 | cdef Py_ssize_t flat_len |
2884 | cdef Py_ssize_t key_len |
2885 | cdef Py_ssize_t node_len |
2886 | - cdef PyObject * val |
2887 | cdef char * value |
2888 | cdef Py_ssize_t value_len |
2889 | cdef char * out |
2890 | @@ -303,13 +337,12 @@ |
2891 | cdef int first_ref_list |
2892 | cdef int first_reference |
2893 | cdef int i |
2894 | - cdef PyObject *ref_bit |
2895 | cdef Py_ssize_t ref_bit_len |
2896 | |
2897 | - if not PyTuple_CheckExact(node): |
2898 | - raise TypeError('We expected a tuple() for node not: %s' |
2899 | + if not PyTuple_CheckExact(node) and not StaticTuple_CheckExact(node): |
2900 | + raise TypeError('We expected a tuple() or StaticTuple() for node not: %s' |
2901 | % type(node)) |
2902 | - node_len = PyTuple_GET_SIZE(node) |
2903 | + node_len = len(node) |
2904 | have_reference_lists = reference_lists |
2905 | if have_reference_lists: |
2906 | if node_len != 4: |
2907 | @@ -318,8 +351,17 @@ |
2908 | elif node_len < 3: |
2909 | raise ValueError('Without ref_lists, we need at least 3 entries not: %s' |
2910 | % len(node)) |
2911 | - # I don't expect that we can do faster than string.join() |
2912 | - string_key = '\0'.join(<object>PyTuple_GET_ITEM_ptr_object(node, 1)) |
2913 | + # TODO: We can probably do better than string.join(), namely |
2914 | + # when key has only 1 item, we can just grab that string |
2915 | + # And when there are 2 items, we could do a single malloc + len() + 1 |
2916 | + # also, doing .join() requires a PyObject_GetAttrString call, which |
2917 | + # we could also avoid. |
2918 | + # TODO: Note that pyrex 0.9.6 generates fairly crummy code here, using the |
2919 | + # python object interface, versus 0.9.8+ which uses a helper that |
2920 | + # checks if this supports the sequence interface. |
2921 | + # We *could* do more work on our own, and grab the actual items |
2922 | + # lists. For now, just ask people to use a better compiler. :) |
2923 | + string_key = '\0'.join(node[1]) |
2924 | |
2925 | # TODO: instead of using string joins, precompute the final string length, |
2926 | # and then malloc a single string and copy everything in. |
2927 | @@ -336,7 +378,7 @@ |
2928 | refs_len = 0 |
2929 | if have_reference_lists: |
2930 | # Figure out how many bytes it will take to store the references |
2931 | - ref_lists = <object>PyTuple_GET_ITEM_ptr_object(node, 3) |
2932 | + ref_lists = node[3] |
2933 | next_len = len(ref_lists) # TODO: use a Py function |
2934 | if next_len > 0: |
2935 | # If there are no nodes, we don't need to do any work |
2936 | @@ -350,31 +392,31 @@ |
2937 | # references |
2938 | refs_len = refs_len + (next_len - 1) |
2939 | for reference in ref_list: |
2940 | - if not PyTuple_CheckExact(reference): |
2941 | + if (not PyTuple_CheckExact(reference) |
2942 | + and not StaticTuple_CheckExact(reference)): |
2943 | raise TypeError( |
2944 | 'We expect references to be tuples not: %s' |
2945 | % type(reference)) |
2946 | - next_len = PyTuple_GET_SIZE(reference) |
2947 | + next_len = len(reference) |
2948 | if next_len > 0: |
2949 | # We will need (len - 1) '\x00' characters to |
2950 | # separate the reference key |
2951 | refs_len = refs_len + (next_len - 1) |
2952 | - for i from 0 <= i < next_len: |
2953 | - ref_bit = PyTuple_GET_ITEM_ptr_object(reference, i) |
2954 | - if not PyString_CheckExact_ptr(ref_bit): |
2955 | + for ref_bit in reference: |
2956 | + if not PyString_CheckExact(ref_bit): |
2957 | raise TypeError('We expect reference bits' |
2958 | ' to be strings not: %s' |
2959 | % type(<object>ref_bit)) |
2960 | - refs_len = refs_len + PyString_GET_SIZE_ptr(ref_bit) |
2961 | + refs_len = refs_len + PyString_GET_SIZE(ref_bit) |
2962 | |
2963 | # So we have the (key NULL refs NULL value LF) |
2964 | key_len = PyString_Size(string_key) |
2965 | - val = PyTuple_GET_ITEM_ptr_object(node, 2) |
2966 | - if not PyString_CheckExact_ptr(val): |
2967 | + val = node[2] |
2968 | + if not PyString_CheckExact(val): |
2969 | raise TypeError('Expected a plain str for value not: %s' |
2970 | - % type(<object>val)) |
2971 | - value = PyString_AS_STRING_ptr(val) |
2972 | - value_len = PyString_GET_SIZE_ptr(val) |
2973 | + % type(val)) |
2974 | + value = PyString_AS_STRING(val) |
2975 | + value_len = PyString_GET_SIZE(val) |
2976 | flat_len = (key_len + 1 + refs_len + 1 + value_len + 1) |
2977 | line = PyString_FromStringAndSize(NULL, flat_len) |
2978 | # Get a pointer to the new buffer |
2979 | @@ -396,14 +438,14 @@ |
2980 | out[0] = c'\r' |
2981 | out = out + 1 |
2982 | first_reference = 0 |
2983 | - next_len = PyTuple_GET_SIZE(reference) |
2984 | + next_len = len(reference) |
2985 | for i from 0 <= i < next_len: |
2986 | if i != 0: |
2987 | out[0] = c'\x00' |
2988 | out = out + 1 |
2989 | - ref_bit = PyTuple_GET_ITEM_ptr_object(reference, i) |
2990 | - ref_bit_len = PyString_GET_SIZE_ptr(ref_bit) |
2991 | - memcpy(out, PyString_AS_STRING_ptr(ref_bit), ref_bit_len) |
2992 | + ref_bit = reference[i] |
2993 | + ref_bit_len = PyString_GET_SIZE(ref_bit) |
2994 | + memcpy(out, PyString_AS_STRING(ref_bit), ref_bit_len) |
2995 | out = out + ref_bit_len |
2996 | out[0] = c'\0' |
2997 | out = out + 1 |
2998 | |
2999 | === modified file 'bzrlib/_chk_map_py.py' |
3000 | --- bzrlib/_chk_map_py.py 2009-04-09 20:23:07 +0000 |
3001 | +++ bzrlib/_chk_map_py.py 2009-11-03 09:40:55 +0000 |
3002 | @@ -19,6 +19,8 @@ |
3003 | import zlib |
3004 | import struct |
3005 | |
3006 | +from bzrlib.static_tuple import StaticTuple |
3007 | + |
3008 | _LeafNode = None |
3009 | _InternalNode = None |
3010 | _unknown = None |
3011 | @@ -93,7 +95,7 @@ |
3012 | value_lines = lines[pos:pos+num_value_lines] |
3013 | pos += num_value_lines |
3014 | value = '\n'.join(value_lines) |
3015 | - items[tuple(elements[:-1])] = value |
3016 | + items[StaticTuple.from_sequence(elements[:-1])] = value |
3017 | if len(items) != length: |
3018 | raise AssertionError("item count (%d) mismatch for key %s," |
3019 | " bytes %r" % (length, key, bytes)) |
3020 | @@ -141,7 +143,7 @@ |
3021 | for line in lines[5:]: |
3022 | line = common_prefix + line |
3023 | prefix, flat_key = line.rsplit('\x00', 1) |
3024 | - items[prefix] = (flat_key,) |
3025 | + items[prefix] = StaticTuple(flat_key,) |
3026 | if len(items) == 0: |
3027 | raise AssertionError("We didn't find any item for %s" % key) |
3028 | result._items = items |
3029 | @@ -155,4 +157,3 @@ |
3030 | result._node_width = len(prefix) |
3031 | result._search_prefix = common_prefix |
3032 | return result |
3033 | - |
3034 | |
3035 | === modified file 'bzrlib/_chk_map_pyx.pyx' |
3036 | --- bzrlib/_chk_map_pyx.pyx 2009-06-22 12:52:39 +0000 |
3037 | +++ bzrlib/_chk_map_pyx.pyx 2009-11-03 09:40:54 +0000 |
3038 | @@ -29,9 +29,8 @@ |
3039 | |
3040 | cdef extern from "Python.h": |
3041 | ctypedef int Py_ssize_t # Required for older pyrex versions |
3042 | - struct _PyObject: |
3043 | + ctypedef struct PyObject: |
3044 | pass |
3045 | - ctypedef _PyObject PyObject |
3046 | int PyTuple_CheckExact(object p) |
3047 | Py_ssize_t PyTuple_GET_SIZE(object t) |
3048 | int PyString_CheckExact(object) |
3049 | @@ -52,6 +51,18 @@ |
3050 | char *PyString_AS_STRING_ptr "PyString_AS_STRING" (PyObject *s) |
3051 | object PyString_FromStringAndSize(char*, Py_ssize_t) |
3052 | |
3053 | +# cimport all of the definitions we will need to access |
3054 | +from _static_tuple_c cimport StaticTuple,\ |
3055 | + import_static_tuple_c, StaticTuple_New, \ |
3056 | + StaticTuple_Intern, StaticTuple_SET_ITEM, StaticTuple_CheckExact |
3057 | + |
3058 | +cdef extern from "_static_tuple_c.h": |
3059 | + # Defined explicitly rather than cimport-ing. Trying to use cimport, the |
3060 | + # type for PyObject is a different class that happens to have the same |
3061 | + # name... |
3062 | + PyObject * StaticTuple_GET_ITEM_ptr "StaticTuple_GET_ITEM" (StaticTuple, |
3063 | + Py_ssize_t) |
3064 | + |
3065 | cdef extern from "zlib.h": |
3066 | ctypedef unsigned long uLong |
3067 | ctypedef unsigned int uInt |
3068 | @@ -60,8 +71,14 @@ |
3069 | uLong crc32(uLong crc, Bytef *buf, uInt len) |
3070 | |
3071 | |
3072 | +# Set up the StaticTuple C_API functionality |
3073 | +import_static_tuple_c() |
3074 | + |
3075 | +cdef object _LeafNode |
3076 | _LeafNode = None |
3077 | +cdef object _InternalNode |
3078 | _InternalNode = None |
3079 | +cdef object _unknown |
3080 | _unknown = None |
3081 | |
3082 | # We shouldn't just copy this from _dirstate_helpers_pyx |
3083 | @@ -91,9 +108,9 @@ |
3084 | cdef char *c_out |
3085 | cdef PyObject *bit |
3086 | |
3087 | - if not PyTuple_CheckExact(key): |
3088 | - raise TypeError('key %r is not a tuple' % (key,)) |
3089 | - num_bits = PyTuple_GET_SIZE(key) |
3090 | + if not StaticTuple_CheckExact(key): |
3091 | + raise TypeError('key %r is not a StaticTuple' % (key,)) |
3092 | + num_bits = len(key) |
3093 | # 4 bytes per crc32, and another 1 byte between bits |
3094 | num_out_bytes = (9 * num_bits) - 1 |
3095 | out = PyString_FromStringAndSize(NULL, num_out_bytes) |
3096 | @@ -105,7 +122,7 @@ |
3097 | # We use the _ptr variant, because GET_ITEM returns a borrowed |
3098 | # reference, and Pyrex assumes that returned 'object' are a new |
3099 | # reference |
3100 | - bit = PyTuple_GET_ITEM_ptr(key, i) |
3101 | + bit = StaticTuple_GET_ITEM_ptr(key, i) |
3102 | if not PyString_CheckExact_ptr(bit): |
3103 | raise TypeError('Bit %d of %r is not a string' % (i, key)) |
3104 | c_bit = <Bytef *>PyString_AS_STRING_ptr(bit) |
3105 | @@ -129,9 +146,9 @@ |
3106 | cdef char *c_out |
3107 | cdef PyObject *bit |
3108 | |
3109 | - if not PyTuple_CheckExact(key): |
3110 | - raise TypeError('key %r is not a tuple' % (key,)) |
3111 | - num_bits = PyTuple_GET_SIZE(key) |
3112 | + if not StaticTuple_CheckExact(key): |
3113 | + raise TypeError('key %r is not a StaticTuple' % (key,)) |
3114 | + num_bits = len(key) |
3115 | # 4 bytes per crc32, and another 1 byte between bits |
3116 | num_out_bytes = (5 * num_bits) - 1 |
3117 | out = PyString_FromStringAndSize(NULL, num_out_bytes) |
3118 | @@ -140,10 +157,10 @@ |
3119 | if i > 0: |
3120 | c_out[0] = c'\x00' |
3121 | c_out = c_out + 1 |
3122 | - bit = PyTuple_GET_ITEM_ptr(key, i) |
3123 | + bit = StaticTuple_GET_ITEM_ptr(key, i) |
3124 | if not PyString_CheckExact_ptr(bit): |
3125 | - raise TypeError('Bit %d of %r is not a string: %r' % (i, key, |
3126 | - <object>bit)) |
3127 | + raise TypeError('Bit %d of %r is not a string: %r' |
3128 | + % (i, key, <object>bit)) |
3129 | c_bit = <Bytef *>PyString_AS_STRING_ptr(bit) |
3130 | c_len = PyString_GET_SIZE_ptr(bit) |
3131 | crc_val = crc32(0, c_bit, c_len) |
3132 | @@ -195,6 +212,7 @@ |
3133 | cdef char *prefix, *value_start, *prefix_tail |
3134 | cdef char *next_null, *last_null, *line_start |
3135 | cdef char *c_entry, *entry_start |
3136 | + cdef StaticTuple entry_bits |
3137 | |
3138 | if _LeafNode is None: |
3139 | from bzrlib import chk_map |
3140 | @@ -265,12 +283,14 @@ |
3141 | if next_line == NULL: |
3142 | raise ValueError('missing trailing newline') |
3143 | cur = next_line + 1 |
3144 | - entry_bits = PyTuple_New(width) |
3145 | + entry_bits = StaticTuple_New(width) |
3146 | for i from 0 <= i < num_prefix_bits: |
3147 | + # TODO: Use PyList_GetItem, or turn prefix_bits into a |
3148 | + # tuple/StaticTuple |
3149 | entry = prefix_bits[i] |
3150 | # SET_ITEM 'steals' a reference |
3151 | Py_INCREF(entry) |
3152 | - PyTuple_SET_ITEM(entry_bits, i, entry) |
3153 | + StaticTuple_SET_ITEM(entry_bits, i, entry) |
3154 | value = PyString_FromStringAndSize(value_start, next_line - value_start) |
3155 | # The next entry bit needs the 'tail' from the prefix, and first part |
3156 | # of the line |
3157 | @@ -288,7 +308,7 @@ |
3158 | memcpy(c_entry + prefix_tail_len, line_start, next_null - line_start) |
3159 | Py_INCREF(entry) |
3160 | i = num_prefix_bits |
3161 | - PyTuple_SET_ITEM(entry_bits, i, entry) |
3162 | + StaticTuple_SET_ITEM(entry_bits, i, entry) |
3163 | while next_null != last_null: # We have remaining bits |
3164 | i = i + 1 |
3165 | if i > width: |
3166 | @@ -301,11 +321,12 @@ |
3167 | entry = PyString_FromStringAndSize(entry_start, |
3168 | next_null - entry_start) |
3169 | Py_INCREF(entry) |
3170 | - PyTuple_SET_ITEM(entry_bits, i, entry) |
3171 | + StaticTuple_SET_ITEM(entry_bits, i, entry) |
3172 | if len(entry_bits) != width: |
3173 | raise AssertionError( |
3174 | 'Incorrect number of elements (%d vs %d)' |
3175 | % (len(entry_bits)+1, width + 1)) |
3176 | + entry_bits = StaticTuple_Intern(entry_bits) |
3177 | PyDict_SetItem(items, entry_bits, value) |
3178 | if len(items) != length: |
3179 | raise ValueError("item count (%d) mismatch for key %s," |
3180 | @@ -343,6 +364,8 @@ |
3181 | _unknown = chk_map._unknown |
3182 | result = _InternalNode(search_key_func=search_key_func) |
3183 | |
3184 | + if not StaticTuple_CheckExact(key): |
3185 | + raise TypeError('key %r is not a StaticTuple' % (key,)) |
3186 | if not PyString_CheckExact(bytes): |
3187 | raise TypeError('bytes must be a plain string not %s' % (type(bytes),)) |
3188 | |
3189 | @@ -384,7 +407,8 @@ |
3190 | memcpy(c_item_prefix + prefix_length, cur, next_null - cur) |
3191 | flat_key = PyString_FromStringAndSize(next_null + 1, |
3192 | next_line - next_null - 1) |
3193 | - PyDict_SetItem(items, item_prefix, (flat_key,)) |
3194 | + flat_key = StaticTuple(flat_key).intern() |
3195 | + PyDict_SetItem(items, item_prefix, flat_key) |
3196 | cur = next_line + 1 |
3197 | assert len(items) > 0 |
3198 | result._items = items |
3199 | @@ -398,4 +422,3 @@ |
3200 | result._node_width = len(item_prefix) |
3201 | result._search_prefix = PyString_FromStringAndSize(prefix, prefix_length) |
3202 | return result |
3203 | - |
3204 | |
3205 | === modified file 'bzrlib/_dirstate_helpers_pyx.pyx' |
3206 | --- bzrlib/_dirstate_helpers_pyx.pyx 2009-08-28 05:00:33 +0000 |
3207 | +++ bzrlib/_dirstate_helpers_pyx.pyx 2009-11-03 09:40:54 +0000 |
3208 | @@ -1202,7 +1202,9 @@ |
3209 | content_change = 0 |
3210 | target_exec = False |
3211 | else: |
3212 | - raise Exception, "unknown kind %s" % path_info[2] |
3213 | + if path is None: |
3214 | + path = self.pathjoin(old_dirname, old_basename) |
3215 | + raise errors.BadFileKindError(path, path_info[2]) |
3216 | if source_minikind == c'd': |
3217 | if path is None: |
3218 | old_path = path = self.pathjoin(old_dirname, old_basename) |
3219 | |
3220 | === added file 'bzrlib/_export_c_api.h' |
3221 | --- bzrlib/_export_c_api.h 1970-01-01 00:00:00 +0000 |
3222 | +++ bzrlib/_export_c_api.h 2009-11-03 09:40:54 +0000 |
3223 | @@ -0,0 +1,104 @@ |
3224 | +/* Copyright (C) 2009 Canonical Ltd |
3225 | + * |
3226 | + * This program is free software; you can redistribute it and/or modify |
3227 | + * it under the terms of the GNU General Public License as published by |
3228 | + * the Free Software Foundation; either version 2 of the License, or |
3229 | + * (at your option) any later version. |
3230 | + * |
3231 | + * This program is distributed in the hope that it will be useful, |
3232 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3233 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3234 | + * GNU General Public License for more details. |
3235 | + * |
3236 | + * You should have received a copy of the GNU General Public License |
3237 | + * along with this program; if not, write to the Free Software |
3238 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
3239 | + */ |
3240 | + |
3241 | + |
3242 | +/* This file contains helper functions for exporting a C API for a CPython |
3243 | + * extension module. |
3244 | + */ |
3245 | + |
3246 | +#ifndef _EXPORT_C_API_H_ |
3247 | +#define _EXPORT_C_API_H_ |
3248 | + |
3249 | +static const char *_C_API_NAME = "_C_API"; |
3250 | + |
3251 | +/** |
3252 | + * Add a C function to the modules _C_API |
3253 | + * This wraps the function in a PyCObject, and inserts that into a dict. |
3254 | + * The key of the dict is the function name, and the description is the |
3255 | + * signature of the function. |
3256 | + * This is generally called during a modules init_MODULE function. |
3257 | + * |
3258 | + * @param module A Python module (the one being initialized) |
3259 | + * @param funcname The name of the function being exported |
3260 | + * @param func A pointer to the function |
3261 | + * @param signature The C signature of the function |
3262 | + * @return 0 if everything is successful, -1 if there is a problem. An |
3263 | + * exception should also be set |
3264 | + */ |
3265 | +static int |
3266 | +_export_function(PyObject *module, char *funcname, void *func, char *signature) |
3267 | +{ |
3268 | + PyObject *d = NULL; |
3269 | + PyObject *c_obj = NULL; |
3270 | + |
3271 | + /* (char *) is because python2.4 declares this api as 'char *' rather than |
3272 | + * const char* which it really is. |
3273 | + */ |
3274 | + d = PyObject_GetAttrString(module, (char *)_C_API_NAME); |
3275 | + if (!d) { |
3276 | + PyErr_Clear(); |
3277 | + d = PyDict_New(); |
3278 | + if (!d) |
3279 | + goto bad; |
3280 | + Py_INCREF(d); |
3281 | + if (PyModule_AddObject(module, (char *)_C_API_NAME, d) < 0) |
3282 | + goto bad; |
3283 | + } |
3284 | + c_obj = PyCObject_FromVoidPtrAndDesc(func, signature, 0); |
3285 | + if (!c_obj) |
3286 | + goto bad; |
3287 | + if (PyDict_SetItemString(d, funcname, c_obj) < 0) |
3288 | + goto bad; |
3289 | + Py_DECREF(d); |
3290 | + return 0; |
3291 | +bad: |
3292 | + Py_XDECREF(c_obj); |
3293 | + Py_XDECREF(d); |
3294 | + return -1; |
3295 | +} |
3296 | + |
3297 | +/* Note: |
3298 | + * It feels like more could be done here. Specifically, if you look at |
3299 | + * _static_tuple_c.h you can see some boilerplate where we have: |
3300 | + * #ifdef STATIC_TUPLE_MODULE // are we exporting or importing |
3301 | + * static RETVAL FUNCNAME PROTO; |
3302 | + * #else |
3303 | + * static RETVAL (*FUNCNAME) PROTO; |
3304 | + * #endif |
3305 | + * |
3306 | + * And then in _static_tuple_c.c we have |
3307 | + * int setup_c_api() |
3308 | + * { |
3309 | + * _export_function(module, #FUNCNAME, FUNCNAME, #PROTO); |
3310 | + * } |
3311 | + * |
3312 | + * And then in _static_tuple_c.h import_##MODULE |
3313 | + * struct function_definition functions[] = { |
3314 | + * {#FUNCNAME, (void **)&FUNCNAME, #RETVAL #PROTO}, |
3315 | + * ... |
3316 | + * {NULL}}; |
3317 | + * |
3318 | + * And some similar stuff for types. However, this would mean that we would |
3319 | + * need a way for the C preprocessor to build up a list of definitions to be |
3320 | + * generated, and then expand that list at the appropriate time. |
3321 | + * I would guess there would be a way to do this, but probably not without a |
3322 | + * lot of magic, and the end result probably wouldn't be very pretty to |
3323 | + * maintain. Perhaps python's dynamic nature has left me jaded about writing |
3324 | + * boilerplate.... |
3325 | + */ |
3326 | + |
3327 | +#endif // _EXPORT_C_API_H_ |
3328 | |
3329 | === added file 'bzrlib/_import_c_api.h' |
3330 | --- bzrlib/_import_c_api.h 1970-01-01 00:00:00 +0000 |
3331 | +++ bzrlib/_import_c_api.h 2009-11-03 09:40:54 +0000 |
3332 | @@ -0,0 +1,189 @@ |
3333 | +/* Copyright (C) 2009 Canonical Ltd |
3334 | + * |
3335 | + * This program is free software; you can redistribute it and/or modify |
3336 | + * it under the terms of the GNU General Public License as published by |
3337 | + * the Free Software Foundation; either version 2 of the License, or |
3338 | + * (at your option) any later version. |
3339 | + * |
3340 | + * This program is distributed in the hope that it will be useful, |
3341 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3342 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3343 | + * GNU General Public License for more details. |
3344 | + * |
3345 | + * You should have received a copy of the GNU General Public License |
3346 | + * along with this program; if not, write to the Free Software |
3347 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
3348 | + */ |
3349 | + |
3350 | +#ifndef _IMPORT_C_API_H_ |
3351 | +#define _IMPORT_C_API_H_ |
3352 | + |
3353 | +/** |
3354 | + * Helper functions to eliminate some of the boilerplate when importing a C API |
3355 | + * from a CPython extension module. |
3356 | + * |
3357 | + * For more information see _export_c_api.h |
3358 | + */ |
3359 | + |
3360 | +static const char *_C_API_NAME = "_C_API"; |
3361 | + |
3362 | +/** |
3363 | + * Import a function from the _C_API_NAME dict that is part of module. |
3364 | + * |
3365 | + * @param module The Python module we are importing from |
3366 | + * the attribute _C_API_NAME will be used as a dictionary |
3367 | + * containing the function pointer we are looking for. |
3368 | + * @param funcname Name of the function we want to import |
3369 | + * @param func A pointer to the function handle where we will store the |
3370 | + * function. |
3371 | + * @param signature The C signature of the function. This is validated |
3372 | + * against the signature stored in the C api, to make sure |
3373 | + * there is no versioning skew. |
3374 | + */ |
3375 | +static int _import_function(PyObject *module, const char *funcname, |
3376 | + void **func, const char *signature) |
3377 | +{ |
3378 | + PyObject *d = NULL; |
3379 | + PyObject *c_obj = NULL; |
3380 | + const char *desc = NULL; |
3381 | + |
3382 | + /* (char *) because Python2.4 defines this as (char *) rather than |
3383 | + * (const char *) |
3384 | + */ |
3385 | + d = PyObject_GetAttrString(module, (char *)_C_API_NAME); |
3386 | + if (!d) { |
3387 | + // PyObject_GetAttrString sets an appropriate exception |
3388 | + goto bad; |
3389 | + } |
3390 | + c_obj = PyDict_GetItemString(d, funcname); |
3391 | + if (!c_obj) { |
3392 | + // PyDict_GetItemString does not set an exception |
3393 | + PyErr_Format(PyExc_AttributeError, |
3394 | + "Module %s did not export a function named %s\n", |
3395 | + PyModule_GetName(module), funcname); |
3396 | + goto bad; |
3397 | + } |
3398 | + desc = (char *)PyCObject_GetDesc(c_obj); |
3399 | + if (!desc || strcmp(desc, signature) != 0) { |
3400 | + if (desc == NULL) { |
3401 | + desc = "<null>"; |
3402 | + } |
3403 | + PyErr_Format(PyExc_TypeError, |
3404 | + "C function %s.%s has wrong signature (expected %s, got %s)", |
3405 | + PyModule_GetName(module), funcname, signature, desc); |
3406 | + goto bad; |
3407 | + } |
3408 | + *func = PyCObject_AsVoidPtr(c_obj); |
3409 | + Py_DECREF(d); |
3410 | + return 0; |
3411 | +bad: |
3412 | + Py_XDECREF(d); |
3413 | + return -1; |
3414 | +} |
3415 | + |
3416 | + |
3417 | +/** |
3418 | + * Get a pointer to an exported PyTypeObject. |
3419 | + * |
3420 | + * @param module The Python module we are importing from |
3421 | + * @param class_name Attribute of the module that should reference the |
3422 | + * Type object. Note that a PyTypeObject is the python |
3423 | + * description of the type, not the raw C structure. |
3424 | + * @return A Pointer to the requested type object. On error NULL will be |
3425 | + * returned and an exception will be set. |
3426 | + */ |
3427 | +static PyTypeObject * |
3428 | +_import_type(PyObject *module, const char *class_name) |
3429 | +{ |
3430 | + PyObject *type = NULL; |
3431 | + |
3432 | + type = PyObject_GetAttrString(module, (char *)class_name); |
3433 | + if (!type) { |
3434 | + goto bad; |
3435 | + } |
3436 | + if (!PyType_Check(type)) { |
3437 | + PyErr_Format(PyExc_TypeError, |
3438 | + "%s.%s is not a type object", |
3439 | + PyModule_GetName(module), class_name); |
3440 | + goto bad; |
3441 | + } |
3442 | + return (PyTypeObject *)type; |
3443 | +bad: |
3444 | + Py_XDECREF(type); |
3445 | + return NULL; |
3446 | +} |
3447 | + |
3448 | + |
3449 | +struct function_description |
3450 | +{ |
3451 | + const char *name; |
3452 | + void **pointer; |
3453 | + const char *signature; |
3454 | +}; |
3455 | + |
3456 | +struct type_description |
3457 | +{ |
3458 | + const char *name; |
3459 | + PyTypeObject **pointer; |
3460 | +}; |
3461 | + |
3462 | +/** |
3463 | + * Helper for importing several functions and types in a data-driven manner. |
3464 | + * |
3465 | + * @param module The name of the module we will be importing |
3466 | + * @param functions A list of function_description objects, describing the |
3467 | + * functions being imported. |
3468 | + * The list should be terminated with {NULL} to indicate |
3469 | + * there are no more functions to import. |
3470 | + * @param types A list of type_description objects describing type |
3471 | + * objects that we want to import. The list should be |
3472 | + * terminated with {NULL} to indicate there are no more |
3473 | + * types to import. |
3474 | + * @return 0 on success, -1 on error and an exception should be set. |
3475 | + */ |
3476 | + |
3477 | +static int |
3478 | +_import_extension_module(const char *module_name, |
3479 | + struct function_description *functions, |
3480 | + struct type_description *types) |
3481 | +{ |
3482 | + PyObject *module = NULL; |
3483 | + struct function_description *cur_func; |
3484 | + struct type_description *cur_type; |
3485 | + int ret_code; |
3486 | + |
3487 | + module = PyImport_ImportModule((char *)module_name); |
3488 | + if (!module) |
3489 | + goto bad; |
3490 | + if (functions != NULL) { |
3491 | + cur_func = functions; |
3492 | + while (cur_func->name != NULL) { |
3493 | + ret_code = _import_function(module, cur_func->name, |
3494 | + cur_func->pointer, |
3495 | + cur_func->signature); |
3496 | + if (ret_code < 0) |
3497 | + goto bad; |
3498 | + cur_func++; |
3499 | + } |
3500 | + } |
3501 | + if (types != NULL) { |
3502 | + PyTypeObject *type_p = NULL; |
3503 | + cur_type = types; |
3504 | + while (cur_type->name != NULL) { |
3505 | + type_p = _import_type(module, cur_type->name); |
3506 | + if (type_p == NULL) |
3507 | + goto bad; |
3508 | + *(cur_type->pointer) = type_p; |
3509 | + cur_type++; |
3510 | + } |
3511 | + } |
3512 | + |
3513 | + Py_XDECREF(module); |
3514 | + return 0; |
3515 | +bad: |
3516 | + Py_XDECREF(module); |
3517 | + return -1; |
3518 | +} |
3519 | + |
3520 | + |
3521 | +#endif // _IMPORT_C_API_H_ |
3522 | |
3523 | === modified file 'bzrlib/_known_graph_py.py' |
3524 | --- bzrlib/_known_graph_py.py 2009-08-25 18:45:40 +0000 |
3525 | +++ bzrlib/_known_graph_py.py 2009-11-03 09:40:55 +0000 |
3526 | @@ -281,3 +281,26 @@ |
3527 | in tsort.merge_sort(as_parent_map, tip_key, |
3528 | mainline_revisions=None, |
3529 | generate_revno=True)] |
3530 | + |
3531 | + def get_parent_keys(self, key): |
3532 | + """Get the parents for a key |
3533 | + |
3534 | + Returns a list containg the parents keys. If the key is a ghost, |
3535 | + None is returned. A KeyError will be raised if the key is not in |
3536 | + the graph. |
3537 | + |
3538 | + :param keys: Key to check (eg revision_id) |
3539 | + :return: A list of parents |
3540 | + """ |
3541 | + return self._nodes[key].parent_keys |
3542 | + |
3543 | + def get_child_keys(self, key): |
3544 | + """Get the children for a key |
3545 | + |
3546 | + Returns a list containg the children keys. A KeyError will be raised |
3547 | + if the key is not in the graph. |
3548 | + |
3549 | + :param keys: Key to check (eg revision_id) |
3550 | + :return: A list of children |
3551 | + """ |
3552 | + return self._nodes[key].child_keys |
3553 | |
3554 | === modified file 'bzrlib/_known_graph_pyx.pyx' |
3555 | --- bzrlib/_known_graph_pyx.pyx 2009-09-02 13:32:52 +0000 |
3556 | +++ bzrlib/_known_graph_pyx.pyx 2009-11-03 09:40:54 +0000 |
3557 | @@ -88,6 +88,18 @@ |
3558 | PyList_Append(keys, child.key) |
3559 | return keys |
3560 | |
3561 | + property parent_keys: |
3562 | + def __get__(self): |
3563 | + if self.parents is None: |
3564 | + return None |
3565 | + |
3566 | + cdef _KnownGraphNode parent |
3567 | + |
3568 | + keys = [] |
3569 | + for parent in self.parents: |
3570 | + PyList_Append(keys, parent.key) |
3571 | + return keys |
3572 | + |
3573 | cdef clear_references(self): |
3574 | self.parents = None |
3575 | self.children = None |
3576 | @@ -549,6 +561,29 @@ |
3577 | # shown a specific impact, yet. |
3578 | sorter = _MergeSorter(self, tip_key) |
3579 | return sorter.topo_order() |
3580 | + |
3581 | + def get_parent_keys(self, key): |
3582 | + """Get the parents for a key |
3583 | + |
3584 | + Returns a list containg the parents keys. If the key is a ghost, |
3585 | + None is returned. A KeyError will be raised if the key is not in |
3586 | + the graph. |
3587 | + |
3588 | + :param keys: Key to check (eg revision_id) |
3589 | + :return: A list of parents |
3590 | + """ |
3591 | + return self._nodes[key].parent_keys |
3592 | + |
3593 | + def get_child_keys(self, key): |
3594 | + """Get the children for a key |
3595 | + |
3596 | + Returns a list containg the children keys. A KeyError will be raised |
3597 | + if the key is not in the graph. |
3598 | + |
3599 | + :param keys: Key to check (eg revision_id) |
3600 | + :return: A list of children |
3601 | + """ |
3602 | + return self._nodes[key].child_keys |
3603 | |
3604 | |
3605 | cdef class _MergeSortNode: |
3606 | |
3607 | === modified file 'bzrlib/_patiencediff_c.c' |
3608 | --- bzrlib/_patiencediff_c.c 2009-03-23 14:59:43 +0000 |
3609 | +++ bzrlib/_patiencediff_c.c 2009-11-03 09:40:55 +0000 |
3610 | @@ -298,7 +298,7 @@ |
3611 | apos = SENTINEL; |
3612 | /* loop through all lines in the linked list */ |
3613 | for (i = h[equiv].a_pos; i != SENTINEL; i = lines_a[i].next) { |
3614 | - /* the index is lower than alo, the the next line */ |
3615 | + /* the index is lower than alo, continue to the next line */ |
3616 | if (i < alo) { |
3617 | h[equiv].a_pos = i; |
3618 | continue; |
3619 | @@ -319,7 +319,7 @@ |
3620 | /* check for duplicates of this line in lines_b[blo:bhi] */ |
3621 | /* loop through all lines in the linked list */ |
3622 | for (i = h[equiv].b_pos; i != SENTINEL; i = lines_b[i].next) { |
3623 | - /* the index is lower than blo, the the next line */ |
3624 | + /* the index is lower than blo, continue to the next line */ |
3625 | if (i < blo) { |
3626 | h[equiv].b_pos = i; |
3627 | continue; |
3628 | |
3629 | === modified file 'bzrlib/_readdir_pyx.pyx' |
3630 | --- bzrlib/_readdir_pyx.pyx 2009-07-27 04:24:36 +0000 |
3631 | +++ bzrlib/_readdir_pyx.pyx 2009-11-03 09:40:54 +0000 |
3632 | @@ -343,8 +343,10 @@ |
3633 | raise OSError(errno, "lstat: " + strerror(errno), |
3634 | path + "/" + entry.d_name) |
3635 | else: |
3636 | - kind = _missing |
3637 | - statvalue = None |
3638 | + # the file seems to have disappeared after being |
3639 | + # seen by readdir - perhaps a transient temporary |
3640 | + # file. there's no point returning it. |
3641 | + continue |
3642 | # We append a 5-tuple that can be modified in-place by the C |
3643 | # api: |
3644 | # inode to sort on (to replace with top_path) |
3645 | |
3646 | === added file 'bzrlib/_simple_set_pyx.pxd' |
3647 | --- bzrlib/_simple_set_pyx.pxd 1970-01-01 00:00:00 +0000 |
3648 | +++ bzrlib/_simple_set_pyx.pxd 2009-11-03 09:40:54 +0000 |
3649 | @@ -0,0 +1,91 @@ |
3650 | +# Copyright (C) 2009 Canonical Ltd |
3651 | +# |
3652 | +# This program is free software; you can redistribute it and/or modify |
3653 | +# it under the terms of the GNU General Public License as published by |
3654 | +# the Free Software Foundation; either version 2 of the License, or |
3655 | +# (at your option) any later version. |
3656 | +# |
3657 | +# This program is distributed in the hope that it will be useful, |
3658 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3659 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3660 | +# GNU General Public License for more details. |
3661 | +# |
3662 | +# You should have received a copy of the GNU General Public License |
3663 | +# along with this program; if not, write to the Free Software |
3664 | +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
3665 | + |
3666 | +"""Interface definition of a class like PySet but without caching the hash. |
3667 | + |
3668 | +This is generally useful when you want to 'intern' objects, etc. Note that this |
3669 | +differs from Set in that we: |
3670 | + 1) Don't have all of the .intersection, .difference, etc functions |
3671 | + 2) Do return the object from the set via queries |
3672 | + eg. SimpleSet.add(key) => saved_key and SimpleSet[key] => saved_key |
3673 | +""" |
3674 | + |
3675 | +cdef extern from "Python.h": |
3676 | + ctypedef struct PyObject: |
3677 | + pass |
3678 | + |
3679 | + |
3680 | +cdef public api class SimpleSet [object SimpleSetObject, type SimpleSet_Type]: |
3681 | + """A class similar to PySet, but with simpler implementation. |
3682 | + |
3683 | + The main advantage is that this class uses only 2N memory to store N |
3684 | + objects rather than 4N memory. The main trade-off is that we do not cache |
3685 | + the hash value of saved objects. As such, it is assumed that computing the |
3686 | + hash will be cheap (such as strings or tuples of strings, etc.) |
3687 | + |
3688 | + This also differs in that you can get back the objects that are stored |
3689 | + (like a dict), but we also don't implement the complete list of 'set' |
3690 | + operations (difference, intersection, etc). |
3691 | + """ |
3692 | + # Data structure definition: |
3693 | + # This is a basic hash table using open addressing. |
3694 | + # http://en.wikipedia.org/wiki/Open_addressing |
3695 | + # Basically that means we keep an array of pointers to Python objects |
3696 | + # (called a table). Each location in the array is called a 'slot'. |
3697 | + # |
3698 | + # An empty slot holds a NULL pointer, a slot where there was an item |
3699 | + # which was then deleted will hold a pointer to _dummy, and a filled slot |
3700 | + # points at the actual object which fills that slot. |
3701 | + # |
3702 | + # The table is always a power of two, and the default location where an |
3703 | + # object is inserted is at hash(object) & (table_size - 1) |
3704 | + # |
3705 | + # If there is a collision, then we search for another location. The |
3706 | + # specific algorithm is in _lookup. We search until we: |
3707 | + # find the object |
3708 | + # find an equivalent object (by tp_richcompare(obj1, obj2, Py_EQ)) |
3709 | + # find a NULL slot |
3710 | + # |
3711 | + # When an object is deleted, we set its slot to _dummy. this way we don't |
3712 | + # have to track whether there was a collision, and find the corresponding |
3713 | + # keys. (The collision resolution algorithm makes that nearly impossible |
3714 | + # anyway, because it depends on the upper bits of the hash.) |
3715 | + # The main effect of this, is that if we find _dummy, then we can insert |
3716 | + # an object there, but we have to keep searching until we find NULL to |
3717 | + # know that the object is not present elsewhere. |
3718 | + |
3719 | + cdef Py_ssize_t _used # active |
3720 | + cdef Py_ssize_t _fill # active + dummy |
3721 | + cdef Py_ssize_t _mask # Table contains (mask+1) slots, a power of 2 |
3722 | + cdef PyObject **_table # Pyrex/Cython doesn't support arrays to 'object' |
3723 | + # so we manage it manually |
3724 | + |
3725 | + cdef PyObject *_get(self, object key) except? NULL |
3726 | + cdef object _add(self, key) |
3727 | + cdef int _discard(self, key) except -1 |
3728 | + cdef int _insert_clean(self, PyObject *key) except -1 |
3729 | + cdef Py_ssize_t _resize(self, Py_ssize_t min_unused) except -1 |
3730 | + |
3731 | + |
3732 | +# TODO: might want to export the C api here, though it is all available from |
3733 | +# the class object... |
3734 | +cdef api SimpleSet SimpleSet_New() |
3735 | +cdef api object SimpleSet_Add(object self, object key) |
3736 | +cdef api int SimpleSet_Contains(object self, object key) except -1 |
3737 | +cdef api int SimpleSet_Discard(object self, object key) except -1 |
3738 | +cdef api PyObject *SimpleSet_Get(SimpleSet self, object key) except? NULL |
3739 | +cdef api Py_ssize_t SimpleSet_Size(object self) except -1 |
3740 | +cdef api int SimpleSet_Next(object self, Py_ssize_t *pos, PyObject **key) |
3741 | |
3742 | === added file 'bzrlib/_simple_set_pyx.pyx' |
3743 | --- bzrlib/_simple_set_pyx.pyx 1970-01-01 00:00:00 +0000 |
3744 | +++ bzrlib/_simple_set_pyx.pyx 2009-11-03 09:40:54 +0000 |
3745 | @@ -0,0 +1,590 @@ |
3746 | +# Copyright (C) 2009 Canonical Ltd |
3747 | +# |
3748 | +# This program is free software; you can redistribute it and/or modify |
3749 | +# it under the terms of the GNU General Public License as published by |
3750 | +# the Free Software Foundation; either version 2 of the License, or |
3751 | +# (at your option) any later version. |
3752 | +# |
3753 | +# This program is distributed in the hope that it will be useful, |
3754 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3755 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3756 | +# GNU General Public License for more details. |
3757 | +# |
3758 | +# You should have received a copy of the GNU General Public License |
3759 | +# along with this program; if not, write to the Free Software |
3760 | +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
3761 | + |
3762 | +"""Definition of a class that is similar to Set with some small changes.""" |
3763 | + |
3764 | +cdef extern from "python-compat.h": |
3765 | + pass |
3766 | + |
3767 | +cdef extern from "Python.h": |
3768 | + ctypedef unsigned long size_t |
3769 | + ctypedef long (*hashfunc)(PyObject*) except -1 |
3770 | + ctypedef object (*richcmpfunc)(PyObject *, PyObject *, int) |
3771 | + ctypedef int (*visitproc)(PyObject *, void *) |
3772 | + ctypedef int (*traverseproc)(PyObject *, visitproc, void *) |
3773 | + int Py_EQ |
3774 | + void Py_INCREF(PyObject *) |
3775 | + void Py_DECREF(PyObject *) |
3776 | + ctypedef struct PyTypeObject: |
3777 | + hashfunc tp_hash |
3778 | + richcmpfunc tp_richcompare |
3779 | + traverseproc tp_traverse |
3780 | + |
3781 | + PyTypeObject *Py_TYPE(PyObject *) |
3782 | + # Note: *Don't* use hash(), Pyrex 0.9.8.5 thinks it returns an 'int', and |
3783 | + # thus silently truncates to 32-bits on 64-bit machines. |
3784 | + long PyObject_Hash(PyObject *) except -1 |
3785 | + |
3786 | + void *PyMem_Malloc(size_t nbytes) |
3787 | + void PyMem_Free(void *) |
3788 | + void memset(void *, int, size_t) |
3789 | + |
3790 | + |
3791 | +# Dummy is an object used to mark nodes that have been deleted. Since |
3792 | +# collisions require us to move a node to an alternative location, if we just |
3793 | +# set an entry to NULL on delete, we won't find any relocated nodes. |
3794 | +# We have to use _dummy_obj because we need to keep a refcount to it, but we |
3795 | +# also use _dummy as a pointer, because it avoids having to put <PyObject*> all |
3796 | +# over the code base. |
3797 | +cdef object _dummy_obj |
3798 | +cdef PyObject *_dummy |
3799 | +_dummy_obj = object() |
3800 | +_dummy = <PyObject *>_dummy_obj |
3801 | + |
3802 | + |
3803 | +cdef object _NotImplemented |
3804 | +_NotImplemented = NotImplemented |
3805 | + |
3806 | + |
3807 | +cdef int _is_equal(PyObject *this, long this_hash, PyObject *other) except -1: |
3808 | + cdef long other_hash |
3809 | + |
3810 | + if this == other: |
3811 | + return 1 |
3812 | + other_hash = PyObject_Hash(other) |
3813 | + if other_hash != this_hash: |
3814 | + return 0 |
3815 | + |
3816 | + # This implements a subset of the PyObject_RichCompareBool functionality. |
3817 | + # Namely it: |
3818 | + # 1) Doesn't try to do anything with old-style classes |
3819 | + # 2) Assumes that both objects have a tp_richcompare implementation, and |
3820 | + # that if that is not enough to compare equal, then they are not |
3821 | + # equal. (It doesn't try to cast them both to some intermediate form |
3822 | + # that would compare equal.) |
3823 | + res = Py_TYPE(this).tp_richcompare(this, other, Py_EQ) |
3824 | + if res is _NotImplemented: |
3825 | + res = Py_TYPE(other).tp_richcompare(other, this, Py_EQ) |
3826 | + if res is _NotImplemented: |
3827 | + return 0 |
3828 | + if res: |
3829 | + return 1 |
3830 | + return 0 |
3831 | + |
3832 | + |
3833 | +cdef public api class SimpleSet [object SimpleSetObject, type SimpleSet_Type]: |
3834 | + """This class can be used to track canonical forms for objects. |
3835 | + |
3836 | + It is similar in function to the interned dictionary that is used by |
3837 | + strings. However: |
3838 | + |
3839 | + 1) It assumes that hash(obj) is cheap, so does not need to inline a copy |
3840 | + of it |
3841 | + 2) It only stores one reference to the object, rather than 2 (key vs |
3842 | + key:value) |
3843 | + |
3844 | + As such, it uses 1/3rd the amount of memory to store a pointer to the |
3845 | + interned object. |
3846 | + """ |
3847 | + # Attributes are defined in the .pxd file |
3848 | + DEF DEFAULT_SIZE=1024 |
3849 | + |
3850 | + def __init__(self): |
3851 | + cdef Py_ssize_t size, n_bytes |
3852 | + |
3853 | + size = DEFAULT_SIZE |
3854 | + self._mask = size - 1 |
3855 | + self._used = 0 |
3856 | + self._fill = 0 |
3857 | + n_bytes = sizeof(PyObject*) * size; |
3858 | + self._table = <PyObject **>PyMem_Malloc(n_bytes) |
3859 | + if self._table == NULL: |
3860 | + raise MemoryError() |
3861 | + memset(self._table, 0, n_bytes) |
3862 | + |
3863 | + def __dealloc__(self): |
3864 | + if self._table != NULL: |
3865 | + PyMem_Free(self._table) |
3866 | + self._table = NULL |
3867 | + |
3868 | + property used: |
3869 | + def __get__(self): |
3870 | + return self._used |
3871 | + |
3872 | + property fill: |
3873 | + def __get__(self): |
3874 | + return self._fill |
3875 | + |
3876 | + property mask: |
3877 | + def __get__(self): |
3878 | + return self._mask |
3879 | + |
3880 | + def _memory_size(self): |
3881 | + """Return the number of bytes of memory consumed by this class.""" |
3882 | + return sizeof(self) + (sizeof(PyObject*)*(self._mask + 1)) |
3883 | + |
3884 | + def __len__(self): |
3885 | + return self._used |
3886 | + |
3887 | + def _test_lookup(self, key): |
3888 | + cdef PyObject **slot |
3889 | + |
3890 | + slot = _lookup(self, key) |
3891 | + if slot[0] == NULL: |
3892 | + res = '<null>' |
3893 | + elif slot[0] == _dummy: |
3894 | + res = '<dummy>' |
3895 | + else: |
3896 | + res = <object>slot[0] |
3897 | + return <int>(slot - self._table), res |
3898 | + |
3899 | + def __contains__(self, key): |
3900 | + """Is key present in this SimpleSet.""" |
3901 | + cdef PyObject **slot |
3902 | + |
3903 | + slot = _lookup(self, key) |
3904 | + if slot[0] == NULL or slot[0] == _dummy: |
3905 | + return False |
3906 | + return True |
3907 | + |
3908 | + cdef PyObject *_get(self, object key) except? NULL: |
3909 | + """Return the object (or nothing) define at the given location.""" |
3910 | + cdef PyObject **slot |
3911 | + |
3912 | + slot = _lookup(self, key) |
3913 | + if slot[0] == NULL or slot[0] == _dummy: |
3914 | + return NULL |
3915 | + return slot[0] |
3916 | + |
3917 | + def __getitem__(self, key): |
3918 | + """Return a stored item that is equivalent to key.""" |
3919 | + cdef PyObject *py_val |
3920 | + |
3921 | + py_val = self._get(key) |
3922 | + if py_val == NULL: |
3923 | + raise KeyError("Key %s is not present" % key) |
3924 | + val = <object>(py_val) |
3925 | + return val |
3926 | + |
3927 | + cdef int _insert_clean(self, PyObject *key) except -1: |
3928 | + """Insert a key into self.table. |
3929 | + |
3930 | + This is only meant to be used during times like '_resize', |
3931 | + as it makes a lot of assuptions about keys not already being present, |
3932 | + and there being no dummy entries. |
3933 | + """ |
3934 | + cdef size_t i, n_lookup |
3935 | + cdef long the_hash |
3936 | + cdef PyObject **table, **slot |
3937 | + cdef Py_ssize_t mask |
3938 | + |
3939 | + mask = self._mask |
3940 | + table = self._table |
3941 | + |
3942 | + the_hash = PyObject_Hash(key) |
3943 | + i = the_hash |
3944 | + for n_lookup from 0 <= n_lookup <= <size_t>mask: # Don't loop forever |
3945 | + slot = &table[i & mask] |
3946 | + if slot[0] == NULL: |
3947 | + slot[0] = key |
3948 | + self._fill = self._fill + 1 |
3949 | + self._used = self._used + 1 |
3950 | + return 1 |
3951 | + i = i + 1 + n_lookup |
3952 | + raise RuntimeError('ran out of slots.') |
3953 | + |
3954 | + def _py_resize(self, min_used): |
3955 | + """Do not use this directly, it is only exposed for testing.""" |
3956 | + return self._resize(min_used) |
3957 | + |
3958 | + cdef Py_ssize_t _resize(self, Py_ssize_t min_used) except -1: |
3959 | + """Resize the internal table. |
3960 | + |
3961 | + The final table will be big enough to hold at least min_used entries. |
3962 | + We will copy the data from the existing table over, leaving out dummy |
3963 | + entries. |
3964 | + |
3965 | + :return: The new size of the internal table |
3966 | + """ |
3967 | + cdef Py_ssize_t new_size, n_bytes, remaining |
3968 | + cdef PyObject **new_table, **old_table, **slot |
3969 | + |
3970 | + new_size = DEFAULT_SIZE |
3971 | + while new_size <= min_used and new_size > 0: |
3972 | + new_size = new_size << 1 |
3973 | + # We rolled over our signed size field |
3974 | + if new_size <= 0: |
3975 | + raise MemoryError() |
3976 | + # Even if min_used == self._mask + 1, and we aren't changing the actual |
3977 | + # size, we will still run the algorithm so that dummy entries are |
3978 | + # removed |
3979 | + # TODO: Test this |
3980 | + # if new_size < self._used: |
3981 | + # raise RuntimeError('cannot shrink SimpleSet to something' |
3982 | + # ' smaller than the number of used slots.') |
3983 | + n_bytes = sizeof(PyObject*) * new_size; |
3984 | + new_table = <PyObject **>PyMem_Malloc(n_bytes) |
3985 | + if new_table == NULL: |
3986 | + raise MemoryError() |
3987 | + |
3988 | + old_table = self._table |
3989 | + self._table = new_table |
3990 | + memset(self._table, 0, n_bytes) |
3991 | + self._mask = new_size - 1 |
3992 | + self._used = 0 |
3993 | + remaining = self._fill |
3994 | + self._fill = 0 |
3995 | + |
3996 | + # Moving everything to the other table is refcount neutral, so we don't |
3997 | + # worry about it. |
3998 | + slot = old_table |
3999 | + while remaining > 0: |
4000 | + if slot[0] == NULL: # unused slot |
4001 | + pass |
4002 | + elif slot[0] == _dummy: # dummy slot |
4003 | + remaining = remaining - 1 |
4004 | + else: # active slot |
4005 | + remaining = remaining - 1 |
4006 | + self._insert_clean(slot[0]) |
4007 | + slot = slot + 1 |
4008 | + PyMem_Free(old_table) |
4009 | + return new_size |
4010 | + |
4011 | + def add(self, key): |
4012 | + """Similar to set.add(), start tracking this key. |
4013 | + |
4014 | + There is one small difference, which is that we return the object that |
4015 | + is stored at the given location. (which is closer to the |
4016 | + dict.setdefault() functionality.) |
4017 | + """ |
4018 | + return self._add(key) |
4019 | + |
4020 | + cdef object _add(self, key): |
4021 | + cdef PyObject **slot, *py_key |
4022 | + cdef int added |
4023 | + |
4024 | + py_key = <PyObject *>key |
4025 | + if (Py_TYPE(py_key).tp_richcompare == NULL |
4026 | + or Py_TYPE(py_key).tp_hash == NULL): |
4027 | + raise TypeError('Types added to SimpleSet must implement' |
4028 | + ' both tp_richcompare and tp_hash') |
4029 | + added = 0 |
4030 | + # We need at least one empty slot |
4031 | + assert self._used < self._mask |
4032 | + slot = _lookup(self, key) |
4033 | + if (slot[0] == NULL): |
4034 | + Py_INCREF(py_key) |
4035 | + self._fill = self._fill + 1 |
4036 | + self._used = self._used + 1 |
4037 | + slot[0] = py_key |
4038 | + added = 1 |
4039 | + elif (slot[0] == _dummy): |
4040 | + Py_INCREF(py_key) |
4041 | + self._used = self._used + 1 |
4042 | + slot[0] = py_key |
4043 | + added = 1 |
4044 | + # No else: clause. If _lookup returns a pointer to |
4045 | + # a live object, then we already have a value at this location. |
4046 | + retval = <object>(slot[0]) |
4047 | + # PySet and PyDict use a 2-3rds full algorithm, we'll follow suit |
4048 | + if added and (self._fill * 3) >= ((self._mask + 1) * 2): |
4049 | + # However, we always work for a load factor of 2:1 |
4050 | + self._resize(self._used * 2) |
4051 | + # Even if we resized and ended up moving retval into a different slot, |
4052 | + # it is still the value that is held at the slot equivalent to 'key', |
4053 | + # so we can still return it |
4054 | + return retval |
4055 | + |
4056 | + def discard(self, key): |
4057 | + """Remove key from the set, whether it exists or not. |
4058 | + |
4059 | + :return: False if the item did not exist, True if it did |
4060 | + """ |
4061 | + if self._discard(key): |
4062 | + return True |
4063 | + return False |
4064 | + |
4065 | + cdef int _discard(self, key) except -1: |
4066 | + cdef PyObject **slot, *py_key |
4067 | + |
4068 | + slot = _lookup(self, key) |
4069 | + if slot[0] == NULL or slot[0] == _dummy: |
4070 | + return 0 |
4071 | + self._used = self._used - 1 |
4072 | + Py_DECREF(slot[0]) |
4073 | + slot[0] = _dummy |
4074 | + # PySet uses the heuristic: If more than 1/5 are dummies, then resize |
4075 | + # them away |
4076 | + # if ((so->_fill - so->_used) * 5 < so->mask) |
4077 | + # However, we are planning on using this as an interning structure, in |
4078 | + # which we will be putting a lot of objects. And we expect that large |
4079 | + # groups of them are going to have the same lifetime. |
4080 | + # Dummy entries hurt a little bit because they cause the lookup to keep |
4081 | + # searching, but resizing is also rather expensive |
4082 | + # For now, we'll just use their algorithm, but we may want to revisit |
4083 | + # it |
4084 | + if ((self._fill - self._used) * 5 > self._mask): |
4085 | + self._resize(self._used * 2) |
4086 | + return 1 |
4087 | + |
4088 | + def __iter__(self): |
4089 | + return _SimpleSet_iterator(self) |
4090 | + |
4091 | + |
4092 | +cdef class _SimpleSet_iterator: |
4093 | + """Iterator over the SimpleSet structure.""" |
4094 | + |
4095 | + cdef Py_ssize_t pos |
4096 | + cdef SimpleSet set |
4097 | + cdef Py_ssize_t _used # track if things have been mutated while iterating |
4098 | + cdef Py_ssize_t len # number of entries left |
4099 | + |
4100 | + def __init__(self, obj): |
4101 | + self.set = obj |
4102 | + self.pos = 0 |
4103 | + self._used = self.set._used |
4104 | + self.len = self.set._used |
4105 | + |
4106 | + def __iter__(self): |
4107 | + return self |
4108 | + |
4109 | + def __next__(self): |
4110 | + cdef Py_ssize_t mask, i |
4111 | + cdef PyObject *key |
4112 | + |
4113 | + if self.set is None: |
4114 | + raise StopIteration |
4115 | + if self.set._used != self._used: |
4116 | + # Force this exception to continue to be raised |
4117 | + self._used = -1 |
4118 | + raise RuntimeError("Set size changed during iteration") |
4119 | + if not SimpleSet_Next(self.set, &self.pos, &key): |
4120 | + self.set = None |
4121 | + raise StopIteration |
4122 | + # we found something |
4123 | + the_key = <object>key # INCREF |
4124 | + self.len = self.len - 1 |
4125 | + return the_key |
4126 | + |
4127 | + def __length_hint__(self): |
4128 | + if self.set is not None and self._used == self.set._used: |
4129 | + return self.len |
4130 | + return 0 |
4131 | + |
4132 | + |
4133 | + |
4134 | +cdef api SimpleSet SimpleSet_New(): |
4135 | + """Create a new SimpleSet object.""" |
4136 | + return SimpleSet() |
4137 | + |
4138 | + |
4139 | +cdef SimpleSet _check_self(object self): |
4140 | + """Check that the parameter is not None. |
4141 | + |
4142 | + Pyrex/Cython will do type checking, but only to ensure that an object is |
4143 | + either the right type or None. You can say "object foo not None" for pure |
4144 | + python functions, but not for C functions. |
4145 | + So this is just a helper for all the apis that need to do the check. |
4146 | + """ |
4147 | + cdef SimpleSet true_self |
4148 | + if self is None: |
4149 | + raise TypeError('self must not be None') |
4150 | + true_self = self |
4151 | + return true_self |
4152 | + |
4153 | + |
4154 | +cdef PyObject **_lookup(SimpleSet self, object key) except NULL: |
4155 | + """Find the slot where 'key' would fit. |
4156 | + |
4157 | + This is the same as a dicts 'lookup' function. |
4158 | + |
4159 | + :param key: An object we are looking up |
4160 | + :param hash: The hash for key |
4161 | + :return: The location in self.table where key should be put. |
4162 | + location == NULL is an exception, but (*location) == NULL just |
4163 | + indicates the slot is empty and can be used. |
4164 | + """ |
4165 | + # This uses Quadratic Probing: |
4166 | + # http://en.wikipedia.org/wiki/Quadratic_probing |
4167 | + # with c1 = c2 = 1/2 |
4168 | + # This leads to probe locations at: |
4169 | + # h0 = hash(k1) |
4170 | + # h1 = h0 + 1 |
4171 | + # h2 = h0 + 3 = h1 + 1 + 1 |
4172 | + # h3 = h0 + 6 = h2 + 1 + 2 |
4173 | + # h4 = h0 + 10 = h2 + 1 + 3 |
4174 | + # Note that all of these are '& mask', but that is computed *after* the |
4175 | + # offset. |
4176 | + # This differs from the algorithm used by Set and Dict. Which, effectively, |
4177 | + # use double-hashing, and a step size that starts large, but dwindles to |
4178 | + # stepping one-by-one. |
4179 | + # This gives more 'locality' in that if you have a collision at offset X, |
4180 | + # the first fallback is X+1, which is fast to check. However, that means |
4181 | + # that an object w/ hash X+1 will also check there, and then X+2 next. |
4182 | + # However, for objects with differing hashes, their chains are different. |
4183 | + # The former checks X, X+1, X+3, ... the latter checks X+1, X+2, X+4, ... |
4184 | + # So different hashes diverge quickly. |
4185 | + # A bigger problem is that we *only* ever use the lowest bits of the hash |
4186 | + # So all integers (x + SIZE*N) will resolve into the same bucket, and all |
4187 | + # use the same collision resolution. We may want to try to find a way to |
4188 | + # incorporate the upper bits of the hash with quadratic probing. (For |
4189 | + # example, X, X+1, X+3+some_upper_bits, X+6+more_upper_bits, etc.) |
4190 | + cdef size_t i, n_lookup |
4191 | + cdef Py_ssize_t mask |
4192 | + cdef long key_hash |
4193 | + cdef PyObject **table, **slot, *cur, **free_slot, *py_key |
4194 | + |
4195 | + py_key = <PyObject *>key |
4196 | + # Note: avoid using hash(obj) because of a bug w/ pyrex 0.9.8.5 and 64-bit |
4197 | + # (it treats hash() as returning an 'int' rather than a 'long') |
4198 | + key_hash = PyObject_Hash(py_key) |
4199 | + i = <size_t>key_hash |
4200 | + mask = self._mask |
4201 | + table = self._table |
4202 | + free_slot = NULL |
4203 | + for n_lookup from 0 <= n_lookup <= <size_t>mask: # Don't loop forever |
4204 | + slot = &table[i & mask] |
4205 | + cur = slot[0] |
4206 | + if cur == NULL: |
4207 | + # Found a blank spot |
4208 | + if free_slot != NULL: |
4209 | + # Did we find an earlier _dummy entry? |
4210 | + return free_slot |
4211 | + else: |
4212 | + return slot |
4213 | + if cur == py_key: |
4214 | + # Found an exact pointer to the key |
4215 | + return slot |
4216 | + if cur == _dummy: |
4217 | + if free_slot == NULL: |
4218 | + free_slot = slot |
4219 | + elif _is_equal(py_key, key_hash, cur): |
4220 | + # Both py_key and cur belong in this slot, return it |
4221 | + return slot |
4222 | + i = i + 1 + n_lookup |
4223 | + raise AssertionError('should never get here') |
4224 | + |
4225 | + |
4226 | +cdef api PyObject **_SimpleSet_Lookup(object self, object key) except NULL: |
4227 | + """Find the slot where 'key' would fit. |
4228 | + |
4229 | + This is the same as a dicts 'lookup' function. This is a private |
4230 | + api because mutating what you get without maintaing the other invariants |
4231 | + is a 'bad thing'. |
4232 | + |
4233 | + :param key: An object we are looking up |
4234 | + :param hash: The hash for key |
4235 | + :return: The location in self._table where key should be put |
4236 | + should never be NULL, but may reference a NULL (PyObject*) |
4237 | + """ |
4238 | + return _lookup(_check_self(self), key) |
4239 | + |
4240 | + |
4241 | +cdef api object SimpleSet_Add(object self, object key): |
4242 | + """Add a key to the SimpleSet (set). |
4243 | + |
4244 | + :param self: The SimpleSet to add the key to. |
4245 | + :param key: The key to be added. If the key is already present, |
4246 | + self will not be modified |
4247 | + :return: The current key stored at the location defined by 'key'. |
4248 | + This may be the same object, or it may be an equivalent object. |
4249 | + (consider dict.setdefault(key, key)) |
4250 | + """ |
4251 | + return _check_self(self)._add(key) |
4252 | + |
4253 | + |
4254 | +cdef api int SimpleSet_Contains(object self, object key) except -1: |
4255 | + """Is key present in self?""" |
4256 | + return (key in _check_self(self)) |
4257 | + |
4258 | + |
4259 | +cdef api int SimpleSet_Discard(object self, object key) except -1: |
4260 | + """Remove the object referenced at location 'key'. |
4261 | + |
4262 | + :param self: The SimpleSet being modified |
4263 | + :param key: The key we are checking on |
4264 | + :return: 1 if there was an object present, 0 if there was not, and -1 on |
4265 | + error. |
4266 | + """ |
4267 | + return _check_self(self)._discard(key) |
4268 | + |
4269 | + |
4270 | +cdef api PyObject *SimpleSet_Get(SimpleSet self, object key) except? NULL: |
4271 | + """Get a pointer to the object present at location 'key'. |
4272 | + |
4273 | + This returns an object which is equal to key which was previously added to |
4274 | + self. This returns a borrowed reference, as it may also return NULL if no |
4275 | + value is present at that location. |
4276 | + |
4277 | + :param key: The value we are looking for |
4278 | + :return: The object present at that location |
4279 | + """ |
4280 | + return _check_self(self)._get(key) |
4281 | + |
4282 | + |
4283 | +cdef api Py_ssize_t SimpleSet_Size(object self) except -1: |
4284 | + """Get the number of active entries in 'self'""" |
4285 | + return _check_self(self)._used |
4286 | + |
4287 | + |
4288 | +cdef api int SimpleSet_Next(object self, Py_ssize_t *pos, PyObject **key): |
4289 | + """Walk over items in a SimpleSet. |
4290 | + |
4291 | + :param pos: should be initialized to 0 by the caller, and will be updated |
4292 | + by this function |
4293 | + :param key: Will return a borrowed reference to key |
4294 | + :return: 0 if nothing left, 1 if we are returning a new value |
4295 | + """ |
4296 | + cdef Py_ssize_t i, mask |
4297 | + cdef SimpleSet true_self |
4298 | + cdef PyObject **table |
4299 | + true_self = _check_self(self) |
4300 | + i = pos[0] |
4301 | + if (i < 0): |
4302 | + return 0 |
4303 | + mask = true_self._mask |
4304 | + table= true_self._table |
4305 | + while (i <= mask and (table[i] == NULL or table[i] == _dummy)): |
4306 | + i = i + 1 |
4307 | + pos[0] = i + 1 |
4308 | + if (i > mask): |
4309 | + return 0 # All done |
4310 | + if (key != NULL): |
4311 | + key[0] = table[i] |
4312 | + return 1 |
4313 | + |
4314 | + |
4315 | +cdef int SimpleSet_traverse(SimpleSet self, visitproc visit, void *arg): |
4316 | + """This is an implementation of 'tp_traverse' that hits the whole table. |
4317 | + |
4318 | + Cython/Pyrex don't seem to let you define a tp_traverse, and they only |
4319 | + define one for you if you have an 'object' attribute. Since they don't |
4320 | + support C arrays of objects, we access the PyObject * directly. |
4321 | + """ |
4322 | + cdef Py_ssize_t pos |
4323 | + cdef PyObject *next_key |
4324 | + cdef int ret |
4325 | + |
4326 | + pos = 0 |
4327 | + while SimpleSet_Next(self, &pos, &next_key): |
4328 | + ret = visit(next_key, arg) |
4329 | + if ret: |
4330 | + return ret |
4331 | + return 0 |
4332 | + |
4333 | +# It is a little bit ugly to do this, but it works, and means that Meliae can |
4334 | +# dump the total memory consumed by all child objects. |
4335 | +(<PyTypeObject *>SimpleSet).tp_traverse = <traverseproc>SimpleSet_traverse |
4336 | |
4337 | === added file 'bzrlib/_static_tuple_c.c' |
4338 | --- bzrlib/_static_tuple_c.c 1970-01-01 00:00:00 +0000 |
4339 | +++ bzrlib/_static_tuple_c.c 2009-11-03 09:40:55 +0000 |
4340 | @@ -0,0 +1,941 @@ |
4341 | +/* Copyright (C) 2009 Canonical Ltd |
4342 | + * |
4343 | + * This program is free software; you can redistribute it and/or modify |
4344 | + * it under the terms of the GNU General Public License as published by |
4345 | + * the Free Software Foundation; either version 2 of the License, or |
4346 | + * (at your option) any later version. |
4347 | + * |
4348 | + * This program is distributed in the hope that it will be useful, |
4349 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4350 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4351 | + * GNU General Public License for more details. |
4352 | + * |
4353 | + * You should have received a copy of the GNU General Public License |
4354 | + * along with this program; if not, write to the Free Software |
4355 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
4356 | + */ |
4357 | + |
4358 | +/* Must be defined before importing _static_tuple_c.h so that we get the right |
4359 | + * linkage. |
4360 | + */ |
4361 | +#define STATIC_TUPLE_MODULE |
4362 | + |
4363 | +#include <Python.h> |
4364 | +#include "python-compat.h" |
4365 | + |
4366 | +#include "_static_tuple_c.h" |
4367 | +#include "_export_c_api.h" |
4368 | + |
4369 | +/* Pyrex 0.9.6.4 exports _simple_set_pyx_api as |
4370 | + * import__simple_set_pyx(), while Pyrex 0.9.8.5 and Cython 0.11.3 export them |
4371 | + * as import_bzrlib___simple_set_pyx(). As such, we just #define one to be |
4372 | + * equivalent to the other in our internal code. |
4373 | + */ |
4374 | +#define import__simple_set_pyx import_bzrlib___simple_set_pyx |
4375 | +#include "_simple_set_pyx_api.h" |
4376 | + |
4377 | +#if defined(__GNUC__) |
4378 | +# define inline __inline__ |
4379 | +#elif defined(_MSC_VER) |
4380 | +# define inline __inline |
4381 | +#else |
4382 | +# define inline |
4383 | +#endif |
4384 | + |
4385 | + |
4386 | +/* The one and only StaticTuple with no values */ |
4387 | +static StaticTuple *_empty_tuple = NULL; |
4388 | +static PyObject *_interned_tuples = NULL; |
4389 | + |
4390 | + |
4391 | +static inline int |
4392 | +_StaticTuple_is_interned(StaticTuple *self) |
4393 | +{ |
4394 | + return self->flags & STATIC_TUPLE_INTERNED_FLAG; |
4395 | +} |
4396 | + |
4397 | + |
4398 | + |
4399 | +static PyObject * |
4400 | +StaticTuple_as_tuple(StaticTuple *self) |
4401 | +{ |
4402 | + PyObject *tpl = NULL, *obj = NULL; |
4403 | + int i, len; |
4404 | + |
4405 | + len = self->size; |
4406 | + tpl = PyTuple_New(len); |
4407 | + if (!tpl) { |
4408 | + /* Malloc failure */ |
4409 | + return NULL; |
4410 | + } |
4411 | + for (i = 0; i < len; ++i) { |
4412 | + obj = (PyObject *)self->items[i]; |
4413 | + Py_INCREF(obj); |
4414 | + PyTuple_SET_ITEM(tpl, i, obj); |
4415 | + } |
4416 | + return tpl; |
4417 | +} |
4418 | + |
4419 | + |
4420 | +static char StaticTuple_as_tuple_doc[] = "as_tuple() => tuple"; |
4421 | + |
4422 | +static StaticTuple * |
4423 | +StaticTuple_Intern(StaticTuple *self) |
4424 | +{ |
4425 | + PyObject *canonical_tuple = NULL; |
4426 | + |
4427 | + if (_interned_tuples == NULL || _StaticTuple_is_interned(self)) { |
4428 | + Py_INCREF(self); |
4429 | + return self; |
4430 | + } |
4431 | + /* SimpleSet_Add returns whatever object is present at self |
4432 | + * or the new object if it needs to add it. |
4433 | + */ |
4434 | + canonical_tuple = SimpleSet_Add(_interned_tuples, (PyObject *)self); |
4435 | + if (!canonical_tuple) { |
4436 | + // Some sort of exception, propogate it. |
4437 | + return NULL; |
4438 | + } |
4439 | + if (canonical_tuple != (PyObject *)self) { |
4440 | + // There was already a tuple with that value |
4441 | + return (StaticTuple *)canonical_tuple; |
4442 | + } |
4443 | + self->flags |= STATIC_TUPLE_INTERNED_FLAG; |
4444 | + // The two references in the dict do not count, so that the StaticTuple |
4445 | + // object does not become immortal just because it was interned. |
4446 | + Py_REFCNT(self) -= 1; |
4447 | + return self; |
4448 | +} |
4449 | + |
4450 | +static char StaticTuple_Intern_doc[] = "intern() => unique StaticTuple\n" |
4451 | + "Return a 'canonical' StaticTuple object.\n" |
4452 | + "Similar to intern() for strings, this makes sure there\n" |
4453 | + "is only one StaticTuple object for a given value\n." |
4454 | + "Common usage is:\n" |
4455 | + " key = StaticTuple('foo', 'bar').intern()\n"; |
4456 | + |
4457 | + |
4458 | +static void |
4459 | +StaticTuple_dealloc(StaticTuple *self) |
4460 | +{ |
4461 | + int i, len; |
4462 | + |
4463 | + if (_StaticTuple_is_interned(self)) { |
4464 | + /* revive dead object temporarily for Discard */ |
4465 | + Py_REFCNT(self) = 2; |
4466 | + if (SimpleSet_Discard(_interned_tuples, (PyObject*)self) != 1) |
4467 | + Py_FatalError("deletion of interned StaticTuple failed"); |
4468 | + self->flags &= ~STATIC_TUPLE_INTERNED_FLAG; |
4469 | + } |
4470 | + len = self->size; |
4471 | + for (i = 0; i < len; ++i) { |
4472 | + Py_XDECREF(self->items[i]); |
4473 | + } |
4474 | + Py_TYPE(self)->tp_free((PyObject *)self); |
4475 | +} |
4476 | + |
4477 | + |
4478 | +/* Similar to PyTuple_New() */ |
4479 | +static StaticTuple * |
4480 | +StaticTuple_New(Py_ssize_t size) |
4481 | +{ |
4482 | + StaticTuple *stuple; |
4483 | + if (size < 0) { |
4484 | + PyErr_BadInternalCall(); |
4485 | + return NULL; |
4486 | + } |
4487 | + |
4488 | + if (size < 0 || size > 255) { |
4489 | + /* Too big or too small */ |
4490 | + PyErr_SetString(PyExc_ValueError, "StaticTuple(...)" |
4491 | + " takes from 0 to 255 items"); |
4492 | + return NULL; |
4493 | + } |
4494 | + if (size == 0 && _empty_tuple != NULL) { |
4495 | + Py_INCREF(_empty_tuple); |
4496 | + return _empty_tuple; |
4497 | + } |
4498 | + /* Note that we use PyObject_NewVar because we want to allocate a variable |
4499 | + * width entry. However we *aren't* truly a PyVarObject because we don't |
4500 | + * use a long for ob_size. Instead we use a plain 'size' that is an int, |
4501 | + * and will be overloaded with flags in the future. |
4502 | + * As such we do the alloc, and then have to clean up anything it does |
4503 | + * incorrectly. |
4504 | + */ |
4505 | + stuple = PyObject_NewVar(StaticTuple, &StaticTuple_Type, size); |
4506 | + if (stuple == NULL) { |
4507 | + return NULL; |
4508 | + } |
4509 | + stuple->size = size; |
4510 | + stuple->flags = 0; |
4511 | + stuple->_unused0 = 0; |
4512 | + stuple->_unused1 = 0; |
4513 | + if (size > 0) { |
4514 | + memset(stuple->items, 0, sizeof(PyObject *) * size); |
4515 | + } |
4516 | +#if STATIC_TUPLE_HAS_HASH |
4517 | + stuple->hash = -1; |
4518 | +#endif |
4519 | + return stuple; |
4520 | +} |
4521 | + |
4522 | + |
4523 | +static StaticTuple * |
4524 | +StaticTuple_FromSequence(PyObject *sequence) |
4525 | +{ |
4526 | + StaticTuple *new = NULL; |
4527 | + PyObject *as_tuple = NULL; |
4528 | + PyObject *item; |
4529 | + Py_ssize_t i, size; |
4530 | + |
4531 | + if (StaticTuple_CheckExact(sequence)) { |
4532 | + Py_INCREF(sequence); |
4533 | + return (StaticTuple *)sequence; |
4534 | + } |
4535 | + if (!PySequence_Check(sequence)) { |
4536 | + as_tuple = PySequence_Tuple(sequence); |
4537 | + if (as_tuple == NULL) |
4538 | + goto done; |
4539 | + sequence = as_tuple; |
4540 | + } |
4541 | + size = PySequence_Size(sequence); |
4542 | + if (size == -1) { |
4543 | + goto done; |
4544 | + } |
4545 | + new = StaticTuple_New(size); |
4546 | + if (new == NULL) { |
4547 | + goto done; |
4548 | + } |
4549 | + for (i = 0; i < size; ++i) { |
4550 | + // This returns a new reference, which we then 'steal' with |
4551 | + // StaticTuple_SET_ITEM |
4552 | + item = PySequence_GetItem(sequence, i); |
4553 | + if (item == NULL) { |
4554 | + Py_DECREF(new); |
4555 | + new = NULL; |
4556 | + goto done; |
4557 | + } |
4558 | + StaticTuple_SET_ITEM(new, i, item); |
4559 | + } |
4560 | +done: |
4561 | + Py_XDECREF(as_tuple); |
4562 | + return (StaticTuple *)new; |
4563 | +} |
4564 | + |
4565 | +static StaticTuple * |
4566 | +StaticTuple_from_sequence(PyObject *self, PyObject *args, PyObject *kwargs) |
4567 | +{ |
4568 | + PyObject *sequence; |
4569 | + if (!PyArg_ParseTuple(args, "O", &sequence)) |
4570 | + return NULL; |
4571 | + return StaticTuple_FromSequence(sequence); |
4572 | +} |
4573 | + |
4574 | + |
4575 | +/* Check that all items we point to are 'valid' */ |
4576 | +static int |
4577 | +StaticTuple_check_items(StaticTuple *self) |
4578 | +{ |
4579 | + int i; |
4580 | + PyObject *obj; |
4581 | + |
4582 | + for (i = 0; i < self->size; ++i) { |
4583 | + obj = self->items[i]; |
4584 | + if (obj == NULL) { |
4585 | + PyErr_SetString(PyExc_RuntimeError, "StaticTuple(...)" |
4586 | + " should not have a NULL entry."); |
4587 | + return 0; |
4588 | + } |
4589 | + if (PyString_CheckExact(obj) |
4590 | + || StaticTuple_CheckExact(obj) |
4591 | + || obj == Py_None |
4592 | + || PyBool_Check(obj) |
4593 | + || PyInt_CheckExact(obj) |
4594 | + || PyLong_CheckExact(obj) |
4595 | + || PyFloat_CheckExact(obj) |
4596 | + || PyUnicode_CheckExact(obj) |
4597 | + ) continue; |
4598 | + PyErr_Format(PyExc_TypeError, "StaticTuple(...)" |
4599 | + " requires that all items are one of" |
4600 | + " str, StaticTuple, None, bool, int, long, float, or unicode" |
4601 | + " not %s.", Py_TYPE(obj)->tp_name); |
4602 | + return 0; |
4603 | + } |
4604 | + return 1; |
4605 | +} |
4606 | + |
4607 | +static PyObject * |
4608 | +StaticTuple_new_constructor(PyTypeObject *type, PyObject *args, PyObject *kwds) |
4609 | +{ |
4610 | + StaticTuple *self; |
4611 | + PyObject *obj = NULL; |
4612 | + Py_ssize_t i, len = 0; |
4613 | + |
4614 | + if (type != &StaticTuple_Type) { |
4615 | + PyErr_SetString(PyExc_TypeError, "we only support creating StaticTuple"); |
4616 | + return NULL; |
4617 | + } |
4618 | + if (!PyTuple_CheckExact(args)) { |
4619 | + PyErr_SetString(PyExc_TypeError, "args must be a tuple"); |
4620 | + return NULL; |
4621 | + } |
4622 | + len = PyTuple_GET_SIZE(args); |
4623 | + self = (StaticTuple *)StaticTuple_New(len); |
4624 | + if (self == NULL) { |
4625 | + return NULL; |
4626 | + } |
4627 | + for (i = 0; i < len; ++i) { |
4628 | + obj = PyTuple_GET_ITEM(args, i); |
4629 | + Py_INCREF(obj); |
4630 | + self->items[i] = obj; |
4631 | + } |
4632 | + if (!StaticTuple_check_items(self)) { |
4633 | + type->tp_dealloc((PyObject *)self); |
4634 | + return NULL; |
4635 | + } |
4636 | + return (PyObject *)self; |
4637 | +} |
4638 | + |
4639 | +static PyObject * |
4640 | +StaticTuple_repr(StaticTuple *self) |
4641 | +{ |
4642 | + PyObject *as_tuple, *tuple_repr, *result; |
4643 | + |
4644 | + as_tuple = StaticTuple_as_tuple(self); |
4645 | + if (as_tuple == NULL) { |
4646 | + return NULL; |
4647 | + } |
4648 | + tuple_repr = PyObject_Repr(as_tuple); |
4649 | + Py_DECREF(as_tuple); |
4650 | + if (tuple_repr == NULL) { |
4651 | + return NULL; |
4652 | + } |
4653 | + result = PyString_FromFormat("StaticTuple%s", |
4654 | + PyString_AsString(tuple_repr)); |
4655 | + return result; |
4656 | +} |
4657 | + |
4658 | +static long |
4659 | +StaticTuple_hash(StaticTuple *self) |
4660 | +{ |
4661 | + /* adapted from tuplehash(), is the specific hash value considered |
4662 | + * 'stable'? |
4663 | + */ |
4664 | + register long x, y; |
4665 | + Py_ssize_t len = self->size; |
4666 | + PyObject **p; |
4667 | + long mult = 1000003L; |
4668 | + |
4669 | +#if STATIC_TUPLE_HAS_HASH |
4670 | + if (self->hash != -1) { |
4671 | + return self->hash; |
4672 | + } |
4673 | +#endif |
4674 | + x = 0x345678L; |
4675 | + p = self->items; |
4676 | + // TODO: We could set specific flags if we know that, for example, all the |
4677 | + // items are strings. I haven't seen a real-world benefit to that |
4678 | + // yet, though. |
4679 | + while (--len >= 0) { |
4680 | + y = PyObject_Hash(*p++); |
4681 | + if (y == -1) /* failure */ |
4682 | + return -1; |
4683 | + x = (x ^ y) * mult; |
4684 | + /* the cast might truncate len; that doesn't change hash stability */ |
4685 | + mult += (long)(82520L + len + len); |
4686 | + } |
4687 | + x += 97531L; |
4688 | + if (x == -1) |
4689 | + x = -2; |
4690 | +#if STATIC_TUPLE_HAS_HASH |
4691 | + self->hash = x; |
4692 | +#endif |
4693 | + return x; |
4694 | +} |
4695 | + |
4696 | +static PyObject * |
4697 | +StaticTuple_richcompare_to_tuple(StaticTuple *v, PyObject *wt, int op) |
4698 | +{ |
4699 | + PyObject *vt; |
4700 | + PyObject *result = NULL; |
4701 | + |
4702 | + vt = StaticTuple_as_tuple((StaticTuple *)v); |
4703 | + if (vt == NULL) { |
4704 | + goto done; |
4705 | + } |
4706 | + if (!PyTuple_Check(wt)) { |
4707 | + PyErr_BadInternalCall(); |
4708 | + goto done; |
4709 | + } |
4710 | + /* Now we have 2 tuples to compare, do it */ |
4711 | + result = PyTuple_Type.tp_richcompare(vt, wt, op); |
4712 | +done: |
4713 | + Py_XDECREF(vt); |
4714 | + return result; |
4715 | +} |
4716 | + |
4717 | +/** Compare two objects to determine if they are equivalent. |
4718 | + * The basic flow is as follows |
4719 | + * 1) First make sure that both objects are StaticTuple instances. If they |
4720 | + * aren't then cast self to a tuple, and have the tuple do the comparison. |
4721 | + * 2) Special case comparison to Py_None, because it happens to occur fairly |
4722 | + * often in the test suite. |
4723 | + * 3) Special case when v and w are the same pointer. As we know the answer to |
4724 | + * all queries without walking individual items. |
4725 | + * 4) For all operations, we then walk the items to find the first paired |
4726 | + * items that are not equal. |
4727 | + * 5) If all items found are equal, we then check the length of self and |
4728 | + * other to determine equality. |
4729 | + * 6) If an item differs, then we apply "op" to those last two items. (eg. |
4730 | + * StaticTuple(A, B) > StaticTuple(A, C) iff B > C) |
4731 | + */ |
4732 | + |
4733 | +static PyObject * |
4734 | +StaticTuple_richcompare(PyObject *v, PyObject *w, int op) |
4735 | +{ |
4736 | + StaticTuple *v_st, *w_st; |
4737 | + Py_ssize_t vlen, wlen, min_len, i; |
4738 | + PyObject *v_obj, *w_obj; |
4739 | + richcmpfunc string_richcompare; |
4740 | + |
4741 | + if (!StaticTuple_CheckExact(v)) { |
4742 | + /* This has never triggered, according to python-dev it seems this |
4743 | + * might trigger if '__op__' is defined but '__rop__' is not, sort of |
4744 | + * case. Such as "None == StaticTuple()" |
4745 | + */ |
4746 | + fprintf(stderr, "self is not StaticTuple\n"); |
4747 | + Py_INCREF(Py_NotImplemented); |
4748 | + return Py_NotImplemented; |
4749 | + } |
4750 | + v_st = (StaticTuple *)v; |
4751 | + if (StaticTuple_CheckExact(w)) { |
4752 | + /* The most common case */ |
4753 | + w_st = (StaticTuple*)w; |
4754 | + } else if (PyTuple_Check(w)) { |
4755 | + /* One of v or w is a tuple, so we go the 'slow' route and cast up to |
4756 | + * tuples to compare. |
4757 | + */ |
4758 | + /* TODO: This seems to be triggering more than I thought it would... |
4759 | + * We probably want to optimize comparing self to other when |
4760 | + * other is a tuple. |
4761 | + */ |
4762 | + return StaticTuple_richcompare_to_tuple(v_st, w, op); |
4763 | + } else if (w == Py_None) { |
4764 | + // None is always less than the object |
4765 | + switch (op) { |
4766 | + case Py_NE:case Py_GT:case Py_GE: |
4767 | + Py_INCREF(Py_True); |
4768 | + return Py_True; |
4769 | + case Py_EQ:case Py_LT:case Py_LE: |
4770 | + Py_INCREF(Py_False); |
4771 | + return Py_False; |
4772 | + default: // Should never happen |
4773 | + return Py_NotImplemented; |
4774 | + } |
4775 | + } else { |
4776 | + /* We don't special case this comparison, we just let python handle |
4777 | + * it. |
4778 | + */ |
4779 | + Py_INCREF(Py_NotImplemented); |
4780 | + return Py_NotImplemented; |
4781 | + } |
4782 | + /* Now we know that we have 2 StaticTuple objects, so let's compare them. |
4783 | + * This code is inspired from tuplerichcompare, except we know our |
4784 | + * objects are limited in scope, so we can inline some comparisons. |
4785 | + */ |
4786 | + if (v == w) { |
4787 | + /* Identical pointers, we can shortcut this easily. */ |
4788 | + switch (op) { |
4789 | + case Py_EQ:case Py_LE:case Py_GE: |
4790 | + Py_INCREF(Py_True); |
4791 | + return Py_True; |
4792 | + case Py_NE:case Py_LT:case Py_GT: |
4793 | + Py_INCREF(Py_False); |
4794 | + return Py_False; |
4795 | + } |
4796 | + } |
4797 | + if (op == Py_EQ |
4798 | + && _StaticTuple_is_interned(v_st) |
4799 | + && _StaticTuple_is_interned(w_st)) |
4800 | + { |
4801 | + /* If both objects are interned, we know they are different if the |
4802 | + * pointer is not the same, which would have been handled by the |
4803 | + * previous if. No need to compare the entries. |
4804 | + */ |
4805 | + Py_INCREF(Py_False); |
4806 | + return Py_False; |
4807 | + } |
4808 | + |
4809 | + /* The only time we are likely to compare items of different lengths is in |
4810 | + * something like the interned_keys set. However, the hash is good enough |
4811 | + * that it is rare. Note that 'tuple_richcompare' also does not compare |
4812 | + * lengths here. |
4813 | + */ |
4814 | + vlen = v_st->size; |
4815 | + wlen = w_st->size; |
4816 | + min_len = (vlen < wlen) ? vlen : wlen; |
4817 | + string_richcompare = PyString_Type.tp_richcompare; |
4818 | + for (i = 0; i < min_len; i++) { |
4819 | + PyObject *result = NULL; |
4820 | + v_obj = StaticTuple_GET_ITEM(v_st, i); |
4821 | + w_obj = StaticTuple_GET_ITEM(w_st, i); |
4822 | + if (v_obj == w_obj) { |
4823 | + /* Shortcut case, these must be identical */ |
4824 | + continue; |
4825 | + } |
4826 | + if (PyString_CheckExact(v_obj) && PyString_CheckExact(w_obj)) { |
4827 | + result = string_richcompare(v_obj, w_obj, Py_EQ); |
4828 | + } else if (StaticTuple_CheckExact(v_obj) && |
4829 | + StaticTuple_CheckExact(w_obj)) |
4830 | + { |
4831 | + /* Both are StaticTuple types, so recurse */ |
4832 | + result = StaticTuple_richcompare(v_obj, w_obj, Py_EQ); |
4833 | + } else { |
4834 | + /* Fall back to generic richcompare */ |
4835 | + result = PyObject_RichCompare(v_obj, w_obj, Py_EQ); |
4836 | + } |
4837 | + if (result == NULL) { |
4838 | + return NULL; /* There seems to be an error */ |
4839 | + } |
4840 | + if (result == Py_False) { |
4841 | + // This entry is not identical, Shortcut for Py_EQ |
4842 | + if (op == Py_EQ) { |
4843 | + return result; |
4844 | + } |
4845 | + Py_DECREF(result); |
4846 | + break; |
4847 | + } |
4848 | + if (result != Py_True) { |
4849 | + /* We don't know *what* richcompare is returning, but it |
4850 | + * isn't something we recognize |
4851 | + */ |
4852 | + PyErr_BadInternalCall(); |
4853 | + Py_DECREF(result); |
4854 | + return NULL; |
4855 | + } |
4856 | + Py_DECREF(result); |
4857 | + } |
4858 | + if (i >= min_len) { |
4859 | + /* We walked off one of the lists, but everything compared equal so |
4860 | + * far. Just compare the size. |
4861 | + */ |
4862 | + int cmp; |
4863 | + PyObject *res; |
4864 | + switch (op) { |
4865 | + case Py_LT: cmp = vlen < wlen; break; |
4866 | + case Py_LE: cmp = vlen <= wlen; break; |
4867 | + case Py_EQ: cmp = vlen == wlen; break; |
4868 | + case Py_NE: cmp = vlen != wlen; break; |
4869 | + case Py_GT: cmp = vlen > wlen; break; |
4870 | + case Py_GE: cmp = vlen >= wlen; break; |
4871 | + default: return NULL; /* cannot happen */ |
4872 | + } |
4873 | + if (cmp) |
4874 | + res = Py_True; |
4875 | + else |
4876 | + res = Py_False; |
4877 | + Py_INCREF(res); |
4878 | + return res; |
4879 | + } |
4880 | + /* The last item differs, shortcut the Py_NE case */ |
4881 | + if (op == Py_NE) { |
4882 | + Py_INCREF(Py_True); |
4883 | + return Py_True; |
4884 | + } |
4885 | + /* It is some other comparison, go ahead and do the real check. */ |
4886 | + if (PyString_CheckExact(v_obj) && PyString_CheckExact(w_obj)) |
4887 | + { |
4888 | + return string_richcompare(v_obj, w_obj, op); |
4889 | + } else if (StaticTuple_CheckExact(v_obj) && |
4890 | + StaticTuple_CheckExact(w_obj)) |
4891 | + { |
4892 | + /* Both are StaticTuple types, so recurse */ |
4893 | + return StaticTuple_richcompare(v_obj, w_obj, op); |
4894 | + } else { |
4895 | + return PyObject_RichCompare(v_obj, w_obj, op); |
4896 | + } |
4897 | +} |
4898 | + |
4899 | + |
4900 | +static Py_ssize_t |
4901 | +StaticTuple_length(StaticTuple *self) |
4902 | +{ |
4903 | + return self->size; |
4904 | +} |
4905 | + |
4906 | + |
4907 | +static PyObject * |
4908 | +StaticTuple__is_interned(StaticTuple *self) |
4909 | +{ |
4910 | + if (_StaticTuple_is_interned(self)) { |
4911 | + Py_INCREF(Py_True); |
4912 | + return Py_True; |
4913 | + } |
4914 | + Py_INCREF(Py_False); |
4915 | + return Py_False; |
4916 | +} |
4917 | + |
4918 | +static char StaticTuple__is_interned_doc[] = "_is_interned() => True/False\n" |
4919 | + "Check to see if this tuple has been interned.\n"; |
4920 | + |
4921 | + |
4922 | +static PyObject * |
4923 | +StaticTuple_reduce(StaticTuple *self) |
4924 | +{ |
4925 | + PyObject *result = NULL, *as_tuple = NULL; |
4926 | + |
4927 | + result = PyTuple_New(2); |
4928 | + if (!result) { |
4929 | + return NULL; |
4930 | + } |
4931 | + as_tuple = StaticTuple_as_tuple(self); |
4932 | + if (as_tuple == NULL) { |
4933 | + Py_DECREF(result); |
4934 | + return NULL; |
4935 | + } |
4936 | + Py_INCREF(&StaticTuple_Type); |
4937 | + PyTuple_SET_ITEM(result, 0, (PyObject *)&StaticTuple_Type); |
4938 | + PyTuple_SET_ITEM(result, 1, as_tuple); |
4939 | + return result; |
4940 | +} |
4941 | + |
4942 | +static char StaticTuple_reduce_doc[] = "__reduce__() => tuple\n"; |
4943 | + |
4944 | + |
4945 | +static PyObject * |
4946 | +StaticTuple_add(PyObject *v, PyObject *w) |
4947 | +{ |
4948 | + Py_ssize_t i, len_v, len_w; |
4949 | + PyObject *item; |
4950 | + StaticTuple *result; |
4951 | + /* StaticTuples and plain tuples may be added (concatenated) to |
4952 | + * StaticTuples. |
4953 | + */ |
4954 | + if (StaticTuple_CheckExact(v)) { |
4955 | + len_v = ((StaticTuple*)v)->size; |
4956 | + } else if (PyTuple_Check(v)) { |
4957 | + len_v = PyTuple_GET_SIZE(v); |
4958 | + } else { |
4959 | + Py_INCREF(Py_NotImplemented); |
4960 | + return Py_NotImplemented; |
4961 | + } |
4962 | + if (StaticTuple_CheckExact(w)) { |
4963 | + len_w = ((StaticTuple*)w)->size; |
4964 | + } else if (PyTuple_Check(w)) { |
4965 | + len_w = PyTuple_GET_SIZE(w); |
4966 | + } else { |
4967 | + Py_INCREF(Py_NotImplemented); |
4968 | + return Py_NotImplemented; |
4969 | + } |
4970 | + result = StaticTuple_New(len_v + len_w); |
4971 | + if (result == NULL) |
4972 | + return NULL; |
4973 | + for (i = 0; i < len_v; ++i) { |
4974 | + // This returns a new reference, which we then 'steal' with |
4975 | + // StaticTuple_SET_ITEM |
4976 | + item = PySequence_GetItem(v, i); |
4977 | + if (item == NULL) { |
4978 | + Py_DECREF(result); |
4979 | + return NULL; |
4980 | + } |
4981 | + StaticTuple_SET_ITEM(result, i, item); |
4982 | + } |
4983 | + for (i = 0; i < len_w; ++i) { |
4984 | + item = PySequence_GetItem(w, i); |
4985 | + if (item == NULL) { |
4986 | + Py_DECREF(result); |
4987 | + return NULL; |
4988 | + } |
4989 | + StaticTuple_SET_ITEM(result, i+len_v, item); |
4990 | + } |
4991 | + if (!StaticTuple_check_items(result)) { |
4992 | + Py_DECREF(result); |
4993 | + return NULL; |
4994 | + } |
4995 | + return (PyObject *)result; |
4996 | +} |
4997 | + |
4998 | +static PyObject * |
4999 | +StaticTuple_item(StaticTuple *self, Py_ssize_t offset) |
5000 | +{ |
I finalized a patch proposed by bialix with a more focused test.
Like bialix tests it catches the two actual bugs in bzr but in addition,
it will catch any such bugs in plugins.