Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Soft delete projects by moving them to trash #10440

Merged
merged 34 commits into from
Jul 27, 2024
Merged

Conversation

4e6
Copy link
Contributor

@4e6 4e6 commented Jul 3, 2024

Pull Request Description

close #10357

Changelog:

  • add: LinuxTrashBin implementing Freedesktop.org trash specification
  • add: WindowsTrashBin calling native platform APIs for Windows
  • add: MacTrashBin calling native platform APIs for MacOS
  • update: project/delete method moves projects to trash and falls back to directory deletion

Important Notes

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • All code follows the
    Scala,
    Java,
    TypeScript,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • Unit tests have been written where possible.

@4e6 4e6 added the CI: No changelog needed Do not require a changelog entry for this PR. label Jul 3, 2024
@4e6 4e6 self-assigned this Jul 3, 2024
@4e6 4e6 changed the title Soft delete project by moving them to trash Soft delete projects by moving them to trash Jul 4, 2024
Copy link
Member

@Akirathan Akirathan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit tests are fine, but in this case, we also need some QA. Please, ensure that the deleted project can be restored (or at least seen) in the trash on all the platforms.

Assert.assertTrue(trash.moveToTrash(path));
Assert.assertFalse(trash.moveToTrash(path));
} finally {
FileUtils.deleteQuietly(path.toFile());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use @Rule TemporaryFolder just like in https://github.com/enso-org/enso/blob/develop/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/exports/ExportExtensionMethodTest.java#L23 and avoid the need to delete the path yourself - JUnit runner will do that for you.

@4e6 4e6 force-pushed the wip/db/10357-add-recycle branch from 536515b to 170284b Compare July 9, 2024 14:49
@4e6 4e6 marked this pull request as ready for review July 9, 2024 17:27
@hubertp hubertp requested a review from JaroslavTulach July 25, 2024 20:54
@JaroslavTulach
Copy link
Member

Update PR description:

close #10357

Changelog:

add: LinuxTrash implementing Freedesktop.org trash specification
add: JnaTrash calling native platform APIs for Windows and macOS
update: project/delete method moves projects to trash and falls back to directory deletion
update: native image configuration with the JNA dependency

It is out of date.

Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RandomUtils seem over complicated and potentially replaceable by UUID. Please update the PR description.

throw new IllegalArgumentException("String size should be positive.");
}

var random = LazyRandom.getInstance();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we just use random = new Random()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To initialize it once

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you need to initialize once? For purposes of randomness, initializing again and again is completely OK unless you expect multiple random values to be needed during the same millisecond.

trashInfo,
toDelete,
contents,
RandomUtils.alphanumericString(SUFFIX_SIZE),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is quite common in Enso to use UUID - which is usually created randomly based on various conditions including time seed. Is not it easier to remove RandomUtils and just ask for UUID?

Copy link
Contributor

@hubertp hubertp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving changes that I haven't committed to this PR. @4e6 please review our work on SVM C's interface.

@hubertp
Copy link
Contributor

hubertp commented Jul 26, 2024

@JaroslavTulach As expected, unit tests on Windows and Mac fail because C's interface is only compiled for native image.
We should either disable those tests for non-Linux or add some workaround in those cases (you mentioned you had some idea?). Alternatively bring back JNA just for testing but I'm not sure it is worth it.

@JaroslavTulach
Copy link
Member

@JaroslavTulach As expected, unit tests on Windows and Mac fail because C's interface is only compiled for native image.

NullPointerException - that's great! We could also get some LinkageError... NPE is easy to recover from.

Can we recover from the exception and fallback to File.delete()?

If you want to check we run in AOT mode and only fallback to File.delete() in such case, there is Boolean.getBoolean("com.oracle.graalvm.isaot") to verify that.

Alternatively bring back JNA just for testing but I'm not sure it is worth it.

No, rather not.

