docs: public static String relativePath(File self, File to) throws IOException {
          String fromPath = self.getCanonicalPath();
          String toPath = to.getCanonicalPath();
  
          // build the path stack info to compare
          String[] fromPathStack = getPathStack(fromPath);
          String[] toPathStack = getPathStack(toPath);
  
          if (0 < toPathStack.length && 0 < fromPathStack.length) {
              if (!fromPathStack[0].equals(toPathStack[0])) {
                  // not the same device (would be "" on Linux/Unix)
  
                  return getPath(Arrays.asList(toPathStack));
              }
          } else {
              // no comparison possible
              return getPath(Arrays.asList(toPathStack));
          }
  
          int minLength = Math.min(fromPathStack.length, toPathStack.length);
          int same = 1; // Used outside the for loop
  
          // get index of parts which are equal
          while (same < minLength && fromPathStack[same].equals(toPathStack[same])) {
              same++;
          }
  
          List<String> relativePathStack = new ArrayList<String>();
  
          // if "from" part is longer, fill it up with ".."
          // to reach path which is equal to both paths
          for (int i = same; i < fromPathStack.length; i++) {
              relativePathStack.add("..");
          }
  
          // fill it up path with parts which were not equal
          relativePathStack.addAll(Arrays.asList(toPathStack).subList(same, toPathStack.length));
  
          return getPath(relativePathStack);
      }