List<DirectoryGroup> (ConfigDirsSearchResult result, @Nullable ProgressIndicator indicator) { List<Path> configs = result.getPaths(); List<DirectoryGroup> groups = new ArrayList<>(configs.size()); String productInfoFileName = SystemInfo.isMac ? ApplicationEx.PRODUCT_INFO_FILE_NAME_MAC : ApplicationEx.PRODUCT_INFO_FILE_NAME; for (Path config : configs) { List<Path> directories = result.findRelatedDirectories(config, myBestBefore != 0); if (directories.isEmpty()) continue; String nameAndVersion = result.getNameAndVersion(config); long lastUpdated = 0, size = 0; int entriesToDelete = 0; boolean isInstalled = false; for (Path directory : directories) { CollectingVisitor visitor = new CollectingVisitor(indicator); try { Files.walkFileTree(directory, visitor); Path homeDir = Path.of(Files.readString(directory.resolve(ApplicationEx.LOCATOR_FILE_NAME))); if (Files.exists(homeDir)) { try (Reader reader = Files.newBufferedReader(homeDir.resolve(productInfoFileName)); JsonParser parser = new JsonFactory().createParser(reader)) { if (nameAndVersion.equals(JacksonUtil.readSingleField(parser, "dataDirectoryName"))) { isInstalled = true; } } catch (NoSuchFileException e) { myLogger.debug(e); isInstalled = true; // the file could be missing from a self-built installation } } } catch (IOException | InvalidPathException e) { myLogger.debug(e); } lastUpdated = Math.max(lastUpdated, visitor.lastUpdated); size += visitor.size; entriesToDelete += visitor.entriesToDelete; } if (myBestBefore == 0 || lastUpdated <= myBestBefore) { groups.add(new DirectoryGroup(nameAndVersion, directories, lastUpdated, size, entriesToDelete, isInstalled)); } } return groups; }