Merge lp:~jelmer/brz/git-subsume into lp:brz

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: 7923
Merged at revision: 7922
Proposed branch: lp:~jelmer/brz/git-subsume
Merge into: lp:brz
Diff against target: 173 lines (+76/-7)
7 files modified
breezy/bzr/bzrdir.py (+1/-1)
breezy/bzr/groupcompress.py (+0/-1)
breezy/bzr/tests/per_bzrdir/test_bzrdir.py (+4/-4)
breezy/bzr/workingtree.py (+1/-1)
breezy/git/dir.py (+27/-0)
breezy/git/tests/test_workingtree.py (+17/-0)
breezy/git/workingtree.py (+26/-0)
To merge this branch: bzr merge lp:~jelmer/brz/git-subsume
Reviewer Review Type Date Requested Status
Jelmer Vernooij Approve
Review via email: mp+456451@code.launchpad.net

Commit message

Implement subsume for git

Description of the change

Implement subsume for git

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :
Download full text (11.3 KiB)

The attempt to merge lp:~jelmer/brz/git-subsume into lp:brz failed. Command exited with 2.
Below is the output from the failed tests.

Collecting setuptools-gettext
  Downloading setuptools_gettext-0.1.7-py3-none-any.whl.metadata (1.5 kB)
Requirement already satisfied: setuptools>=46.1 in ./lib/python3.11/site-packages (from setuptools-gettext) (68.1.2)
Downloading setuptools_gettext-0.1.7-py3-none-any.whl (5.5 kB)
Installing collected packages: setuptools-gettext
Successfully installed setuptools-gettext-0.1.7
Obtaining file:///tmp/tarmac/branch.6dyqo38_
  Installing build dependencies: started
  Installing build dependencies: finished with status 'done'
  Checking if build backend supports build_editable: started
  Checking if build backend supports build_editable: finished with status 'done'
  Getting requirements to build editable: started
  Getting requirements to build editable: finished with status 'done'
  Installing backend dependencies: started
  Installing backend dependencies: finished with status 'done'
  Preparing editable metadata (pyproject.toml): started
  Preparing editable metadata (pyproject.toml): finished with status 'done'
Requirement already satisfied: configobj in /usr/lib/python3/dist-packages (5.0.8)
Requirement already satisfied: fastbencode in /usr/lib/python3/dist-packages (0.2)
Requirement already satisfied: patiencediff in /usr/lib/python3/dist-packages (0.2.13)
Requirement already satisfied: merge3 in /usr/lib/python3/dist-packages (0.0.8)
Requirement already satisfied: dulwich>=0.21.6 in /usr/lib/python3/dist-packages (0.21.6)
Requirement already satisfied: urllib3>=1.24.1 in /usr/lib/python3/dist-packages (1.26.18)
Requirement already satisfied: pyyaml in /usr/lib/python3/dist-packages (6.0.1)
Collecting testtools>=0.9.5
  Downloading testtools-2.7.1-py3-none-any.whl.metadata (5.3 kB)
Collecting testscenarios
  Downloading testscenarios-0.5.0-py2.py3-none-any.whl (21 kB)
Collecting python-subunit
  Downloading python_subunit-1.4.4-py3-none-any.whl.metadata (22 kB)
Collecting cython>=0.29
  Using cached Cython-3.0.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.2 kB)
Requirement already satisfied: ruff in /usr/local/lib/python3.11/dist-packages (0.1.6)
Collecting docutils
  Downloading docutils-0.20.1-py3-none-any.whl.metadata (2.8 kB)
Requirement already satisfied: setuptools in ./lib/python3.11/site-packages (68.1.2)
Collecting sphinx
  Downloading sphinx-7.2.6-py3-none-any.whl.metadata (5.9 kB)
Collecting sphinx-epytext
  Downloading sphinx-epytext-0.0.4.tar.gz (3.6 kB)
  Preparing metadata (setup.py): started
  Preparing metadata (setup.py): finished with status 'done'
