-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Marco Hunsicker
committed
Apr 4, 2018
1 parent
a2ecfdc
commit c0d0a92
Showing
13 changed files
with
370 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
package org.antlr.bazel; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.nio.file.FileVisitResult; | ||
import java.nio.file.Files; | ||
import java.nio.file.LinkOption; | ||
import java.nio.file.Path; | ||
import java.nio.file.PathMatcher; | ||
import java.nio.file.Paths; | ||
import java.nio.file.SimpleFileVisitor; | ||
import java.nio.file.attribute.BasicFileAttributes; | ||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertFalse; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
|
||
/** | ||
* Fetches dependencies. | ||
* | ||
* @author Marco Hunsicker | ||
*/ | ||
class Dependencies | ||
{ | ||
private static final Map<Version, String[]> DEPENDENCIES = download(); | ||
|
||
/** | ||
* Returns the ANTLR 4 dependencies. | ||
* | ||
* @return the ANTLR 4 dependencies. | ||
*/ | ||
public static String[] antlr2() | ||
{ | ||
return DEPENDENCIES.get(Version.V2); | ||
} | ||
|
||
|
||
/** | ||
* Returns the ANTLR 3 dependencies. | ||
* | ||
* @return the ANTLR 3 dependencies. | ||
*/ | ||
public static String[] antlr3() | ||
{ | ||
return DEPENDENCIES.get(Version.V3); | ||
} | ||
|
||
|
||
/** | ||
* Returns the ANTLR 2 dependencies. | ||
* | ||
* @return the ANTLR 2 dependencies. | ||
*/ | ||
public static String[] antlr4() | ||
{ | ||
return DEPENDENCIES.get(Version.V4); | ||
} | ||
|
||
|
||
private static Map<Version, String[]> download() | ||
{ | ||
try | ||
{ | ||
// the Bazel workspace root we use for dependency loading | ||
Path workspace = Paths.get("src/it/resources/antlr/DownloadDependencies") | ||
.toRealPath(); | ||
assertTrue(Files.exists(workspace)); | ||
|
||
Path base = getBaseDirectory(workspace); | ||
|
||
Map<Version, String[]> deps = loadDependencies(base); | ||
|
||
// if short-circuiting did not work, fetch the dependencies | ||
if (deps.isEmpty()) | ||
{ | ||
fetchDependencies(workspace, base); | ||
deps = loadDependencies(base); | ||
} | ||
|
||
assertFalse(deps.isEmpty()); | ||
|
||
return deps; | ||
} | ||
catch (Exception ex) | ||
{ | ||
throw new IllegalStateException("Failed to load dependencies", ex); | ||
} | ||
} | ||
|
||
|
||
private static void fetchDependencies(Path workspace, Path base) throws Exception | ||
{ | ||
Process p = new ProcessBuilder().command("bazel", "fetch", "//...") | ||
.directory(Paths.get(".").toRealPath().toFile()) | ||
.inheritIO() | ||
.directory(workspace.toFile()) | ||
.start(); | ||
p.waitFor(); | ||
|
||
if (p.exitValue() != 0) | ||
{ | ||
// cleanup if something went wrong to make short-circuiting reliable | ||
Path external = base.resolve("external"); | ||
|
||
if (Files.exists(base)) | ||
{ | ||
Disk.delete(external); | ||
} | ||
} | ||
|
||
assertEquals(0, p.exitValue()); | ||
} | ||
|
||
|
||
private static Path getBaseDirectory(Path root) throws Exception | ||
{ | ||
Process p = new ProcessBuilder().command("bazel", "info", "output_base") | ||
.directory(Paths.get(".").toRealPath().toFile()) | ||
.redirectErrorStream(true) | ||
.directory(root.toFile()) | ||
.start(); | ||
|
||
try (BufferedReader reader = new BufferedReader( | ||
new InputStreamReader(p.getInputStream()))) | ||
{ | ||
StringBuilder buf = new StringBuilder(); | ||
String line = null; | ||
|
||
while ((line = reader.readLine()) != null) | ||
{ | ||
buf.append(line); | ||
} | ||
|
||
Path base = Paths.get(buf.toString()); | ||
assertTrue(Files.exists(base)); | ||
|
||
return base; | ||
} | ||
finally | ||
{ | ||
p.waitFor(); | ||
assertEquals(0, p.exitValue()); | ||
} | ||
} | ||
|
||
|
||
private static Map<Version, String[]> loadDependencies(final Path base) | ||
throws IOException | ||
{ | ||
final Collection<String> deps2 = new ArrayList<>(); | ||
final Collection<String> deps3 = new ArrayList<>(); | ||
final Collection<String> deps4 = new ArrayList<>(); | ||
|
||
Path external = base.resolve("external"); | ||
|
||
if (Files.exists(external)) | ||
{ | ||
Files.walkFileTree(external, new SimpleFileVisitor<Path>() | ||
{ | ||
PathMatcher archives = base.getFileSystem() | ||
.getPathMatcher("glob:**/*.jar"); | ||
PathMatcher antlr4 = base.getFileSystem() | ||
.getPathMatcher( | ||
"regex:.*(antlr4|antlr4-runtime|antlr-runtime|ST4|javax.json)-.*.jar"); | ||
PathMatcher antlr3 = base.getFileSystem() | ||
.getPathMatcher("regex:.*/(antlr-3|antlr-runtime|ST4).*.jar"); | ||
PathMatcher antlr2 = base.getFileSystem() | ||
.getPathMatcher("glob:**/antlr-2*.jar"); | ||
|
||
@Override | ||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) | ||
throws IOException | ||
{ | ||
if (archives.matches(file) | ||
&& Files.isRegularFile(file, LinkOption.NOFOLLOW_LINKS)) | ||
{ | ||
if (antlr4.matches(file)) | ||
{ | ||
deps4.add(file.toString()); | ||
} | ||
|
||
if (antlr3.matches(file)) | ||
{ | ||
deps3.add(file.toString()); | ||
} | ||
|
||
if (antlr2.matches(file)) | ||
{ | ||
deps2.add(file.toString()); | ||
} | ||
} | ||
|
||
return super.visitFile(file, attrs); | ||
} | ||
}); | ||
|
||
Map<Version, String[]> result = new HashMap<>(); | ||
result.put(Version.V2, deps2.toArray(new String[deps2.size()])); | ||
result.put(Version.V3, deps3.toArray(new String[deps3.size()])); | ||
result.put(Version.V4, deps4.toArray(new String[deps4.size()])); | ||
|
||
return result; | ||
} | ||
|
||
return Collections.emptyMap(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package org.antlr.bazel; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.CopyOption; | ||
import java.nio.file.FileVisitResult; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.SimpleFileVisitor; | ||
import java.nio.file.StandardCopyOption; | ||
import java.nio.file.attribute.BasicFileAttributes; | ||
|
||
|
||
/** | ||
* Disk helper. | ||
* | ||
* @author Marco Hunsicker | ||
*/ | ||
class Disk | ||
{ | ||
private static final CopyOption[] ATTRIBUTES = | ||
{ StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING }; | ||
|
||
/** Creates a new Disk object. */ | ||
private Disk() | ||
{ | ||
super(); | ||
} | ||
|
||
/** | ||
* Copies the given file or directory to the given destination. | ||
* | ||
* @param path the file or directory. | ||
* @param target the target. | ||
* @param options the options. | ||
* | ||
* @throws IOException if an I/O error occurred. | ||
*/ | ||
public static void copy(final Path path, final Path target, CopyOption... options) | ||
throws IOException | ||
{ | ||
final CopyOption[] opt = (options.length == 0) ? ATTRIBUTES : options; | ||
|
||
if (Files.isDirectory(path)) | ||
{ | ||
Files.walkFileTree(path, new SimpleFileVisitor<Path>() | ||
{ | ||
@Override | ||
public FileVisitResult preVisitDirectory(Path dir, | ||
BasicFileAttributes attrs) throws IOException | ||
{ | ||
Files.createDirectories( | ||
target.resolve(path.relativize(dir).toString())); | ||
|
||
return FileVisitResult.CONTINUE; | ||
} | ||
|
||
|
||
@Override | ||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) | ||
throws IOException | ||
{ | ||
Files.copy(file, | ||
target.resolve(path.relativize(file).toString()), | ||
opt); | ||
|
||
return FileVisitResult.CONTINUE; | ||
} | ||
}); | ||
} | ||
else | ||
{ | ||
Files.copy(path, target, opt); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Deletes the given file or directory. | ||
* | ||
* @param path the path. | ||
* | ||
* @throws IOException if an I/O error occurred. | ||
*/ | ||
public static void delete(Path path) throws IOException | ||
{ | ||
if (Files.isDirectory(path)) | ||
{ | ||
Files.walkFileTree(path, DeleteVisitor.INSTANCE); | ||
} | ||
else if (Files.exists(path)) | ||
{ | ||
Files.delete(path); | ||
} | ||
} | ||
|
||
private static class DeleteVisitor extends SimpleFileVisitor<Path> | ||
{ | ||
public static final DeleteVisitor INSTANCE = new DeleteVisitor(); | ||
|
||
@Override | ||
public FileVisitResult postVisitDirectory(Path dir, IOException cause) | ||
throws IOException | ||
{ | ||
Files.delete(dir); | ||
|
||
return FileVisitResult.CONTINUE; | ||
} | ||
|
||
|
||
@Override | ||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) | ||
throws IOException | ||
{ | ||
Files.delete(file); | ||
|
||
return FileVisitResult.CONTINUE; | ||
} | ||
} | ||
} |
Oops, something went wrong.