diff --git a/osbuild/objectstore.py b/osbuild/objectstore.py index 922d5eec..4536e4a1 100644 --- a/osbuild/objectstore.py +++ b/osbuild/objectstore.py @@ -244,18 +244,20 @@ class Object: if self.mode != want: raise ValueError(f"Wrong object mode: {self.mode}, want {want}") - def export(self, to_directory: PathLike): + def export(self, to_directory: PathLike, skip_preserve_owner=False): """Copy object into an external directory""" - subprocess.run( - [ - "cp", - "--reflink=auto", - "-a", - os.fspath(self.tree) + "/.", - os.fspath(to_directory), - ], - check=True, - ) + cp_cmd = [ + "cp", + "--reflink=auto", + "-a", + ] + if skip_preserve_owner: + cp_cmd += ["--no-preserve=ownership"] + cp_cmd += [ + os.fspath(self.tree) + "/.", + os.fspath(to_directory), + ] + subprocess.run(cp_cmd, check=True) def __fspath__(self): return self.tree diff --git a/test/mod/test_objectstore.py b/test/mod/test_objectstore.py index e7aa348a..94711601 100644 --- a/test/mod/test_objectstore.py +++ b/test/mod/test_objectstore.py @@ -320,3 +320,32 @@ def test_store_server(tmp_path): with pytest.raises(RuntimeError): _ = client.read_tree_at("42", tmp_path, "/nonexistent") + + +@pytest.mark.skipif(os.getuid() != 0, reason="needs root") +def test_object_export_preserves_ownership_by_default(tmp_path, object_store): + tree = object_store.new("a") + p = Path(tree, "A") + p.touch() + os.chown(os.fspath(p), 1000, 1000) + tree.export(tmp_path) + + expected_exported_path = Path(tmp_path, "A") + assert expected_exported_path.exists() + assert expected_exported_path.stat().st_uid == 1000 + assert expected_exported_path.stat().st_gid == 1000 + + +@pytest.mark.skipif(os.getuid() != 0, reason="needs root") +def test_object_export_preserves_override(tmp_path, object_store): + tree = object_store.new("a") + p = Path(tree, "A") + p.touch() + os.chown(os.fspath(p), 1000, 1000) + tree.export(tmp_path, skip_preserve_owner=True) + + expected_exported_path = Path(tmp_path, "A") + assert expected_exported_path.exists() + assert expected_exported_path.stat().st_uid == 0 + assert expected_exported_path.stat().st_gid == 0 +