From 47ec7fd28c3b813aad03a42e7082a2b23e9b50c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Spo=CC=88nemann?= Date: Tue, 7 Jun 2016 17:33:15 +0200 Subject: [PATCH] Created splitting project, implemented project finder --- splitting/.classpath | 6 + splitting/.project | 17 ++ .../.settings/org.eclipse.jdt.core.prefs | 11 ++ splitting/build.gradle | 29 ++++ splitting/settings.gradle | 0 .../eclipse/xtext/splitting/FindProjects.java | 162 ++++++++++++++++++ 6 files changed, 225 insertions(+) create mode 100644 splitting/.classpath create mode 100644 splitting/.project create mode 100644 splitting/.settings/org.eclipse.jdt.core.prefs create mode 100644 splitting/build.gradle create mode 100644 splitting/settings.gradle create mode 100644 splitting/src/org/eclipse/xtext/splitting/FindProjects.java diff --git a/splitting/.classpath b/splitting/.classpath new file mode 100644 index 000000000..fceb4801b --- /dev/null +++ b/splitting/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/splitting/.project b/splitting/.project new file mode 100644 index 000000000..255dd984a --- /dev/null +++ b/splitting/.project @@ -0,0 +1,17 @@ + + + splitting + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/splitting/.settings/org.eclipse.jdt.core.prefs b/splitting/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..3a2153707 --- /dev/null +++ b/splitting/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/splitting/build.gradle b/splitting/build.gradle new file mode 100644 index 000000000..1e8f89124 --- /dev/null +++ b/splitting/build.gradle @@ -0,0 +1,29 @@ +apply plugin: 'java' + +def splitDir = file("$buildDir/splitting") + +sourceSets.main.java.srcDirs = ['src'] + +def splittingPath = "$buildDir/splitting" +def allHistoryFiles = file(splittingPath + "/all-files.txt") +def allProjects = file(splittingPath + "/all-projects.txt") +def unmappedPaths = file(splittingPath + "/unmapped-paths.txt") + +task listFiles(type: Exec) { + outputs.file allHistoryFiles + workingDir '..' + commandLine 'git', 'log', '--pretty=format:', '--name-only', '--diff-filter=A' + doFirst { + new File(allHistoryFiles.parent).mkdirs() + standardOutput = new FileOutputStream(allHistoryFiles) + } +} + +task findProjects(type: JavaExec) { + dependsOn(sourceSets.main.runtimeClasspath, listFiles) + inputs.file allHistoryFiles + outputs.files allProjects, unmappedPaths + classpath = sourceSets.main.runtimeClasspath.filter{it.exists()} + main = "org.eclipse.xtext.splitting.FindProjects" + args splittingPath +} diff --git a/splitting/settings.gradle b/splitting/settings.gradle new file mode 100644 index 000000000..e69de29bb diff --git a/splitting/src/org/eclipse/xtext/splitting/FindProjects.java b/splitting/src/org/eclipse/xtext/splitting/FindProjects.java new file mode 100644 index 000000000..f3e293e9c --- /dev/null +++ b/splitting/src/org/eclipse/xtext/splitting/FindProjects.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.xtext.splitting; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class FindProjects { + + public static final String ALL_FILES = "all-files.txt"; + public static final String ALL_PROJECTS = "all-projects.txt"; + public static final String UNMAPPED_PATHS = "unmapped-paths.txt"; + + public static void main(String[] args) { + if (args.length != 1) { + System.err.println("Expected file list as argument."); + return; + } + String workingDir = args[0]; + try { + final Directory root = new Directory(".", null); + try (BufferedReader reader = new BufferedReader(new FileReader(workingDir + "/" + ALL_FILES))) { + // Gather all paths in a directory structure + String line; + while ((line = reader.readLine()) != null) { + String[] segments = line.split("/"); + DirectoryEntry current = root; + for (int i = 0; i < segments.length; i++) { + String segment = segments[i].replaceAll("\"|\\\\.", ""); + if (!segment.isEmpty() && current instanceof Directory) { + Directory currentDir = (Directory) current; + if (currentDir.entries.containsKey(segment)) + current = currentDir.entries.get(segment); + else { + DirectoryEntry newEntry; + if (i == segments.length - 1) + newEntry = new DirectoryEntry(segment, currentDir); + else + newEntry = new Directory(segment, currentDir); + currentDir.entries.put(segment, newEntry); + current = newEntry; + } + } + } + } + } + + // Find the projects and unmapped paths that are relevant for the repository history + final List projects = new ArrayList<>(); + final List otherPaths = new ArrayList<>(); + findProjects(root, projects, otherPaths, false); + + // Write the collected projects into a file + Collections.sort(projects); + try (FileWriter writer = new FileWriter(workingDir + "/" + ALL_PROJECTS)) { + for (Directory project : projects) { + writer.write(project.toString()); + writer.write('\n'); + } + } + + // Write the unmapped paths into another file + Collections.sort(otherPaths); + try (FileWriter writer = new FileWriter(workingDir + "/" + UNMAPPED_PATHS)) { + for (DirectoryEntry path : otherPaths) { + writer.write(path.toString()); + writer.write('\n'); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static boolean findProjects(Directory dir, List projects, List otherPaths, boolean skipOtherPaths) { + boolean containsProject = dir.parent != null && dir.entries.values().stream().anyMatch((e) -> e.name.equals(".project")); + if (containsProject) { + projects.add(dir); + skipOtherPaths = true; + } + Set subDirsWithProjects = new HashSet<>(); + for (DirectoryEntry entry : dir.entries.values()) { + if (entry instanceof Directory) { + Directory subDir = (Directory) entry; + if (findProjects(subDir, projects, otherPaths, skipOtherPaths)) + subDirsWithProjects.add(subDir); + } + } + if (!skipOtherPaths && !subDirsWithProjects.isEmpty()) { + for (DirectoryEntry entry : dir.entries.values()) { + if (!subDirsWithProjects.contains(entry)) + otherPaths.add(entry); + } + } + return containsProject || !subDirsWithProjects.isEmpty(); + } + + private static class DirectoryEntry implements Comparable { + final String name; + final Directory parent; + + DirectoryEntry(String name, Directory parent) { + this.name = name; + this.parent = parent; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Directory) { + Directory other = (Directory) obj; + return this.parent == other.parent && this.name.equals(other.name); + } + return false; + } + + @Override + public int hashCode() { + if (parent == null) + return name.hashCode(); + else + return parent.hashCode() * 7 + name.hashCode(); + } + + @Override + public int compareTo(DirectoryEntry other) { + if (this.parent == other.parent) + return this.name.compareTo(other.name); + else + return this.toString().compareTo(other.toString()); + } + + @Override + public String toString() { + if (parent == null || parent.parent == null) + return name; + else + return parent.toString() + "/" + name; + } + } + + private static class Directory extends DirectoryEntry { + final Map entries = new HashMap<>(); + + Directory(String name, Directory parent) { + super(name, parent); + } + } + +}