FileOpUtils { @NonNull public static String makeRelative(@NonNull File baseDir, @NonNull File toBeRelative, FileOp fop) throws IOException { return makeRelativeImpl( baseDir.getCanonicalPath(), toBeRelative.getCanonicalPath(), fop.isWindows(), File.separator); } private  FileOpUtils(); @NonNull static FileOp create(); static void recursiveCopy(@NonNull File src, @NonNull File dest, @NonNull FileOp fop,
            @NonNull ProgressIndicator progress); static void safeRecursiveOverwrite(@NonNull File src, @NonNull File dest,
            @NonNull FileOp fop, @NonNull ProgressIndicator progress); @Nullable static File getNewTempDir(@NonNull String base, @NonNull FileOp fileOp); @NonNull @VisibleForTesting static File getTempDir(@NonNull String base, int i); @NonNull static File append(@NonNull File base, @NonNull String... segments); @NonNull static File append(@NonNull String base, @NonNull String... segments); @NonNull static String makeRelative(@NonNull File baseDir, @NonNull File toBeRelative, FileOp fop); static void retainTempDirs(Set<File> retain, String base, FileOp mFop);  }
@Test public void makeRelative() throws Exception { assertEquals("dir3", FileOpUtils.makeRelativeImpl("/dir1/dir2", "/dir1/dir2/dir3", false, "/")); assertEquals("../../../dir3", FileOpUtils.makeRelativeImpl("/dir1/dir2/dir4/dir5/dir6", "/dir1/dir2/dir3", false, "/")); assertEquals("dir3/dir4/dir5/dir6", FileOpUtils.makeRelativeImpl("/dir1/dir2/", "/dir1/dir2/dir3/dir4/dir5/dir6", false, "/")); assertEquals("../DIR2/dir3/DIR4/dir5/DIR6", FileOpUtils.makeRelativeImpl("/dir1/dir2/", "/dir1/DIR2/dir3/DIR4/dir5/DIR6", false, "/")); assertEquals("", FileOpUtils.makeRelativeImpl("/dir1/dir2/dir3", "/dir1/dir2/dir3", false, "/")); assertEquals("..\\..\\..\\dir3", FileOpUtils.makeRelativeImpl("C:\\dir1\\dir2\\dir4\\dir5\\dir6", "C:\\dir1\\dir2\\dir3", true, "\\")); assertEquals("dir3/DIR4/dir5/DIR6", FileOpUtils.makeRelativeImpl("/DIR1/dir2/", "/dir1/DIR2/dir3/DIR4/dir5/DIR6", true, "/")); assertEquals("..\\..\\..\\dir3", FileOpUtils.makeRelativeImpl("\\\\myserver.domain\\dir1\\dir2\\dir4\\dir5\\dir6", "\\\\myserver.domain\\dir1\\dir2\\dir3", true, "\\")); try { FileOpUtils.makeRelativeImpl("C:\\dir1\\dir2\\dir4\\dir5\\dir6", "D:\\dir1\\dir2\\dir3", true, "\\"); fail("Expected: IOException. Actual: no exception."); } catch (IOException e) { assertEquals("makeRelative: incompatible drive letters", e.getMessage()); } }