Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions breezy/git/fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,11 +712,12 @@ def __init__(self, actual):
self.wants = []
self.remote_refs = {}

def __call__(self, refs):
def __call__(self, refs, depth=None):
"""Record refs and determine wants.

Args:
refs: Dictionary of remote references.
depth: Optional depth for shallow clones.

Returns:
List of wanted refs.
Expand All @@ -727,5 +728,5 @@ def __call__(self, refs):
if not isinstance(refs, dict):
raise TypeError(refs)
self.remote_refs = refs
self.wants = self.actual(refs)
self.wants = self.actual(refs, depth)
return self.wants
15 changes: 9 additions & 6 deletions breezy/git/interrepo.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ def get_determine_wants_heads(self, wants, include_tags=False, tag_selector=None
"""
wants = set(wants)

def determine_wants(refs):
def determine_wants(refs, depth=None):
unpeel_lookup = {}
for k, v in refs.items():
if k.endswith(PEELED_TAG_SUFFIX):
Expand All @@ -507,11 +507,12 @@ def determine_wants(refs):

return determine_wants

def determine_wants_all(self, refs):
def determine_wants_all(self, refs, depth=None):
"""Determine all objects to fetch from refs.

Args:
refs: Dictionary of ref names to object IDs.
depth: Optional depth for shallow clones.

Returns:
List of object IDs to fetch.
Expand Down Expand Up @@ -582,11 +583,12 @@ def _target_has_shas(self, shas):
revids[revid] = sha
return {revids[r] for r in self.target.has_revisions(revids)}

def determine_wants_all(self, refs):
def determine_wants_all(self, refs, depth=None):
"""Determine all objects to fetch from refs.

Args:
refs: Dictionary of ref names to object IDs.
depth: Optional depth for shallow clones.

Returns:
List of object IDs to fetch.
Expand Down Expand Up @@ -818,7 +820,7 @@ def fetch_refs(
old_refs = self._get_target_either_refs()
ref_changes = {}

def determine_wants(heads):
def determine_wants(heads, depth=None):
old_refs = {k: (v, None) for (k, v) in heads.items()}
new_refs = update_refs(old_refs)
ret = []
Expand Down Expand Up @@ -946,7 +948,7 @@ def get_determine_wants_branches(self, branches, include_tags=False):
Function that determines what objects to fetch.
"""

def determine_wants(refs):
def determine_wants(refs, depth=None):
ret = []
for name, value in refs.items():
if value == ZERO_SHA:
Expand All @@ -961,11 +963,12 @@ def determine_wants(refs):

return determine_wants

def determine_wants_all(self, refs):
def determine_wants_all(self, refs, depth=None):
"""Determine all objects to fetch from refs.

Args:
refs: Dictionary of ref names to object IDs.
depth: Optional depth for shallow clones.

Returns:
List of object IDs to fetch.
Expand Down
15 changes: 9 additions & 6 deletions breezy/git/object_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
from collections.abc import Iterable, Iterator

from dulwich.object_store import BaseObjectStore
from dulwich.objects import ZERO_SHA, Blob, Commit, ObjectID, ShaFile, Tree, sha_to_hex
from dulwich.pack import Pack, PackData, pack_objects_to_data
from dulwich.objects import ZERO_SHA, Blob, Commit, ObjectID, Tree, sha_to_hex
from dulwich.pack import Pack, PackData, UnpackedObject, pack_objects_to_data

from .. import errors, lru_cache, osutils, trace, ui
from ..bzr.testament import StrictTestament3
Expand Down Expand Up @@ -602,11 +602,10 @@ def _update_sha_map_revision(self, revid):
def iter_unpacked_subset(
self,
shas,
*,
include_comp=False,
allow_missing: bool = False,
convert_ofs_delta: bool = True,
) -> Iterator[ShaFile]:
) -> Iterator[UnpackedObject]:
"""Iterate over unpacked objects (not supported in this implementation).

Args:
Expand Down Expand Up @@ -981,7 +980,7 @@ def find_missing_objects(
progress=None,
get_tagged=None,
get_parents=lambda x: [],
) -> Iterator[tuple[ObjectID, bytes | None]]:
) -> Iterator[tuple[ObjectID, tuple[int, bytes | None] | None]]:
"""Iterate over the contents of a pack file.

