bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 
1711.3.2
by John Arbash Meinel
 Add the read_bundle_from_url command, which handles lots of exceptions  | 
1  | 
# Copyright (C) 2006 by Canonical Ltd
 | 
2  | 
#
 | 
|
3  | 
# This program is free software; you can redistribute it and/or modify
 | 
|
4  | 
# it under the terms of the GNU General Public License as published by
 | 
|
5  | 
# the Free Software Foundation; either version 2 of the License, or
 | 
|
6  | 
# (at your option) any later version.
 | 
|
7  | 
#
 | 
|
8  | 
# This program is distributed in the hope that it will be useful,
 | 
|
9  | 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|
10  | 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|
11  | 
# GNU General Public License for more details.
 | 
|
12  | 
#
 | 
|
13  | 
# You should have received a copy of the GNU General Public License
 | 
|
14  | 
# along with this program; if not, write to the Free Software
 | 
|
15  | 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|
16  | 
||
17  | 
"""Read in a bundle stream, and process it into a BundleReader object."""
 | 
|
| 
0.5.7
by John Arbash Meinel
 Added a bunch more information about changesets. Can now read back in all of the meta information.  | 
18  | 
|
| 
1185.82.96
by Aaron Bentley
 Got first binary test passing  | 
19  | 
import base64  | 
| 
1185.82.78
by Aaron Bentley
 Cleanups  | 
20  | 
from cStringIO import StringIO  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
21  | 
import os  | 
22  | 
import pprint  | 
|
23  | 
||
| 
1711.3.2
by John Arbash Meinel
 Add the read_bundle_from_url command, which handles lots of exceptions  | 
24  | 
import bzrlib.errors  | 
| 
1185.82.131
by Aaron Bentley
 Move BadBundle error (and subclasses) to errors.py  | 
25  | 
from bzrlib.errors import (TestamentMismatch, BzrError,  | 
| 
1185.82.139
by Aaron Bentley
 Raise NotABundle when a non-bundle is supplied  | 
26  | 
MalformedHeader, MalformedPatches, NotABundle)  | 
| 
0.5.116
by John Arbash Meinel
 Fixed a bug based on the new InventoryEntry separation.  | 
27  | 
from bzrlib.inventory import (Inventory, InventoryEntry,  | 
28  | 
InventoryDirectory, InventoryFile,  | 
|
29  | 
InventoryLink)  | 
|
| 
1711.4.19
by John Arbash Meinel
 Bundles were still using os.path.join to compute paths rather than osutils.pathjoin  | 
30  | 
from bzrlib.osutils import sha_file, sha_string, pathjoin  | 
| 
1185.82.78
by Aaron Bentley
 Cleanups  | 
31  | 
from bzrlib.revision import Revision, NULL_REVISION  | 
| 
1185.82.116
by Aaron Bentley
 Introduce StrictTestament, get test failing for the right reasons  | 
32  | 
from bzrlib.testament import StrictTestament  | 
| 
1185.82.78
by Aaron Bentley
 Cleanups  | 
33  | 
from bzrlib.trace import mutter, warning  | 
| 
1711.3.2
by John Arbash Meinel
 Add the read_bundle_from_url command, which handles lots of exceptions  | 
34  | 
import bzrlib.transport  | 
| 
1185.82.78
by Aaron Bentley
 Cleanups  | 
35  | 
from bzrlib.tree import Tree  | 
| 
1711.3.2
by John Arbash Meinel
 Add the read_bundle_from_url command, which handles lots of exceptions  | 
36  | 
import bzrlib.urlutils  | 
| 
1185.82.78
by Aaron Bentley
 Cleanups  | 
37  | 
from bzrlib.xml5 import serializer_v5  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
38  | 
|
| 
0.5.57
by John Arbash Meinel
 Simplified the header, only output base if it is not the expected one.  | 
39  | 
|
| 
0.5.36
by John Arbash Meinel
 Updated so that read_changeset is able to parse the output  | 
40  | 
class RevisionInfo(object):  | 
41  | 
"""Gets filled out for each revision object that is read.  | 
|
42  | 
    """
 | 
|
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
43  | 
def __init__(self, revision_id):  | 
44  | 
self.revision_id = revision_id  | 
|
| 
0.5.36
by John Arbash Meinel
 Updated so that read_changeset is able to parse the output  | 
45  | 
self.sha1 = None  | 
46  | 
self.committer = None  | 
|
| 
0.5.39
by John Arbash Meinel
 (broken) Working on changing the processing to use a ChangesetTree.  | 
47  | 
self.date = None  | 
| 
0.5.36
by John Arbash Meinel
 Updated so that read_changeset is able to parse the output  | 
48  | 
self.timestamp = None  | 
49  | 
self.timezone = None  | 
|
50  | 
self.inventory_sha1 = None  | 
|
51  | 
||
| 
1185.82.27
by Aaron Bentley
 Fixed most revision attribute handling  | 
52  | 
self.parent_ids = None  | 
| 
1185.82.74
by Aaron Bentley
 Allow custom base for any revision  | 
53  | 
self.base_id = None  | 
| 
0.5.36
by John Arbash Meinel
 Updated so that read_changeset is able to parse the output  | 
54  | 
self.message = None  | 
| 
1185.82.27
by Aaron Bentley
 Fixed most revision attribute handling  | 
55  | 
self.properties = None  | 
| 
1185.82.77
by Aaron Bentley
 Move tree actions to RevisionInfo  | 
56  | 
self.tree_actions = None  | 
| 
0.5.36
by John Arbash Meinel
 Updated so that read_changeset is able to parse the output  | 
57  | 
|
58  | 
def __str__(self):  | 
|
59  | 
return pprint.pformat(self.__dict__)  | 
|
60  | 
||
| 
0.5.37
by John Arbash Meinel
 Made read_changeset able to spit out 'Revision' entities.  | 
61  | 
def as_revision(self):  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
62  | 
rev = Revision(revision_id=self.revision_id,  | 
| 
0.5.37
by John Arbash Meinel
 Made read_changeset able to spit out 'Revision' entities.  | 
63  | 
committer=self.committer,  | 
64  | 
timestamp=float(self.timestamp),  | 
|
65  | 
timezone=int(self.timezone),  | 
|
66  | 
inventory_sha1=self.inventory_sha1,  | 
|
67  | 
message='\n'.join(self.message))  | 
|
68  | 
||
| 
1185.82.28
by Aaron Bentley
 Got parent_id handling working  | 
69  | 
if self.parent_ids:  | 
70  | 
rev.parent_ids.extend(self.parent_ids)  | 
|
| 
1185.82.35
by Aaron Bentley
 Read revision properties  | 
71  | 
|
| 
1185.82.59
by Aaron Bentley
 Behave properly when there are no properties in a revision  | 