.warn(
"Moving to MacOS's Trash Bin is not supported in non-AOT mode. Deleting"
+ " permanently");
return path.toFile().delete();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should return false. Right now the project manager logic removes the project directory permanently if was unable to move it to trash bin.

private static final Platform OPERATING_SYSTEM = detectOperatingSystem();

/**
* @GuardedBy("this")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not a javadoc annotation

throw new IllegalArgumentException("String size should be positive.");
}

var random = LazyRandom.getInstance();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To initialize it once


@Override
public boolean moveToTrash(Path path) {
if (Platform.getOperatingSystem().isMacOs())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say this check is unnecessary because the class is not exposed, and its instantiation depends on the Platform.getOperatingSystem(). I.e. the factory method guarantees the correct OS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would fail native image build otherwise.


@Override
public boolean moveToTrash(Path path) {
if (Platform.getOperatingSystem().isWindows())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say unnecessary, the same way as for macOS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason as for MacOS - native image build.

.warn(
"Moving to Windows' Trash Bin is not supported in non-AOT mode. Deleting"
+ " permanently");
return path.toFile().delete();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just return false, the project manager logic will delete the project directory permanently as a fallback action.

ifTrue = log.info("Project moved to trash [{}].", projectId),
ifFalse =
log.info("Failed to trash the project. Deleting [{}].", projectId) *>
deleteProject *>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the fallback logic that deletes the project permanently

@enso-bot enso-bot bot mentioned this pull request Jul 27, 2024
2 tasks
import java.util.stream.Collectors;
import org.slf4j.Logger;

public class TrashBinFallback {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class shouldn't be public.

Suggested change
public class TrashBinFallback {
class TrashBinFallback {

@@ -15,7 +15,7 @@
import org.slf4j.LoggerFactory;

@CContext(WindowsTrashBin.ShellApi.class)
final class WindowsTrashBin implements TrashBin {
final class WindowsTrashBin extends TrashBinFallback implements TrashBin {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using inheritance for implementation purposes not for any meaningful type hierarchy. What would Lišková said about it?

I would personally make hardDeletePath a static utility method in some existing class. But if you hide all these classes from the Javadoc, then I don't care.

Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try sbt desktop-environment/doc and verify it doesn't contain unnecessary elements. Otherwise good, get this in.

@4e6
Copy link
Contributor Author

4e6 commented Jul 27, 2024

Windows build works correctly for me

@4e6 4e6 added the CI: Ready to merge This PR is eligible for automatic merge label Jul 27, 2024
@mergify mergify bot merged commit 446834b into develop Jul 27, 2024
42 checks passed
@mergify mergify bot deleted the wip/db/10357-add-recycle branch July 27, 2024 13:37
@hubertp
Copy link
Contributor

hubertp commented Jul 28, 2024

I don't think disabling tests for Mac and Windows was desirable. Pretty sure folks will try it in dev mode and complain that we don't delete directories. Hard delete was better.

@4e6
Copy link
Contributor Author

4e6 commented Jul 29, 2024

Pretty sure folks will try it in dev mode and complain that we don't delete directories. Hard delete was better.

Hard delete will work in dev mode

_ <- CovariantFlatMap[F].ifM(moveProjectToTrash)(
ifTrue = log.info("Project moved to trash [{}].", projectId),
ifFalse =
log.info("Failed to trash the project. Deleting [{}].", projectId) *>
deleteProject *>
log.info("Project deleted [{}]", projectId)


private LazyRandom() {}

public static Random getInstance() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you really want to...

To initialize it once

... then this method is missing synchronized modifier.

private RandomUtils() {}

/** Delay the {@link Random} instance initialization when building the native image. */
private static final class LazyRandom {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delay the {@link Random} instance initialization when building the native image.

Remove LazyRandom class. There is no point having it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: Clean build required CI runners will be cleaned before and after this PR is built. CI: No changelog needed Do not require a changelog entry for this PR. CI: Ready to merge This PR is eligible for automatic merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add "recycle"/"soft delete"/"move to trash" endpoint for Project Manager
5 participants