:param haves: List of SHA1s of objects that should not be sent
Expand Down Expand Up @@ -1035,7 +1034,11 @@ def find_missing_objects(
rev, tree, lossy=(not self.mapping.roundtripping)
):
if obj.id not in seen:
yield (obj.id, path.encode("utf-8") if path else None)
pack_hint = (
obj.type_num,
path.encode("utf-8") if path else None,
)
yield (obj.id, pack_hint)
seen.add(obj.id)

def add_thin_pack(self):
Expand Down
26 changes: 24 additions & 2 deletions breezy/git/tests/test_workingtree.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@
from ..tree import tree_delta_from_git_changes


def _normalize_tree_change(change):
"""Normalize a tree change to tuple format for comparison.

Handles both old format (tuples) and new format (TreeEntry objects).
"""
change_type, old, new = change

# Handle both old format (None, None, None) and new format None
if old is None:
oldpath, oldmode, oldsha = None, None, None
else:
(oldpath, oldmode, oldsha) = old
if new is None:
newpath, newmode, newsha = None, None, None
else:
(newpath, newmode, newsha) = new

return (change_type, (oldpath, oldmode, oldsha), (newpath, newmode, newsha))


def changes_between_git_tree_and_working_copy(
source_store,
from_tree_sha,
Expand All @@ -47,15 +67,17 @@ def changes_between_git_tree_and_working_copy(
"""Determine the changes between a git tree and a working tree with index."""
to_tree_sha, extras = target.git_snapshot(want_unversioned=want_unversioned)
store = OverlayObjectStore([source_store, target.store])
return tree_changes(
changes = tree_changes(
store,
from_tree_sha,
to_tree_sha,
include_trees=include_trees,
rename_detector=rename_detector,
want_unchanged=want_unchanged,
change_type_same=True,
), extras
)
# Normalize changes to tuple format for test compatibility
return (_normalize_tree_change(c) for c in changes), extras


class GitWorkingTreeTests(TestCaseWithTransport):
Expand Down
37 changes: 30 additions & 7 deletions breezy/git/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -1287,8 +1287,15 @@ def tree_delta_from_git_changes(
ret = delta.TreeDelta()
added = []
for change_type, old, new in changes:
(oldpath, oldmode, oldsha) = old
(newpath, newmode, newsha) = new
# Handle both old format (None, None, None) and new format None
if old is None:
oldpath, oldmode, oldsha = None, None, None
else:
(oldpath, oldmode, oldsha) = old
if new is None:
newpath, newmode, newsha = None, None, None
else:
(newpath, newmode, newsha) = new
if newpath == b"" and not include_root:
continue
copied = change_type == "copy"
Expand Down Expand Up @@ -1456,8 +1463,15 @@ def changes_from_git_changes(
for change_type, old, new in changes:
if change_type == "unchanged" and not include_unchanged:
continue
(oldpath, oldmode, oldsha) = old
(newpath, newmode, newsha) = new
# Handle both old format (None, None, None) and new format None
if old is None:
oldpath, oldmode, oldsha = None, None, None
else:
(oldpath, oldmode, oldsha) = old
if new is None:
newpath, newmode, newsha = None, None, None
else:
(newpath, newmode, newsha) = new
oldpath_decoded = decode_git_path(oldpath) if oldpath is not None else None
newpath_decoded = decode_git_path(newpath) if newpath is not None else None
if not (
Expand Down Expand Up @@ -1795,11 +1809,20 @@ def find_source_paths(self, paths, recurse="none"):
ret = {}
changes = self._iter_git_changes(specific_files=paths, include_trees=False)[0]
for _change_type, old, new in changes:
if new[0] is None:
# Handle both old format (None, None, None) and new format None
if old is None:
oldpath, _oldmode, _oldsha = None, None, None
else:
(oldpath, _oldmode, _oldsha) = old
if new is None:
newpath_bytes, _newmode, _newsha = None, None, None
else:
(newpath_bytes, _newmode, _newsha) = new
if newpath_bytes is None:
continue
newpath = decode_git_path(new[0])
newpath = decode_git_path(newpath_bytes)
if newpath in paths:
ret[newpath] = decode_git_path(old[0]) if old[0] else None
ret[newpath] = decode_git_path(oldpath) if oldpath else None
for path in paths:
if path not in ret:
if self.target.has_filename(path):
Expand Down
2 changes: 1 addition & 1 deletion crates/bazaar-py/src/dirstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ impl SHA1Provider {
&mut self,
py: Python<'a>,
path: &Bound<PyAny>,
) -> PyResult<(PyObject, Bound<'a, PyBytes>)> {
) -> PyResult<(Py<PyAny>, Bound<'a, PyBytes>)> {
let path = extract_path(path)?;
let (md, sha1) = self.provider.stat_and_sha1(&path)?;
let pmd = StatResult { metadata: md };
Expand Down
6 changes: 3 additions & 3 deletions crates/bazaar-py/src/groupcompress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl GroupCompressBlock {
fn extract<'a>(
&mut self,
py: Python<'a>,
_key: PyObject,
_key: Py<PyAny>,
offset: usize,
length: usize,
) -> PyResult<Vec<Bound<'a, PyBytes>>> {
Expand Down Expand Up @@ -229,7 +229,7 @@ impl GroupCompressBlock {
}

#[pyo3(signature = (include_text = None))]
fn _dump(&mut self, py: Python, include_text: Option<bool>) -> PyResult<PyObject> {
fn _dump(&mut self, py: Python, include_text: Option<bool>) -> PyResult<Py<PyAny>> {
let ret = self
.0
.dump(include_text)
Expand Down Expand Up @@ -293,7 +293,7 @@ impl TraditionalGroupCompressor {
#[new]
#[allow(unused_variables)]
#[pyo3(signature = (settings = None))]
fn new(settings: Option<PyObject>) -> Self {
fn new(settings: Option<Py<PyAny>>) -> Self {
Self(Some(
bazaar::groupcompress::compressor::TraditionalGroupCompressor::new(),
))
Expand Down
12 changes: 6 additions & 6 deletions crates/bazaar-py/src/hashcache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct HashCache {
}

pub struct PyContentFilter {
content_filter: PyObject,
content_filter: Py<PyAny>,
}

#[pyclass]
Expand Down Expand Up @@ -47,7 +47,7 @@ impl PyContentFilter {
input: Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send + Sync>,
worker: &str,
) -> Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send + Sync> {
Python::with_gil(|py| {
Python::attach(|py| {
let worker = self.content_filter.getattr(py, worker);
let py_input = PyChunkIterator { input };
let py_output = worker.unwrap().call1(py, (py_input,));
Expand All @@ -56,7 +56,7 @@ impl PyContentFilter {
}
let py_output = py_output.unwrap();
let next = move || {
Python::with_gil(|py| {
Python::attach(|py| {
let item = py_output.call_method0(py, "__next__");
match item {
Err(e) => Some(Err(map_py_err_to_io_err(e))),
Expand Down Expand Up @@ -92,10 +92,10 @@ impl ContentFilter for PyContentFilter {
}

fn content_filter_to_fn(
content_filter_provider: PyObject,
content_filter_provider: Py<PyAny>,
) -> Box<dyn Fn(&Path, u64) -> Box<dyn ContentFilter> + Send + Sync> {
Box::new(move |path, ctime| {
Python::with_gil(|py| {
Python::attach(|py| {
Box::new(PyContentFilter {
content_filter: content_filter_provider.call1(py, (path, ctime)).unwrap(),
})
Expand Down Expand Up @@ -128,7 +128,7 @@ impl HashCache {
root: &str,
cache_file_name: &str,
mode: Option<u32>,
content_filter_provider: Option<PyObject>,
content_filter_provider: Option<Py<PyAny>>,
) -> Self {
Self {
hashcache: Box::new(bazaar::hashcache::HashCache::new(
Expand Down
Loading
Loading