Merge lp:~mbp/bzr/deprecation-old into lp:~bzr/bzr/trunk-old

Proposed by Martin Pool on 2009-06-05
Status: Merged
Merged at revision: not available
Proposed branch: lp:~mbp/bzr/deprecation-old
Merge into: lp:~bzr/bzr/trunk-old
Diff against target: 769 lines
To merge this branch: bzr merge lp:~mbp/bzr/deprecation-old
Reviewer Review Type Date Requested Status
John A Meinel 2009-06-05 Approve on 2009-06-08
Review via email: mp+7135@code.launchpad.net
To post a comment you must log in.
Martin Pool (mbp) wrote :

This deprecates and deletes old progress bar related code, and the weave.py main method.

lp:~mbp/bzr/deprecation-old updated on 2009-06-06
4416. By Canonical.com Patch Queue Manager <email address hidden> on 2009-06-06

(mbp) better handling of 'directory not empty' over sftp

John A Meinel (jameinel) wrote :

This seems okay, though I wonder if you deleted too many tests.

Usually when we deprecate something, we keep it under test, and add a "callDeprecated" or "applyDeprecated" wrap around its call. Which ensures that
1) it is still properly deprecated
2) And it still works the way it used to, until it is removed

Deleting the tests of things that were already deprecated is, of course, fine.

Anyway, just take another quick look and see if you really wanted to delete all of TestProgressTypes, and if so, go ahead and merge.

review: Approve
Martin Pool (mbp) wrote :

2009/6/8 John A Meinel <email address hidden>:
> Review: Approve
> This seems okay, though I wonder if you deleted too many tests.
>
> Usually when we deprecate something, we keep it under test, and add a "callDeprecated" or "applyDeprecated" wrap around its call. Which ensures that
> 1) it is still properly deprecated
> 2) And it still works the way it used to, until it is removed
>
> Deleting the tests of things that were already deprecated is, of course, fine.
>
> Anyway, just take another quick look and see if you really wanted to delete all of TestProgressTypes, and if so, go ahead and merge.

I wondered whether we should delete them too, however, keeping them
and getting them to catch warnings in all the right places was just
more work than seemed worthwhile for code that's going away. It also
makes it more clear where testing is needed for the new code. :)

The specific problem was that although it's easy to test that one
particular deprecated function works, there's no obvious way to say
"and it's ok if it calls other deprecated code in turn." Really we
also shouldn't issue warnings in that case even at run time. Some
fixes are possible but I didn't want to do them here.

--
Martin <http://launchpad.net/~mbp/>

lp:~mbp/bzr/deprecation-old updated on 2009-06-09
4417. By Canonical.com Patch Queue Manager <email address hidden> on 2009-06-09

(mbp) allow passing body as attachment to mutt

4418. By Canonical.com Patch Queue Manager <email address hidden> on 2009-06-09

(mbp) remove deprecated progress bar and weave code

4419. By Canonical.com Patch Queue Manager <email address hidden> on 2009-06-09

(andrew) Fix traceback in 'bzr serve' on Windows when a TCP client
 disconnects.

4420. By Canonical.com Patch Queue Manager <email address hidden> on 2009-06-09

(Gary van der Merwe) Add bzrlib.graph.StackedParentsProvider as a
 public API, deprecating the old name of '_StackedParentsProvider'.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2009-06-05 23:21:51 +0000