72  | 
if self.properties:  | 
73  | 
for property in self.properties:  | 
|
74  | 
key_end = property.find(': ')  | 
|
75  | 
assert key_end is not None  | 
|
76  | 
key = property[:key_end].encode('utf-8')  | 
|
77  | 
value = property[key_end+2:].encode('utf-8')  | 
|
78  | 
rev.properties[key] = value  | 
|
| 
1185.82.35
by Aaron Bentley
 Read revision properties  | 
79  | 
|
| 
0.5.37
by John Arbash Meinel
 Made read_changeset able to spit out 'Revision' entities.  | 
80  | 
return rev  | 
81  | 
||
| 
1185.82.123
by Aaron Bentley
 Cleanups to prepare for review  | 
82  | 
|
| 
1185.82.130
by Aaron Bentley
 Rename changesets to revision bundles  | 
83  | 
class BundleInfo(object):  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
84  | 
"""This contains the meta information. Stuff that allows you to  | 
85  | 
    recreate the revision or inventory XML.
 | 
|
| 
0.5.7
by John Arbash Meinel
 Added a bunch more information about changesets. Can now read back in all of the meta information.  | 
86  | 
    """
 | 
87  | 
def __init__(self):  | 
|
88  | 
self.committer = None  | 
|
89  | 
self.date = None  | 
|
| 
0.5.17
by John Arbash Meinel
 adding apply-changset, plus more meta information.  | 
90  | 
self.message = None  | 
| 
0.5.36
by John Arbash Meinel
 Updated so that read_changeset is able to parse the output  | 
91  | 
|
| 
0.5.39
by John Arbash Meinel
 (broken) Working on changing the processing to use a ChangesetTree.  | 
92  | 
        # A list of RevisionInfo objects
 | 
| 
0.5.36
by John Arbash Meinel
 Updated so that read_changeset is able to parse the output  | 
93  | 
self.revisions = []  | 
| 
0.5.56
by John Arbash Meinel
 A couple more fixups, it seems actually capable now of writing out a changeset, and reading it back.  | 
94  | 
|
95  | 
        # The next entries are created during complete_info() and
 | 
|
96  | 
        # other post-read functions.
 | 
|
97  | 
||
98  | 
        # A list of real Revision objects
 | 
|
99  | 
self.real_revisions = []  | 
|
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
100  | 
|
101  | 
self.timestamp = None  | 
|
102  | 
self.timezone = None  | 
|
| 
0.5.15
by John Arbash Meinel
 Created an apply-changeset function, and modified output for better parsing.  | 
103  | 
|
| 
0.5.7
by John Arbash Meinel
 Added a bunch more information about changesets. Can now read back in all of the meta information.  | 
104  | 
def __str__(self):  | 
105  | 
return pprint.pformat(self.__dict__)  | 
|
106  | 
||
| 
0.5.39
by John Arbash Meinel
 (broken) Working on changing the processing to use a ChangesetTree.  | 
107  | 
def complete_info(self):  | 
108  | 
"""This makes sure that all information is properly  | 
|
109  | 
        split up, based on the assumptions that can be made
 | 
|
110  | 
        when information is missing.
 | 
|
111  | 
        """
 | 
|
| 
1185.82.130
by Aaron Bentley
 Rename changesets to revision bundles  | 
112  | 
from bzrlib.bundle.common import unpack_highres_date  | 
| 
0.5.56
by John Arbash Meinel
 A couple more fixups, it seems actually capable now of writing out a changeset, and reading it back.  | 
113  | 
        # Put in all of the guessable information.
 | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
114  | 
if not self.timestamp and self.date:  | 
| 
0.5.81
by John Arbash Meinel
 Cleaning up from pychecker.  | 
115  | 
self.timestamp, self.timezone = unpack_highres_date(self.date)  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
116  | 
|
| 
0.5.56
by John Arbash Meinel
 A couple more fixups, it seems actually capable now of writing out a changeset, and reading it back.  | 
117  | 
self.real_revisions = []  | 
| 
0.5.39
by John Arbash Meinel
 (broken) Working on changing the processing to use a ChangesetTree.  | 
118  | 
for rev in self.revisions:  | 
| 
0.5.60
by John Arbash Meinel
 read_changeset now parses the date: subheader of revisions correctly.  | 
119  | 
if rev.timestamp is None:  | 
120  | 
if rev.date is not None:  | 
|
121  | 
rev.timestamp, rev.timezone = \  | 
|
| 
0.5.81
by John Arbash Meinel
 Cleaning up from pychecker.  | 
122  | 
unpack_highres_date(rev.date)  | 
| 
0.5.60
by John Arbash Meinel
 read_changeset now parses the date: subheader of revisions correctly.  | 
123  | 
else:  | 
124  | 
rev.timestamp = self.timestamp  | 
|
125  | 
rev.timezone = self.timezone  | 
|
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
126  | 
if rev.message is None and self.message:  | 
127  | 
rev.message = self.message  | 
|
128  | 
if rev.committer is None and self.committer:  | 
|
129  | 
rev.committer = self.committer  | 
|
| 
0.5.56
by John Arbash Meinel
 A couple more fixups, it seems actually capable now of writing out a changeset, and reading it back.  | 
130  | 
self.real_revisions.append(rev.as_revision())  | 
131  | 
||
| 
1185.82.48
by Aaron Bentley
 Inching closer to supporting multiple revisions per changeset  | 
132  | 
def get_base(self, revision):  | 
| 
1185.82.74
by Aaron Bentley
 Allow custom base for any revision  | 
133  | 
revision_info = self.get_revision_info(revision.revision_id)  | 
134  | 
if revision_info.base_id is not None:  | 
|
135  | 
if revision_info.base_id == NULL_REVISION:  | 
|
136  | 
return None  | 
|
137  | 
else:  | 
|
138  | 
return revision_info.base_id  | 
|
| 
1185.82.48
by Aaron Bentley
 Inching closer to supporting multiple revisions per changeset  | 
139  | 
if len(revision.parent_ids) == 0:  | 
140  | 
            # There is no base listed, and
 | 
|
141  | 
            # the lowest revision doesn't have a parent
 | 
|
142  | 
            # so this is probably against the empty tree
 | 
|
143  | 
            # and thus base truly is None
 | 
|
144  | 
return None  | 
|
145  | 
else:  | 
|
| 
1185.82.73
by Aaron Bentley
 Use rightmost parent always  | 
146  | 
return revision.parent_ids[-1]  | 
| 
0.5.56
by John Arbash Meinel
 A couple more fixups, it seems actually capable now of writing out a changeset, and reading it back.  | 
147  | 
|
| 
0.5.67
by John Arbash Meinel
 Working on apply_changeset  | 
148  | 
def _get_target(self):  | 
| 
0.5.81
by John Arbash Meinel
 Cleaning up from pychecker.  | 
149  | 
"""Return the target revision."""  | 
| 
0.5.67
by John Arbash Meinel
 Working on apply_changeset  | 
