diff --git a/cpp/src/arrow/filesystem/gcsfs.cc b/cpp/src/arrow/filesystem/gcsfs.cc index aa69890d336..fb77be56e7b 100644 --- a/cpp/src/arrow/filesystem/gcsfs.cc +++ b/cpp/src/arrow/filesystem/gcsfs.cc @@ -182,6 +182,12 @@ class GcsFileSystem::Impl { return GetFileInfoImpl(path, std::move(meta).status(), FileType::Directory); } + Status CopyFile(const GcsPath& src, const GcsPath& dest) { + auto metadata = + client_.RewriteObjectBlocking(src.bucket, src.object, dest.bucket, dest.object); + return internal::ToArrowStatus(metadata.status()); + } + Result> OpenInputStream(const GcsPath& path) { auto stream = client_.ReadObject(path.bucket, path.object); ARROW_GCS_RETURN_NOT_OK(stream.status()); @@ -274,7 +280,9 @@ Status GcsFileSystem::Move(const std::string& src, const std::string& dest) { } Status GcsFileSystem::CopyFile(const std::string& src, const std::string& dest) { - return Status::NotImplemented("The GCS FileSystem is not fully implemented"); + ARROW_ASSIGN_OR_RAISE(auto s, GcsPath::FromString(src)); + ARROW_ASSIGN_OR_RAISE(auto d, GcsPath::FromString(dest)); + return impl_->CopyFile(s, d); } Result> GcsFileSystem::OpenInputStream( diff --git a/cpp/src/arrow/filesystem/gcsfs_test.cc b/cpp/src/arrow/filesystem/gcsfs_test.cc index 3304d4bcc73..f3e12cb5974 100644 --- a/cpp/src/arrow/filesystem/gcsfs_test.cc +++ b/cpp/src/arrow/filesystem/gcsfs_test.cc @@ -286,6 +286,19 @@ TEST_F(GcsIntegrationTest, GetFileInfoObject) { arrow::fs::AssertFileInfo(fs.get(), PreexistingObjectPath(), FileType::File); } +TEST_F(GcsIntegrationTest, CopyFileSuccess) { + auto fs = internal::MakeGcsFileSystemForTest(TestGcsOptions()); + const auto destination_path = kPreexistingBucket + std::string("/copy-destination"); + ASSERT_OK(fs->CopyFile(PreexistingObjectPath(), destination_path)); + arrow::fs::AssertFileInfo(fs.get(), destination_path, FileType::File); +} + +TEST_F(GcsIntegrationTest, CopyFileNotFound) { + auto fs = internal::MakeGcsFileSystemForTest(TestGcsOptions()); + const auto destination_path = kPreexistingBucket + std::string("/copy-destination"); + ASSERT_RAISES(IOError, fs->CopyFile(NotFoundObjectPath(), destination_path)); +} + TEST_F(GcsIntegrationTest, ReadObjectString) { auto fs = internal::MakeGcsFileSystemForTest(TestGcsOptions());