docs: public void copy(
        JimfsPath source,
        FileSystemView destView,
        JimfsPath dest,
        Set<CopyOption> options,
        boolean move)
        throws IOException {
      checkNotNull(source);
      checkNotNull(destView);
      checkNotNull(dest);
      checkNotNull(options);
  
      boolean sameFileSystem = isSameFileSystem(destView);
  
      File sourceFile;
      File copyFile = null; // non-null after block completes iff source file was copied
      lockBoth(store.writeLock(), destView.store.writeLock());
      try {
        DirectoryEntry sourceEntry = lookUp(source, options).requireExists(source);
        DirectoryEntry destEntry = destView.lookUp(dest, Options.NOFOLLOW_LINKS);
  
        Directory sourceParent = sourceEntry.directory();
        sourceFile = sourceEntry.file();
  
        Directory destParent = destEntry.directory();
  
        if (move && sourceFile.isDirectory()) {
          if (sameFileSystem) {
            checkMovable(sourceFile, source);
            checkNotAncestor(sourceFile, destParent, destView);
          } else {
            // move to another file system is accomplished by copy-then-delete, so the source file
            // must be deletable to be moved
            checkDeletable(sourceFile, DeleteMode.ANY, source);
          }
        }
  
        if (destEntry.exists()) {
          if (destEntry.file().equals(sourceFile)) {
            return;
          } else if (options.contains(REPLACE_EXISTING)) {
            destView.delete(destEntry, DeleteMode.ANY, dest);
          } else {
            throw new FileAlreadyExistsException(dest.toString());
          }
        }
  
        if (move && sameFileSystem) {
          // Real move on the same file system.
          sourceParent.unlink(source.name());
          sourceParent.updateModifiedTime();
  
          destParent.link(dest.name(), sourceFile);
          destParent.updateModifiedTime();
        } else {
          // Doing a copy OR a move to a different file system, which must be implemented by copy and
          // delete.
  
          // By default, don't copy attributes.
          AttributeCopyOption attributeCopyOption = AttributeCopyOption.NONE;
          if (move) {
            // Copy only the basic attributes of the file to the other file system, as it may not
            // support all the attribute views that this file system does. This also matches the
            // behavior of moving a file to a foreign file system with a different
            // FileSystemProvider.
            attributeCopyOption = AttributeCopyOption.BASIC;
          } else if (options.contains(COPY_ATTRIBUTES)) {
            // As with move, if we're copying the file to a different file system, only copy its
            // basic attributes.
            attributeCopyOption =
                sameFileSystem ? AttributeCopyOption.ALL : AttributeCopyOption.BASIC;
          }
  
          // Copy the file, but don't copy its content while we're holding the file store locks.
          copyFile = destView.store.copyWithoutContent(sourceFile, attributeCopyOption);
          destParent.link(dest.name(), copyFile);
          destParent.updateModifiedTime();
  
          // In order for the copy to be atomic (not strictly necessary, but seems preferable since
          // we can) lock both source and copy files before leaving the file store locks. This
          // ensures that users cannot observe the copy's content until the content has been copied.
          // This also marks the source file as opened, preventing its content from being deleted
          // until after it's copied if the source file itself is deleted in the next step.
          lockSourceAndCopy(sourceFile, copyFile);
  
          if (move) {
            // It should not be possible for delete to throw an exception here, because we already
            // checked that the file was deletable above.
            delete(sourceEntry, DeleteMode.ANY, source);
          }
        }
      } finally {
        destView.store.writeLock().unlock();
        store.writeLock().unlock();
      }
  
      if (copyFile != null) {
        // Copy the content. This is done outside the above block to minimize the time spent holding
        // file store locks, since copying the content of a regular file could take a (relatively)
        // long time. If done inside the above block, copying using Files.copy can be slower than
        // copying with an InputStream and an OutputStream if many files are being copied on
        // different threads.
        try {
          sourceFile.copyContentTo(copyFile);
        } finally {
          // Unlock the files, allowing the content of the copy to be observed by the user. This also
          // closes the source file, allowing its content to be deleted if it was deleted.
          unlockSourceAndCopy(sourceFile, copyFile);
        }
      }
    }