protected static void change(String filePath, final @Nullable String newContent) { try { File file = new File(FileUtil.toSystemDependentName(filePath)); assertTrue("File " + file.getAbsolutePath() + " doesn't exist", file.exists()); if (newContent != null) { FileUtil.writeToFile(file, newContent); } long oldTimestamp = FileSystemUtil.lastModified(file); long time = System.currentTimeMillis(); setLastModified(file, time); if (FileSystemUtil.lastModified(file) <= oldTimestamp) { setLastModified(file, time + 1); long newTimeStamp = FileSystemUtil.lastModified(file); if (newTimeStamp <= oldTimestamp) { //Mac OS and some versions of Linux truncates timestamp to nearest second setLastModified(file, time + 1000); newTimeStamp = FileSystemUtil.lastModified(file); assertTrue("Failed to change timestamp for " + file.getAbsolutePath(), newTimeStamp > oldTimestamp); } sleepUntil(newTimeStamp); } } catch (IOException e) { throw new RuntimeException(e); } }
public static void cleanupDeleteOnExitHookList() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { // try to reduce file set retained by java.io.DeleteOnExitHook List<String> list; synchronized (DELETE_ON_EXIT_HOOK_CLASS) { if (DELETE_ON_EXIT_HOOK_DOT_FILES.isEmpty()) return; list = new ArrayList<String>(DELETE_ON_EXIT_HOOK_DOT_FILES); } for (int i = list.size() - 1; i >= 0; i--) { String path = list.get(i); if (FileSystemUtil.getAttributes(path) == null || new File(path).delete()) { synchronized (DELETE_ON_EXIT_HOOK_CLASS) { DELETE_ON_EXIT_HOOK_DOT_FILES.remove(path); } } } }
private File getMirrorFile(@NotNull File originalFile) { if (!myFileSystem.isMakeCopyOfJar(originalFile)) return originalFile; final FileAttributes originalAttributes = FileSystemUtil.getAttributes(originalFile); if (originalAttributes == null) return originalFile; final String folderPath = getJarsDir(); if (!new File(folderPath).exists() && !new File(folderPath).mkdirs()) { return originalFile; } if (FSRecords.weHaveContentHashes) { return getMirrorWithContentHash(originalFile, originalAttributes); } final String mirrorName = originalFile.getName() + "." + Integer.toHexString(originalFile.getPath().hashCode()); final File mirrorFile = new File(folderPath, mirrorName); final FileAttributes mirrorAttributes = FileSystemUtil.getAttributes(mirrorFile); return mirrorDiffers(originalAttributes, mirrorAttributes, false) ? copyToMirror(originalFile, mirrorFile) : mirrorFile; }
private static void cleanupDeleteOnExitHookList() throws Exception { // try to reduce file set retained by java.io.DeleteOnExitHook List<String> list; synchronized (DELETE_ON_EXIT_HOOK_CLASS) { if (DELETE_ON_EXIT_HOOK_DOT_FILES.isEmpty()) { return; } list = DELETE_ON_EXIT_HOOK_DOT_FILES .stream() .filter(p -> p instanceof String) .map(p -> (String) p) .collect(Collectors.toList()); } for (int i = list.size() - 1; i >= 0; i--) { String path = list.get(i); if (FileSystemUtil.getAttributes(path) == null || new File(path).delete()) { synchronized (DELETE_ON_EXIT_HOOK_CLASS) { DELETE_ON_EXIT_HOOK_DOT_FILES.remove(path); } } } }
private File getMirrorFile(@Nonnull File originalFile) { if (!myFileSystem.isMakeCopyOfJar(originalFile)) return originalFile; final FileAttributes originalAttributes = FileSystemUtil.getAttributes(originalFile); if (originalAttributes == null) return originalFile; final String folderPath = getJarsDir(); if (!new File(folderPath).exists() && !new File(folderPath).mkdirs()) { return originalFile; } if (FSRecords.weHaveContentHashes) { return getMirrorWithContentHash(originalFile, originalAttributes); } final String mirrorName = originalFile.getName() + "." + Integer.toHexString(originalFile.getPath().hashCode()); final File mirrorFile = new File(folderPath, mirrorName); final FileAttributes mirrorAttributes = FileSystemUtil.getAttributes(mirrorFile); return mirrorDiffers(originalAttributes, mirrorAttributes, false) ? copyToMirror(originalFile, mirrorFile) : mirrorFile; }
@Nonnull private FileAccessorCache.Handle<ArchiveFile> getZipFileHandle() throws IOException { FileAccessorCache.Handle<ArchiveFile> handle = ourZipFileFileAccessorCache.get(this); if (getFile() == getFileToUse()) { // files are canonicalized // IDEA-148458, http://bugs.java.com/view_bug.do?bug_id=4425695, JVM crashes on use of opened ZipFile after it was updated // Reopen file if the file has been changed FileAttributes attributes = FileSystemUtil.getAttributes(getCanonicalPathToZip()); if (attributes == null) { throw new FileNotFoundException(getCanonicalPathToZip()); } if (attributes.lastModified == myFileStamp && attributes.length == myFileLength) return handle; // Note that zip_util.c#ZIP_Get_From_Cache will allow us to have duplicated ZipFile instances without a problem removeZipHandlerFromCache(); handle.release(); handle = ourZipFileFileAccessorCache.get(this); } return handle; }
/** * @return true if there were changed files reported for the specified target, _after_ the target compilation had been started */ public boolean hasUnprocessedChanges(@NotNull CompileContext context, @NotNull BuildTarget<?> target) { if (!myInitialScanPerformed.contains(target)) { return false; } final FilesDelta delta = myDeltas.get(target); if (delta == null) { return false; } final long targetBuildStart = context.getCompilationStartStamp(target); if (targetBuildStart <= 0L) { return false; } final CompileScope scope = context.getScope(); try { delta.lockData(); for (Set<File> files : delta.getSourcesToRecompile().values()) { for (File file : files) { if ((getEventRegistrationStamp(file) > targetBuildStart || FileSystemUtil.lastModified(file) > targetBuildStart) && scope.isAffected(target, file)) { return true; } } } } finally { delta.unlockData(); } return false; }
private static void extractFileAndAddToJar(final JarOutputStream jarOutputStream, final JarBasedArtifactRootDescriptor root, final String relativeOutputPath, final Set<String> writtenPaths) throws IOException { final long timestamp = FileSystemUtil.lastModified(root.getRootFile()); root.processEntries(new JarBasedArtifactRootDescriptor.EntryProcessor() { @Override public void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException { String pathInJar = addParentDirectories(jarOutputStream, writtenPaths, JpsArtifactPathUtil .appendToPath(relativeOutputPath, relativePath)); if (inputStream == null) { addDirectoryEntry(jarOutputStream, pathInJar + "/", writtenPaths); } else if (writtenPaths.add(pathInJar)) { ZipEntry newEntry = new ZipEntry(pathInJar); newEntry.setTime(timestamp); if (entry.getMethod() == ZipEntry.STORED) { newEntry.setMethod(ZipEntry.STORED); newEntry.setSize(entry.getSize()); newEntry.setCrc(entry.getCrc()); } jarOutputStream.putNextEntry(newEntry); FileUtil.copy(inputStream, jarOutputStream); jarOutputStream.closeEntry(); } } }); }
private static void traverseRecursively(CompileContext context, final BuildRootDescriptor rd, final CompilationRound round, final File file, @NotNull final Timestamps tsStorage, final boolean forceDirty, @Nullable Set<File> currentFiles, @Nullable FileFilter filter, @NotNull FSCache fsCache) throws IOException { BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex(); final File[] children = fsCache.getChildren(file); if (children != null) { // is directory if (children.length > 0 && rootIndex.isDirectoryAccepted(file, rd)) { for (File child : children) { traverseRecursively(context, rd, round, child, tsStorage, forceDirty, currentFiles, filter, fsCache); } } } else { // is file if (rootIndex.isFileAccepted(file, rd) && (filter == null || filter.accept(file))) { boolean markDirty = forceDirty; if (!markDirty) { markDirty = tsStorage.getStamp(file, rd.getTarget()) != FileSystemUtil.lastModified(file); } if (markDirty) { // if it is full project rebuild, all storages are already completely cleared; // so passing null because there is no need to access the storage to clear non-existing data final Timestamps marker = context.isProjectRebuild() ? null : tsStorage; context.getProjectDescriptor().fsState.markDirty(context, round, file, rd, marker, false); } if (currentFiles != null) { currentFiles.add(file); } } } }
@Nullable public FileAttributes getAttributes(@NotNull String relativePath) { if (relativePath.isEmpty()) { FileAttributes attributes = FileSystemUtil.getAttributes(myPath); return attributes != null ? new FileAttributes(true, false, false, false, DEFAULT_LENGTH, DEFAULT_TIMESTAMP, false) : null; } else { EntryInfo entry = getEntryInfo(relativePath); return entry != null ? new FileAttributes(entry.isDirectory, false, false, false, entry.length, entry.timestamp, false) : null; } }
@NotNull private static File convertToIOFileAndCheck(@NotNull final VirtualFile file) throws FileNotFoundException { final File ioFile = convertToIOFile(file); final FileAttributes attributes = FileSystemUtil.getAttributes(ioFile); if (attributes != null && !attributes.isFile()) { LOG.warn("not a file: " + ioFile + ", " + attributes); throw new FileNotFoundException("Not a file: " + ioFile); } return ioFile; }
@Override public FileAttributes getAttributes(@NotNull final VirtualFile file) { String path = normalize(file.getPath()); if (path == null) return null; if (file.getParent() == null && path.startsWith("//")) { return FAKE_ROOT_ATTRIBUTES; // fake Windows roots } return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(path)); }
@Nullable public static String getExecutablePath(@NotNull final String homeDirectory, @NotNull String name) { File binPath = new File(homeDirectory); File binDir = binPath.getParentFile(); if (binDir == null) return null; File runner = new File(binDir, name); if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath()); runner = new File(new File(binDir, "Scripts"), name); if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath()); runner = new File(new File(binDir.getParentFile(), "Scripts"), name); if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath()); runner = new File(new File(binDir.getParentFile(), "local"), name); if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath()); runner = new File(new File(new File(binDir.getParentFile(), "local"), "bin"), name); if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath()); // if interpreter is a symlink if (FileSystemUtil.isSymLink(homeDirectory)) { String resolvedPath = FileSystemUtil.resolveSymLink(homeDirectory); if (resolvedPath != null) { return getExecutablePath(resolvedPath, name); } } // Search in standard unix path runner = new File(new File("/usr", "bin"), name); if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath()); runner = new File(new File(new File("/usr", "local"), "bin"), name); if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath()); return null; }
private static void collectPythonInstallations(String pythonPath, Set<String> candidates) { VirtualFile rootVDir = LocalFileSystem.getInstance().findFileByPath(pythonPath); if (rootVDir != null) { if (rootVDir instanceof NewVirtualFile) { ((NewVirtualFile)rootVDir).markDirty(); } rootVDir.refresh(true, false); for (VirtualFile dir : rootVDir.getChildren()) { final String dirName = dir.getName().toLowerCase(); if (dir.isDirectory()) { if ("Current".equals(dirName) || dirName.startsWith("2") || dirName.startsWith("3")) { final VirtualFile binDir = dir.findChild("bin"); if (binDir != null && binDir.isDirectory()) { for (String name : POSSIBLE_BINARY_NAMES) { final VirtualFile child = binDir.findChild(name); if (child == null) continue; String path = child.getPath(); if (FileSystemUtil.isSymLink(path)) { path = FileSystemUtil.resolveSymLink(path); } if (path != null && !candidates.contains(path)) { candidates.add(path); break; } } } } } } } }
public static void collectUnixPythons(String path, Set<String> candidates) { VirtualFile rootDir = LocalFileSystem.getInstance().findFileByPath(path); if (rootDir != null) { if (rootDir instanceof NewVirtualFile) { ((NewVirtualFile)rootDir).markDirty(); } rootDir.refresh(true, false); VirtualFile[] suspects = rootDir.getChildren(); for (VirtualFile child : suspects) { if (!child.isDirectory()) { final String childName = child.getName().toLowerCase(); for (String name : NAMES) { if (childName.startsWith(name) || PYTHON_RE.matcher(childName).matches()) { String childPath = child.getPath(); if (FileSystemUtil.isSymLink(childPath)) { childPath = FileSystemUtil.resolveSymLink(childPath); } if (childPath != null && !childName.endsWith("-config") && !childName.startsWith("pythonw") && !childName.endsWith("m") && !candidates.contains(childPath)) { candidates.add(childPath); } break; } } } } } }
/** * @return true if marked something, false otherwise */ public boolean markAllUpToDate(CompileContext context, final BuildRootDescriptor rd, final Timestamps stamps) throws IOException { boolean marked = false; final FilesDelta delta = getDelta(rd.getTarget()); final Set<File> files = delta.clearRecompile(rd); if (files != null) { CompileScope scope = context.getScope(); final long compilationStartStamp = context.getCompilationStartStamp(); for (File file : files) { if (scope.isAffected(rd.getTarget(), file)) { final long currentFileStamp = FileSystemUtil.lastModified(file); if (!rd.isGenerated() && (currentFileStamp > compilationStartStamp || getEventRegistrationStamp(file) > compilationStartStamp)) { // if the file was modified after the compilation had started, // do not save the stamp considering file dirty if (Utils.IS_TEST_MODE) { LOG.info("Timestamp after compilation started; marking dirty again: " + file.getPath()); } delta.markRecompile(rd, file); } else { marked = true; stamps.saveStamp(file, rd.getTarget(), currentFileStamp); } } else { if (Utils.IS_TEST_MODE) { LOG.info("Not affected by compile scope; marking dirty again: " + file.getPath()); } delta.markRecompile(rd, file); } } } return marked; }
private static void traverseRecursively(CompileContext context, final BuildRootDescriptor rd, final File file, @NotNull final Timestamps tsStorage, final boolean forceDirty, @Nullable Set<File> currentFiles, @Nullable FileFilter filter, @NotNull FSCache fsCache) throws IOException { BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex(); final File[] children = fsCache.getChildren(file); if (children != null) { // is directory if (children.length > 0 && rootIndex.isDirectoryAccepted(file, rd)) { for (File child : children) { traverseRecursively(context, rd, child, tsStorage, forceDirty, currentFiles, filter, fsCache); } } } else { // is file if (rootIndex.isFileAccepted(file, rd) && (filter == null || filter.accept(file))) { boolean markDirty = forceDirty; if (!markDirty) { markDirty = tsStorage.getStamp(file, rd.getTarget()) != FileSystemUtil.lastModified(file); } if (markDirty) { // if it is full project rebuild, all storages are already completely cleared; // so passing null because there is no need to access the storage to clear non-existing data final Timestamps marker = context.isProjectRebuild() ? null : tsStorage; context.getProjectDescriptor().fsState.markDirty(context, file, rd, marker, false); } if (currentFiles != null) { currentFiles.add(file); } } } }
@Override public File getMirrorFile(@NotNull File originalFile) { if (!myFileSystem.isMakeCopyOfJar(originalFile)) return originalFile; final FileAttributes originalAttributes = FileSystemUtil.getAttributes(originalFile); if (originalAttributes == null) return originalFile; final String folderPath = getJarsDir(); if (!new File(folderPath).exists() && !new File(folderPath).mkdirs()) { return originalFile; } if (FSRecords.weHaveContentHashes) { return getMirrorWithContentHash(originalFile, originalAttributes); } final String mirrorName = originalFile.getName() + "." + Integer.toHexString(originalFile.getPath().hashCode()); final File mirrorFile = new File(folderPath, mirrorName); final FileAttributes mirrorAttributes = FileSystemUtil.getAttributes(mirrorFile); if (mirrorAttributes == null || originalAttributes.length != mirrorAttributes.length || Math.abs(originalAttributes.lastModified - mirrorAttributes.lastModified) > FS_TIME_RESOLUTION) { return copyToMirror(originalFile, mirrorFile); } return mirrorFile; }
@NotNull @Override protected String getDeploymentName(DeploymentModel deployment, File source) throws Exception { String path = source.getAbsolutePath(); String deploymentName = source.isDirectory() || path.endsWith(".jar") ? path : FileUtil.getNameWithoutExtension(path); if (FileSystemUtil.isSymLink(deploymentName)) { String resolvedPath = FileSystemUtil.resolveSymLink(deploymentName); if (resolvedPath != null) { return resolvedPath; } } return deploymentName; }
@Nullable @Override public FileAttributes getAttributes(@Nonnull VirtualFile file) { String path = normalize(file.getPath()); if (path == null) return null; if (file.getParent() == null && path.startsWith("//")) { return FAKE_ROOT_ATTRIBUTES; // fake Windows roots } return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(path)); }
@Nullable public FileAttributes getAttributes(@Nonnull String relativePath) { if (relativePath.isEmpty()) { FileAttributes attributes = FileSystemUtil.getAttributes(myPath); return attributes != null ? new FileAttributes(true, false, false, false, DEFAULT_LENGTH, DEFAULT_TIMESTAMP, false) : null; } else { EntryInfo entry = getEntryInfo(relativePath); return entry != null ? new FileAttributes(entry.isDirectory, false, false, false, entry.length, entry.timestamp, false) : null; } }
@Nonnull private static File convertToIOFileAndCheck(@Nonnull final VirtualFile file) throws FileNotFoundException { final File ioFile = convertToIOFile(file); final FileAttributes attributes = FileSystemUtil.getAttributes(ioFile); if (attributes != null && !attributes.isFile()) { LOG.warn("not a file: " + ioFile + ", " + attributes); throw new FileNotFoundException("Not a file: " + ioFile); } return ioFile; }
@Override public void moveFile(Object requestor, @Nonnull final VirtualFile file, @Nonnull final VirtualFile newParent) throws IOException { String name = file.getName(); if (!file.exists()) { throw new IOException(VfsBundle.message("vfs.file.not.exist.error", file.getPath())); } if (file.getParent() == null) { throw new IOException(VfsBundle.message("cannot.rename.root.directory", file.getPath())); } if (!newParent.exists() || !newParent.isDirectory()) { throw new IOException(VfsBundle.message("vfs.target.not.directory.error", newParent.getPath())); } if (newParent.findChild(name) != null) { throw new IOException(VfsBundle.message("vfs.target.already.exists.error", newParent.getPath() + "/" + name)); } File ioFile = convertToIOFile(file); if (FileSystemUtil.getAttributes(ioFile) == null) { throw new FileNotFoundException(VfsBundle.message("file.not.exist.error", ioFile.getPath())); } File ioParent = convertToIOFile(newParent); if (!ioParent.isDirectory()) { throw new IOException(VfsBundle.message("target.not.directory.error", ioParent.getPath())); } File ioTarget = new File(ioParent, name); if (ioTarget.exists()) { throw new IOException(VfsBundle.message("target.already.exists.error", ioTarget.getPath())); } if (!auxMove(file, newParent)) { if (!ioFile.renameTo(ioTarget)) { throw new IOException(VfsBundle.message("move.failed.error", ioFile.getPath(), ioParent.getPath())); } } auxNotifyCompleted(handler -> handler.move(file, newParent)); }
@Override public FileAttributes getAttributes(@Nonnull final VirtualFile file) { String path = normalize(file.getPath()); if (path == null) return null; if (file.getParent() == null && path.startsWith("//")) { return FAKE_ROOT_ATTRIBUTES; // fake Windows roots } return FileSystemUtil.getAttributes(FileUtil.toSystemDependentName(path)); }
private static Map<String, String> resolvePaths(Collection<String> recursiveRoots, Collection<String> flatRoots) { Map<String, String> result = ContainerUtil.newConcurrentMap(); List<String> roots = ContainerUtil.concat(Arrays.asList(recursiveRoots, flatRoots)); JobLauncher.getInstance().invokeConcurrentlyUnderProgress(roots, null, false, false, root -> { ContainerUtil.putIfNotNull(root, FileSystemUtil.resolveSymLink(root), result); return true; }); return result; }
@Override protected ArchiveFile createAccessor(ZipHandler key) throws IOException { final String canonicalPathToZip = key.getCanonicalPathToZip(); FileAttributes attributes = FileSystemUtil.getAttributes(canonicalPathToZip); key.myFileStamp = attributes != null ? attributes.lastModified : DEFAULT_TIMESTAMP; key.myFileLength = attributes != null ? attributes.length : DEFAULT_LENGTH; return key.createArchiveFile(canonicalPathToZip); }
/** * @return true if marked something, false otherwise */ public boolean markAllUpToDate(CompileContext context, final BuildRootDescriptor rd, final Timestamps stamps) throws IOException { boolean marked = false; final BuildTarget<?> target = rd.getTarget(); final FilesDelta delta = getDelta(target); final long targetBuildStartStamp = context.getCompilationStartStamp(target); // prevent modifications to the data structure from external FS events delta.lockData(); try { final Set<File> files = delta.clearRecompile(rd); if (files != null) { CompileScope scope = context.getScope(); for (File file : files) { if (scope.isAffected(target, file)) { final long currentFileStamp = FileSystemUtil.lastModified(file); if (!rd.isGenerated() && (currentFileStamp > targetBuildStartStamp || getEventRegistrationStamp(file) > targetBuildStartStamp)) { // if the file was modified after the compilation had started, // do not save the stamp considering file dirty // Important! // Event registration stamp check is essential for the files that were actually changed _before_ targetBuildStart, // but corresponding change event was received and processed _after_ targetBuildStart if (Utils.IS_TEST_MODE) { LOG.info("Timestamp after compilation started; marking dirty again: " + file.getPath()); } delta.markRecompile(rd, file); } else { marked = true; stamps.saveStamp(file, target, currentFileStamp); } } else { if (Utils.IS_TEST_MODE) { LOG.info("Not affected by compile scope; marking dirty again: " + file.getPath()); } delta.markRecompile(rd, file); } } } return marked; } finally { delta.unlockData(); } }
@Override public String resolveSymLink(@NotNull VirtualFile file) { return FileSystemUtil.resolveSymLink(file.getPath()); }
@Override public void moveFile(Object requestor, @NotNull final VirtualFile file, @NotNull final VirtualFile newParent) throws IOException { String name = file.getName(); if (!file.exists()) { throw new IOException(VfsBundle.message("vfs.file.not.exist.error", file.getPath())); } if (file.getParent() == null) { throw new IOException(VfsBundle.message("cannot.rename.root.directory", file.getPath())); } if (!newParent.exists() || !newParent.isDirectory()) { throw new IOException(VfsBundle.message("vfs.target.not.directory.error", newParent.getPath())); } if (newParent.findChild(name) != null) { throw new IOException(VfsBundle.message("vfs.target.already.exists.error", newParent.getPath() + "/" + name)); } File ioFile = convertToIOFile(file); if (FileSystemUtil.getAttributes(ioFile) == null) { throw new FileNotFoundException(VfsBundle.message("file.not.exist.error", ioFile.getPath())); } File ioParent = convertToIOFile(newParent); if (!ioParent.isDirectory()) { throw new IOException(VfsBundle.message("target.not.directory.error", ioParent.getPath())); } File ioTarget = new File(ioParent, name); if (ioTarget.exists()) { throw new IOException(VfsBundle.message("target.already.exists.error", ioTarget.getPath())); } if (!auxMove(file, newParent)) { if (!ioFile.renameTo(ioTarget)) { throw new IOException(VfsBundle.message("move.failed.error", ioFile.getPath(), ioParent.getPath())); } } auxNotifyCompleted(new ThrowableConsumer<LocalFileOperationsHandler, IOException>() { @Override public void consume(LocalFileOperationsHandler handler) throws IOException { handler.move(file, newParent); } }); }
@Override public String resolveSymLink(@Nonnull VirtualFile file) { return FileSystemUtil.resolveSymLink(file.getPath()); }