@@ -149,52 +149,72 @@ def test_raises_on_missing_command(self):
149149class TestLaunchpadWrapper :
150150 """Test LaunchpadWrapper queue and filtering logic."""
151151
152- def test_queue_copy_accumulates_names (self ):
152+ def test_queue_copy_accumulates_packages (self ):
153153 wrapper = LaunchpadWrapper ()
154- wrapper .queue_copy ("kolibri-server" , "jammy" , "noble" , "Release" )
155- wrapper .queue_copy ("kolibri-server" , "jammy" , "focal" , "Release" )
154+ wrapper .queue_copy ("kolibri-server" , "0.5.1-0ubuntu1" , " jammy" , "noble" , "Release" )
155+ wrapper .queue_copy ("kolibri-server" , "0.5.1-0ubuntu1" , " jammy" , "focal" , "Release" )
156156
157157 assert ("jammy" , "noble" , "Release" ) in wrapper .queue
158158 assert ("jammy" , "focal" , "Release" ) in wrapper .queue
159- assert "kolibri-server" in wrapper .queue [("jammy" , "noble" , "Release" )]
159+ assert ( "kolibri-server" , "0.5.1-0ubuntu1" ) in wrapper .queue [("jammy" , "noble" , "Release" )]
160160
161161 def test_queue_starts_empty (self ):
162162 wrapper = LaunchpadWrapper ()
163163 assert len (wrapper .queue ) == 0
164164
165- def test_perform_queued_copies_calls_sync_sources (self ):
165+ def test_perform_queued_copies_calls_copy_package (self ):
166166 wrapper = LaunchpadWrapper ()
167- wrapper .queue_copy ("kolibri-server" , "jammy" , "noble" , "Release" )
167+ wrapper .queue_copy ("kolibri-server" , "0.5.1-0ubuntu1" , " jammy" , "noble" , "Release" )
168168
169169 mock_ppa = MagicMock ()
170170 wrapper .perform_queued_copies (mock_ppa )
171171
172- mock_ppa .syncSources .assert_called_once_with (
172+ mock_ppa .copyPackage .assert_called_once_with (
173173 from_archive = mock_ppa ,
174+ include_binaries = True ,
174175 to_series = "noble" ,
175176 to_pocket = "Release" ,
176- include_binaries = True ,
177- source_names = [ "kolibri-server" ] ,
177+ source_name = "kolibri-server" ,
178+ version = "0.5.1-0ubuntu1" ,
178179 )
179180
180181 def test_perform_queued_copies_skips_empty_queues (self ):
181182 wrapper = LaunchpadWrapper ()
182183 mock_ppa = MagicMock ()
183184 wrapper .perform_queued_copies (mock_ppa )
184185
185- mock_ppa .syncSources .assert_not_called ()
186+ mock_ppa .copyPackage .assert_not_called ()
187+
188+ def test_perform_queued_copies_handles_already_published (self ):
189+ """Idempotency: copyPackage errors for already-copied packages are handled gracefully."""
190+ wrapper = LaunchpadWrapper ()
191+ wrapper .queue_copy ("kolibri-server" , "0.5.1-0ubuntu1" , "jammy" , "noble" , "Release" )
192+
193+ class MockBadRequest (Exception ):
194+ pass
195+
196+ mock_ppa = MagicMock ()
197+ mock_ppa .copyPackage .side_effect = MockBadRequest (
198+ "kolibri-server 0.5.1-0ubuntu1 in noble (same version already published)"
199+ )
200+
201+ with patch ("launchpad_copy.lre" ) as mock_lre :
202+ mock_lre .BadRequest = MockBadRequest
203+ wrapper .perform_queued_copies (mock_ppa )
204+
205+ # Should not raise — the error is handled gracefully
186206
187- def test_perform_queued_copies_handles_already_synced (self ):
188- """Idempotency: syncSources errors for already-copied packages are handled gracefully."""
207+ def test_perform_queued_copies_handles_obsolete_series (self ):
208+ """copyPackage errors for obsolete series are handled gracefully."""
189209 wrapper = LaunchpadWrapper ()
190- wrapper .queue_copy ("kolibri-server" , "jammy" , "noble " , "Release" )
210+ wrapper .queue_copy ("kolibri-server" , "0.5.1-0ubuntu1" , " jammy" , "trusty " , "Release" )
191211
192212 class MockBadRequest (Exception ):
193213 pass
194214
195215 mock_ppa = MagicMock ()
196- mock_ppa .syncSources .side_effect = MockBadRequest (
197- "kolibri-server 0.9.0 in noble (same version already published) "
216+ mock_ppa .copyPackage .side_effect = MockBadRequest (
217+ "trusty is obsolete and will not accept new uploads "
198218 )
199219
200220 with patch ("launchpad_copy.lre" ) as mock_lre :
@@ -203,17 +223,17 @@ class MockBadRequest(Exception):
203223
204224 # Should not raise — the error is handled gracefully
205225
206- def test_perform_queued_copies_logs_already_synced (self , caplog ):
207- """Idempotency: logs a message when syncSources finds package already exists."""
226+ def test_perform_queued_copies_logs_already_published (self , caplog ):
227+ """Idempotency: logs a message when copyPackage finds package already exists."""
208228 wrapper = LaunchpadWrapper ()
209- wrapper .queue_copy ("kolibri-server" , "jammy" , "noble" , "Release" )
229+ wrapper .queue_copy ("kolibri-server" , "0.5.1-0ubuntu1" , " jammy" , "noble" , "Release" )
210230
211231 class MockBadRequest (Exception ):
212232 pass
213233
214234 mock_ppa = MagicMock ()
215- mock_ppa .syncSources .side_effect = MockBadRequest (
216- "kolibri-server 0.9.0 in noble (same version already published)"
235+ mock_ppa .copyPackage .side_effect = MockBadRequest (
236+ "kolibri-server 0.5.1-0ubuntu1 in noble (same version already published)"
217237 )
218238
219239 with (
0 commit comments