bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 70
by mbp at sourcefrog Prepare for smart recursive add. | 1 | # Copyright (C) 2005 Canonical Ltd
 | 
| 1
by mbp at sourcefrog import from baz patch-364 | 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 | """Tree classes, representing directory at point in time.
 | |
| 18 | """
 | |
| 19 | ||
| 849
by Martin Pool - Put files inside an exported tarball into a top-level directory rather than | 20 | import os | 
| 1196
by Martin Pool - [WIP] retrieve historical texts from weaves | 21 | from cStringIO import StringIO | 
| 800
by Martin Pool Merge John's import-speedup branch: | 22 | |
| 974.1.26
by aaron.bentley at utoronto merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 | 23 | import bzrlib | 
| 1196
by Martin Pool - [WIP] retrieve historical texts from weaves | 24 | from bzrlib.errors import BzrError, BzrCheckError | 
| 974.1.26
by aaron.bentley at utoronto merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 | 25 | from bzrlib.inventory import Inventory | 
| 1732.1.1
by John Arbash Meinel deprecating appendpath, it does exactly what pathjoin does | 26 | from bzrlib.osutils import fingerprint_file | 
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 27 | import bzrlib.revision | 
| 28 | from bzrlib.trace import mutter, note | |
| 1
by mbp at sourcefrog import from baz patch-364 | 29 | |
| 558
by Martin Pool - All top-level classes inherit from object | 30 | class Tree(object): | 
| 1
by mbp at sourcefrog import from baz patch-364 | 31 | """Abstract file tree. | 
| 32 | ||
| 33 |     There are several subclasses:
 | |
| 34 |     
 | |
| 35 |     * `WorkingTree` exists as files on disk editable by the user.
 | |
| 36 | ||
| 37 |     * `RevisionTree` is a tree as recorded at some point in the past.
 | |
| 38 | ||
| 39 |     * `EmptyTree`
 | |
| 40 | ||
| 41 |     Trees contain an `Inventory` object, and also know how to retrieve
 | |
| 42 |     file texts mentioned in the inventory, either from a working
 | |
| 43 |     directory or from a store.
 | |
| 44 | ||
| 45 |     It is possible for trees to contain files that are not described
 | |
| 46 |     in their inventory or vice versa; for this use `filenames()`.
 | |
| 47 | ||
| 48 |     Trees can be compared, etc, regardless of whether they are working
 | |
| 49 |     trees or versioned trees.
 | |
| 50 |     """
 | |
| 51 | ||
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 52 | def conflicts(self): | 
| 53 | """Get a list of the conflicts in the tree. | |
| 54 | ||
| 55 |         Each conflict is an instance of bzrlib.conflicts.Conflict.
 | |
| 56 |         """
 | |
| 57 | return [] | |
| 58 | ||
| 59 | def get_parent_ids(self): | |
| 60 | """Get the parent ids for this tree. | |
| 61 | ||
| 62 |         :return: a list of parent ids. [] is returned to indicate
 | |
| 63 |         a tree with no parents.
 | |
| 64 |         :raises: BzrError if the parents are not known.
 | |
| 65 |         """
 | |
| 66 | raise NotImplementedError(self.get_parent_ids) | |
| 67 | ||
| 1
by mbp at sourcefrog import from baz patch-364 | 68 | def has_filename(self, filename): | 
| 69 | """True if the tree has given filename.""" | |
| 70 | raise NotImplementedError() | |
| 71 | ||
| 1185.12.39
by abentley Propogated has_or_had_id to Tree | 72 | def has_id(self, file_id): | 
| 73 | return self.inventory.has_id(file_id) | |
| 74 | ||
| 75 | def has_or_had_id(self, file_id): | |
| 76 | if file_id == self.inventory.root.file_id: | |
| 1185.12.38
by abentley semi-broke merge | 77 | return True | 
| 1
by mbp at sourcefrog import from baz patch-364 | 78 | return self.inventory.has_id(file_id) | 
| 79 | ||
| 462
by Martin Pool - New form 'file_id in tree' to check if the file is present | 80 | __contains__ = has_id | 
| 81 | ||
| 82 | def __iter__(self): | |
| 83 | return iter(self.inventory) | |
| 84 | ||
| 1
by mbp at sourcefrog import from baz patch-364 | 85 | def id2path(self, file_id): | 
| 86 | return self.inventory.id2path(file_id) | |
| 87 | ||
| 1465
by Robert Collins Bugfix the new pull --clobber to not generate spurious conflicts. | 88 | def kind(self, file_id): | 
| 89 | raise NotImplementedError("subclasses must implement kind") | |
| 90 | ||
| 1
by mbp at sourcefrog import from baz patch-364 | 91 | def _get_inventory(self): | 
| 92 | return self._inventory | |
| 974.1.26
by aaron.bentley at utoronto merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 | 93 | |
| 94 | def get_file_by_path(self, path): | |
| 95 | return self.get_file(self._inventory.path2id(path)) | |
| 1
by mbp at sourcefrog import from baz patch-364 | 96 | |
| 97 | inventory = property(_get_inventory, | |
| 98 | doc="Inventory of this Tree") | |
| 99 | ||
| 100 | def _check_retrieved(self, ie, f): | |
| 1364
by Martin Pool - remove extra verification of files retrieved from tree | 101 | if not __debug__: | 
| 102 |             return  
 | |
