bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 2255.7.83
by John Arbash Meinel Update some obvious copyright headers to include 2007. | 1 | # Copyright (C) 2005, 2006, 2007 Canonical Ltd
 | 
| 1773.4.1
by Martin Pool Add pyflakes makefile target; fix many warnings | 2 | #
 | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 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.
 | |
| 1887.1.1
by Adeodato Simó Do not separate paragraphs in the copyright statement with blank lines, | 7 | #
 | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 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.
 | |
| 1887.1.1
by Adeodato Simó Do not separate paragraphs in the copyright statement with blank lines, | 12 | #
 | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 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 | ||
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 17 | import cStringIO | 
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 18 | import re | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 19 | |
| 1911.2.6
by John Arbash Meinel Cache revision ids and file ids as part of xml processing. A custom xml parser could just call decode/encode directly. | 20 | from bzrlib import ( | 
| 21 | cache_utf8, | |
| 2100.3.1
by Aaron Bentley Start roundtripping tree-reference entries | 22 | errors, | 
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 23 | inventory, | 
| 2598.5.2
by Aaron Bentley Got all tests passing with Branch returning 'null:' for null revision | 24 | revision as _mod_revision, | 
| 1911.2.6
by John Arbash Meinel Cache revision ids and file ids as part of xml processing. A custom xml parser could just call decode/encode directly. | 25 |     )
 | 
