/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.1.1 by Martin Pool
Check in old existing knit code.
1
#! /usr/bin/python
2
3
# Copyright (C) 2005 Canonical Ltd
4
5
# GNU GPL v2
6
7
# Author: Martin Pool <mbp@canonical.com>
8
9
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
10
"""knit - a weave-like structure"""
11
12
13
class Knit(object):
14
    """knit - versioned text file storage.
15
    
16
    A Knit manages versions of line-based text files, keeping track of the
17
    originating version for each line.
18
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
19
    Texts can be identified in either of two ways:
20
21
    * a nonnegative index number.
22
23
    * a version-id string.
24
25
    Typically the index number will be valid only inside this knit and
26
    the version-id is used to reference it in the larger world.
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
27
28
    _l
0.1.5 by Martin Pool
Add test for storing two text versions.
29
        List of edit instructions.
30
31
        Each line is stored as a tuple of (index-id, text).  The line
32
        is present in the version equal to index-id.
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
33
34
    _v
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
35
        List of versions, indexed by index number.
36
37
        For each version we store the tuple (included_versions), which
38
        lists the previous versions also considered active.
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
39
    """
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
40
    def __init__(self):
41
        self._l = []
42
        self._v = []
0.1.5 by Martin Pool
Add test for storing two text versions.
43
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
44
        
45
    def add(self, text):
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
46
        """Add a single text on top of the weave.
47
48
        Returns the index number of the newly added version."""
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
49
        if not isinstance(text, list):
50
            raise ValueError("text should be a list, not %s" % type(text))
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
51
52
        idx = len(self._v)
0.1.5 by Martin Pool
Add test for storing two text versions.
53
54
        # all of the previous texts are turned off; just append lines at the bottom
55
        for line in text:
56
            self._l.append((idx, line))
57
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
58
        included = ()
59
        vers_info = (included,)
60
        self._v.append(vers_info)
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
61
        return idx
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
62
63
    
0.1.7 by Martin Pool
Add trivial annotate text
64
    def annotate(self, index):
65
        return list(self.annotate_iter(index))
66
67
68
    def annotate_iter(self, index):
69
        """Yield list of (index-id, line) pairs for the specified version.
70
71
        The index indicates when the line originated in the weave."""
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
72
        vers_info = self._v[index]
73
74
        included = set(vers_info[0])
75
        included.add(index)
0.1.8 by Martin Pool
Unify get/annotate code
76
0.1.7 by Martin Pool
Add trivial annotate text
77
        for origin, line in self._l:
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
78
            if origin in included:
0.1.7 by Martin Pool
Add trivial annotate text
79
                yield origin, line
80
81
0.1.5 by Martin Pool
Add test for storing two text versions.
82
    def getiter(self, index):
83
        """Yield lines for the specified version."""
0.1.8 by Martin Pool
Unify get/annotate code
84
        for origin, line in self.annotate_iter(index):
85
            yield line
0.1.5 by Martin Pool
Add test for storing two text versions.
86
87
0.1.4 by Martin Pool
Start indexing knits by both integer and version string.
88
    def get(self, index):
0.1.5 by Martin Pool
Add test for storing two text versions.
89
        return list(self.getiter(index))
0.1.1 by Martin Pool
Check in old existing knit code.
90
91
0.1.11 by Martin Pool
Add Knit.dump method
92
    def dump(self, to_file):
93
        from pprint import pprint
94
        print >>to_file, "knit lines:"
95
        pprint(self._l, to_file)
96
97
0.1.13 by Martin Pool
Knit structure now allows for versions to include the lines present in other
98
    def check(self):
99
        for vers_info in self._v:
100
            included = set()
101
            for vi in vers_info[0]:
102
                if vi < 0 or vi >= index:
103
                    raise ValueError("invalid included_version %d for index %d"
104
                                     % (vi, index))
105
                if vi in included:
106
                    raise ValueError("repeated included_version %d for index %d"
107
                                     % (vi, index))
108
                included.add(vi)
109
            
110
111
0.1.1 by Martin Pool
Check in old existing knit code.
112
113
def update_knit(knit, new_vers, new_lines):
114
    """Return a new knit whose text matches new_lines.
115
116
    First of all the knit is diffed against the new lines, considering
117
    only the text of the lines from the knit.  This identifies lines
118
    unchanged from the knit, plus insertions and deletions.
119
120
    The deletions are marked as deleted.  The insertions are added
121
    with their new values.
122
123
    
124
    """
125
    if not isinstance(new_vers, int):
126
        raise TypeError('new version-id must be an int: %r' % new_vers)
127
    
128
    from difflib import SequenceMatcher
129
    knit_lines = knit2text(knit)
130
    m = SequenceMatcher(None, knit_lines, new_lines)
131
132
    for block in m.get_matching_blocks():
133
        print "a[%d] and b[%d] match for %d elements" % block
134
    
135
    new_knit = []
136
    for tag, i1, i2, j1, j2 in m.get_opcodes():
137
        print ("%7s a[%d:%d] (%s) b[%d:%d] (%s)" %
138
               (tag, i1, i2, knit_lines[i1:i2], j1, j2, new_lines[j1:j2]))
139
140
        if tag == 'equal':
141
            new_knit.extend(knit[i1:i2])
142
        elif tag == 'delete':
143
            for i in range(i1, i2):
144
                kl = knit[i]
145
                new_knit.append((kl[0], kl[1], False))
146
147
    return new_knit
148
        
0.1.2 by Martin Pool
Import testsweet module adapted from bzr.
149