150  | 
if len(self.real_revisions) > 0:  | 
| 
1185.82.48
by Aaron Bentley
 Inching closer to supporting multiple revisions per changeset  | 
151  | 
return self.real_revisions[0].revision_id  | 
| 
0.5.67
by John Arbash Meinel
 Working on apply_changeset  | 
152  | 
elif len(self.revisions) > 0:  | 
| 
1185.82.48
by Aaron Bentley
 Inching closer to supporting multiple revisions per changeset  | 
153  | 
return self.revisions[0].revision_id  | 
| 
0.5.67
by John Arbash Meinel
 Working on apply_changeset  | 
154  | 
return None  | 
155  | 
||
156  | 
target = property(_get_target, doc='The target revision id')  | 
|
157  | 
||
| 
1185.82.49
by Aaron Bentley
 SPOT fixes, fix inventory validation  | 
158  | 
def get_revision(self, revision_id):  | 
159  | 
for r in self.real_revisions:  | 
|
160  | 
if r.revision_id == revision_id:  | 
|
161  | 
return r  | 
|
162  | 
raise KeyError(revision_id)  | 
|
163  | 
||
164  | 
def get_revision_info(self, revision_id):  | 
|
165  | 
for r in self.revisions:  | 
|
166  | 
if r.revision_id == revision_id:  | 
|
167  | 
return r  | 
|
168  | 
raise KeyError(revision_id)  | 
|
169  | 
||
| 
1793.2.1
by Aaron Bentley
 Move revision_tree into BundleInfo  | 
170  | 
def revision_tree(self, repository, revision_id, base=None):  | 
171  | 
revision = self.get_revision(revision_id)  | 
|
172  | 
base = self.get_base(revision)  | 
|
173  | 
assert base != revision_id  | 
|
174  | 
self._validate_references_from_repository(repository)  | 
|
175  | 
revision_info = self.get_revision_info(revision_id)  | 
|
176  | 
inventory_revision_id = revision_id  | 
|
177  | 
bundle_tree = BundleTree(repository.revision_tree(base),  | 
|
178  | 
inventory_revision_id)  | 
|
179  | 
self._update_tree(bundle_tree, revision_id)  | 
|
180  | 
||
181  | 
inv = bundle_tree.inventory  | 
|
182  | 
self._validate_inventory(inv, revision_id)  | 
|
183  | 
self._validate_revision(inv, revision_id)  | 
|
184  | 
||
185  | 
return bundle_tree  | 
|
| 
0.5.62
by John Arbash Meinel
 Doing some internal validation before allowing processing to continue, additional checks at the command level.  | 