Collecting fastimport
  Downloading fastimport-0.9.14.tar.gz (41 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 41.8/41.8 kB 1.7 MB/s eta 0:00:00
  Preparing metadata (setup.py): started
  Preparing metadata (setup.py): finished with status 'done'
Requirement already satisfied: launchpadlib>=1.6.3 in /usr/lib/python3/dist-packages (1.11.0)
Requirement already satisfied: paramiko>=1.6.2 in /usr/local/lib/python3.11/dist-packages (3.3.1)
Requirement already satisfied: gpg in /usr/lib/python3/dist-packages (1.18.0)
...

lp:~jelmer/brz/git-subsume updated
7923. By Jelmer Vernooij

Fix ruff

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/bzr/bzrdir.py'
2--- breezy/bzr/bzrdir.py 2023-11-16 15:15:57 +0000
3+++ breezy/bzr/bzrdir.py 2023-11-28 16:07:00 +0000
4@@ -559,7 +559,7 @@
5 self.root_transport.copy_tree(".bzr", backup_dir)
6 return (old_path, new_path)
7
8- def retire_bzrdir(self, limit=10000):
9+ def retire_controldir(self, limit=10000):
10 """Permanently disable the bzrdir.
11
12 This is done by renaming it to give the user some ability to recover
13
14=== modified file 'breezy/bzr/groupcompress.py'
15--- breezy/bzr/groupcompress.py 2023-11-17 15:05:58 +0000
16+++ breezy/bzr/groupcompress.py 2023-11-28 16:07:00 +0000
17@@ -850,7 +850,6 @@
18 """
19
20 chunks: list[bytes]
21-
22 def __init__(self, settings=None):
23 """Create a GroupCompressor."""
24 self._last = None
25
26=== modified file 'breezy/bzr/tests/per_bzrdir/test_bzrdir.py'
27--- breezy/bzr/tests/per_bzrdir/test_bzrdir.py 2023-11-16 15:15:02 +0000
28+++ breezy/bzr/tests/per_bzrdir/test_bzrdir.py 2023-11-28 16:07:00 +0000
29@@ -584,7 +584,7 @@
30 )
31 self.assertEqual([rev2], target.open_workingtree().get_parent_ids())
32
33- def test_retire_bzrdir(self):
34+ def test_retire_controldir(self):
35 bd = self.make_controldir(".")
36 transport = bd.root_transport
37 # must not overwrite existing directories
38@@ -596,11 +596,11 @@
39 transport=transport,
40 )
41 self.assertTrue(transport.has(".bzr"))
42- bd.retire_bzrdir()
43+ bd.retire_controldir()
44 self.assertFalse(transport.has(".bzr"))
45 self.assertTrue(transport.has(".bzr.retired.1"))
46
47- def test_retire_bzrdir_limited(self):
48+ def test_retire_controldir_limited(self):
49 bd = self.make_controldir(".")
50 transport = bd.root_transport
51 # must not overwrite existing directories
52@@ -613,7 +613,7 @@
53 )
54 self.assertTrue(transport.has(".bzr"))
55 self.assertRaises(
56- (FileExists, errors.DirectoryNotEmpty), bd.retire_bzrdir, limit=0
57+ (FileExists, errors.DirectoryNotEmpty), bd.retire_controldir, limit=0
58 )
59
60 def test_get_branch_transport(self):
61
62=== modified file 'breezy/bzr/workingtree.py'
63--- breezy/bzr/workingtree.py 2023-11-16 15:15:02 +0000
64+++ breezy/bzr/workingtree.py 2023-11-28 16:07:00 +0000
65@@ -1025,7 +1025,7 @@
66 for parent_id in other_tree.get_parent_ids():
67 self.branch.fetch(other_tree.branch, parent_id)
68 self.add_parent_tree_id(parent_id)
69- other_tree.controldir.retire_bzrdir()
70+ other_tree.controldir.retire_controldir()
71
72 def extract(self, sub_path, format=None):
73 """Extract a subtree from this tree.
74
75=== modified file 'breezy/git/dir.py'
76--- breezy/git/dir.py 2023-11-16 21:12:11 +0000
77+++ breezy/git/dir.py 2023-11-28 16:07:00 +0000
78@@ -143,6 +143,33 @@
79 def _available_backup_name(self, base):
80 return osutils.available_backup_name(base, self.root_transport.has)
81
82+ def retire_controldir(self, limit=10000):
83+ """Permanently disable the controldir.
84+
85+ This is done by renaming it to give the user some ability to recover
86+ if there was a problem.
87+
88+ This will have horrible consequences if anyone has anything locked or
89+ in use.
90+ :param limit: number of times to retry
91+ """
92+ i = 0
93+ while True:
94+ try:
95+ to_path = ".git.retired.%d" % i
96+ self.root_transport.rename(".git", to_path)
97+ trace.note(
98+ "renamed {} to {}".format(
99+ self.root_transport.abspath(".git"), to_path)
100+ )
101+ return
102+ except (brz_errors.TransportError, OSError, brz_errors.PathError):
103+ i += 1
104+ if i > limit:
105+ raise
106+ else:
107+ pass
108+
109 def sprout(
110 self,
111 url,
112
113=== modified file 'breezy/git/tests/test_workingtree.py'
114--- breezy/git/tests/test_workingtree.py 2023-11-07 10:54:10 +0000
115+++ breezy/git/tests/test_workingtree.py 2023-11-28 16:07:00 +0000
116@@ -424,3 +424,20 @@
117 t.add(b"a", S_IFGITLINK, a.id)
118 self.store.add_object(t)
119 self.expectDelta([], tree_id=t.id)
120+
121+ def test_subsume(self):
122+ self.build_tree(["a", "b"])
123+ self.wt.add(["a", "b"])
124+ myrevid = self.wt.commit("")
125+
126+ subwt = self.make_branch_and_tree("c", format="git")
127+ self.build_tree(["c/d"])
128+ subwt.add(["d"])
129+ subrevid = subwt.commit("")
130+
131+ self.wt.subsume(subwt)
132+ self.assertEqual([myrevid, subrevid], self.wt.get_parent_ids())
133+ self.assertFalse(os.path.exists("c/.git"))
134+ self.assertTrue(os.path.exists("c/.git.retired.0"))
135+ changes = list(self.wt.iter_changes(self.wt.basis_tree()))
136+ self.assertEqual(2, len(changes))
137
138=== modified file 'breezy/git/workingtree.py'
139--- breezy/git/workingtree.py 2023-11-26 21:02:55 +0000
140+++ breezy/git/workingtree.py 2023-11-28 16:07:00 +0000
141@@ -1620,6 +1620,32 @@
142
143 _marker = object()
144
145+ def subsume(self, other_tree):
146+ for parent_id in other_tree.get_parent_ids():
147+ self.branch.repository.fetch(other_tree.branch.repository, parent_id)
148+ self.set_parent_ids(self.get_parent_ids() + other_tree.get_parent_ids())
149+ with self.lock_tree_write(), other_tree.lock_tree_write():
150+ try:
151+ other_tree_path = self.relpath(other_tree.basedir)
152+ except errors.PathNotChild as err:
153+ raise errors.BadSubsumeSource(
154+ self, other_tree, "Tree is not contained by the other"
155+ ) from err
156+
157+ other_tree_bytes = encode_git_path(other_tree_path)
158+
159+ ids = {}
160+ for p, e in other_tree.index.iteritems():
161+ newp = other_tree_bytes + b"/" + p
162+ self.index[newp] = e
163+ self._index_dirty = True
164+ ids[e.sha] = newp
165+
166+ self.store.add_objects(
167+ [(other_tree.store[i], p) for (i, p) in ids.items()])
168+
169+ other_tree.controldir.retire_controldir()
170+
171 def update(
172 self,
173 change_reporter=None,

Subscribers

People subscribed via source and target branches