| 1773.4.1
by Martin Pool Add pyflakes makefile target; fix many warnings | 26 | from bzrlib.xml_serializer import SubElement, Element, Serializer | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 27 | from bzrlib.inventory import ROOT_ID, Inventory, InventoryEntry | 
| 1773.4.1
by Martin Pool Add pyflakes makefile target; fix many warnings | 28 | from bzrlib.revision import Revision | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 29 | from bzrlib.errors import BzrError | 
| 30 | ||
| 31 | ||
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 32 | _utf8_re = None | 
| 2249.5.10
by John Arbash Meinel Make sure xml5 can handle unicode or utf8 strings | 33 | _unicode_re = None | 
| 34 | _xml_escape_map = { | |
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 35 | "&":'&', | 
| 36 | "'":"'", # FIXME: overkill | |
| 37 | "\"":""", | |
| 38 | "<":"<", | |
| 39 | ">":">", | |
| 40 |     }
 | |
| 41 | ||
| 42 | ||
| 43 | def _ensure_utf8_re(): | |
| 2249.5.10
by John Arbash Meinel Make sure xml5 can handle unicode or utf8 strings | 44 | """Make sure the _utf8_re and _unicode_re regexes have been compiled.""" | 
| 45 | global _utf8_re, _unicode_re | |
| 46 | if _utf8_re is None: | |
| 47 | _utf8_re = re.compile('[&<>\'\"]|[\x80-\xff]+') | |
| 48 | if _unicode_re is None: | |
| 49 | _unicode_re = re.compile(u'[&<>\'\"\u0080-\uffff]') | |
| 50 | ||
| 51 | ||
| 52 | def _unicode_escape_replace(match, _map=_xml_escape_map): | |
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 53 | """Replace a string of non-ascii, non XML safe characters with their escape | 
| 54 | ||
| 55 |     This will escape both Standard XML escapes, like <>"', etc.
 | |
| 56 |     As well as escaping non ascii characters, because ElementTree did.
 | |
| 57 |     This helps us remain compatible to older versions of bzr. We may change
 | |
| 58 |     our policy in the future, though.
 | |
| 59 |     """
 | |
| 1934.1.7
by John Arbash Meinel Comment why we do caching the way we do | 60 |     # jam 20060816 Benchmarks show that try/KeyError is faster if you
 | 
| 61 |     # expect the entity to rarely miss. There is about a 10% difference
 | |
| 62 |     # in overall time. But if you miss frequently, then if None is much
 | |
| 63 |     # faster. For our use case, we *rarely* have a revision id, file id
 | |
| 64 |     # or path name that is unicode. So use try/KeyError.
 | |
| 1934.1.12
by John Arbash Meinel Switch back to using Entity serializer, since performance is equivalent, yet still compatible | 65 | try: | 
| 66 | return _map[match.group()] | |
| 67 | except KeyError: | |
| 68 | return "&#%d;" % ord(match.group()) | |
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 69 | |
| 70 | ||
| 2249.5.10
by John Arbash Meinel Make sure xml5 can handle unicode or utf8 strings | 71 | def _utf8_escape_replace(match, _map=_xml_escape_map): | 
| 72 | """Escape utf8 characters into XML safe ones. | |
| 73 | ||
| 74 |     This uses 2 tricks. It is either escaping "standard" characters, like "&<>,
 | |
| 75 |     or it is handling characters with the high-bit set. For ascii characters,
 | |
| 76 |     we just lookup the replacement in the dictionary. For everything else, we
 | |
| 77 |     decode back into Unicode, and then use the XML escape code.
 | |
| 78 |     """
 | |
| 79 | try: | |
| 80 | return _map[match.group()] | |
| 81 | except KeyError: | |
| 82 | return ''.join('&#%d;' % ord(uni_chr) | |
| 83 | for uni_chr in match.group().decode('utf8')) | |
| 84 | ||
| 85 | ||
| 86 | _to_escaped_map = {} | |
| 87 | ||
| 88 | def _encode_and_escape(unicode_or_utf8_str, _map=_to_escaped_map): | |
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 89 | """Encode the string into utf8, and escape invalid XML characters""" | 
| 1934.1.7
by John Arbash Meinel Comment why we do caching the way we do | 90 |     # We frequently get entities we have not seen before, so it is better
 | 
| 91 |     # to check if None, rather than try/KeyError
 | |
| 2249.5.10
by John Arbash Meinel Make sure xml5 can handle unicode or utf8 strings | 92 | text = _map.get(unicode_or_utf8_str) | 
| 1934.1.5
by John Arbash Meinel Cache the entity escaping cuts us down to 450ms | 93 | if text is None: | 
| 2249.5.10
by John Arbash Meinel Make sure xml5 can handle unicode or utf8 strings | 94 | if unicode_or_utf8_str.__class__ == unicode: | 
| 95 |             # The alternative policy is to do a regular UTF8 encoding
 | |
| 96 |             # and then escape only XML meta characters.
 | |
| 97 |             # Performance is equivalent once you use cache_utf8. *However*
 | |
| 98 |             # this makes the serialized texts incompatible with old versions
 | |
| 99 |             # of bzr. So no net gain. (Perhaps the read code would handle utf8
 | |
| 100 |             # better than entity escapes, but cElementTree seems to do just fine
 | |
| 101 |             # either way)
 | |
| 102 | text = str(_unicode_re.sub(_unicode_escape_replace, | |
| 103 | unicode_or_utf8_str)) + '"' | |
| 104 | else: | |
| 105 |             # Plain strings are considered to already be in utf-8 so we do a
 | |
| 106 |             # slightly different method for escaping.
 | |
| 107 | text = _utf8_re.sub(_utf8_escape_replace, | |
| 108 | unicode_or_utf8_str) + '"' | |
| 109 | _map[unicode_or_utf8_str] = text | |
| 1934.1.5
by John Arbash Meinel Cache the entity escaping cuts us down to 450ms | 110 | return text | 
| 111 | ||
| 112 | ||
| 2249.5.4
by John Arbash Meinel When reading XML, always return utf-8 revision ids. | 113 | def _get_utf8_or_ascii(a_str, | 
| 114 | _encode_utf8=cache_utf8.encode, | |
| 115 | _get_cached_ascii=cache_utf8.get_cached_ascii): | |
| 116 | """Return a cached version of the string. | |
| 117 | ||
| 118 |     cElementTree will return a plain string if the XML is plain ascii. It only
 | |
| 119 |     returns Unicode when it needs to. We want to work in utf-8 strings. So if
 | |
| 120 |     cElementTree returns a plain string, we can just return the cached version.
 | |
| 121 |     If it is Unicode, then we need to encode it.
 | |
| 122 | ||
| 123 |     :param a_str: An 8-bit string or Unicode as returned by
 | |
| 124 |                   cElementTree.Element.get()
 | |
| 125 |     :return: A utf-8 encoded 8-bit string.
 | |
| 126 |     """
 | |
| 127 |     # This is fairly optimized because we know what cElementTree does, this is
 | |
| 128 |     # not meant as a generic function for all cases. Because it is possible for
 | |
| 129 |     # an 8-bit string to not be ascii or valid utf8.
 | |
| 130 | if a_str.__class__ == unicode: | |
| 131 | return _encode_utf8(a_str) | |
| 132 | else: | |
| 133 | return _get_cached_ascii(a_str) | |
| 134 | ||
| 135 | ||
| 1934.1.5
by John Arbash Meinel Cache the entity escaping cuts us down to 450ms | 136 | def _clear_cache(): | 
| 137 | """Clean out the unicode => escaped map""" | |
| 2249.5.10
by John Arbash Meinel Make sure xml5 can handle unicode or utf8 strings | 138 | _to_escaped_map.clear() | 
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 139 | |
| 140 | ||
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 141 | class Serializer_v5(Serializer): | 
| 142 | """Version 5 serializer | |
| 143 | ||
| 144 |     Packs objects into XML and vice versa.
 | |
| 145 |     """
 | |
| 146 | ||
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 147 | __slots__ = [] | 
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 148 | |
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 149 | root_id = ROOT_ID | 
| 1910.2.48
by Aaron Bentley Update from review comments | 150 | support_altered_by_hack = True | 
| 151 |     # This format supports the altered-by hack that reads file ids directly out
 | |
| 152 |     # of the versionedfile, without doing XML parsing.
 | |
| 153 | ||
| 2100.3.1
by Aaron Bentley Start roundtripping tree-reference entries | 154 | supported_kinds = set(['file', 'directory', 'symlink']) | 
| 2520.4.97
by Aaron Bentley Hack in support for inventory conversion | 155 | format_num = '5' | 
| 2100.3.1
by Aaron Bentley Start roundtripping tree-reference entries | 156 | |
| 2889.1.1
by Robert Collins * The class ``bzrlib.repofmt.knitrepo.KnitRepository3`` has been folded into | 157 | def _check_revisions(self, inv): | 
| 158 | """Extension point for subclasses to check during serialisation. | |
| 159 | ||
| 160 |         By default no checking is done.
 | |
| 161 | ||
| 162 |         :param inv: An inventory about to be serialised, to be checked.
 | |
| 163 |         :raises: AssertionError if an error has occured.
 | |
| 164 |         """
 | |
| 165 | ||
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 166 | def write_inventory_to_lines(self, inv): | 
| 167 | """Return a list of lines with the encoded inventory.""" | |
| 168 | return self.write_inventory(inv, None) | |
| 169 | ||
| 170 | def write_inventory_to_string(self, inv, working=False): | |
| 171 | """Just call write_inventory with a StringIO and return the value. | |
| 172 | ||
| 173 |         :param working: If True skip history data - text_sha1, text_size,
 | |
| 174 |             reference_revision, symlink_target.
 | |
| 175 |         """
 | |
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 176 | sio = cStringIO.StringIO() | 
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 177 | self.write_inventory(inv, sio, working) | 
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 178 | return sio.getvalue() | 
| 179 | ||
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 180 | def write_inventory(self, inv, f, working=False): | 
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 181 | """Write inventory to a file. | 
| 182 |         
 | |
| 183 |         :param inv: the inventory to write.
 | |
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 184 |         :param f: the file to write. (May be None if the lines are the desired
 | 
| 185 |             output).
 | |
| 186 |         :param working: If True skip history data - text_sha1, text_size,
 | |
| 187 |             reference_revision, symlink_target.
 | |
| 188 |         :return: The inventory as a list of lines.
 | |
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 189 |         """
 | 
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 190 | _ensure_utf8_re() | 
| 2889.1.1
by Robert Collins * The class ``bzrlib.repofmt.knitrepo.KnitRepository3`` has been folded into | 191 | self._check_revisions(inv) | 
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 192 | output = [] | 
| 1934.1.8
by John Arbash Meinel Passing around the append function rather than the list shaves off another 10%, down to 400ms | 193 | append = output.append | 
| 194 | self._append_inventory_root(append, inv) | |
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 195 | entries = inv.iter_entries() | 
| 1934.1.4
by John Arbash Meinel rewrite escaper to use xml numerical entities, rather than using encode('utf8') | 196 |         # Skip the root
 | 
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 197 | root_path, root_ie = entries.next() | 
| 198 | for path, ie in entries: | |
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 199 | if ie.parent_id != self.root_id: | 
| 200 | parent_str = ' parent_id="' | |
| 201 | parent_id = _encode_and_escape(ie.parent_id) | |
| 202 | else: | |
| 203 | parent_str = '' | |
| 204 | parent_id = '' | |
| 205 | if ie.kind == 'file': | |
| 206 | if ie.executable: | |
| 207 | executable = ' executable="yes"' | |
| 208 | else: | |
| 209 | executable = '' | |
| 210 | if not working: | |
| 211 | append('<file%s file_id="%s name="%s%s%s revision="%s ' | |
| 212 | 'text_sha1="%s" text_size="%d" />\n' % ( | |
| 213 | executable, _encode_and_escape(ie.file_id), | |
| 214 | _encode_and_escape(ie.name), parent_str, parent_id, | |
| 215 | _encode_and_escape(ie.revision), ie.text_sha1, | |
| 216 | ie.text_size)) | |
| 217 | else: | |
| 218 | append('<file%s file_id="%s name="%s%s%s />\n' % ( | |
| 219 | executable, _encode_and_escape(ie.file_id), | |
| 220 | _encode_and_escape(ie.name), parent_str, parent_id)) | |
| 221 | elif ie.kind == 'directory': | |
| 222 | if not working: | |
| 223 | append('<directory file_id="%s name="%s%s%s revision="%s ' | |
| 224 | '/>\n' % ( | |
| 225 | _encode_and_escape(ie.file_id), | |
| 226 | _encode_and_escape(ie.name), | |
| 227 | parent_str, parent_id, | |
| 228 | _encode_and_escape(ie.revision))) | |
| 229 | else: | |
| 230 | append('<directory file_id="%s name="%s%s%s />\n' % ( | |
| 231 | _encode_and_escape(ie.file_id), | |
| 232 | _encode_and_escape(ie.name), | |
| 233 | parent_str, parent_id)) | |
| 234 | elif ie.kind == 'symlink': | |
| 235 | if not working: | |
| 236 | append('<symlink file_id="%s name="%s%s%s revision="%s ' | |
| 237 | 'symlink_target="%s />\n' % ( | |
| 238 | _encode_and_escape(ie.file_id), | |
| 239 | _encode_and_escape(ie.name), | |
| 240 | parent_str, parent_id, | |
| 241 | _encode_and_escape(ie.revision), | |
| 242 | _encode_and_escape(ie.symlink_target))) | |
| 243 | else: | |
| 244 | append('<symlink file_id="%s name="%s%s%s />\n' % ( | |
| 245 | _encode_and_escape(ie.file_id), | |
| 246 | _encode_and_escape(ie.name), | |
| 247 | parent_str, parent_id)) | |
| 248 | elif ie.kind == 'tree-reference': | |
| 249 | if ie.kind not in self.supported_kinds: | |
| 250 | raise errors.UnsupportedInventoryKind(ie.kind) | |
| 251 | if not working: | |
| 252 | append('<tree-reference file_id="%s name="%s%s%s ' | |
| 253 | 'revision="%s reference_revision="%s />\n' % ( | |
| 254 | _encode_and_escape(ie.file_id), | |
| 255 | _encode_and_escape(ie.name), | |
| 256 | parent_str, parent_id, | |
| 257 | _encode_and_escape(ie.revision), | |
| 258 | _encode_and_escape(ie.reference_revision))) | |
| 259 | else: | |
| 260 | append('<tree-reference file_id="%s name="%s%s%s />\n' % ( | |
| 261 | _encode_and_escape(ie.file_id), | |
| 262 | _encode_and_escape(ie.name), | |
| 263 | parent_str, parent_id)) | |
| 264 | else: | |
| 265 | raise errors.UnsupportedInventoryKind(ie.kind) | |
| 1934.1.8
by John Arbash Meinel Passing around the append function rather than the list shaves off another 10%, down to 400ms | 266 | append('</inventory>\n') | 
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 267 | if f is not None: | 
| 268 | f.writelines(output) | |
| 1934.1.5
by John Arbash Meinel Cache the entity escaping cuts us down to 450ms | 269 |         # Just to keep the cache from growing without bounds
 | 
| 270 |         # but we may actually not want to do clear the cache
 | |
| 1934.1.6
by John Arbash Meinel With a full cache the time is down to 381 ms | 271 |         #_clear_cache()
 | 
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 272 | return output | 
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 273 | |
| 1934.1.8
by John Arbash Meinel Passing around the append function rather than the list shaves off another 10%, down to 400ms | 274 | def _append_inventory_root(self, append, inv): | 
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 275 | """Append the inventory root to output.""" | 
| 276 | if inv.root.file_id not in (None, ROOT_ID): | |
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 277 | fileid1 = ' file_id="' | 
| 278 | fileid2 = _encode_and_escape(inv.root.file_id) | |
| 279 | else: | |
| 280 | fileid1 = "" | |
| 281 | fileid2 = "" | |
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 282 | if inv.revision_id is not None: | 
| 2817.2.1
by Robert Collins * Inventory serialisation no longer double-sha's the content. | 283 | revid1 = ' revision_id="' | 
| 284 | revid2 = _encode_and_escape(inv.revision_id) | |
| 285 | else: | |
| 286 | revid1 = "" | |
| 287 | revid2 = "" | |
| 288 | append('<inventory%s%s format="5"%s%s>\n' % ( | |
| 289 | fileid1, fileid2, revid1, revid2)) | |
| 1934.1.3
by John Arbash Meinel [merge] robert's custom XML serializer, and cleanup for benchmarks and iter_entries() differences | 290 | |
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 291 | def _pack_revision(self, rev): | 
| 292 | """Revision object -> xml tree""" | |
| 2249.5.5
by John Arbash Meinel better comment for why we are decoding | 293 |         # For the XML format, we need to write them as Unicode rather than as
 | 
| 294 |         # utf-8 strings. So that cElementTree can handle properly escaping
 | |
| 295 |         # them.
 | |
| 2249.5.4
by John Arbash Meinel When reading XML, always return utf-8 revision ids. | 296 | decode_utf8 = cache_utf8.decode | 
| 2249.5.5
by John Arbash Meinel better comment for why we are decoding | 297 | revision_id = rev.revision_id | 
| 298 | if isinstance(revision_id, str): | |
| 299 | revision_id = decode_utf8(revision_id) | |
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 300 | root = Element('revision', | 
| 301 | committer = rev.committer, | |
| 2102.4.1
by John Arbash Meinel Switch to using millisecond resolution in Revision XML | 302 | timestamp = '%.3f' % rev.timestamp, | 
| 2249.5.5
by John Arbash Meinel better comment for why we are decoding | 303 | revision_id = revision_id, | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 304 | inventory_sha1 = rev.inventory_sha1, | 
| 1393.1.59
by Martin Pool - put 'format=5' on inventory and revision xml | 305 | format='5', | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 306 |                        )
 | 
| 1913.1.1
by John Arbash Meinel Fix bug #55783 | 307 | if rev.timezone is not None: | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 308 | root.set('timezone', str(rev.timezone)) | 
| 309 | root.text = '\n' | |
| 310 | msg = SubElement(root, 'message') | |
| 311 | msg.text = rev.message | |
| 312 | msg.tail = '\n' | |
| 1313
by Martin Pool - rename to Revision.parent_ids to avoid confusion with old usage | 313 | if rev.parent_ids: | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 314 | pelts = SubElement(root, 'parents') | 
| 315 | pelts.tail = pelts.text = '\n' | |
| 1313
by Martin Pool - rename to Revision.parent_ids to avoid confusion with old usage | 316 | for parent_id in rev.parent_ids: | 
| 1311
by Martin Pool - remove RevisionReference; just hold parent ids directly | 317 | assert isinstance(parent_id, basestring) | 
| 2598.5.2
by Aaron Bentley Got all tests passing with Branch returning 'null:' for null revision | 318 | _mod_revision.check_not_reserved_id(parent_id) | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 319 | p = SubElement(pelts, 'revision_ref') | 
| 320 | p.tail = '\n' | |
| 2249.5.5
by John Arbash Meinel better comment for why we are decoding | 321 | if isinstance(parent_id, str): | 
| 322 | parent_id = decode_utf8(parent_id) | |
| 323 | p.set('revision_id', parent_id) | |
| 1185.16.36
by Martin Pool - store revision properties in revision xml | 324 | if rev.properties: | 
| 325 | self._pack_revision_properties(rev, root) | |
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 326 | return root | 
| 1185.16.36
by Martin Pool - store revision properties in revision xml | 327 | |
| 328 | def _pack_revision_properties(self, rev, under_element): | |
| 329 | top_elt = SubElement(under_element, 'properties') | |
| 330 | for prop_name, prop_value in sorted(rev.properties.items()): | |
| 331 | assert isinstance(prop_name, basestring) | |
| 332 | assert isinstance(prop_value, basestring) | |
| 333 | prop_elt = SubElement(top_elt, 'property') | |
| 334 | prop_elt.set('name', prop_name) | |
| 335 | prop_elt.text = prop_value | |
| 336 | prop_elt.tail = '\n' | |
| 337 | top_elt.tail = '\n' | |
| 338 | ||
| 2889.1.1
by Robert Collins * The class ``bzrlib.repofmt.knitrepo.KnitRepository3`` has been folded into | 339 | def _unpack_inventory(self, elt, revision_id): | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 340 | """Construct from XML Element | 
| 341 |         """
 | |
| 342 | assert elt.tag == 'inventory' | |
| 343 | root_id = elt.get('file_id') or ROOT_ID | |
| 2294.1.10
by John Arbash Meinel Switch all apis over to utf8 file ids. All tests pass | 344 | root_id = _get_utf8_or_ascii(root_id) | 
| 345 | ||
| 1393.1.59
by Martin Pool - put 'format=5' on inventory and revision xml | 346 | format = elt.get('format') | 
| 347 | if format is not None: | |
| 348 | if format != '5': | |
| 349 | raise BzrError("invalid format version %r on inventory" | |
| 350 | % format) | |
| 2917.2.1
by John Arbash Meinel Fix bug #152360. The xml5 serializer should be using | 351 | data_revision_id = elt.get('revision_id') | 
| 352 | if data_revision_id is not None: | |
| 353 | revision_id = cache_utf8.encode(data_revision_id) | |
| 1638.1.2
by Robert Collins Change the basis-inventory file to not have the revision-id in the file name. | 354 | inv = Inventory(root_id, revision_id=revision_id) | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 355 | for e in elt: | 
| 356 | ie = self._unpack_entry(e) | |
| 2294.1.9
by John Arbash Meinel Minor performance improvement, use None as signal rather than ROOT_ID | 357 | if ie.parent_id is None: | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 358 | ie.parent_id = root_id | 
| 359 | inv.add(ie) | |
| 2889.1.1
by Robert Collins * The class ``bzrlib.repofmt.knitrepo.KnitRepository3`` has been folded into | 360 | if revision_id is not None: | 
| 361 | inv.root.revision = revision_id | |
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 362 | return inv | 
| 363 | ||
| 2294.1.9
by John Arbash Meinel Minor performance improvement, use None as signal rather than ROOT_ID | 364 | def _unpack_entry(self, elt): | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 365 | kind = elt.tag | 
| 1399.1.6
by Robert Collins move exporting functionality into inventory.py - uncovers bug in symlink support | 366 | if not InventoryEntry.versionable_kind(kind): | 
| 1092.2.20
by Robert Collins symlink and weaves, whaddya know | 367 | raise AssertionError('unsupported entry kind %s' % kind) | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 368 | |
| 2249.5.4
by John Arbash Meinel When reading XML, always return utf-8 revision ids. | 369 | get_cached = _get_utf8_or_ascii | 
| 1911.2.6
by John Arbash Meinel Cache revision ids and file ids as part of xml processing. A custom xml parser could just call decode/encode directly. | 370 | |
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 371 | parent_id = elt.get('parent_id') | 
| 2294.1.10
by John Arbash Meinel Switch all apis over to utf8 file ids. All tests pass | 372 | if parent_id is not None: | 
| 373 | parent_id = get_cached(parent_id) | |
| 374 | file_id = get_cached(elt.get('file_id')) | |
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 375 | |
| 1399.1.8
by Robert Collins factor out inventory directory logic into 'InventoryDirectory' class | 376 | if kind == 'directory': | 
| 1911.2.6
by John Arbash Meinel Cache revision ids and file ids as part of xml processing. A custom xml parser could just call decode/encode directly. | 377 | ie = inventory.InventoryDirectory(file_id, | 
| 1399.1.8
by Robert Collins factor out inventory directory logic into 'InventoryDirectory' class | 378 | elt.get('name'), | 
| 379 | parent_id) | |
| 1399.1.9
by Robert Collins factor out file related logic from InventoryEntry to InventoryFile | 380 | elif kind == 'file': | 
| 1911.2.6
by John Arbash Meinel Cache revision ids and file ids as part of xml processing. A custom xml parser could just call decode/encode directly. | 381 | ie = inventory.InventoryFile(file_id, | 
| 1399.1.9
by Robert Collins factor out file related logic from InventoryEntry to InventoryFile | 382 | elt.get('name'), | 
| 383 | parent_id) | |
| 384 | ie.text_sha1 = elt.get('text_sha1') | |
| 385 | if elt.get('executable') == 'yes': | |
| 386 | ie.executable = True | |
| 387 | v = elt.get('text_size') | |
| 388 | ie.text_size = v and int(v) | |
| 1399.1.10
by Robert Collins remove kind from the InventoryEntry constructor - only child classes should be created now | 389 | elif kind == 'symlink': | 
| 1911.2.6
by John Arbash Meinel Cache revision ids and file ids as part of xml processing. A custom xml parser could just call decode/encode directly. | 390 | ie = inventory.InventoryLink(file_id, | 
| 1399.1.10
by Robert Collins remove kind from the InventoryEntry constructor - only child classes should be created now | 391 | elt.get('name'), | 
| 392 | parent_id) | |
| 393 | ie.symlink_target = elt.get('symlink_target') | |
| 1399.1.8
by Robert Collins factor out inventory directory logic into 'InventoryDirectory' class | 394 | else: | 
| 2100.3.1
by Aaron Bentley Start roundtripping tree-reference entries | 395 | raise errors.UnsupportedInventoryKind(kind) | 
| 1911.2.6
by John Arbash Meinel Cache revision ids and file ids as part of xml processing. A custom xml parser could just call decode/encode directly. | 396 | revision = elt.get('revision') | 
| 397 | if revision is not None: | |
| 398 | revision = get_cached(revision) | |
| 399 | ie.revision = revision | |
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 400 | |
| 401 | return ie | |
| 402 | ||
| 403 | def _unpack_revision(self, elt): | |
| 404 | """XML Element -> Revision object""" | |
| 405 | assert elt.tag == 'revision' | |
| 1393.1.59
by Martin Pool - put 'format=5' on inventory and revision xml | 406 | format = elt.get('format') | 
| 407 | if format is not None: | |
| 408 | if format != '5': | |
| 409 | raise BzrError("invalid format version %r on inventory" | |
| 410 | % format) | |
| 2249.5.4
by John Arbash Meinel When reading XML, always return utf-8 revision ids. | 411 | get_cached = _get_utf8_or_ascii | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 412 | rev = Revision(committer = elt.get('committer'), | 
| 413 | timestamp = float(elt.get('timestamp')), | |
| 1911.2.6
by John Arbash Meinel Cache revision ids and file ids as part of xml processing. A custom xml parser could just call decode/encode directly. | 414 | revision_id = get_cached(elt.get('revision_id')), | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 415 | inventory_sha1 = elt.get('inventory_sha1') | 
| 416 |                        )
 | |
| 417 | parents = elt.find('parents') or [] | |
| 418 | for p in parents: | |
| 419 | assert p.tag == 'revision_ref', \ | |
| 420 | "bad parent node tag %r" % p.tag | |
| 1911.2.6
by John Arbash Meinel Cache revision ids and file ids as part of xml processing. A custom xml parser could just call decode/encode directly. | 421 | rev.parent_ids.append(get_cached(p.get('revision_id'))) | 
| 1185.16.37
by Martin Pool - properties are retrieved when revisions are loaded | 422 | self._unpack_revision_properties(elt, rev) | 
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 423 | v = elt.get('timezone') | 
| 1913.1.1
by John Arbash Meinel Fix bug #55783 | 424 | if v is None: | 
| 425 | rev.timezone = 0 | |
| 426 | else: | |
| 427 | rev.timezone = int(v) | |
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 428 | rev.message = elt.findtext('message') # text of <message> | 
| 429 | return rev | |
| 430 | ||
| 1185.16.37
by Martin Pool - properties are retrieved when revisions are loaded | 431 | def _unpack_revision_properties(self, elt, rev): | 
| 432 | """Unpack properties onto a revision.""" | |
| 433 | props_elt = elt.find('properties') | |
| 434 | assert len(rev.properties) == 0 | |
| 435 | if not props_elt: | |
| 436 |             return
 | |
| 437 | for prop_elt in props_elt: | |
| 438 | assert prop_elt.tag == 'property', \ | |
| 1773.4.1
by Martin Pool Add pyflakes makefile target; fix many warnings | 439 | "bad tag under properties list: %r" % prop_elt.tag | 
| 1185.16.37
by Martin Pool - properties are retrieved when revisions are loaded | 440 | name = prop_elt.get('name') | 
| 441 | value = prop_elt.text | |
| 1886.1.1
by John Arbash Meinel Fix bug #47782, | 442 |             # If a property had an empty value ('') cElementTree reads
 | 
| 443 |             # that back as None, convert it back to '', so that all
 | |
| 444 |             # properties have string values
 | |
| 445 | if value is None: | |
| 446 | value = '' | |
| 1185.16.37
by Martin Pool - properties are retrieved when revisions are loaded | 447 | assert name not in rev.properties, \ | 
| 1773.4.1
by Martin Pool Add pyflakes makefile target; fix many warnings | 448 | "repeated property %r" % name | 
| 1185.16.37
by Martin Pool - properties are retrieved when revisions are loaded | 449 | rev.properties[name] = value | 
| 450 | ||
| 451 | ||
| 1189
by Martin Pool - BROKEN: partial support for commit into weave | 452 | serializer_v5 = Serializer_v5() |