~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/weave.py

Fix push to only push revisions in the current ancestry. (bug???)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#! /usr/bin/python
2
2
 
3
3
# Copyright (C) 2005 Canonical Ltd
4
 
#
 
4
 
5
5
# This program is free software; you can redistribute it and/or modify
6
6
# it under the terms of the GNU General Public License as published by
7
7
# the Free Software Foundation; either version 2 of the License, or
8
8
# (at your option) any later version.
9
 
#
 
9
 
10
10
# This program is distributed in the hope that it will be useful,
11
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
13
# GNU General Public License for more details.
14
 
#
 
14
 
15
15
# You should have received a copy of the GNU General Public License
16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
27
# property.
28
28
 
29
29
# TODO: Nothing here so far assumes the lines are really \n newlines,
30
 
# rather than being split up in some other way.  We could accommodate
 
30
# rather than being split up in some other way.  We could accomodate
31
31
# binaries, perhaps by naively splitting on \n or perhaps using
32
32
# something like a rolling checksum.
33
33
 
70
70
 
71
71
from copy import copy
72
72
from cStringIO import StringIO
 
73
from difflib import SequenceMatcher
73
74
import os
74
75
import sha
75
76
import time
76
 
import warnings
77
77
 
78
 
from bzrlib import (
79
 
    progress,
80
 
    )
81
78
from bzrlib.trace import mutter
82
79
from bzrlib.errors import (WeaveError, WeaveFormatError, WeaveParentMismatch,
83
80
        RevisionAlreadyPresent,
87
84
        )
88
85
import bzrlib.errors as errors
89
86
from bzrlib.osutils import sha_strings
90
 
import bzrlib.patiencediff
91
 
from bzrlib.symbol_versioning import (deprecated_method,
92
 
        deprecated_function,
93
 
        zero_eight,
94
 
        )
 
87
from bzrlib.symbol_versioning import *
95
88
from bzrlib.tsort import topo_sort
96
89
from bzrlib.versionedfile import VersionedFile, InterVersionedFile
97
90
from bzrlib.weavefile import _read_weave_v5, write_weave_v5
187
180
    """
188
181
 
189
182
    __slots__ = ['_weave', '_parents', '_sha1s', '_names', '_name_map',
190
 
                 '_weave_name', '_matcher']
 
183
                 '_weave_name']
191
184
    
192
 
    def __init__(self, weave_name=None, access_mode='w', matcher=None):
 
185
    def __init__(self, weave_name=None, access_mode='w'):
193
186
        super(Weave, self).__init__(access_mode)
194
187
        self._weave = []
195
188
        self._parents = []
197
190
        self._names = []
198
191
        self._name_map = {}
199
192
        self._weave_name = weave_name
200
 
        if matcher is None:
201
 
            self._matcher = bzrlib.patiencediff.PatienceSequenceMatcher
202
 
        else:
203
 
            self._matcher = matcher
204
193
 
205
194
    def __repr__(self):
206
195
        return "Weave(%r)" % self._weave_name
238
227
 
239
228
    @deprecated_method(zero_eight)
240
229
    def lookup(self, name):
241
 
        """Backwards compatibility thunk:
 
230
        """Backwards compatability thunk:
242
231
 
243
232
        Return name, as name is valid in the api now, and spew deprecation
244
233
        warnings everywhere.
247
236
 
248
237
    def _lookup(self, name):
249
238
        """Convert symbolic version name to index."""
250
 
        self.check_not_reserved_id(name)
251
239
        try:
252
240
            return self._name_map[name]
253
241
        except KeyError:
269
257
 
270
258
    def has_version(self, version_id):
271
259
        """See VersionedFile.has_version."""
272
 
        return (version_id in self._name_map)
 
260
        return self._name_map.has_key(version_id)
273
261
 
274
262
    __contains__ = has_version
275
263
 
530
518
        if lines == basis_lines:
531
519
            return new_version            
532
520
 
533
 
        # add a sentinel, because we can also match against the final line
 
521
        # add a sentinal, because we can also match against the final line
534
522
        basis_lineno.append(len(self._weave))
535
523
 
536
524
        # XXX: which line of the weave should we really consider
540
528
        #print 'basis_lines:', basis_lines
541
529
        #print 'new_lines:  ', lines
542
530
 
543
 
        s = self._matcher(None, basis_lines, lines)
 
531
        s = SequenceMatcher(None, basis_lines, lines)
544
532
 
545
533
        # offset gives the number of lines that have been inserted
546
534
        # into the weave up to the current point; if the original edit instruction
607
595
        else:
608
596
            return self.get_ancestry(version_ids)
609
597
 
610
 
    def get_ancestry(self, version_ids, topo_sorted=True):
 
598
    def get_ancestry(self, version_ids):
611
599
        """See VersionedFile.get_ancestry."""
612
600
        if isinstance(version_ids, basestring):
613
601
            version_ids = [version_ids]
641
629
        """
642
630
        return len(other_parents.difference(my_parents)) == 0
643
631
 
 
632
    def annotate(self, version_id):
 
633
        if isinstance(version_id, int):
 
634
            warn('Weave.annotate(int) is deprecated. Please use version names'
 
635
                 ' in all circumstances as of 0.8',
 
636
                 DeprecationWarning,
 
637
                 stacklevel=2
 
638
                 )
 
639
            result = []
 
640
            for origin, lineno, text in self._extract([version_id]):
 
641
                result.append((origin, text))
 
642
            return result
 
643
        else:
 
644
            return super(Weave, self).annotate(version_id)
 