| 130
by mbp at sourcefrog - fixup checks on retrieved files to cope with compression, | 103 | fp = fingerprint_file(f) | 
| 104 | f.seek(0) | |
| 105 | ||
| 184
by mbp at sourcefrog pychecker fixups | 106 | if ie.text_size != None: | 
| 131
by mbp at sourcefrog check size and sha1 of files retrieved from the tree | 107 | if ie.text_size != fp['size']: | 
| 694
by Martin Pool - weed out all remaining calls to bailout() and remove the function | 108 | raise BzrError("mismatched size for file %r in %r" % (ie.file_id, self._store), | 
| 1
by mbp at sourcefrog import from baz patch-364 | 109 | ["inventory expects %d bytes" % ie.text_size, | 
| 130
by mbp at sourcefrog - fixup checks on retrieved files to cope with compression, | 110 | "file is actually %d bytes" % fp['size'], | 
| 1
by mbp at sourcefrog import from baz patch-364 | 111 | "store is probably damaged/corrupt"]) | 
| 112 | ||
| 130
by mbp at sourcefrog - fixup checks on retrieved files to cope with compression, | 113 | if ie.text_sha1 != fp['sha1']: | 
| 694
by Martin Pool - weed out all remaining calls to bailout() and remove the function | 114 | raise BzrError("wrong SHA-1 for file %r in %r" % (ie.file_id, self._store), | 
| 1
by mbp at sourcefrog import from baz patch-364 | 115 | ["inventory expects %s" % ie.text_sha1, | 
| 130
by mbp at sourcefrog - fixup checks on retrieved files to cope with compression, | 116 | "file is actually %s" % fp['sha1'], | 
| 1
by mbp at sourcefrog import from baz patch-364 | 117 | "store is probably damaged/corrupt"]) | 
| 118 | ||
| 119 | ||
| 1196
by Martin Pool - [WIP] retrieve historical texts from weaves | 120 | def print_file(self, file_id): | 
| 121 | """Print file with id `file_id` to stdout.""" | |
| 176
by mbp at sourcefrog New cat command contributed by janmar. | 122 | import sys | 
| 1196
by Martin Pool - [WIP] retrieve historical texts from weaves | 123 | sys.stdout.write(self.get_file_text(file_id)) | 
| 1543.1.1
by Denys Duchier lock operations for trees - use them for diff | 124 | |
| 125 | def lock_read(self): | |
| 126 |         pass
 | |
| 127 | ||
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 128 | def unknowns(self): | 
| 129 | """What files are present in this tree and unknown. | |
| 130 |         
 | |
| 131 |         :return: an iterator over the unknown files.
 | |
| 132 |         """
 | |
| 133 | return iter([]) | |
| 134 | ||
| 1543.1.1
by Denys Duchier lock operations for trees - use them for diff | 135 | def unlock(self): | 
| 136 |         pass
 | |
