Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ task exportBlueFiles {
}
}

jar {
manifest {
attributes(
'Main-Class': 'blue.contract.packager.utils.BluePreprocessor'
)
}

duplicatesStrategy = DuplicatesStrategy.EXCLUDE

zip64 = true

from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}

exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
}

test {
useJUnitPlatform()
reports {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
package blue.contract.packager.graphbuilder;

import blue.contract.packager.BluePackageExporter;
import blue.contract.packager.model.DependencyGraph;
import blue.language.model.Node;

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;

import static blue.contract.packager.BluePackageExporter.EXTENDS_FILE_NAME;
import static blue.language.utils.UncheckedObjectMapper.YAML_MAPPER;

public class FileSystemDependencyGraphBuilder implements DependencyGraphBuilder {
private final Path rootPath;

public FileSystemDependencyGraphBuilder(Path rootPath) {
private final Set<String> ignorePatterns;

public FileSystemDependencyGraphBuilder(Path rootPath, Set<String> ignorePatterns) {
this.rootPath = rootPath;
this.ignorePatterns = ignorePatterns;
}

public FileSystemDependencyGraphBuilder(Path rootPath) {
this(rootPath, new HashSet<>());
}

@Override
Expand All @@ -29,18 +39,38 @@ public DependencyGraph buildDependencyGraph(String rootDir) throws IOException {

try (DirectoryStream<Path> stream = Files.newDirectoryStream(fullPath)) {
for (Path path : stream) {
if (Files.isDirectory(path)) {
if (Files.isDirectory(path) && !shouldIgnore(path)) {
String dirName = path.getFileName().toString();
String dependency = readDependency(path.resolve(EXTENDS_FILE_NAME));
graph.addDirectory(dirName, dependency);
processFiles(path, dirName, graph);

// Check if this directory contains any .blue files
if (containsBlueFiles(path)) {
Path extendsFile = path.resolve(EXTENDS_FILE_NAME);
String dependency = Files.exists(extendsFile) ?
readDependency(extendsFile) :
BluePackageExporter.ROOT_DEPENDENCY;

graph.addDirectory(dirName, dependency);
processFiles(path, dirName, graph);
}
}
}
}

return graph;
}

private boolean shouldIgnore(Path path) {
String pathName = path.getFileName().toString();
return ignorePatterns.stream().anyMatch(pattern ->
pathName.matches(pattern.replace("*", ".*").replace("?", ".?")));
}

private boolean containsBlueFiles(Path directory) throws IOException {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory, "*.blue")) {
return stream.iterator().hasNext();
}
}

private String readDependency(Path path) throws IOException {
if (!Files.exists(path)) {
throw new IOException("Dependency file not found: " + path);
Expand Down
15 changes: 14 additions & 1 deletion src/main/java/blue/contract/packager/model/BluePackage.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,20 @@ public Node getPackageContent() {
}

public Map<String, String> getMappings() {
return new HashMap<>(mappings);
// Extract mappings from packageContent if they're not already in the mappings map
if (mappings.isEmpty() && packageContent != null) {
Node mappingsNode = packageContent.getItems()
.get(1) // Second item contains mappings
.getProperties()
.get("mappings");

if (mappingsNode != null && mappingsNode.getProperties() != null) {
mappingsNode.getProperties().forEach((key, valueNode) -> {
mappings.put(key, valueNode.getValue().toString());
});
}
}
return mappings;
}

public Map<String, Node> getPreprocessedNodes() {
Expand Down
170 changes: 170 additions & 0 deletions src/main/java/blue/contract/packager/utils/BluePreprocessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package blue.contract.packager.utils;

import blue.contract.packager.BluePackageExporter;
import blue.contract.packager.graphbuilder.FileSystemDependencyGraphBuilder;
import blue.contract.packager.model.BluePackage;
import blue.language.model.Node;
import blue.language.utils.BlueIdCalculator;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Set;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Arrays;

import static blue.language.utils.UncheckedObjectMapper.YAML_MAPPER;

public class BluePreprocessor {
public static void main(String[] args) {
if (args.length < 2 || args[0].equals("-h") || args[0].equals("--help")) {
printUsage();
System.exit(args.length < 2 ? 1 : 0);
}

try {
String inputDir = args[0];
String outputDir = args[1];
Set<String> ignorePatterns = new HashSet<>();
boolean verbose = false;

// Parse additional arguments
for (int i = 2; i < args.length; i++) {
if (args[i].equals("--ignore") && i + 1 < args.length) {
String[] patterns = args[i + 1].split(",");
ignorePatterns.addAll(Arrays.asList(patterns));
i++; // Skip the next argument as we've already processed it
} else if (args[i].equals("--verbose")) {
verbose = true;
}
}

// Add default ignore patterns
ignorePatterns.addAll(Arrays.asList(
".git",
".github",
"node_modules",
"build",
".gradle",
"blue-preprocessed"
));

if (verbose) {
System.out.println("Input directory: " + inputDir);
System.out.println("Output directory: " + outputDir);
System.out.println("Ignored patterns: " + String.join(", ", ignorePatterns));
}

Path inputPath = Paths.get(inputDir);
Path outputPath = Paths.get(outputDir);

if (!Files.exists(inputPath)) {
System.err.println("Input directory does not exist: " + inputPath);
System.exit(1);
}

// Create output directory if it doesn't exist
Files.createDirectories(outputPath);

// Create builder with ignore patterns
FileSystemDependencyGraphBuilder builder = new FileSystemDependencyGraphBuilder(inputPath, ignorePatterns);
List<BluePackage> packages = BluePackageExporter.exportPackages("", builder);

writePreprocessedFiles(packages, outputPath);

System.out.println("Preprocessing completed successfully.");
System.out.println("Preprocessed files written to: " + outputPath.toAbsolutePath());

} catch (Exception e) {
System.err.println("Error during preprocessing: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
}

private static void printUsage() {
System.out.println("Usage: blue-preprocessor <input-dir> <output-dir> [options]");
System.out.println("Options:");
System.out.println(" --ignore <patterns> Comma-separated list of directory patterns to ignore");
System.out.println(" --verbose Print detailed processing information");
System.out.println(" --help Show this help message");
System.out.println("\nDefault ignored patterns: .git, .github, node_modules, build, .gradle");
}

private static void writePreprocessedFiles(List<BluePackage> packages, Path outputPath) throws Exception {
System.out.println("Writing preprocessed files...");

// Write package-specific files
for (BluePackage pkg : packages) {
String pkgName = pkg.getDirectoryName();
System.out.println("Processing package: " + pkgName);

Path packageDir = outputPath.resolve(pkgName);
Files.createDirectories(packageDir);

// Write preprocessed nodes
for (Map.Entry<String, Node> entry : pkg.getPreprocessedNodes().entrySet()) {
String fileName = entry.getKey() + ".blue";
Path filePath = packageDir.resolve(fileName);
String yaml = YAML_MAPPER.writeValueAsString(entry.getValue());
Files.writeString(filePath, yaml);
//System.out.println(" - Wrote: " + fileName);
}

// Write package.blue
Path packageBluePath = packageDir.resolve("package.blue");
String packageBlueYaml = YAML_MAPPER.writeValueAsString(pkg.getPackageContent());
Files.writeString(packageBluePath, packageBlueYaml);
//System.out.println(" - Wrote: package.blue");

// Extract and write package-specific blue-ids.yaml
Map<String, String> packageMappings = extractMappingsFromPackage(pkg);
if (!packageMappings.isEmpty()) {
Path packageBlueIdsPath = packageDir.resolve("blue-ids.yaml");
String blueIdsYaml = YAML_MAPPER.writeValueAsString(packageMappings);
Files.writeString(packageBlueIdsPath, blueIdsYaml);
//System.out.println(" - Wrote: blue-ids.yaml with " + packageMappings.size() + " mappings");
}
}

// Write root blue-ids.yaml with package blueIds
Map<String, String> packageBlueIds = new HashMap<>();
for (BluePackage pkg : packages) {
String packageBlueId = extractPackageBlueId(pkg);
if (packageBlueId != null) {
packageBlueIds.put(pkg.getDirectoryName(), packageBlueId);
}
}

Path rootBlueIdsPath = outputPath.resolve("blue-ids.yaml");
String rootBlueIdsYaml = YAML_MAPPER.writeValueAsString(packageBlueIds);
Files.writeString(rootBlueIdsPath, rootBlueIdsYaml);
System.out.println("Wrote root blue-ids.yaml with " + packageBlueIds.size() + " package IDs");
}

private static String extractPackageBlueId(BluePackage pkg) {
Node packageContent = pkg.getPackageContent();
return BlueIdCalculator.calculateBlueId(packageContent);
}

private static Map<String, String> extractMappingsFromPackage(BluePackage pkg) {
Node packageContent = pkg.getPackageContent();
if (packageContent != null && packageContent.getItems() != null && packageContent.getItems().size() > 1) {
Node mappingsContainer = packageContent.getItems().get(1);
if (mappingsContainer.getProperties() != null) {
Node mappingsNode = mappingsContainer.getProperties().get("mappings");
if (mappingsNode != null && mappingsNode.getProperties() != null) {
Map<String, String> mappings = new HashMap<>();
mappingsNode.getProperties().forEach((key, valueNode) -> {
mappings.put(key, valueNode.getValue().toString());
});
return mappings;
}
}
}
return new HashMap<>();
}
}
Loading