645
    
644
646
    def annotate_iter(self, version_id):
645
647
        """Yield list of (version-id, line) pairs for the specified version.
646
648
 
654
656
        """_walk has become visit, a supported api."""
655
657
        return self._walk_internal()
656
658
 
657
 
    def iter_lines_added_or_present_in_versions(self, version_ids=None,
658
 
                                                pb=None):
 
659
    def iter_lines_added_or_present_in_versions(self, version_ids=None):
659
660
        """See VersionedFile.iter_lines_added_or_present_in_versions()."""
660
661
        if version_ids is None:
661
662
            version_ids = self.versions()
1064
1065
 
1065
1066
    @deprecated_method(zero_eight)
1066
1067
    def reweave(self, other, pb=None, msg=None):
1067
 
        """reweave has been superseded by plain use of join."""
 
1068
        """reweave has been superceded by plain use of join."""
1068
1069
        return self.join(other, pb, msg)
1069
1070
 
1070
1071
    def _reweave(self, other, pb, msg):
1107
1108
 
1108
1109
    def _add_lines(self, version_id, parents, lines, parent_texts):
1109
1110
        """Add a version and save the weave."""
1110
 
        self.check_not_reserved_id(version_id)
1111
1111
        result = super(WeaveFile, self)._add_lines(version_id, parents, lines,
1112
1112
                                                   parent_texts)
1113
1113
        self._save()
1124
1124
        sio = StringIO()
1125
1125
        write_weave_v5(self, sio)
1126
1126
        sio.seek(0)
1127
 
        transport.put_file(name + WeaveFile.WEAVE_SUFFIX, sio, self._filemode)
 
1127
        transport.put(name + WeaveFile.WEAVE_SUFFIX, sio, self._filemode)
1128
1128
 
1129
1129
    def create_empty(self, name, transport, filemode=None):
1130
1130
        return WeaveFile(name, transport, filemode, create=True)
1135
1135
        sio = StringIO()
1136
1136
        write_weave_v5(self, sio)
1137
1137
        sio.seek(0)
1138
 
        self._transport.put_file(self._weave_name + WeaveFile.WEAVE_SUFFIX,
1139
 
                                 sio,
1140
 
                                 self._filemode)
 
1138
        self._transport.put(self._weave_name + WeaveFile.WEAVE_SUFFIX,
 
1139
                            sio,
 
1140
                            self._filemode)
1141
1141
 
1142
1142
    @staticmethod
1143
1143
    def get_suffixes():
1235
1235
    from bzrlib.weavefile import read_weave
1236
1236
 
1237
1237
    wf = file(weave_file, 'rb')
1238
 
    w = read_weave(wf)
 
1238
    w = read_weave(wf, WeaveVersionedFile)
1239
1239
    # FIXME: doesn't work on pipes
1240
1240
    weave_size = wf.tell()
1241
1241
 
1356
1356
        sys.stdout.writelines(w.get_iter(int(argv[3])))
1357
1357
        
1358
1358
    elif cmd == 'diff':
 
1359
        from difflib import unified_diff
1359
1360
        w = readit()
1360
1361
        fn = argv[2]
1361
1362
        v1, v2 = map(int, argv[3:5])
1362
1363
        lines1 = w.get(v1)
1363
1364
        lines2 = w.get(v2)
1364
 
        diff_gen = bzrlib.patiencediff.unified_diff(lines1, lines2,
 
1365
        diff_gen = unified_diff(lines1, lines2,
1365
1366
                                '%s version %d' % (fn, v1),
1366
1367
                                '%s version %d' % (fn, v2))
1367
1368
        sys.stdout.writelines(diff_gen)
1415
1416
        raise ValueError('unknown command %r' % cmd)
1416
1417
    
1417
1418
 
 
1419
 
 
1420
def profile_main(argv):
 
1421
    import tempfile, hotshot, hotshot.stats
 
1422
 
 
1423
    prof_f = tempfile.NamedTemporaryFile()
 
1424
 
 
1425
    prof = hotshot.Profile(prof_f.name)
 
1426
 
 
1427
    ret = prof.runcall(main, argv)
 
1428
    prof.close()
 
1429
 
 
1430
    stats = hotshot.stats.load(prof_f.name)
 
1431
    #stats.strip_dirs()
 
1432
    stats.sort_stats('cumulative')
 
1433
    ## XXX: Might like to write to stderr or the trace file instead but
 
1434
    ## print_stats seems hardcoded to stdout
 
1435
    stats.print_stats(20)
 
1436
            
 
1437
    return ret
 
1438
 
 
1439
 
 
1440
def lsprofile_main(argv): 
 
1441
    from bzrlib.lsprof import profile
 
1442
    ret,stats = profile(main, argv)
 
1443
    stats.sort()
 
1444
    stats.pprint()
 
1445
    return ret
 
1446
 
 
1447
 
1418
1448
if __name__ == '__main__':
1419
1449
    import sys
1420
 
    sys.exit(main(sys.argv))
 
1450
    if '--profile' in sys.argv:
 
1451
        args = sys.argv[:]
 
1452
        args.remove('--profile')
 
1453
        sys.exit(profile_main(args))
 
1454
    elif '--lsprof' in sys.argv:
 
1455
        args = sys.argv[:]
 
1456
        args.remove('--lsprof')
 
1457
        sys.exit(lsprofile_main(args))
 
1458
    else:
 
1459
        sys.exit(main(sys.argv))
1421
1460
 
1422
1461
 
1423
1462
class InterWeave(InterVersionedFile):