~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/plugins/multiparent.py

Don't encode unicode messages to UTF-8 in mutter() (the stream writer does it).

Use a codec wrapped log file in tests to match the real environment.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""Implementation of multiparent diffs for versionedfile-like storage
2
 
 
3
 
Provides mp-regen and mp-extract commands.
4
 
Focus is on comparing size/performance to knits.
5
 
"""
6
 
 
7
 
from bzrlib.lazy_import import lazy_import
8
 
 
9
 
lazy_import(globals(), """
10
 
import (
11
 
        errno,
12
 
        os,
13
 
        sys,
14
 
        time,
15
 
        )
16
 
 
17
 
from bzrlib import (
18
 
    commands,
19
 
    urlutils
20
 
    )
21
 
from bzrlib.workingtree import WorkingTree
22
 
from bzrlib.tests import TestUtil
23
 
 
24
 
from bzrlib.plugins.multiparent.multiparent import (
25
 
    MultiVersionedFile,
26
 
    MultiMemoryVersionedFile,
27
 
    )
28
 
""")
29
 
 
30
 
class cmd_mp_regen(commands.Command):
31
 
    """Generate a multiparent versionedfile"""
32
 
 
33
 
    takes_args = ['file?']
34
 
    takes_options = [commands.Option('sync-snapshots',
35
 
                                     help='Snapshots follow source'),
36
 
                     commands.Option('snapshot-interval', type=int,
37
 
                                     help='take snapshots every x revisions'),
38
 
                     commands.Option('outfile', type=unicode,
39
 
                                     help='Write pseudo-knit to this file'),
40
 
                     commands.Option('memory', help='Use memory, not disk'),
41
 
                     commands.Option('extract', help='test extract time'),
42
 
                     commands.Option('single', help='use a single parent'),
43
 
                     commands.Option('verify', help='verify added texts'),
44
 
                     commands.Option('cache', help='Aggresively cache'),
45
 
                     commands.Option('size', help='Aggressive size'),
46
 
                     commands.Option('build', help='Aggressive build'),
47
 
                    ]
48
 
    hidden = True
49
 
 
50
 
    def run(self, file=None, sync_snapshots=False, snapshot_interval=26,
51
 
            lsprof_timed=False, dump=False, extract=False, single=False,
52
 
            verify=False, outfile=None, memory=False, cache=False,
53
 
            size=False, build=False):
54
 
        file_weave = get_file_weave(file)
55
 
        url = file_weave.transport.abspath(file_weave.filename)
56
 
        print >> sys.stderr, 'Importing: %s' % \
57
 
            urlutils.local_path_from_url(url)
58
 
        if sync_snapshots:
59
 
            print >> sys.stderr, 'Snapshots follow input'
60
 
        else:
61
 
            print >> sys.stderr, 'Snapshot interval: %d' % snapshot_interval
62
 
        if not memory:
63
 
            if outfile is None:
64
 
                filename = 'pknit'
65
 
            else:
66
 
                filename = outfile
67
 
            vf = MultiVersionedFile(filename, snapshot_interval)
68
 
        else:
69
 
            vf = MultiMemoryVersionedFile(snapshot_interval)
70
 
        vf.destroy()
71
 
        old_snapshots = set(r for r in file_weave.versions() if
72
 
                        file_weave._index.get_method(r) == 'fulltext')
73
 
        if sync_snapshots:
74
 
            to_sync = old_snapshots
75
 
        elif size or build:
76
 
            assert memory
77
 
            to_sync = set()
78
 
        else:
79
 
            to_sync = vf.select_snapshots(file_weave)
80
 
        print >> sys.stderr, "%d fulltext(s)" % len(old_snapshots)
81
 
        print >> sys.stderr, "%d planned snapshots" % len(to_sync)
82
 
 
83
 
        try:
84
 
            vf.import_versionedfile(file_weave, to_sync, single_parent=single,
85
 
                                    verify=verify, no_cache=not cache)
86
 
            if size:
87
 
                snapshots = vf.select_by_size(len(old_snapshots))
88
 
                for version_id in snapshots:
89
 
                    vf.make_snapshot(version_id)
90
 
            if build:
91
 
                ranking = vf.get_build_ranking()
92
 
                snapshots = ranking[:len(old_snapshots) -\
93
 
                    len(vf._snapshots)]
94
 
                for version_id in snapshots:
95
 
                    vf.make_snapshot(version_id)
96
 
        except:
97
 
            vf.destroy()
98
 
            raise
99
 
        try:
100
 
            print >> sys.stderr, "%d actual snapshots" % len(vf._snapshots)
101
 
            if not cache:
102
 
                vf.clear_cache()
103
 
            if memory:
104
 
                if outfile is not None:
105
 
                    vf_file = MultiVersionedFile(outfile)
106
 
                vf_file.import_diffs(vf)
107
 
            else:
108
 
                vf_file = vf
109
 
        finally:
110
 
            if outfile is None:
111
 
                vf.destroy()
112
 
            else:
113
 
                vf_file.save()
114
 
 
115
 
class cmd_mp_extract(commands.Command):
116
 
    """Test extraction time multiparent knits"""
117
 
 
118
 
    takes_options = [
119
 
        commands.Option('lsprof-timed', help='Use lsprof'),
120
 
        commands.Option('parallel', help='extract multiple versions at once'),
121
 
        commands.Option('count', help='Number of cycles to do', type=int),
122
 
        ]
123
 
 
124
 
    takes_args = ['filename', 'vfile?']
125
 
 
126
 
    def run(self, filename, vfile=None, lsprof_timed=False, count=1000,
127
 
            parallel=False):
128
 
        vf = MultiVersionedFile(filename)
129
 
        vf.load()
130
 
        snapshots = [r for r in vf.versions() if vf.get_diff(r).is_snapshot()]
131
 
        print '%d snapshots' % len(snapshots)
132
 
        revisions = list(vf.versions())
133
 
        revisions = revisions[-count:]
134
 
        print 'Testing extract time of %d revisions' % len(revisions)
135
 
        if parallel:
136
 
            revisions_list = [revisions]
137
 
        else:
138
 
            revisions_list = [[r] for r in revisions]
139
 
        start = time.clock()
140
 
        for revisions in revisions_list:
141
 
            vf = MultiVersionedFile(filename)
142
 
            vf.load()
143
 
            vf.get_line_list(revisions)
144
 
        print >> sys.stderr, time.clock() - start
145
 
        if lsprof_timed:
146
 
            from bzrlib.lsprof import profile
147
 
            vf.clear_cache()
148
 
            ret, stats = profile(vf.get_line_list, revisions_list[-1][-1])
149
 
            stats.sort()
150
 
            stats.pprint()
151
 
        start = time.clock()
152
 
        for revisions in revisions_list:
153
 
            file_weave = get_file_weave(vfile)
154
 
            file_weave.get_line_list(revisions)
155
 
        print >> sys.stderr, time.clock() - start
156
 
 
157
 
 
158
 
def get_file_weave(filename=None, wt=None):
159
 
    if filename is None:
160
 
        wt, path = WorkingTree.open_containing('.')
161
 
        return wt.branch.repository.get_inventory_weave()
162
 
    else:
163
 
        wt, path = WorkingTree.open_containing(filename)
164
 
        file_id = wt.path2id(path)
165
 
        bt = wt.branch.repository.revision_tree(wt.last_revision())
166
 
        return bt.get_weave(file_id)
167
 
 
168
 
 
169
 
commands.register_command(cmd_mp_regen)
170
 
commands.register_command(cmd_mp_extract)