| Server IP : 74.208.236.52 / Your IP : 216.73.216.70 Web Server : Apache System : Linux infong527 4.4.400-icpu-115 #2 SMP Mon Jul 6 08:15:05 UTC 2026 x86_64 User : u44043973 ( 5404757) PHP Version : 8.4.24 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /lib/python3/dist-packages/breezy/bzr/ |
Upload File : |
# Copyright (C) 2005-2012 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
"""Debug commands for the bzr formats."""
from io import BytesIO
from .. import errors, osutils, transport
from ..commands import Command, display_command
from ..option import Option
from ..workingtree import WorkingTree
from . import btree_index
def as_tuples(obj):
"""Ensure that the object and any referenced objects are plain tuples.
:param obj: a list, tuple or StaticTuple
:return: a plain tuple instance, with all children also being tuples.
"""
result = []
for item in obj:
if isinstance(item, (tuple, list)):
item = as_tuples(item)
result.append(item)
return tuple(result)
class cmd_dump_btree(Command):
__doc__ = """Dump the contents of a btree index file to stdout.
PATH is a btree index file, it can be any URL. This includes things like
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
By default, the tuples stored in the index file will be displayed. With
--raw, we will uncompress the pages, but otherwise display the raw bytes
stored in the index.
"""
# TODO: Do we want to dump the internal nodes as well?
# TODO: It would be nice to be able to dump the un-parsed information,
# rather than only going through iter_all_entries. However, this is
# good enough for a start
hidden = True
encoding_type = "exact"
takes_args = ["path"]
takes_options = [
Option(
"raw",
help="Write the uncompressed bytes out, rather than the parsed tuples.",
),
]
def run(self, path, raw=False):
dirname, basename = osutils.split(path)
t = transport.get_transport(dirname)
if raw:
self._dump_raw_bytes(t, basename)
else:
self._dump_entries(t, basename)
def _get_index_and_bytes(self, trans, basename):
"""Create a BTreeGraphIndex and raw bytes."""
bt = btree_index.BTreeGraphIndex(trans, basename, None)
bytes = trans.get_bytes(basename)
bt._file = BytesIO(bytes)
bt._size = len(bytes)
return bt, bytes
def _dump_raw_bytes(self, trans, basename):
import zlib
# We need to parse at least the root node.
# This is because the first page of every row starts with an
# uncompressed header.
bt, bytes = self._get_index_and_bytes(trans, basename)
for page_idx, page_start in enumerate(
range(0, len(bytes), btree_index._PAGE_SIZE)
):
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
page_bytes = bytes[page_start:page_end]
if page_idx == 0:
self.outf.write("Root node:\n")
header_end, data = bt._parse_header_from_bytes(page_bytes)
self.outf.write(page_bytes[:header_end])
page_bytes = data
self.outf.write(f"\nPage {page_idx}\n")
if len(page_bytes) == 0:
self.outf.write("(empty)\n")
else:
decomp_bytes = zlib.decompress(page_bytes)
self.outf.write(decomp_bytes)
self.outf.write("\n")
def _dump_entries(self, trans, basename):
try:
st = trans.stat(basename)
except errors.TransportNotPossible:
# We can't stat, so we'll fake it because we have to do the 'get()'
# anyway.
bt, _ = self._get_index_and_bytes(trans, basename)
else:
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
for node in bt.iter_all_entries():
# Node is made up of:
# (index, key, value, [references])
try:
refs = node[3]
except IndexError:
refs_as_tuples = None
else:
refs_as_tuples = as_tuples(refs)
if refs_as_tuples is not None:
refs_as_tuples = tuple(
tuple(tuple(r.decode("utf-8") for r in t1) for t1 in t2)
for t2 in refs_as_tuples
)
as_tuple = (
tuple([r.decode("utf-8") for r in node[1]]),
node[2].decode("utf-8"),
refs_as_tuples,
)
self.outf.write("{}\n".format(as_tuple))
class cmd_file_id(Command):
__doc__ = """Print file_id of a particular file or directory.
The file_id is assigned when the file is first added and remains the
same through all revisions where the file exists, even when it is
moved or renamed.
"""
hidden = True
_see_also = ["inventory", "ls"]
takes_args = ["filename"]
@display_command
def run(self, filename):
tree, relpath = WorkingTree.open_containing(filename)
file_id = tree.path2id(relpath)
if file_id is None:
raise errors.NotVersionedError(filename)
else:
self.outf.write(file_id.decode("utf-8") + "\n")
class cmd_file_path(Command):
__doc__ = """Print path of file_ids to a file or directory.
This prints one line for each directory down to the target,
starting at the branch root.
"""
hidden = True
takes_args = ["filename"]
@display_command
def run(self, filename):
tree, relpath = WorkingTree.open_containing(filename)
fid = tree.path2id(relpath)
if fid is None:
raise errors.NotVersionedError(filename)
segments = osutils.splitpath(relpath)
for pos in range(1, len(segments) + 1):
path = osutils.joinpath(segments[:pos])
self.outf.write("{}\n".format(tree.path2id(path)))