def _upload_delta( store_client, *, snap_name: str, snap_filename: str, source_snap: str, built_at: str, channels: Optional[List[str]] = None, ) -> Dict[str, Any]: delta_format = "xdelta3" logger.debug("Found cached source snap {}.".format(source_snap)) target_snap = os.path.join(os.getcwd(), snap_filename) try: xdelta_generator = deltas.XDelta3Generator(source_path=source_snap, target_path=target_snap) delta_filename = xdelta_generator.make_delta() except (DeltaGenerationError, DeltaGenerationTooBigError, ToolMissingError) as e: raise storeapi.errors.StoreDeltaApplicationError(str(e)) snap_hashes = { "source_hash": calculate_sha3_384(source_snap), "target_hash": calculate_sha3_384(target_snap), "delta_hash": calculate_sha3_384(delta_filename), } try: logger.debug("Uploading delta {!r}.".format(delta_filename)) delta_tracker = store_client.upload( snap_name=snap_name, snap_filename=delta_filename, built_at=built_at, channels=channels, delta_format=delta_format, source_hash=snap_hashes["source_hash"], target_hash=snap_hashes["target_hash"], delta_hash=snap_hashes["delta_hash"], ) result = delta_tracker.track() delta_tracker.raise_for_code() except storeapi.errors.StoreReviewError as e: if e.code == "processing_upload_delta_error": raise storeapi.errors.StoreDeltaApplicationError(str(e)) else: raise except storeapi.errors.StoreServerError as e: raise storeapi.errors.StoreUploadError(snap_name, e.response) finally: if os.path.isfile(delta_filename): try: os.remove(delta_filename) except OSError: logger.warning( "Unable to remove delta {}.".format(delta_filename)) return result
def test_xdelta3(self): self.generate_snap_pair() base_delta = deltas.XDelta3Generator(source_path=self.source_file, target_path=self.target_file) path = base_delta.make_delta(is_for_test=True) self.assertThat(path, m.FileExists()) expect_path = "{}.{}".format(base_delta.target_path, base_delta.delta_file_extname) self.assertThat(path, m.Equals(expect_path))
def test_xdelta3_logs(self): self.generate_snap_pair() base_delta = deltas.XDelta3Generator(source_path=self.source_file, target_path=self.target_file) base_delta.make_delta(is_for_test=True) self.assertThat( self.fake_logger.output, m.Contains('Generating xdelta3 delta for {}'.format( os.path.basename(base_delta.target_path)))) self.assertThat(self.fake_logger.output, m.Contains('xdelta3 delta diff generation'))
def test_raises_DeltaToolError_when_xdelta3_not_installed(self): self.patch(file_utils, 'executable_exists', lambda a: False) self.patch(shutil, 'which', lambda a: None) self.assertThat( lambda: deltas.XDelta3Generator( source_path=self.source_file, target_path=self.target_file), m.raises(deltas.errors.DeltaToolError) ) self.assertRaises(deltas.errors.DeltaToolError, deltas.XDelta3Generator, source_path=self.source_file, target_path=self.target_file)
def test_raises_DeltaToolError_when_xdelta3_not_installed(self): self.patch(file_utils, 'executable_exists', lambda a: False) self.patch(shutil, 'which', lambda a: None) self.assertThat( lambda: deltas.XDelta3Generator(source_path=self.source_file, target_path=self.target_file), m.raises(deltas.errors.DeltaToolError)) exception = self.assertRaises(deltas.errors.DeltaToolError, deltas.XDelta3Generator, source_path=self.source_file, target_path=self.target_file) expected = 'delta_tool_path must be set in subclass!' self.assertEqual(str(exception), expected)
def _push_delta(snap_name, snap_filename, source_snap, built_at): store = storeapi.StoreClient() delta_format = "xdelta3" logger.debug("Found cached source snap {}.".format(source_snap)) target_snap = os.path.join(os.getcwd(), snap_filename) try: xdelta_generator = deltas.XDelta3Generator(source_path=source_snap, target_path=target_snap) delta_filename = xdelta_generator.make_delta() except (DeltaGenerationError, DeltaGenerationTooBigError, DeltaToolError) as e: raise storeapi.errors.StoreDeltaApplicationError(str(e)) snap_hashes = { "source_hash": calculate_sha3_384(source_snap), "target_hash": calculate_sha3_384(target_snap), "delta_hash": calculate_sha3_384(delta_filename), } try: logger.debug("Pushing delta {!r}.".format(delta_filename)) with _requires_login(): delta_tracker = store.upload( snap_name, delta_filename, delta_format=delta_format, source_hash=snap_hashes["source_hash"], target_hash=snap_hashes["target_hash"], delta_hash=snap_hashes["delta_hash"], built_at=built_at, ) result = delta_tracker.track() delta_tracker.raise_for_code() except storeapi.errors.StoreReviewError as e: if e.code == "processing_upload_delta_error": raise storeapi.errors.StoreDeltaApplicationError(str(e)) else: raise except storeapi.errors.StoreServerError as e: raise storeapi.errors.StorePushError(snap_name, e.response) finally: if os.path.isfile(delta_filename): try: os.remove(delta_filename) except OSError: logger.warning( "Unable to remove delta {}.".format(delta_filename)) return result
def test_xdelta3_return_invalid_code(self, mock_subproc_popen): # mock the subprocess.Popen with a unexpected returncode process_mock = mock.Mock() attrs = {"returncode": -1} process_mock.configure_mock(**attrs) mock_subproc_popen.return_value = process_mock self.generate_snap_pair() base_delta = deltas.XDelta3Generator(source_path=self.source_file, target_path=self.target_file) self.assertThat( lambda: base_delta.make_delta(is_for_test=True), m.raises(deltas.errors.DeltaGenerationError), )
def _push_delta(snap_name, snap_filename, source_snap): store = storeapi.StoreClient() delta_format = 'xdelta3' logger.info('Found cached source snap {}.'.format(source_snap)) target_snap = os.path.join(os.getcwd(), snap_filename) try: xdelta_generator = deltas.XDelta3Generator(source_path=source_snap, target_path=target_snap) delta_filename = xdelta_generator.make_delta() except (DeltaGenerationError, DeltaGenerationTooBigError, DeltaToolError) as e: raise StoreDeltaApplicationError(str(e)) snap_hashes = { 'source_hash': calculate_sha3_384(source_snap), 'target_hash': calculate_sha3_384(target_snap), 'delta_hash': calculate_sha3_384(delta_filename) } try: logger.info('Pushing delta {}.'.format(delta_filename)) with _requires_login(): delta_tracker = store.upload( snap_name, delta_filename, delta_format=delta_format, source_hash=snap_hashes['source_hash'], target_hash=snap_hashes['target_hash'], delta_hash=snap_hashes['delta_hash']) result = delta_tracker.track() delta_tracker.raise_for_code() except storeapi.errors.StoreReviewError as e: if e.code == 'processing_upload_delta_error': raise StoreDeltaApplicationError else: raise finally: if os.path.isfile(delta_filename): try: os.remove(delta_filename) except OSError: logger.warning( 'Unable to remove delta {}.'.format(delta_filename)) return result
def test_xdelta3_with_progress_indicator(self): self.generate_snap_pair() base_delta = deltas.XDelta3Generator(source_path=self.source_file, target_path=self.target_file) message = "creating delta file from {!r}...".format(self.source_file) maxval = 10 progress_indicator = ProgressBar(widgets=[message, AnimatedMarker()], maxval=maxval) progress_indicator.start() path = base_delta.make_delta(progress_indicator=progress_indicator, is_for_test=True) progress_indicator.finish() self.assertThat(path, m.FileExists()) expect_path = "{}.{}".format(base_delta.target_path, base_delta.delta_file_extname) self.assertThat(path, m.Equals(expect_path))
def test_xdelta3_with_custom_output_dir(self): self.generate_snap_pair() base_delta = deltas.XDelta3Generator(source_path=self.source_file, target_path=self.target_file) delta_filename = "{}.{}".format( os.path.split(base_delta.target_path)[1], base_delta.delta_file_extname) existed_output_dir = self.useFixture(fixtures.TempDir()).path path = base_delta.make_delta(existed_output_dir, is_for_test=True) expect_path = os.path.join(existed_output_dir, delta_filename) self.assertThat(path, m.FileExists()) self.assertThat(path, m.Equals(expect_path)) none_existed_output_dir = (self.useFixture(fixtures.TempDir()).path + "/whatever/") path = base_delta.make_delta(none_existed_output_dir, is_for_test=True) expect_path = os.path.join(none_existed_output_dir, delta_filename) self.assertThat(path, m.FileExists()) self.assertThat(path, m.Equals(expect_path))