| 1658.1.9
by Martin Pool Give an error for bzr diff on an nonexistent file (Malone #3619) | 137 | |
| 138 | def filter_unversioned_files(self, paths): | |
| 139 | """Filter out paths that are not versioned. | |
| 140 | ||
| 141 |         :return: set of paths.
 | |
| 142 |         """
 | |
| 1658.1.10
by Martin Pool diff on unversiond files should give an error (Malone #3619) | 143 |         # NB: we specifically *don't* call self.has_filename, because for
 | 
| 144 |         # WorkingTrees that can indicate files that exist on disk but that 
 | |
| 145 |         # are not versioned.
 | |
| 146 | pred = self.inventory.has_filename | |
| 147 | return set((p for p in paths if not pred(p))) | |
| 176
by mbp at sourcefrog New cat command contributed by janmar. | 148 | |
| 149 | ||
| 1
by mbp at sourcefrog import from baz patch-364 | 150 | class RevisionTree(Tree): | 
| 151 | """Tree viewing a previous revision. | |
| 152 | ||
| 153 |     File text can be retrieved from the text store.
 | |
| 154 | ||
| 254
by Martin Pool - Doc cleanups from Magnus Therning | 155 |     TODO: Some kind of `__repr__` method, but a good one
 | 
| 1
by mbp at sourcefrog import from baz patch-364 | 156 |            probably means knowing the branch and revision number,
 | 
| 157 |            or at least passing a description to the constructor.
 | |
| 158 |     """
 | |
| 159 | ||
| 1185.50.28
by John Arbash Meinel Lots of updates for 'bzr check' | 160 | def __init__(self, branch, inv, revision_id): | 
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 161 |         # for compatability the 'branch' parameter has not been renamed to 
 | 
| 162 |         # repository at this point. However, we should change RevisionTree's
 | |
| 163 |         # construction to always be via Repository and not via direct 
 | |
| 164 |         # construction - this will mean that we can change the constructor
 | |
| 165 |         # with much less chance of breaking client code.
 | |
| 166 | self._repository = branch | |
| 1185.50.28
by John Arbash Meinel Lots of updates for 'bzr check' | 167 | self._weave_store = branch.weave_store | 
| 1
by mbp at sourcefrog import from baz patch-364 | 168 | self._inventory = inv | 
| 1196
by Martin Pool - [WIP] retrieve historical texts from weaves | 169 | self._revision_id = revision_id | 
| 170 | ||
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 171 | def get_parent_ids(self): | 
| 172 | """See Tree.get_parent_ids. | |
| 173 | ||
| 174 |         A RevisionTree's parents match the revision graph.
 | |
| 175 |         """
 | |
| 176 | parent_ids = self._repository.get_revision(self._revision_id).parent_ids | |
| 177 | return parent_ids | |
| 178 | ||
| 1185.82.3
by John Arbash Meinel Working on creating a factor for serializing changesets. | 179 | def get_revision_id(self): | 
| 180 | """Return the revision id associated with this tree.""" | |
| 181 | return self._revision_id | |
| 182 | ||
| 1210
by Martin Pool - get correct old file version in RevisionTree | 183 | def get_weave(self, file_id): | 
| 1417.1.8
by Robert Collins use transactions in the weave store interface, which enables caching for log | 184 | return self._weave_store.get_weave(file_id, | 
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 185 | self._repository.get_transaction()) | 
| 1369
by Martin Pool - try to avoid redundant conversion of strings when retrieving from weaves | 186 | |
| 187 | def get_file_lines(self, file_id): | |
| 188 | ie = self._inventory[file_id] | |
| 189 | weave = self.get_weave(file_id) | |
| 1563.2.13
by Robert Collins InterVersionedFile implemented. | 190 | return weave.get_lines(ie.revision) | 
| 1210
by Martin Pool - get correct old file version in RevisionTree | 191 | |
| 1196
by Martin Pool - [WIP] retrieve historical texts from weaves | 192 | def get_file_text(self, file_id): | 
| 1369
by Martin Pool - try to avoid redundant conversion of strings when retrieving from weaves | 193 | return ''.join(self.get_file_lines(file_id)) | 
| 194 | ||
| 1
by mbp at sourcefrog import from baz patch-364 | 195 | def get_file(self, file_id): | 
| 1196
by Martin Pool - [WIP] retrieve historical texts from weaves | 196 | return StringIO(self.get_file_text(file_id)) | 
| 1
by mbp at sourcefrog import from baz patch-364 | 197 | |
| 198 | def get_file_size(self, file_id): | |
| 199 | return self._inventory[file_id].text_size | |
| 200 | ||
| 1732.1.19
by John Arbash Meinel If you have the path, use it rather than looking it up again | 201 | def get_file_sha1(self, file_id, path=None): | 
| 1
by mbp at sourcefrog import from baz patch-364 | 202 | ie = self._inventory[file_id] | 
| 974.1.12
by aaron.bentley at utoronto Switched from text-id to hashcache for merge optimization | 203 | if ie.kind == "file": | 
| 204 | return ie.text_sha1 | |
| 1732.1.19
by John Arbash Meinel If you have the path, use it rather than looking it up again | 205 | return None | 
| 1
by mbp at sourcefrog import from baz patch-364 | 206 | |
| 1740.2.5
by Aaron Bentley Merge from bzr.dev | 207 | def get_file_mtime(self, file_id, path=None): | 
| 208 | ie = self._inventory[file_id] | |
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 209 | revision = self._repository.get_revision(ie.revision) | 
| 1740.2.5
by Aaron Bentley Merge from bzr.dev | 210 | return revision.timestamp | 
| 211 | ||
| 1732.1.19
by John Arbash Meinel If you have the path, use it rather than looking it up again | 212 | def is_executable(self, file_id, path=None): | 
| 1185.12.28
by Aaron Bentley Removed use of readonly path for executability test | 213 | ie = self._inventory[file_id] | 
| 214 | if ie.kind != "file": | |
| 215 | return None | |
| 1398
by Robert Collins integrate in Gustavos x-bit patch | 216 | return self._inventory[file_id].executable | 
| 217 | ||
| 1
by mbp at sourcefrog import from baz patch-364 | 218 | def has_filename(self, filename): | 
| 219 | return bool(self.inventory.path2id(filename)) | |
| 220 | ||
| 1551.6.36
by Aaron Bentley Revert --debris/--detritus changes | 221 | def list_files(self): | 
| 1
by mbp at sourcefrog import from baz patch-364 | 222 |         # The only files returned by this are those from the version
 | 
| 1732.1.14
by John Arbash Meinel Some speedups by not calling pathjoin() | 223 | for path, entry in self.inventory.iter_entries(): | 
| 224 | yield path, 'V', entry.kind, entry.file_id, entry | |
| 1
by mbp at sourcefrog import from baz patch-364 | 225 | |
| 1092.2.6
by Robert Collins symlink support updated to work | 226 | def get_symlink_target(self, file_id): | 
| 227 | ie = self._inventory[file_id] | |
| 228 | return ie.symlink_target; | |
| 1
by mbp at sourcefrog import from baz patch-364 | 229 | |
| 1185.12.28
by Aaron Bentley Removed use of readonly path for executability test | 230 | def kind(self, file_id): | 
| 231 | return self._inventory[file_id].kind | |
| 1399.1.2
by Robert Collins push kind character creation into InventoryEntry and TreeEntry | 232 | |
| 1543.1.1
by Denys Duchier lock operations for trees - use them for diff | 233 | def lock_read(self): | 
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 234 | self._repository.lock_read() | 
| 1543.1.1
by Denys Duchier lock operations for trees - use them for diff | 235 | |
| 236 | def unlock(self): | |
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 237 | self._repository.unlock() | 
| 1543.1.1
by Denys Duchier lock operations for trees - use them for diff | 238 | |
| 1465
by Robert Collins Bugfix the new pull --clobber to not generate spurious conflicts. | 239 | |
| 1
by mbp at sourcefrog import from baz patch-364 | 240 | class EmptyTree(Tree): | 
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 241 | |
| 974.1.26
by aaron.bentley at utoronto merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472 | 242 | def __init__(self): | 
| 243 | self._inventory = Inventory() | |
| 1
by mbp at sourcefrog import from baz patch-364 | 244 | |
| 1773.2.1
by Robert Collins Teach all trees about unknowns, conflicts and get_parent_ids. | 245 | def get_parent_ids(self): | 
| 246 | """See Tree.get_parent_ids. | |
| 247 | ||
| 248 |         An EmptyTree always has NULL_REVISION as the only parent.
 | |
| 249 |         """
 | |
| 250 | return [] | |
| 251 | ||
| 1092.2.6
by Robert Collins symlink support updated to work | 252 | def get_symlink_target(self, file_id): | 
| 253 | return None | |
| 254 | ||
| 1
by mbp at sourcefrog import from baz patch-364 | 255 | def has_filename(self, filename): | 
| 256 | return False | |
| 257 | ||
| 1465
by Robert Collins Bugfix the new pull --clobber to not generate spurious conflicts. | 258 | def kind(self, file_id): | 
| 259 | assert self._inventory[file_id].kind == "root_directory" | |
| 260 | return "root_directory" | |
| 261 | ||
| 1551.6.36
by Aaron Bentley Revert --debris/--detritus changes | 262 | def list_files(self): | 
| 1732.1.14
by John Arbash Meinel Some speedups by not calling pathjoin() | 263 | return iter([]) | 
| 1
by mbp at sourcefrog import from baz patch-364 | 264 | |
| 974.1.12
by aaron.bentley at utoronto Switched from text-id to hashcache for merge optimization | 265 | def __contains__(self, file_id): | 
| 266 | return file_id in self._inventory | |
| 267 | ||
| 1732.1.19
by John Arbash Meinel If you have the path, use it rather than looking it up again | 268 | def get_file_sha1(self, file_id, path=None): | 
| 974.1.14
by aaron.bentley at utoronto Fixed bugs in merge optimization | 269 | assert self._inventory[file_id].kind == "root_directory" | 
| 270 | return None | |
| 271 | ||
| 272 | ||
| 1
by mbp at sourcefrog import from baz patch-364 | 273 | ######################################################################
 | 
| 274 | # diff
 | |
| 275 | ||
| 276 | # TODO: Merge these two functions into a single one that can operate
 | |
| 277 | # on either a whole tree or a set of files.
 | |
| 278 | ||
| 279 | # TODO: Return the diff in order by filename, not by category or in
 | |
| 280 | # random order.  Can probably be done by lock-stepping through the
 | |
| 281 | # filenames from both trees.
 | |
| 282 | ||
| 283 | ||
| 284 | def file_status(filename, old_tree, new_tree): | |
| 285 | """Return single-letter status, old and new names for a file. | |
| 286 | ||
| 287 |     The complexity here is in deciding how to represent renames;
 | |
| 288 |     many complex cases are possible.
 | |
| 289 |     """
 | |
| 290 | old_inv = old_tree.inventory | |
| 291 | new_inv = new_tree.inventory | |
| 292 | new_id = new_inv.path2id(filename) | |
| 293 | old_id = old_inv.path2id(filename) | |
| 294 | ||
| 295 | if not new_id and not old_id: | |
| 296 |         # easy: doesn't exist in either; not versioned at all
 | |
| 297 | if new_tree.is_ignored(filename): | |
| 298 | return 'I', None, None | |
| 299 | else: | |
| 300 | return '?', None, None | |
| 301 | elif new_id: | |
| 302 |         # There is now a file of this name, great.
 | |
| 303 |         pass
 | |
| 304 | else: | |
| 305 |         # There is no longer a file of this name, but we can describe
 | |
| 306 |         # what happened to the file that used to have
 | |
| 307 |         # this name.  There are two possibilities: either it was
 | |
| 308 |         # deleted entirely, or renamed.
 | |
| 309 | assert old_id | |
| 310 | if new_inv.has_id(old_id): | |
| 311 | return 'X', old_inv.id2path(old_id), new_inv.id2path(old_id) | |
| 312 | else: | |
| 313 | return 'D', old_inv.id2path(old_id), None | |
| 314 | ||
| 315 |     # if the file_id is new in this revision, it is added
 | |
| 316 | if new_id and not old_inv.has_id(new_id): | |
| 317 | return 'A' | |
| 318 | ||
| 319 |     # if there used to be a file of this name, but that ID has now
 | |
| 320 |     # disappeared, it is deleted
 | |
| 321 | if old_id and not new_inv.has_id(old_id): | |
| 322 | return 'D' | |
| 323 | ||
| 324 | return 'wtf?' | |
| 325 | ||
| 326 | ||
| 327 | ||
| 164
by mbp at sourcefrog new 'renames' command | 328 | def find_renames(old_inv, new_inv): | 
| 329 | for file_id in old_inv: | |
| 330 | if file_id not in new_inv: | |
| 331 |             continue
 | |
| 332 | old_name = old_inv.id2path(file_id) | |
| 333 | new_name = new_inv.id2path(file_id) | |
| 334 | if old_name != new_name: | |
| 335 | yield (old_name, new_name) | |
| 336 | ||
| 678
by Martin Pool - export to tarballs | 337 | |
| 338 |