Skip to content

Commit

Permalink
Merge pull request #30687 from scrocquesel/gh-30685
Browse files Browse the repository at this point in the history
Allow to exclude/include proto files from dependencies
  • Loading branch information
cescoffier authored Feb 13, 2023
2 parents 7c4fa52 + d3c19c2 commit 2d4fe75
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 9 deletions.
18 changes: 18 additions & 0 deletions docs/src/main/asciidoc/grpc-getting-started.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,24 @@ The value of the property may be `none`, which is the default value, or a comma

NOTE: `option java_generic_services = true;` will automatically be removed from proto file containing it.

If the dependency contains a lot of proto files and you want to generate classes for only a subset of them, you can specify glob patterns per dependency. The path to match are relative to the path `src/main/resources` in the dependency.

For instance, having the following properties in your `application.properties`:

[source,properties]
----
quarkus.generate-code.grpc.scan-for-proto-includes."<groupId>\:<artifactId>"=foo/**,bar/**,banana/a-proto.proto
quarkus.generate-code.grpc.scan-for-proto-excludes."<groupId>\:<artifactId>"=foo/private/**,bar/another-proto.proto
----

will include:

* all files in the `foo/` directory and its subdirectories except for files in `foo/private/` and its subdirectories,
* all files in the `bar/` directory and its subdirectories except for `another-proto.proto`.
* `banana/a-proto.proto` file.

NOTE: `:` character in the property keys must be escaped.

== Different gRPC implementations / types

Another thing to take note as well is that Quarkus' gRPC support currently includes 3 different types of gRPC usage:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.quarkus.deployment.CodeGenProvider;
import io.quarkus.deployment.util.ProcessUtil;
import io.quarkus.maven.dependency.ResolvedDependency;
import io.quarkus.paths.PathFilter;
import io.quarkus.runtime.util.HashUtil;
import io.quarkus.utilities.JavaBinFinder;
import io.quarkus.utilities.OS;
Expand All @@ -47,6 +48,8 @@ public class GrpcCodeGen implements CodeGenProvider {
private static final String PROTOC_GROUPID = "com.google.protobuf";

private static final String SCAN_DEPENDENCIES_FOR_PROTO = "quarkus.generate-code.grpc.scan-for-proto";
private static final String SCAN_DEPENDENCIES_FOR_PROTO_INCLUDE_PATTERN = "quarkus.generate-code.grpc.scan-for-proto-include.\"%s\"";
private static final String SCAN_DEPENDENCIES_FOR_PROTO_EXCLUDE_PATTERN = "quarkus.generate-code.grpc.scan-for-proto-exclude.\"%s\"";
private static final String SCAN_FOR_IMPORTS = "quarkus.generate-code.grpc.scan-for-imports";

private static final String POST_PROCESS_SKIP = "quarkus.generate.code.grpc-post-processing.skip";
Expand Down Expand Up @@ -205,10 +208,18 @@ private Collection<Path> gatherProtosFromDependencies(Path workDir, Set<String>
ApplicationModel appModel = context.applicationModel();
List<Path> protoFilesFromDependencies = new ArrayList<>();
for (ResolvedDependency artifact : appModel.getRuntimeDependencies()) {
String packageId = String.format("%s:%s", artifact.getGroupId(), artifact.getArtifactId());
Collection<String> includes = properties
.getOptionalValues(String.format(SCAN_DEPENDENCIES_FOR_PROTO_INCLUDE_PATTERN, packageId), String.class)
.orElse(List.of());
Collection<String> excludes = properties
.getOptionalValues(String.format(SCAN_DEPENDENCIES_FOR_PROTO_EXCLUDE_PATTERN, packageId), String.class)
.orElse(List.of());

if (scanAll
|| dependenciesToScan.contains(
String.format("%s:%s", artifact.getGroupId(), artifact.getArtifactId()))) {
extractProtosFromArtifact(workDir, protoFilesFromDependencies, protoDirectories, artifact, true);
|| dependenciesToScan.contains(packageId)) {
extractProtosFromArtifact(workDir, protoFilesFromDependencies, protoDirectories, artifact, includes, excludes,
true);
}
}
return protoFilesFromDependencies;
Expand Down Expand Up @@ -244,17 +255,19 @@ private Collection<String> gatherDirectoriesWithImports(Path workDir, CodeGenCon
if (scanAll
|| dependenciesToScan.contains(
String.format("%s:%s", artifact.getGroupId(), artifact.getArtifactId()))) {
extractProtosFromArtifact(workDir, new ArrayList<>(), importDirectories, artifact, false);
extractProtosFromArtifact(workDir, new ArrayList<>(), importDirectories, artifact, List.of(),
List.of(), false);
}
}
return importDirectories;
}

private void extractProtosFromArtifact(Path workDir, Collection<Path> protoFiles,
Set<String> protoDirectories, ResolvedDependency artifact, boolean isDependency) throws CodeGenException {
Set<String> protoDirectories, ResolvedDependency artifact, Collection<String> filesToInclude,
Collection<String> filesToExclude, boolean isDependency) throws CodeGenException {

try {
artifact.getContentTree().walk(
artifact.getContentTree(new PathFilter(filesToInclude, filesToExclude)).walk(
pathVisit -> {
Path path = pathVisit.getPath();
if (Files.isRegularFile(path) && path.getFileName().toString().endsWith(PROTO)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.quarkus.paths.EmptyPathTree;
import io.quarkus.paths.MultiRootPathTree;
import io.quarkus.paths.PathCollection;
import io.quarkus.paths.PathFilter;
import io.quarkus.paths.PathTree;

public interface ResolvedDependency extends Dependency {
Expand All @@ -28,6 +29,10 @@ default ArtifactSources getSources() {
}

default PathTree getContentTree() {
return getContentTree(null);
}

default PathTree getContentTree(PathFilter pathFilter) {
final WorkspaceModule module = getWorkspaceModule();
final PathTree workspaceTree = module == null ? EmptyPathTree.getInstance() : module.getContentTree(getClassifier());
if (!workspaceTree.isEmpty()) {
Expand All @@ -39,12 +44,12 @@ default PathTree getContentTree() {
}
if (paths.isSinglePath()) {
final Path p = paths.getSinglePath();
return isJar() ? PathTree.ofDirectoryOrArchive(p) : PathTree.ofDirectoryOrFile(p);
return isJar() ? PathTree.ofDirectoryOrArchive(p, pathFilter) : PathTree.ofDirectoryOrFile(p, pathFilter);
}
final PathTree[] trees = new PathTree[paths.size()];
int i = 0;
for (Path p : paths) {
trees[i++] = PathTree.ofDirectoryOrArchive(p);
trees[i++] = PathTree.ofDirectoryOrArchive(p, pathFilter);
}
return new MultiRootPathTree(trees);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
public interface PathTree {

static PathTree ofDirectoryOrFile(Path p) {
return ofDirectoryOrFile(p, null);
}

static PathTree ofDirectoryOrFile(Path p, PathFilter filter) {
try {
final BasicFileAttributes fileAttributes = Files.readAttributes(p, BasicFileAttributes.class);
return fileAttributes.isDirectory() ? new DirectoryPathTree(p) : new FilePathTree(p);
return fileAttributes.isDirectory() ? new DirectoryPathTree(p, filter) : new FilePathTree(p, filter);
} catch (IOException e) {
throw new IllegalArgumentException(p + " does not exist", e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
quarkus.generate-code.grpc.scan-for-proto=io.quarkus:quarkus-integration-test-external-proto
quarkus.generate-code.grpc.scan-for-proto-include."io.quarkus\:quarkus-integration-test-external-proto"=dir/**,invalids/invalid2.proto
quarkus.generate-code.grpc.scan-for-proto-exclude."io.quarkus\:quarkus-integration-test-external-proto"=dir/invalid.proto,invalids/invalid2.proto

%vertx.quarkus.grpc.clients.hello.host=localhost
%vertx.quarkus.grpc.clients.hello.port=8081
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// not a proto file
syntax = "invalid";
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// not a proto file
syntax = "invalid";
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// not a proto file
syntax = "invalid";

0 comments on commit 2d4fe75

Please sign in to comment.