186  | 
|
| 
1185.82.15
by Aaron Bentley
 Disabled validate_revisions (needs info it doesn't have), updated API to repos  | 
187  | 
def _validate_references_from_repository(self, repository):  | 
188  | 
"""Now that we have a repository which should have some of the  | 
|
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
189  | 
        revisions we care about, go through and validate all of them
 | 
190  | 
        that we can.
 | 
|
191  | 
        """
 | 
|
192  | 
rev_to_sha = {}  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
193  | 
inv_to_sha = {}  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
194  | 
def add_sha(d, revision_id, sha1):  | 
195  | 
if revision_id is None:  | 
|
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
196  | 
if sha1 is not None:  | 
197  | 
raise BzrError('A Null revision should always'  | 
|
198  | 
'have a null sha1 hash')  | 
|
199  | 
                return
 | 
|
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
200  | 
if revision_id in d:  | 
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
201  | 
                # This really should have been validated as part
 | 
202  | 
                # of _validate_revisions but lets do it again
 | 
|
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
203  | 
if sha1 != d[revision_id]:  | 
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
204  | 
raise BzrError('** Revision %r referenced with 2 different'  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
205  | 
' sha hashes %s != %s' % (revision_id,  | 
206  | 
sha1, d[revision_id]))  | 
|
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
207  | 
else:  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
208  | 
d[revision_id] = sha1  | 
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
209  | 
|
210  | 
        # All of the contained revisions were checked
 | 
|
211  | 
        # in _validate_revisions
 | 
|
212  | 
checked = {}  | 
|
| 
1793.2.1
by Aaron Bentley
 Move revision_tree into BundleInfo  | 
213  | 
for rev_info in self.revisions:  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
214  | 
checked[rev_info.revision_id] = True  | 
215  | 
add_sha(rev_to_sha, rev_info.revision_id, rev_info.sha1)  | 
|
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
216  | 
|
| 
1793.2.1
by Aaron Bentley
 Move revision_tree into BundleInfo  | 
217  | 
for (rev, rev_info) in zip(self.real_revisions, self.revisions):  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
218  | 
add_sha(inv_to_sha, rev_info.revision_id, rev_info.inventory_sha1)  | 
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
219  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
220  | 
count = 0  | 
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
221  | 
missing = {}  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
222  | 
for revision_id, sha1 in rev_to_sha.iteritems():  | 
| 
1185.82.15
by Aaron Bentley
 Disabled validate_revisions (needs info it doesn't have), updated API to repos  | 
223  | 
if repository.has_revision(revision_id):  | 
| 
1185.82.121
by Aaron Bentley
 Move calculation of Testament sha1s to Testament  | 
224  | 
testament = StrictTestament.from_revision(repository,  | 
225  | 
revision_id)  | 
|
226  | 
local_sha1 = testament.as_sha1()  | 
|
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
227  | 
if sha1 != local_sha1:  | 
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
228  | 
raise BzrError('sha1 mismatch. For revision id {%s}'  | 
| 
1185.82.130
by Aaron Bentley
 Rename changesets to revision bundles  | 
229  | 
'local: %s, bundle: %s' % (revision_id, local_sha1, sha1))  | 
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
230  | 
else:  | 
231  | 
count += 1  | 
|
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
232  | 
elif revision_id not in checked:  | 
233  | 
missing[revision_id] = sha1  | 
|
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
234  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
235  | 
for inv_id, sha1 in inv_to_sha.iteritems():  | 
| 
1185.82.15
by Aaron Bentley
 Disabled validate_revisions (needs info it doesn't have), updated API to repos  | 
236  | 
if repository.has_revision(inv_id):  | 
| 
1185.82.123
by Aaron Bentley
 Cleanups to prepare for review  | 
237  | 
                # Note: branch.get_inventory_sha1() just returns the value that
 | 
238  | 
                # is stored in the revision text, and that value may be out
 | 
|
239  | 
                # of date. This is bogus, because that means we aren't
 | 
|
240  | 
                # validating the actual text, just that we wrote and read the
 | 
|
241  | 
                # string. But for now, what the hell.
 | 
|
| 
1185.82.15
by Aaron Bentley
 Disabled validate_revisions (needs info it doesn't have), updated API to repos  | 
242  | 
local_sha1 = repository.get_inventory_sha1(inv_id)  | 
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
243  | 
if sha1 != local_sha1:  | 
244  | 
raise BzrError('sha1 mismatch. For inventory id {%s}'  | 
|
| 
1185.82.130
by Aaron Bentley
 Rename changesets to revision bundles  | 
245  | 
'local: %s, bundle: %s' %  | 
246  | 
(inv_id, local_sha1, sha1))  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
247  | 
else:  | 
248  | 
count += 1  | 
|
249  | 
||
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
250  | 
if len(missing) > 0:  | 
251  | 
            # I don't know if this is an error yet
 | 
|
252  | 
warning('Not all revision hashes could be validated.'  | 
|
253  | 
' Unable validate %d hashes' % len(missing))  | 
|
| 
1185.82.130
by Aaron Bentley
 Rename changesets to revision bundles  | 
254  | 
mutter('Verified %d sha hashes for the bundle.' % count)  | 
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
255  | 
|
| 
1185.82.49
by Aaron Bentley
 SPOT fixes, fix inventory validation  | 
256  | 
def _validate_inventory(self, inv, revision_id):  | 
| 
1185.82.130
by Aaron Bentley
 Rename changesets to revision bundles  | 
257  | 
"""At this point we should have generated the BundleTree,  | 
| 
0.5.63
by John Arbash Meinel
 Moving the validation into part of the reading.  | 
258  | 
        so build up an inventory, and make sure the hashes match.
 | 
259  | 
        """
 | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
260  | 
|
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
261  | 
assert inv is not None  | 
262  | 
||
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
263  | 
        # Now we should have a complete inventory entry.
 | 
| 
0.5.117
by John Arbash Meinel
 Almost there. Just need to track down a few remaining bugs.  | 
264  | 
s = serializer_v5.write_inventory_to_string(inv)  | 
265  | 
sha1 = sha_string(s)  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
266  | 
        # Target revision is the last entry in the real_revisions list
 | 
| 
1793.2.1
by Aaron Bentley
 Move revision_tree into BundleInfo  | 
267  | 
rev = self.get_revision(revision_id)  | 
| 
1185.82.49
by Aaron Bentley
 SPOT fixes, fix inventory validation  | 
268  | 
assert rev.revision_id == revision_id  | 
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
269  | 
if sha1 != rev.inventory_sha1:  | 
| 
0.5.117
by John Arbash Meinel
 Almost there. Just need to track down a few remaining bugs.  | 
270  | 
open(',,bogus-inv', 'wb').write(s)  | 
| 
1185.82.61
by Aaron Bentley
 Downgrade inventory mismatch to warning (source can be inaccurate)  | 
271  | 
warning('Inventory sha hash mismatch for revision %s. %s'  | 
272  | 
' != %s' % (revision_id, sha1, rev.inventory_sha1))  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
273  | 
|
| 
1793.2.1
by Aaron Bentley
 Move revision_tree into BundleInfo  | 
274  | 
def _validate_revision(self, inventory, revision_id):  | 
275  | 
"""Make sure all revision entries match their checksum."""  | 
|
276  | 
||
277  | 
        # This is a mapping from each revision id to it's sha hash
 | 
|
278  | 
rev_to_sha1 = {}  | 
|
279  | 
||
280  | 
rev = self.get_revision(revision_id)  | 
|
281  | 
rev_info = self.get_revision_info(revision_id)  | 
|
282  | 
assert rev.revision_id == rev_info.revision_id  | 
|
283  | 
assert rev.revision_id == revision_id  | 
|
284  | 
sha1 = StrictTestament(rev, inventory).as_sha1()  | 
|
285  | 
if sha1 != rev_info.sha1:  | 
|
286  | 
raise TestamentMismatch(rev.revision_id, rev_info.sha1, sha1)  | 
|
287  | 
if rev_to_sha1.has_key(rev.revision_id):  | 
|
288  | 
raise BzrError('Revision {%s} given twice in the list'  | 
|
289  | 
% (rev.revision_id))  | 
|
290  | 
rev_to_sha1[rev.revision_id] = sha1  | 
|
291  | 
||
292  | 
def _update_tree(self, bundle_tree, revision_id):  | 
|
293  | 
"""This fills out a BundleTree based on the information  | 
|
294  | 
        that was read in.
 | 
|
295  | 
||
296  | 
        :param bundle_tree: A BundleTree to update with the new information.
 | 
|
297  | 
        """
 | 
|
298  | 
||
299  | 
def get_rev_id(last_changed, path, kind):  | 
|
300  | 
if last_changed is not None:  | 
|
301  | 
changed_revision_id = last_changed.decode('utf-8')  | 
|
302  | 
else:  | 
|
303  | 
changed_revision_id = revision_id  | 
|
304  | 
bundle_tree.note_last_changed(path, changed_revision_id)  | 
|
305  | 
return changed_revision_id  | 
|
306  | 
||
307  | 
def extra_info(info, new_path):  | 
|
308  | 
last_changed = None  | 
|
309  | 
encoding = None  | 
|
310  | 
for info_item in info:  | 
|
311  | 
try:  | 
|
312  | 
name, value = info_item.split(':', 1)  | 
|
313  | 
except ValueError:  | 
|
314  | 
raise 'Value %r has no colon' % info_item  | 
|
315  | 
if name == 'last-changed':  | 
|
316  | 
last_changed = value  | 
|
317  | 
elif name == 'executable':  | 
|
318  | 
assert value in ('yes', 'no'), value  | 
|
319  | 
val = (value == 'yes')  | 
|
320  | 
bundle_tree.note_executable(new_path, val)  | 
|
321  | 
elif name == 'target':  | 
|
322  | 
bundle_tree.note_target(new_path, value)  | 
|
323  | 
elif name == 'encoding':  | 
|
324  | 
encoding = value  | 
|
325  | 
return last_changed, encoding  | 
|
326  | 
||
327  | 
def do_patch(path, lines, encoding):  | 
|
328  | 
if encoding is not None:  | 
|
329  | 
assert encoding == 'base64'  | 
|
330  | 
patch = base64.decodestring(''.join(lines))  | 
|
331  | 
else:  | 
|
332  | 
patch = ''.join(lines)  | 
|
333  | 
bundle_tree.note_patch(path, patch)  | 
|
334  | 
||
335  | 
def renamed(kind, extra, lines):  | 
|
336  | 
info = extra.split(' // ')  | 
|
337  | 
if len(info) < 2:  | 
|
338  | 
raise BzrError('renamed action lines need both a from and to'  | 
|
339  | 
': %r' % extra)  | 
|
340  | 
old_path = info[0]  | 
|
341  | 
if info[1].startswith('=> '):  | 
|
342  | 
new_path = info[1][3:]  | 
|
343  | 
else:  | 
|
344  | 
new_path = info[1]  | 
|
345  | 
||
346  | 
bundle_tree.note_rename(old_path, new_path)  | 
|
347  | 
last_modified, encoding = extra_info(info[2:], new_path)  | 
|
348  | 
revision = get_rev_id(last_modified, new_path, kind)  | 
|
349  | 
if lines:  | 
|
350  | 
do_patch(new_path, lines, encoding)  | 
|
351  | 
||
352  | 
def removed(kind, extra, lines):  | 
|
353  | 
info = extra.split(' // ')  | 
|
354  | 
if len(info) > 1:  | 
|
355  | 
                # TODO: in the future we might allow file ids to be
 | 
|
356  | 
                # given for removed entries
 | 
|
357  | 
raise BzrError('removed action lines should only have the path'  | 
|
358  | 
': %r' % extra)  | 
|
359  | 
path = info[0]  | 
|
360  | 
bundle_tree.note_deletion(path)  | 
|
361  | 
||
362  | 
def added(kind, extra, lines):  | 
|
363  | 
info = extra.split(' // ')  | 
|
364  | 
if len(info) <= 1:  | 
|
365  | 
raise BzrError('add action lines require the path and file id'  | 
|
366  | 
': %r' % extra)  | 
|
367  | 
elif len(info) > 5:  | 
|
368  | 
raise BzrError('add action lines have fewer than 5 entries.'  | 
|
369  | 
': %r' % extra)  | 
|
370  | 
path = info[0]  | 
|
371  | 
if not info[1].startswith('file-id:'):  | 
|
372  | 
raise BzrError('The file-id should follow the path for an add'  | 
|
373  | 
': %r' % extra)  | 
|
374  | 
file_id = info[1][8:]  | 
|
375  | 
||
376  | 
bundle_tree.note_id(file_id, path, kind)  | 
|
377  | 
            # this will be overridden in extra_info if executable is specified.
 | 
|
378  | 
bundle_tree.note_executable(path, False)  | 
|
379  | 
last_changed, encoding = extra_info(info[2:], path)  | 
|
380  | 
revision = get_rev_id(last_changed, path, kind)  | 
|
381  | 
if kind == 'directory':  | 
|
382  | 
                return
 | 
|
383  | 
do_patch(path, lines, encoding)  | 
|
384  | 
||
385  | 
def modified(kind, extra, lines):  | 
|
386  | 
info = extra.split(' // ')  | 
|
387  | 
if len(info) < 1:  | 
|
388  | 
raise BzrError('modified action lines have at least'  | 
|
389  | 
'the path in them: %r' % extra)  | 
|
390  | 
path = info[0]  | 
|
391  | 
||
392  | 
last_modified, encoding = extra_info(info[1:], path)  | 
|
393  | 
revision = get_rev_id(last_modified, path, kind)  | 
|
394  | 
if lines:  | 
|
395  | 
do_patch(path, lines, encoding)  | 
|
396  | 
||
397  | 
valid_actions = {  | 
|
398  | 
'renamed':renamed,  | 
|
399  | 
'removed':removed,  | 
|
400  | 
'added':added,  | 
|
401  | 
'modified':modified  | 
|
402  | 
        }
 | 
|
403  | 
for action_line, lines in \  | 
|
404  | 
self.get_revision_info(revision_id).tree_actions:  | 
|
405  | 
first = action_line.find(' ')  | 
|
406  | 
if first == -1:  | 
|
407  | 
raise BzrError('Bogus action line'  | 
|
408  | 
' (no opening space): %r' % action_line)  | 
|
409  | 
second = action_line.find(' ', first+1)  | 
|
410  | 
if second == -1:  | 
|
411  | 
raise BzrError('Bogus action line'  | 
|
412  | 
' (missing second space): %r' % action_line)  | 
|
413  | 
action = action_line[:first]  | 
|
414  | 
kind = action_line[first+1:second]  | 
|
415  | 
if kind not in ('file', 'directory', 'symlink'):  | 
|
416  | 
raise BzrError('Bogus action line'  | 
|
417  | 
' (invalid object kind %r): %r' % (kind, action_line))  | 
|
418  | 
extra = action_line[second+1:]  | 
|
419  | 
||
420  | 
if action not in valid_actions:  | 
|
421  | 
raise BzrError('Bogus action line'  | 
|
422  | 
' (unrecognized action): %r' % action_line)  | 
|
423  | 
valid_actions[action](kind, extra, lines)  | 
|
424  | 
||
425  | 
||
| 
1185.82.130
by Aaron Bentley
 Rename changesets to revision bundles  | 
426  | 
class BundleTree(Tree):  | 
| 
1185.82.16
by Aaron Bentley
 Ensured revision ID is stored in ChangesetTree inventories  | 
427  | 
def __init__(self, base_tree, revision_id):  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
428  | 
self.base_tree = base_tree  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
429  | 
self._renamed = {} # Mapping from old_path => new_path  | 
430  | 
self._renamed_r = {} # new_path => old_path  | 
|
431  | 
self._new_id = {} # new_path => new_id  | 
|
432  | 
self._new_id_r = {} # new_id => new_path  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
433  | 
self._kinds = {} # new_id => kind  | 
| 
0.5.118
by John Arbash Meinel
 Got most of test_changeset to work. Still needs work for Aaron's test code.  | 
434  | 
self._last_changed = {} # new_id => revision_id  | 
| 
1185.82.66
by Aaron Bentley
 Handle new executable files  | 
435  | 
self._executable = {} # new_id => executable value  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
436  | 
self.patches = {}  | 
| 
1185.82.87
by Aaron Bentley
 Got symlink adding working  | 
437  | 
self._targets = {} # new path => new symlink target  | 
| 
0.5.48
by aaron.bentley at utoronto
 Implemented deletion for ChangesetTrees  | 
438  | 
self.deleted = []  | 
| 
0.5.52
by aaron.bentley at utoronto
 Make contents-addressing configurable  | 
439  | 
self.contents_by_id = True  | 
| 
1185.82.16
by Aaron Bentley
 Ensured revision ID is stored in ChangesetTree inventories  | 
440  | 
self.revision_id = revision_id  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
441  | 
self._inventory = None  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
442  | 
|
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
443  | 
def __str__(self):  | 
444  | 
return pprint.pformat(self.__dict__)  | 
|
445  | 
||
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
446  | 
def note_rename(self, old_path, new_path):  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
447  | 
"""A file/directory has been renamed from old_path => new_path"""  | 
| 
1185.82.70
by Aaron Bentley
 Handle renamed files better  | 
448  | 
assert not self._renamed.has_key(new_path)  | 
449  | 
assert not self._renamed_r.has_key(old_path)  | 
|
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
450  | 
self._renamed[new_path] = old_path  | 
451  | 
self._renamed_r[old_path] = new_path  | 
|
452  | 
||
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
453  | 
def note_id(self, new_id, new_path, kind='file'):  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
454  | 
"""Files that don't exist in base need a new id."""  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
455  | 
self._new_id[new_path] = new_id  | 
456  | 
self._new_id_r[new_id] = new_path  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
457  | 
self._kinds[new_id] = kind  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
458  | 
|
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
459  | 
def note_last_changed(self, file_id, revision_id):  | 
| 
0.5.118
by John Arbash Meinel
 Got most of test_changeset to work. Still needs work for Aaron's test code.  | 
460  | 
if (self._last_changed.has_key(file_id)  | 
461  | 
and self._last_changed[file_id] != revision_id):  | 
|
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
462  | 
raise BzrError('Mismatched last-changed revision for file_id {%s}'  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
463  | 
': %s != %s' % (file_id,  | 
| 
0.5.118
by John Arbash Meinel
 Got most of test_changeset to work. Still needs work for Aaron's test code.  | 
464  | 
self._last_changed[file_id],  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
465  | 
revision_id))  | 
| 
0.5.118
by John Arbash Meinel
 Got most of test_changeset to work. Still needs work for Aaron's test code.  | 
466  | 
self._last_changed[file_id] = revision_id  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
467  | 
|
| 
0.5.44
by aaron.bentley at utoronto
 Got get_file working for new files  | 
468  | 
def note_patch(self, new_path, patch):  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
469  | 
"""There is a patch for a given filename."""  | 
| 
0.5.44
by aaron.bentley at utoronto
 Got get_file working for new files  | 
470  | 
self.patches[new_path] = patch  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
471  | 
|
| 
1185.82.87
by Aaron Bentley
 Got symlink adding working  | 
472  | 
def note_target(self, new_path, target):  | 
473  | 
"""The symlink at the new path has the given target"""  | 
|
474  | 
self._targets[new_path] = target  | 
|
475  | 
||
| 
0.5.48
by aaron.bentley at utoronto
 Implemented deletion for ChangesetTrees  | 
476  | 
def note_deletion(self, old_path):  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
477  | 
"""The file at old_path has been deleted."""  | 
| 
0.5.48
by aaron.bentley at utoronto
 Implemented deletion for ChangesetTrees  | 
478  | 
self.deleted.append(old_path)  | 
479  | 
||
| 
1185.82.66
by Aaron Bentley
 Handle new executable files  | 
480  | 
def note_executable(self, new_path, executable):  | 
481  | 
self._executable[new_path] = executable  | 
|
482  | 
||
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
483  | 
def old_path(self, new_path):  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
484  | 
"""Get the old_path (path in the base_tree) for the file at new_path"""  | 
| 
0.6.1
by Aaron Bentley
 Fleshed out MockTree, fixed all test failures  | 
485  | 
assert new_path[:1] not in ('\\', '/')  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
486  | 
old_path = self._renamed.get(new_path)  | 
487  | 
if old_path is not None:  | 
|
488  | 
return old_path  | 
|
489  | 
dirname,basename = os.path.split(new_path)  | 
|
| 
0.5.56
by John Arbash Meinel
 A couple more fixups, it seems actually capable now of writing out a changeset, and reading it back.  | 
490  | 
        # dirname is not '' doesn't work, because
 | 
491  | 
        # dirname may be a unicode entry, and is
 | 
|
492  | 
        # requires the objects to be identical
 | 
|
493  | 
if dirname != '':  | 
|
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
494  | 
old_dir = self.old_path(dirname)  | 
495  | 
if old_dir is None:  | 
|
| 
0.5.42
by aaron.bentley at utoronto
 Improved rename handling  | 
496  | 
old_path = None  | 
497  | 
else:  | 
|
| 
1711.4.19
by John Arbash Meinel
 Bundles were still using os.path.join to compute paths rather than osutils.pathjoin  | 
498  | 
old_path = pathjoin(old_dir, basename)  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
499  | 
else:  | 
| 
0.5.42
by aaron.bentley at utoronto
 Improved rename handling  | 
500  | 
old_path = new_path  | 
501  | 
        #If the new path wasn't in renamed, the old one shouldn't be in
 | 
|
502  | 
        #renamed_r
 | 
|
503  | 
if self._renamed_r.has_key(old_path):  | 
|
504  | 
return None  | 
|
505  | 
return old_path  | 
|
506  | 
||
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
507  | 
def new_path(self, old_path):  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
508  | 
"""Get the new_path (path in the target_tree) for the file at old_path  | 
509  | 
        in the base tree.
 | 
|
510  | 
        """
 | 
|
| 
0.6.1
by Aaron Bentley
 Fleshed out MockTree, fixed all test failures  | 
511  | 
assert old_path[:1] not in ('\\', '/')  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
512  | 
new_path = self._renamed_r.get(old_path)  | 
513  | 
if new_path is not None:  | 
|
514  | 
return new_path  | 
|
515  | 
if self._renamed.has_key(new_path):  | 
|
516  | 
return None  | 
|
517  | 
dirname,basename = os.path.split(old_path)  | 
|
| 
0.5.81
by John Arbash Meinel
 Cleaning up from pychecker.  | 
518  | 
if dirname != '':  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
519  | 
new_dir = self.new_path(dirname)  | 
520  | 
if new_dir is None:  | 
|
| 
0.5.42
by aaron.bentley at utoronto
 Improved rename handling  | 
521  | 
new_path = None  | 
522  | 
else:  | 
|
| 
1711.4.19
by John Arbash Meinel
 Bundles were still using os.path.join to compute paths rather than osutils.pathjoin  | 
523  | 
new_path = pathjoin(new_dir, basename)  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
524  | 
else:  | 
| 
0.5.42
by aaron.bentley at utoronto
 Improved rename handling  | 
525  | 
new_path = old_path  | 
526  | 
        #If the old path wasn't in renamed, the new one shouldn't be in
 | 
|
527  | 
        #renamed_r
 | 
|
528  | 
if self._renamed.has_key(new_path):  | 
|
529  | 
return None  | 
|
530  | 
return new_path  | 
|
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
531  | 
|
532  | 
def path2id(self, path):  | 
|
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
533  | 
"""Return the id of the file present at path in the target tree."""  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
534  | 
file_id = self._new_id.get(path)  | 
535  | 
if file_id is not None:  | 
|
536  | 
return file_id  | 
|
| 
0.5.43
by aaron.bentley at utoronto
 Handled moves and adds properly  | 
537  | 
old_path = self.old_path(path)  | 
538  | 
if old_path is None:  | 
|
539  | 
return None  | 
|
| 
0.5.48
by aaron.bentley at utoronto
 Implemented deletion for ChangesetTrees  | 
540  | 
if old_path in self.deleted:  | 
541  | 
return None  | 
|
| 
0.5.66
by John Arbash Meinel
 Refactoring, moving test code into test (switching back to assert is None)  | 
542  | 
if hasattr(self.base_tree, 'path2id'):  | 
543  | 
return self.base_tree.path2id(old_path)  | 
|
544  | 
else:  | 
|
545  | 
return self.base_tree.inventory.path2id(old_path)  | 
|
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
546  | 
|
547  | 
def id2path(self, file_id):  | 
|
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
548  | 
"""Return the new path in the target tree of the file with id file_id"""  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
549  | 
path = self._new_id_r.get(file_id)  | 
550  | 
if path is not None:  | 
|
551  | 
return path  | 
|
| 
0.5.43
by aaron.bentley at utoronto
 Handled moves and adds properly  | 
552  | 
old_path = self.base_tree.id2path(file_id)  | 
553  | 
if old_path is None:  | 
|
554  | 
return None  | 
|
| 
0.5.48
by aaron.bentley at utoronto
 Implemented deletion for ChangesetTrees  | 
555  | 
if old_path in self.deleted:  | 
556  | 
return None  | 
|
| 
0.5.43
by aaron.bentley at utoronto
 Handled moves and adds properly  | 
557  | 
return self.new_path(old_path)  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
558  | 
|
| 
0.5.52
by aaron.bentley at utoronto
 Make contents-addressing configurable  | 
559  | 
def old_contents_id(self, file_id):  | 
| 
1185.82.94
by Aaron Bentley
 Remove old chatter  | 
560  | 
"""Return the id in the base_tree for the given file_id.  | 
561  | 
        Return None if the file did not exist in base.
 | 
|
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
562  | 
        """
 | 
| 
0.5.52
by aaron.bentley at utoronto
 Make contents-addressing configurable  | 
563  | 
if self.contents_by_id:  | 
564  | 
if self.base_tree.has_id(file_id):  | 
|
565  | 
return file_id  | 
|
566  | 
else:  | 
|
567  | 
return None  | 
|
568  | 
new_path = self.id2path(file_id)  | 
|
569  | 
return self.base_tree.path2id(new_path)  | 
|
570  | 
||
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
571  | 
def get_file(self, file_id):  | 
| 
0.5.55
by John Arbash Meinel
 Lots of updates. Using a minimized annotations for changesets.  | 
572  | 
"""Return a file-like object containing the new contents of the  | 
573  | 
        file given by file_id.
 | 
|
574  | 
||
575  | 
        TODO:   It might be nice if this actually generated an entry
 | 
|
576  | 
                in the text-store, so that the file contents would
 | 
|
577  | 
                then be cached.
 | 
|
578  | 
        """
 | 
|
| 
0.5.52
by aaron.bentley at utoronto
 Make contents-addressing configurable  | 
579  | 
base_id = self.old_contents_id(file_id)  | 
| 
0.5.50
by aaron.bentley at utoronto
 Evaluate patches against file paths, not file ids  | 
580  | 
if base_id is not None:  | 
581  | 
patch_original = self.base_tree.get_file(base_id)  | 
|
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
582  | 
else:  | 
583  | 
patch_original = None  | 
|
| 
0.5.52
by aaron.bentley at utoronto
 Make contents-addressing configurable  | 
584  | 
file_patch = self.patches.get(self.id2path(file_id))  | 
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
585  | 
if file_patch is None:  | 
| 
1185.82.42
by Aaron Bentley
 Handle new directories properly  | 
586  | 
if (patch_original is None and  | 
587  | 
self.get_kind(file_id) == 'directory'):  | 
|
588  | 
return StringIO()  | 
|
589  | 
assert patch_original is not None, "None: %s" % file_id  | 
|
| 
0.5.44
by aaron.bentley at utoronto
 Got get_file working for new files  | 
590  | 
return patch_original  | 
| 
0.5.94
by Aaron Bentley
 Switched to native patch application, added tests for terminating newlines  | 
591  | 
|
592  | 
assert not file_patch.startswith('\\'), \  | 
|
593  | 
'Malformed patch for %s, %r' % (file_id, file_patch)  | 
|
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
594  | 
return patched_file(file_patch, patch_original)  | 
595  | 
||
| 
1185.82.87
by Aaron Bentley
 Got symlink adding working  | 
596  | 
def get_symlink_target(self, file_id):  | 
597  | 
new_path = self.id2path(file_id)  | 
|
598  | 
try:  | 
|
599  | 
return self._targets[new_path]  | 
|
600  | 
except KeyError:  | 
|
601  | 
return self.base_tree.get_symlink_target(file_id)  | 
|
602  | 
||
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
603  | 
def get_kind(self, file_id):  | 
604  | 
if file_id in self._kinds:  | 
|
605  | 
return self._kinds[file_id]  | 
|
606  | 
return self.base_tree.inventory[file_id].kind  | 
|
607  | 
||
| 
1185.82.66
by Aaron Bentley
 Handle new executable files  | 
608  | 
def is_executable(self, file_id):  | 
| 
1185.82.93
by Aaron Bentley
 Code cleanup  | 
609  | 
path = self.id2path(file_id)  | 
610  | 
if path in self._executable:  | 
|
611  | 
return self._executable[path]  | 
|
| 
1185.82.66
by Aaron Bentley
 Handle new executable files  | 
612  | 
else:  | 
613  | 
return self.base_tree.inventory[file_id].executable  | 
|
614  | 
||
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
615  | 
def get_last_changed(self, file_id):  | 
| 
1185.82.95
by Aaron Bentley
 Restore path-orientation of ChangesetTree  | 
616  | 
path = self.id2path(file_id)  | 
617  | 
if path in self._last_changed:  | 
|
618  | 
return self._last_changed[path]  | 
|
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
619  | 
return self.base_tree.inventory[file_id].revision  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
620  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
621  | 
def get_size_and_sha1(self, file_id):  | 
622  | 
"""Return the size and sha1 hash of the given file id.  | 
|
623  | 
        If the file was not locally modified, this is extracted
 | 
|
624  | 
        from the base_tree. Rather than re-reading the file.
 | 
|
625  | 
        """
 | 
|
626  | 
new_path = self.id2path(file_id)  | 
|
627  | 
if new_path is None:  | 
|
628  | 
return None, None  | 
|
629  | 
if new_path not in self.patches:  | 
|
630  | 
            # If the entry does not have a patch, then the
 | 
|
631  | 
            # contents must be the same as in the base_tree
 | 
|
632  | 
ie = self.base_tree.inventory[file_id]  | 
|
| 
0.5.69
by John Arbash Meinel
 Applying patch from Robey Pointer to clean up apply_changeset.  | 
633  | 
if ie.text_size is None:  | 
634  | 
return ie.text_size, ie.text_sha1  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
635  | 
return int(ie.text_size), ie.text_sha1  | 
| 
0.5.94
by Aaron Bentley
 Switched to native patch application, added tests for terminating newlines  | 
636  | 
fileobj = self.get_file(file_id)  | 
637  | 
content = fileobj.read()  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
638  | 
return len(content), sha_string(content)  | 
639  | 
||
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
640  | 
def _get_inventory(self):  | 
| 
1185.82.130
by Aaron Bentley
 Rename changesets to revision bundles  | 
641  | 
"""Build up the inventory entry for the BundleTree.  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
642  | 
|
643  | 
        This need to be called before ever accessing self.inventory
 | 
|
644  | 
        """
 | 
|
645  | 
from os.path import dirname, basename  | 
|
646  | 
||
647  | 
assert self.base_tree is not None  | 
|
648  | 
base_inv = self.base_tree.inventory  | 
|
649  | 
root_id = base_inv.root.file_id  | 
|
650  | 
try:  | 
|
651  | 
            # New inventories have a unique root_id
 | 
|
| 
1185.82.16
by Aaron Bentley
 Ensured revision ID is stored in ChangesetTree inventories  | 
652  | 
inv = Inventory(root_id, self.revision_id)  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
653  | 
except TypeError:  | 
| 
1185.82.16
by Aaron Bentley
 Ensured revision ID is stored in ChangesetTree inventories  | 
654  | 
inv = Inventory(revision_id=self.revision_id)  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
655  | 
|
656  | 
def add_entry(file_id):  | 
|
657  | 
path = self.id2path(file_id)  | 
|
658  | 
if path is None:  | 
|
659  | 
                return
 | 
|
660  | 
parent_path = dirname(path)  | 
|
| 
0.5.116
by John Arbash Meinel
 Fixed a bug based on the new InventoryEntry separation.  | 
661  | 
if parent_path == u'':  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
662  | 
parent_id = root_id  | 
663  | 
else:  | 
|
664  | 
parent_id = self.path2id(parent_path)  | 
|
665  | 
||
666  | 
kind = self.get_kind(file_id)  | 
|
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
667  | 
revision_id = self.get_last_changed(file_id)  | 
| 
0.5.83
by John Arbash Meinel
 Tests pass. Now ChangesetTree has it's own inventory.  | 
668  | 
|
669  | 
name = basename(path)  | 
|
| 
0.5.116
by John Arbash Meinel
 Fixed a bug based on the new InventoryEntry separation.  | 
670  | 
if kind == 'directory':  | 
671  | 
ie = InventoryDirectory(file_id, name, parent_id)  | 
|
672  | 
elif kind == 'file':  | 
|
673  | 
ie = InventoryFile(file_id, name, parent_id)  | 
|
| 
1185.82.66
by Aaron Bentley
 Handle new executable files  | 
674  | 
ie.executable = self.is_executable(file_id)  | 
| 
0.5.116
by John Arbash Meinel
 Fixed a bug based on the new InventoryEntry separation.  | 
675  | 
elif kind == 'symlink':  | 
676  | 
ie = InventoryLink(file_id, name, parent_id)  | 
|
| 
1185.82.87
by Aaron Bentley
 Got symlink adding working  | 
677  | 
ie.symlink_target = self.get_symlink_target(file_id)  | 
| 
0.5.115
by John Arbash Meinel
 Getting closer to being able to read back the changesets, still broken, though.  | 
678  | 
ie.revision = revision_id  | 
679  | 
||
| 
1185.82.88
by Aaron Bentley
 Get symlink modification, renames and deletion under test  | 
680  | 
if kind in ('directory', 'symlink'):  | 
| 
0.5.83
by John Arbash Meinel
 Tests pass. Now ChangesetTree has it's own inventory.  | 
681  | 
ie.text_size, ie.text_sha1 = None, None  | 
682  | 
else:  | 
|
683  | 
ie.text_size, ie.text_sha1 = self.get_size_and_sha1(file_id)  | 
|
| 
1185.82.88
by Aaron Bentley
 Get symlink modification, renames and deletion under test  | 
684  | 
if (ie.text_size is None) and (kind == 'file'):  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
685  | 
raise BzrError('Got a text_size of None for file_id %r' % file_id)  | 
686  | 
inv.add(ie)  | 
|
687  | 
||
| 
0.6.1
by Aaron Bentley
 Fleshed out MockTree, fixed all test failures  | 
688  | 
sorted_entries = self.sorted_path_id()  | 
689  | 
for path, file_id in sorted_entries:  | 
|
690  | 
if file_id == inv.root.file_id:  | 
|
| 
0.5.83
by John Arbash Meinel
 Tests pass. Now ChangesetTree has it's own inventory.  | 
691  | 
                continue
 | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
692  | 
add_entry(file_id)  | 
693  | 
||
694  | 
return inv  | 
|
695  | 
||
696  | 
    # Have to overload the inherited inventory property
 | 
|
697  | 
    # because _get_inventory is only called in the parent.
 | 
|
698  | 
    # Reading the docs, property() objects do not use
 | 
|
699  | 
    # overloading, they use the function as it was defined
 | 
|
700  | 
    # at that instant
 | 
|
701  | 
inventory = property(_get_inventory)  | 
|
| 
0.5.64
by John Arbash Meinel
 SUCCESS, we now are able to validate the inventory XML.  | 
702  | 
|
| 
0.5.49
by aaron.bentley at utoronto
 Implemented iteration over ids  | 
703  | 
def __iter__(self):  | 
| 
0.5.82
by John Arbash Meinel
 Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids  | 
704  | 
for path, entry in self.inventory.iter_entries():  | 
| 
0.5.69
by John Arbash Meinel
 Applying patch from Robey Pointer to clean up apply_changeset.  | 
705  | 
yield entry.file_id  | 
| 
0.5.49
by aaron.bentley at utoronto
 Implemented iteration over ids  | 
706  | 
|
| 
0.6.1
by Aaron Bentley
 Fleshed out MockTree, fixed all test failures  | 
707  | 
def sorted_path_id(self):  | 
708  | 
paths = []  | 
|
709  | 
for result in self._new_id.iteritems():  | 
|
710  | 
paths.append(result)  | 
|
711  | 
for id in self.base_tree:  | 
|
712  | 
path = self.id2path(id)  | 
|
713  | 
if path is None:  | 
|
714  | 
                continue
 | 
|
715  | 
paths.append((path, id))  | 
|
716  | 
paths.sort()  | 
|
717  | 
return paths  | 
|
718  | 
||
| 
1185.82.123
by Aaron Bentley
 Cleanups to prepare for review  | 
719  | 
|
| 
0.5.41
by aaron.bentley at utoronto
 Added non-working ChangesetTree  | 
720  | 
def patched_file(file_patch, original):  | 
| 
0.5.94
by Aaron Bentley
 Switched to native patch application, added tests for terminating newlines  | 
721  | 
"""Produce a file-like object with the patched version of a text"""  | 
| 
1185.82.13
by Aaron Bentley
 Got old changeset tests running  | 
722  | 
from bzrlib.patches import iter_patched  | 
723  | 
from bzrlib.iterablefile import IterableFile  | 
|
| 
0.5.94
by Aaron Bentley
 Switched to native patch application, added tests for terminating newlines  | 
724  | 
if file_patch == "":  | 
725  | 
return IterableFile(())  | 
|
726  | 
return IterableFile(iter_patched(original, file_patch.splitlines(True)))  |