From 57b3fcb18c9062eba33e70a2f334bdbc50fa5d94 Mon Sep 17 00:00:00 2001 From: dharshib Date: Tue, 7 Oct 2025 15:02:58 +0530 Subject: [PATCH 1/4] Handle file already exists error when replace false --- ballerina/tests/file-test.bal | 48 +++++++++++++------ .../stdlib/file/nativeimpl/Utils.java | 5 +- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/ballerina/tests/file-test.bal b/ballerina/tests/file-test.bal index c09540c..2fe7a9a 100644 --- a/ballerina/tests/file-test.bal +++ b/ballerina/tests/file-test.bal @@ -245,7 +245,12 @@ function testCreateDirWithoutParentDir() { } @test:Config {} -function testCopyFile() { +function testCopyFileToNonExistentFileReplaceFalse() { + error? removeResult = remove(tmpdir + copyFile); + if removeResult is error { + test:assertFail("Error removing test resource!"); + } + MetaData|error srcmetadata = getMetaData(srcFile); if srcmetadata is MetaData { srcFileLength = srcmetadata.size; @@ -267,41 +272,54 @@ function testCopyFile() { } } -@test:Config {dependsOn: [testCopyFile]} -function testCopyFileReplaceFalse() { - MetaData|error srcMmetadata = getMetaData(srcModifiedFile); - if srcMmetadata is MetaData { - srcModifiedFileLength = srcMmetadata.size; +@test:Config {dependsOn: [testCopyFileToNonExistentFileReplaceFalse]} +function testCopyFileToExistingFileReplaceFalse() { + error? copyResult = copy(srcFile, tmpdir + copyFile); + if copyResult is error { + string expectedErrMsg = "The target file already exists"; + test:assertTrue(copyResult.message().includes(expectedErrMsg)); + } else { + test:assertFail("File copy succeeded to an existing file when replace false!"); + } +} + +@test:Config {dependsOn: [testCopyFileToExistingFileReplaceFalse]} +function testCopyFileToExistingFileReplaceTrue() { + MetaData|error srcMetadata = getMetaData(srcModifiedFile); + if srcMetadata is MetaData { + srcModifiedFileLength = srcMetadata.size; } else { test:assertFail("Error retrieving source file size!"); } - - error? copyResult = copy(srcModifiedFile, tmpdir + copyFile); + error? copyResult = copy(srcModifiedFile, tmpdir + copyFile, REPLACE_EXISTING); if copyResult is error { test:assertFail("File not copied!"); } else { MetaData|error metadata = getMetaData(tmpdir + copyFile); if metadata is MetaData { int destFileLength = metadata.size; - test:assertEquals(destFileLength, srcFileLength, "File size mismatch!"); - test:assertNotEquals(destFileLength, srcModifiedFileLength); + test:assertEquals(destFileLength, srcModifiedFileLength, "File size mismatch!"); + test:assertNotEquals(destFileLength, srcFileLength); + error? removeResult = remove(tmpdir + copyFile); + if removeResult is error { + test:assertFail("Error removing test resource!"); + } } else { test:assertFail("Error retrieving destination file size!"); } } } -@test:Config {dependsOn: [testCopyFileReplaceFalse]} -function testCopyFileReplaceTrue() { - error? copyResult = copy(srcModifiedFile, tmpdir + copyFile, REPLACE_EXISTING); +@test:Config {dependsOn: [testCopyFileToExistingFileReplaceTrue]} +function testCopyFileToNonExistentFileReplaceTrue() { + error? copyResult = copy(srcFile, tmpdir + copyFile, REPLACE_EXISTING); if copyResult is error { test:assertFail("File not copied!"); } else { MetaData|error metadata = getMetaData(tmpdir + copyFile); if metadata is MetaData { int destFileLength = metadata.size; - test:assertEquals(destFileLength, srcModifiedFileLength, "File size mismatch!"); - test:assertNotEquals(destFileLength, srcFileLength); + test:assertEquals(destFileLength, srcFileLength, "File size mismatch!"); error? removeResult = remove(tmpdir + copyFile); if removeResult is error { test:assertFail("Error removing test resource!"); diff --git a/native/src/main/java/io/ballerina/stdlib/file/nativeimpl/Utils.java b/native/src/main/java/io/ballerina/stdlib/file/nativeimpl/Utils.java index 974ec37..a999068 100644 --- a/native/src/main/java/io/ballerina/stdlib/file/nativeimpl/Utils.java +++ b/native/src/main/java/io/ballerina/stdlib/file/nativeimpl/Utils.java @@ -299,6 +299,9 @@ public static Object copy(BString sourcePath, BString destinationPath, BString.. } catch (NoSuchFileException ex) { return FileUtils.getBallerinaError(FileConstants.FILE_NOT_FOUND_ERROR, "The target directory does not exist: " + ex.getMessage()); + } catch (FileAlreadyExistsException ex) { + return FileUtils.getBallerinaError(FileConstants.INVALID_OPERATION_ERROR, + "The target file already exists: " + ex.getMessage()); } catch (IOException ex) { return FileUtils.getBallerinaError(FileConstants.FILE_SYSTEM_ERROR, "An error occurred when copying the file/s: " + ex.getMessage()); @@ -335,7 +338,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO Path newFile = target.resolve(source.relativize(file)); try { Files.copy(file, newFile, copyOptions); - } catch (NoSuchFileException e) { + } catch (IOException e) { throw e; } catch (Exception e) { log.debug(e.getMessage()); From 5ee517881a5bc1ddec7bf36a1468da4116116e67 Mon Sep 17 00:00:00 2001 From: dharshib Date: Tue, 7 Oct 2025 15:24:17 +0530 Subject: [PATCH 2/4] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index c7aa6dd..306a8b3 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -114,7 +114,7 @@ dependencies = [ [[package]] org = "ballerina" name = "os" -version = "1.10.0" +version = "1.10.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"} From 3c8b115566751be6ec44bf6fb02561bc81d714b6 Mon Sep 17 00:00:00 2001 From: dharshib Date: Tue, 7 Oct 2025 15:45:51 +0530 Subject: [PATCH 3/4] Fix FileNotFoundError when removing source file --- ballerina/tests/file-test.bal | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ballerina/tests/file-test.bal b/ballerina/tests/file-test.bal index 2fe7a9a..f6b6598 100644 --- a/ballerina/tests/file-test.bal +++ b/ballerina/tests/file-test.bal @@ -247,7 +247,8 @@ function testCreateDirWithoutParentDir() { @test:Config {} function testCopyFileToNonExistentFileReplaceFalse() { error? removeResult = remove(tmpdir + copyFile); - if removeResult is error { + if removeResult is error && removeResult !is FileNotFoundError { + io:println(">>>> " + removeResult.toString()); test:assertFail("Error removing test resource!"); } From a8b03de2eecb3062ef9d0c8db8f90c80682f8633 Mon Sep 17 00:00:00 2001 From: dharshib Date: Fri, 10 Oct 2025 10:42:06 +0530 Subject: [PATCH 4/4] Refactor testCopyFileToNonExistentFileReplaceFalse test cases to use beforefunc --- ballerina/tests/file-test.bal | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ballerina/tests/file-test.bal b/ballerina/tests/file-test.bal index f6b6598..cb8d3c7 100644 --- a/ballerina/tests/file-test.bal +++ b/ballerina/tests/file-test.bal @@ -244,14 +244,18 @@ function testCreateDirWithoutParentDir() { } } -@test:Config {} -function testCopyFileToNonExistentFileReplaceFalse() { - error? removeResult = remove(tmpdir + copyFile); - if removeResult is error && removeResult !is FileNotFoundError { - io:println(">>>> " + removeResult.toString()); - test:assertFail("Error removing test resource!"); +function RemoveCopySource() returns error? { + boolean|error isSourceExists = test(tmpdir + copyFile, EXISTS); + if isSourceExists is boolean && isSourceExists { + check remove(tmpdir + copyFile); } +} +@test:Config { + before: RemoveCopySource, + dependsOn: [testRemove, testFileExists] +} +function testCopyFileToNonExistentFileReplaceFalse() { MetaData|error srcmetadata = getMetaData(srcFile); if srcmetadata is MetaData { srcFileLength = srcmetadata.size;