3+++ NEWS 2009-06-06 02:35:12 +0000
4@@ -103,13 +103,19 @@
5
6 * Added osutils.parent_directories(). (Ian Clatworthy)
7
8+* ``bzrlib.progress.ProgressBar``, ``ChildProgress``, ``DotsProgressBar``,
9+ ``TTYProgressBar`` and ``child_progress`` are now deprecated; use
10+ ``ui_factory.nested_progress_bar`` instead. (Martin Pool)
11+
12 * TreeTransformBase no longer assumes that limbo is provided via disk.
13 DiskTreeTransform now provides disk functionality. (Aaron Bentley)
14
15-
16 Internals
17 *********
18
19+* Remove ``weave.py`` script for accessing internals of old weave-format
20+ repositories. (Martin Pool)
21+
22 Testing
23 *******
24
25
26=== modified file 'bzrlib/progress.py'
27--- bzrlib/progress.py 2009-03-23 14:59:43 +0000
28+++ bzrlib/progress.py 2009-06-06 02:35:12 +0000
29@@ -36,11 +36,13 @@
30 )
31 from bzrlib.trace import mutter
32 from bzrlib.symbol_versioning import (
33+ deprecated_function,
34 deprecated_in,
35 deprecated_method,
36 )
37
38
39+# XXX: deprecated; can be removed when the ProgressBar factory is removed
40 def _supports_progress(f):
41 """Detect if we can use pretty progress bars on the output stream f.
42
43@@ -140,6 +142,7 @@
44 self.ui_factory.clear_term()
45
46
47+@deprecated_function(deprecated_in((1, 16, 0)))
48 def ProgressBar(to_file=None, **kwargs):
49 """Abstract factory"""
50 if to_file is None:
51@@ -163,75 +166,6 @@
52 return _progress_bar_types[requested_bar_type](to_file=to_file, **kwargs)
53
54
55-class ProgressBarStack(object):
56- """A stack of progress bars.
57-
58- This class is deprecated: instead, ask the ui factory for a new progress
59- task and finish it when it's done.
60- """
61-
62- @deprecated_method(deprecated_in((1, 12, 0)))
63- def __init__(self,
64- to_file=None,
65- show_pct=False,
66- show_spinner=True,
67- show_eta=False,
68- show_bar=True,
69- show_count=True,
70- to_messages_file=None,
71- klass=None):
72- """Setup the stack with the parameters the progress bars should have."""
73- if to_file is None:
74- to_file = sys.stderr
75- if to_messages_file is None:
76- to_messages_file = sys.stdout
77- self._to_file = to_file
78- self._show_pct = show_pct
79- self._show_spinner = show_spinner
80- self._show_eta = show_eta
81- self._show_bar = show_bar
82- self._show_count = show_count
83- self._to_messages_file = to_messages_file
84- self._stack = []
85- self._klass = klass or ProgressBar
86-
87- def top(self):
88- if len(self._stack) != 0:
89- return self._stack[-1]
90- else:
91- return None
92-
93- def bottom(self):
94- if len(self._stack) != 0:
95- return self._stack[0]
96- else:
97- return None
98-
99- def get_nested(self):
100- """Return a nested progress bar."""
101- if len(self._stack) == 0:
102- func = self._klass
103- else:
104- func = self.top().child_progress
105- new_bar = func(to_file=self._to_file,
106- show_pct=self._show_pct,
107- show_spinner=self._show_spinner,
108- show_eta=self._show_eta,
109- show_bar=self._show_bar,
110- show_count=self._show_count,
111- to_messages_file=self._to_messages_file,
112- _stack=self)
113- self._stack.append(new_bar)
114- return new_bar
115-
116- def return_pb(self, bar):
117- """Return bar after its been used."""
118- if bar is not self._stack[-1]:
119- warnings.warn("%r is not currently active" % (bar,))
120- else:
121- self._stack.pop()
122-
123-
124 class _BaseProgressBar(object):
125
126 def __init__(self,
127@@ -278,6 +212,7 @@
128 self.to_messages_file.write(fmt_string % args)
129 self.to_messages_file.write('\n')
130
131+ @deprecated_function(deprecated_in((1, 16, 0)))
132 def child_progress(self, **kwargs):
133 return ChildProgress(**kwargs)
134
135@@ -309,6 +244,7 @@
136
137 class DotsProgressBar(_BaseProgressBar):
138
139+ @deprecated_function(deprecated_in((1, 16, 0)))
140 def __init__(self, **kwargs):
141 _BaseProgressBar.__init__(self, **kwargs)
142 self.last_msg = None
143@@ -335,8 +271,6 @@
144 self.tick()
145
146
147-
148-
149 class TTYProgressBar(_BaseProgressBar):
150 """Progress bar display object.
151
152@@ -359,7 +293,7 @@
153 """
154 SPIN_CHARS = r'/-\|'
155
156-
157+ @deprecated_function(deprecated_in((1, 16, 0)))
158 def __init__(self, **kwargs):
159 from bzrlib.osutils import terminal_width
160 _BaseProgressBar.__init__(self, **kwargs)
161@@ -519,11 +453,10 @@
162 #self.to_file.flush()
163
164
165-
166-
167 class ChildProgress(_BaseProgressBar):
168 """A progress indicator that pushes its data to the parent"""
169
170+ @deprecated_function(deprecated_in((1, 16, 0)))
171 def __init__(self, _stack, **kwargs):
172 _BaseProgressBar.__init__(self, _stack=_stack, **kwargs)
173 self.parent = _stack.top()
174@@ -565,23 +498,6 @@
175 self.parent.note(*args, **kwargs)
176
177
178-class InstrumentedProgress(TTYProgressBar):
179- """TTYProgress variant that tracks outcomes"""
180-
181- def __init__(self, *args, **kwargs):
182- self.always_throttled = True
183- self.never_throttle = False
184- TTYProgressBar.__init__(self, *args, **kwargs)
185-
186- def throttle(self, old_message):
187- if self.never_throttle:
188- result = False
189- else:
190- result = TTYProgressBar.throttle(self, old_message)
191- if result is False:
192- self.always_throttled = False
193-
194-
195 def str_tdelta(delt):
196 if delt is None:
197 return "-:--:--"
198
199=== modified file 'bzrlib/tests/test_progress.py'
200--- bzrlib/tests/test_progress.py 2009-03-23 14:59:43 +0000
201+++ bzrlib/tests/test_progress.py 2009-06-06 02:35:12 +0000
202@@ -18,29 +18,12 @@
203 from StringIO import StringIO
204
205 from bzrlib import errors
206-from bzrlib.progress import (
207- DummyProgress,
208- ChildProgress,
209- TTYProgressBar,
210- DotsProgressBar,
211- ProgressBarStack,
212- InstrumentedProgress,
213- )
214 from bzrlib.tests import TestCase
215 from bzrlib.symbol_versioning import (
216 deprecated_in,
217 )
218
219
220-class FakeStack:
221-
222- def __init__(self, top):
223- self.__top = top
224-
225- def top(self):
226- return self.__top
227-
228-
229 class _TTYStringIO(StringIO):
230 """A helper class which makes a StringIO look like a terminal"""
231
232@@ -53,259 +36,3 @@
233
234 def isatty(self):
235 return False
236-
237-
238-class TestProgress(TestCase):
239-
240- def setUp(self):
241- TestCase.setUp(self)
242- q = DummyProgress()
243- self.top = ChildProgress(_stack=FakeStack(q))
244-
245- def test_propogation(self):
246- self.top.update('foobles', 1, 2)
247- self.assertEqual(self.top.message, 'foobles')
248- self.assertEqual(self.top.current, 1)
249- self.assertEqual(self.top.total, 2)
250- self.assertEqual(self.top.child_fraction, 0)
251- child = ChildProgress(_stack=FakeStack(self.top))
252- child.update('baubles', 2, 4)
253- self.assertEqual(self.top.message, 'foobles')
254- self.assertEqual(self.top.current, 1)
255- self.assertEqual(self.top.total, 2)
256- self.assertEqual(self.top.child_fraction, 0.5)
257- grandchild = ChildProgress(_stack=FakeStack(child))
258- grandchild.update('barbells', 1, 2)
259- self.assertEqual(self.top.child_fraction, 0.625)
260- self.assertEqual(child.child_fraction, 0.5)
261- child.update('baubles', 3, 4)
262- self.assertEqual(child.child_fraction, 0)
263- self.assertEqual(self.top.child_fraction, 0.75)
264- grandchild.update('barbells', 1, 2)
265- self.assertEqual(self.top.child_fraction, 0.875)
266- grandchild.update('barbells', 2, 2)
267- self.assertEqual(self.top.child_fraction, 1)
268- child.update('baubles', 4, 4)
269- self.assertEqual(self.top.child_fraction, 1)
270- #test clamping
271- grandchild.update('barbells', 2, 2)
272- self.assertEqual(self.top.child_fraction, 1)
273-
274- def test_implementations(self):
275- for implementation in (TTYProgressBar, DotsProgressBar,
276- DummyProgress):
277- self.check_parent_handling(implementation)
278-
279- def check_parent_handling(self, parentclass):
280- top = parentclass(to_file=StringIO())
281- top.update('foobles', 1, 2)
282- child = ChildProgress(_stack=FakeStack(top))
283- child.update('baubles', 4, 4)
284- top.update('lala', 2, 2)
285- child.update('baubles', 4, 4)
286-
287- def test_stacking(self):
288- self.check_stack(TTYProgressBar, ChildProgress)
289- self.check_stack(DotsProgressBar, ChildProgress)
290- self.check_stack(DummyProgress, DummyProgress)
291-
292- def check_stack(self, parent_class, child_class):
293- stack = self.applyDeprecated(
294- deprecated_in((1, 12, 0)),
295- ProgressBarStack,
296- klass=parent_class, to_file=StringIO())
297- parent = stack.get_nested()
298- try:
299- self.assertIs(parent.__class__, parent_class)
300- child = stack.get_nested()
301- try:
302- self.assertIs(child.__class__, child_class)
303- finally:
304- child.finished()
305- finally:
306- parent.finished()
307-
308- def test_throttling(self):
309- pb = InstrumentedProgress(to_file=StringIO())
310- # instantaneous updates should be squelched
311- pb.update('me', 1, 1)
312- self.assertTrue(pb.always_throttled)
313- pb = InstrumentedProgress(to_file=StringIO())
314- # It's like an instant sleep(1)!
315- pb.start_time -= 1
316- # Updates after a second should not be squelched
317- pb.update('me', 1, 1)
318- self.assertFalse(pb.always_throttled)
319-
320- def test_clear(self):
321- sio = StringIO()
322- pb = TTYProgressBar(to_file=sio, show_eta=False)
323- pb.width = 20 # Just make it easier to test
324- # This should not output anything
325- pb.clear()
326- # These two should not be displayed because
327- # of throttling
328- pb.update('foo', 1, 3)
329- pb.update('bar', 2, 3)
330- # So pb.clear() has nothing to do
331- pb.clear()
332-
333- # Make sure the next update isn't throttled
334- pb.start_time -= 1
335- pb.update('baz', 3, 3)
336- pb.clear()
337-
338- self.assertEqual('\r[=========] baz 3/3'
339- '\r \r',
340- sio.getvalue())
341-
342- def test_no_eta(self):
343- # An old version of the progress bar would
344- # store every update if show_eta was false
345- # because the eta routine was where it was
346- # cleaned out
347- pb = InstrumentedProgress(to_file=StringIO(), show_eta=False)
348- # Just make sure this first few are throttled
349- pb.start_time += 5
350-
351- # These messages are throttled, and don't contribute
352- for count in xrange(100):
353- pb.update('x', count, 300)
354- self.assertEqual(0, len(pb.last_updates))
355-
356- # Unthrottle by time
357- pb.start_time -= 10
358-
359- # These happen too fast, so only one gets through
360- for count in xrange(100):
361- pb.update('x', count+100, 200)
362- self.assertEqual(1, len(pb.last_updates))
363-
364- pb.MIN_PAUSE = 0.0
365-
366- # But all of these go through, don't let the
367- # last_update list grow without bound
368- for count in xrange(100):
369- pb.update('x', count+100, 200)
370-
371- self.assertEqual(pb._max_last_updates, len(pb.last_updates))
372-
373-
374-class TestProgressTypes(TestCase):
375- """Test that the right ProgressBar gets instantiated at the right time."""
376-
377- def get_nested(self, outf, term, env_progress=None):
378- """Setup so that ProgressBar thinks we are in the supplied terminal."""
379- orig_term = os.environ.get('TERM')
380- orig_progress = os.environ.get('BZR_PROGRESS_BAR')
381- os.environ['TERM'] = term
382- if env_progress is not None:
383- os.environ['BZR_PROGRESS_BAR'] = env_progress
384- elif orig_progress is not None:
385- del os.environ['BZR_PROGRESS_BAR']
386-
387- def reset():
388- if orig_term is None:
389- del os.environ['TERM']
390- else:
391- os.environ['TERM'] = orig_term
392- # We may have never created BZR_PROGRESS_BAR
393- # So we can't just delete like we can 'TERM' (which is always set)
394- if orig_progress is None:
395- if 'BZR_PROGRESS_BAR' in os.environ:
396- del os.environ['BZR_PROGRESS_BAR']
397- else:
398- os.environ['BZR_PROGRESS_BAR'] = orig_progress
399-
400- self.addCleanup(reset)
401-
402- stack = self.applyDeprecated(
403- deprecated_in((1, 12, 0)),
404- ProgressBarStack,
405- to_file=outf)
406- pb = stack.get_nested()
407- pb.start_time -= 1 # Make sure it is ready to write
408- pb.width = 20 # And it is of reasonable size
409- return pb
410-
411- def test_tty_progress(self):
412- # Make sure the ProgressBarStack thinks it is
413- # writing out to a terminal, and thus uses a TTYProgressBar
414- out = _TTYStringIO()
415- pb = self.get_nested(out, 'xterm')
416- self.assertIsInstance(pb, TTYProgressBar)
417- try:
418- pb.update('foo', 1, 2)
419- pb.update('bar', 2, 2)
420- finally:
421- pb.finished()
422-
423- self.assertEqual('\r/ [==== ] foo 1/2'
424- '\r- [=======] bar 2/2'
425- '\r \r',
426- out.getvalue())
427-
428- def test_noninteractive_progress(self):
429- out = _NonTTYStringIO()
430- pb = self.get_nested(out, 'xterm')
431- self.assertIsInstance(pb, DummyProgress)
432- try:
433- pb.update('foo', 1, 2)
434- pb.update('bar', 2, 2)
435- finally:
436- pb.finished()
437- self.assertEqual('', out.getvalue())
438-
439- def test_dots_progress(self):
440- # make sure we get the right progress bar when not on a terminal
441- out = _NonTTYStringIO()
442- pb = self.get_nested(out, 'xterm', 'dots')
443- self.assertIsInstance(pb, DotsProgressBar)
444- try:
445- pb.update('foo', 1, 2)
446- pb.update('bar', 2, 2)
447- finally:
448- pb.finished()
449- self.assertEqual('foo: .'
450- '\nbar: .'
451- '\n',
452- out.getvalue())
453-
454- def test_no_isatty_progress(self):
455- # Make sure ProgressBarStack handles a plain StringIO()
456- import cStringIO
457- out = cStringIO.StringIO()
458- pb = self.get_nested(out, 'xterm')
459- pb.finished()
460- self.assertIsInstance(pb, DummyProgress)
461-
462- def test_dumb_progress(self):
463- # using a terminal that can't do cursor movement
464- out = _TTYStringIO()
465- pb = self.get_nested(out, 'dumb')
466- pb.finished()
467- self.assertIsInstance(pb, DummyProgress)
468-
469- def test_progress_env_tty(self):
470- # The environ variable BZR_PROGRESS_BAR controls what type of
471- # progress bar we will get, even if it wouldn't usually be that type
472- import cStringIO
473-
474- # Usually, this would be a DotsProgressBar
475- out = cStringIO.StringIO()
476- pb = self.get_nested(out, 'dumb', 'tty')
477- pb.finished()
478- # Even though we are not a tty, the env_var will override
479- self.assertIsInstance(pb, TTYProgressBar)
480-
481- def test_progress_env_none(self):
482- # Even though we are in a valid tty, no progress
483- out = _TTYStringIO()
484- pb = self.get_nested(out, 'xterm', 'none')
485- pb.finished()
486- self.assertIsInstance(pb, DummyProgress)
487-
488- def test_progress_env_invalid(self):
489- out = _TTYStringIO()
490- self.assertRaises(errors.InvalidProgressBarType, self.get_nested,
491- out, 'xterm', 'nonexistant')
492
493=== modified file 'bzrlib/tests/test_ui.py'
494--- bzrlib/tests/test_ui.py 2009-05-15 10:14:51 +0000
495+++ bzrlib/tests/test_ui.py 2009-06-06 02:35:12 +0000
496@@ -25,12 +25,6 @@
497
498 import bzrlib
499 import bzrlib.errors as errors
500-from bzrlib.progress import (
501- DotsProgressBar,
502- ProgressBarStack,
503- ProgressTask,
504- TTYProgressBar,
505- )
506 from bzrlib.symbol_versioning import (
507 deprecated_in,
508 )
509@@ -164,33 +158,6 @@
510 pb2.finished()
511 pb1.finished()
512
513- def test_progress_stack(self):
514- # test the progress bar stack which the default text factory
515- # uses.
516- stderr = StringIO()
517- stdout = StringIO()
518- # make a stack, which accepts parameters like a pb.
519- stack = self.applyDeprecated(
520- deprecated_in((1, 12, 0)),
521- ProgressBarStack,
522- to_file=stderr, to_messages_file=stdout)
523- # but is not one
524- self.assertFalse(getattr(stack, 'note', False))
525- pb1 = stack.get_nested()
526- pb2 = stack.get_nested()
527- warnings, _ = self.callCatchWarnings(pb1.finished)
528- self.assertEqual(len(warnings), 1)
529- pb2.finished()
530- pb1.finished()
531- # the text ui factory never actually removes the stack once its setup.
532- # we need to be able to nest again correctly from here.
533- pb1 = stack.get_nested()
534- pb2 = stack.get_nested()
535- warnings, _ = self.callCatchWarnings(pb1.finished)
536- self.assertEqual(len(warnings), 1)
537- pb2.finished()
538- pb1.finished()
539-
540 def assert_get_bool_acceptance_of_user_input(self, factory):
541 factory.stdin = StringIO("y\nyes with garbage\n"
542 "yes\nn\nnot an answer\n"
543
544=== modified file 'bzrlib/weave.py'
545--- bzrlib/weave.py 2009-04-08 16:33:19 +0000
546+++ bzrlib/weave.py 2009-06-06 02:35:12 +0000
547@@ -1,6 +1,4 @@
548-#! /usr/bin/python
549-
550-# Copyright (C) 2005 Canonical Ltd
551+# Copyright (C) 2005, 2009 Canonical Ltd
552 #
553 # This program is free software; you can redistribute it and/or modify
554 # it under the terms of the GNU General Public License as published by
555@@ -1025,6 +1023,7 @@
556 wr._add(name, lines, [wr._lookup(i) for i in combined_parents[name]])
557 return wr
558
559+
560 def _reweave_parent_graphs(wa, wb):
561 """Return combined parent ancestry for two weaves.
562
563@@ -1035,206 +1034,3 @@
564 p = combined.setdefault(name, set())
565 p.update(map(weave._idx_to_name, weave._parents[idx]))
566 return combined
567-
568-
569-def weave_toc(w):
570- """Show the weave's table-of-contents"""
571- print '%6s %50s %10s %10s' % ('ver', 'name', 'sha1', 'parents')
572- for i in (6, 50, 10, 10):
573- print '-' * i,
574- print
575- for i in range(w.num_versions()):
576- sha1 = w._sha1s[i]
577- name = w._names[i]
578- parent_str = ' '.join(map(str, w._parents[i]))
579- print '%6d %-50.50s %10.10s %s' % (i, name, sha1, parent_str)
580-
581-
582-
583-def weave_stats(weave_file, pb):
584- from bzrlib.weavefile import read_weave
585-
586- wf = file(weave_file, 'rb')
587- w = read_weave(wf)
588- # FIXME: doesn't work on pipes
589- weave_size = wf.tell()
590-
591- total = 0
592- vers = len(w)
593- for i in range(vers):
594- pb.update('checking sizes', i, vers)
595- for origin, lineno, line in w._extract([i]):
596- total += len(line)
597-
598- pb.clear()
599-
600- print 'versions %9d' % vers
601- print 'weave file %9d bytes' % weave_size
602- print 'total contents %9d bytes' % total
603- print 'compression ratio %9.2fx' % (float(total) / float(weave_size))
604- if vers:
605- avg = total/vers
606- print 'average size %9d bytes' % avg
607- print 'relative size %9.2fx' % (float(weave_size) / float(avg))
608-
609-
610-def usage():
611- print """bzr weave tool
612-
613-Experimental tool for weave algorithm.
614-
615-usage:
616- weave init WEAVEFILE
617- Create an empty weave file
618- weave get WEAVEFILE VERSION
619- Write out specified version.
620- weave check WEAVEFILE
621- Check consistency of all versions.
622- weave toc WEAVEFILE
623- Display table of contents.
624- weave add WEAVEFILE NAME [BASE...] < NEWTEXT
625- Add NEWTEXT, with specified parent versions.
626- weave annotate WEAVEFILE VERSION
627- Display origin of each line.
628- weave merge WEAVEFILE VERSION1 VERSION2 > OUT
629- Auto-merge two versions and display conflicts.
630- weave diff WEAVEFILE VERSION1 VERSION2
631- Show differences between two versions.
632-
633-example:
634-
635- % weave init foo.weave
636- % vi foo.txt
637- % weave add foo.weave ver0 < foo.txt
638- added version 0
639-
640- (create updated version)
641- % vi foo.txt
642- % weave get foo.weave 0 | diff -u - foo.txt
643- % weave add foo.weave ver1 0 < foo.txt
644- added version 1
645-
646- % weave get foo.weave 0 > foo.txt (create forked version)
647- % vi foo.txt
648- % weave add foo.weave ver2 0 < foo.txt
649- added version 2
650-
651- % weave merge foo.weave 1 2 > foo.txt (merge them)
652- % vi foo.txt (resolve conflicts)
653- % weave add foo.weave merged 1 2 < foo.txt (commit merged version)
654-
655-"""
656-
657-
658-
659-def main(argv):
660- import sys
661- import os
662- try:
663- import bzrlib
664- except ImportError:
665- # in case we're run directly from the subdirectory
666- sys.path.append('..')
667- import bzrlib
668- from bzrlib.weavefile import write_weave, read_weave
669- from bzrlib.progress import ProgressBar
670-
671- try:
672- import psyco
673- psyco.full()
674- except ImportError:
675- pass
676-
677- if len(argv) < 2:
678- usage()
679- return 0
680-
681- cmd = argv[1]
682-
683- def readit():
684- return read_weave(file(argv[2], 'rb'))
685-
686- if cmd == 'help':
687- usage()
688- elif cmd == 'add':
689- w = readit()
690- # at the moment, based on everything in the file
691- name = argv[3]
692- parents = map(int, argv[4:])
693- lines = sys.stdin.readlines()
694- ver = w.add(name, parents, lines)
695- write_weave(w, file(argv[2], 'wb'))
696- print 'added version %r %d' % (name, ver)
697- elif cmd == 'init':
698- fn = argv[2]
699- if os.path.exists(fn):
700- raise IOError("file exists")
701- w = Weave()
702- write_weave(w, file(fn, 'wb'))
703- elif cmd == 'get': # get one version
704- w = readit()
705- sys.stdout.writelines(w.get_iter(int(argv[3])))
706-
707- elif cmd == 'diff':
708- w = readit()
709- fn = argv[2]
710- v1, v2 = map(int, argv[3:5])
711- lines1 = w.get(v1)
712- lines2 = w.get(v2)
713- diff_gen = bzrlib.patiencediff.unified_diff(lines1, lines2,
714- '%s version %d' % (fn, v1),
715- '%s version %d' % (fn, v2))
716- sys.stdout.writelines(diff_gen)
717-
718- elif cmd == 'annotate':
719- w = readit()
720- # newline is added to all lines regardless; too hard to get
721- # reasonable formatting otherwise
722- lasto = None
723- for origin, text in w.annotate(int(argv[3])):
724- text = text.rstrip('\r\n')
725- if origin == lasto:
726- print ' | %s' % (text)
727- else:
728- print '%5d | %s' % (origin, text)
729- lasto = origin
730-
731- elif cmd == 'toc':
732- weave_toc(readit())
733-
734- elif cmd == 'stats':
735- weave_stats(argv[2], ProgressBar())
736-
737- elif cmd == 'check':
738- w = readit()
739- pb = ProgressBar()
740- w.check(pb)
741- pb.clear()
742- print '%d versions ok' % w.num_versions()
743-
744- elif cmd == 'inclusions':
745- w = readit()
746- print ' '.join(map(str, w.inclusions([int(argv[3])])))
747-
748- elif cmd == 'parents':
749- w = readit()
750- print ' '.join(map(str, w._parents[int(argv[3])]))
751-
752- elif cmd == 'plan-merge':
753- # replaced by 'bzr weave-plan-merge'
754- w = readit()
755- for state, line in w.plan_merge(int(argv[3]), int(argv[4])):
756- if line:
757- print '%14s | %s' % (state, line),
758- elif cmd == 'merge':
759- # replaced by 'bzr weave-merge-text'
760- w = readit()
761- p = w.plan_merge(int(argv[3]), int(argv[4]))
762- sys.stdout.writelines(w.weave_merge(p))
763- else:
764- raise ValueError('unknown command %r' % cmd)
765-
766-
767-if __name__ == '__main__':
768- import sys
769- sys.exit(main(sys.argv))