From 7c12a48684b3483cfb2f4a726321ceed887a5261 Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Mon, 30 Apr 2018 12:55:25 +0200 Subject: [PATCH] Generate import mappings. Instead of generating a list of import paths based on the difnames of the imported protos, generate maps to the package local names. This is needed to handle the case of packages containing a proto with the same name. An example here is the annotation.proto in this module. Fixes #633 --- protoc-gen-swagger/defs.bzl | 47 ++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/protoc-gen-swagger/defs.bzl b/protoc-gen-swagger/defs.bzl index 35a94226821..ada033139c6 100644 --- a/protoc-gen-swagger/defs.bzl +++ b/protoc-gen-swagger/defs.bzl @@ -1,39 +1,57 @@ """Generated an open-api spec for a grpc api spec. -Reads the the api spec in protobuf format and generate an open-api spec. +Reads the the api spec in protobuf format and generate an open-api spec. Optionally applies settings from the grpc-service configuration. """ -def _collect_includes(srcs): - includes = ["."] + +def _collect_includes(gen_dir, srcs): + """Build an include path mapping. + + It is important to not just collect unique dirnames, to also support + proto files of the same name from different packages. + + The implementation below is similar to what bazel does in its + ProtoCompileActionBuilder.java + """ + includes = [] for src in srcs: - include = src.dirname - if include and not include in includes: - includes += [include] + ref_path = src.path + + if ref_path.startswith(gen_dir): + ref_path = ref_path[len(gen_dir):].lstrip("/") + + if src.owner.workspace_root: + workspace_root = src.owner.workspace_root + ref_path = ref_path[len(workspace_root):].lstrip("/") + + include = ref_path + "=" + src.path + if include not in includes: + includes.append(include) return includes -def _run_proto_gen_swagger(direct_proto_srcs, transitive_proto_srcs, actions, protoc, protoc_gen_swagger, grpc_api_configuration): +def _run_proto_gen_swagger(ctx, direct_proto_srcs, transitive_proto_srcs, actions, protoc, protoc_gen_swagger, grpc_api_configuration): swagger_files = [] for proto in direct_proto_srcs: swagger_file = actions.declare_file( "%s.swagger.json" % proto.basename[:-len(".proto")], sibling = proto, ) - + inputs = direct_proto_srcs + transitive_proto_srcs + [protoc_gen_swagger] - + options=["logtostderr=true"] if grpc_api_configuration: options.append("grpc_api_configuration=%s" % grpc_api_configuration.path) inputs.append(grpc_api_configuration) + includes = _collect_includes(ctx.genfiles_dir.path, direct_proto_srcs + transitive_proto_srcs) + args = actions.args() args.add("--plugin=%s" % protoc_gen_swagger.path) - args.add("--swagger_out=%s:%s" % (",".join(options), swagger_file.dirname)) - args.add("-Iexternal/com_google_protobuf/src") - args.add("-Iexternal/com_github_googleapis_googleapis") - args.add(["-I%s" % include for include in _collect_includes(direct_proto_srcs + transitive_proto_srcs)]) - args.add(proto.basename) + args.add("--swagger_out=%s:%s" % (",".join(options), ctx.bin_dir.path)) + args.add(["-I%s" % include for include in includes]) + args.add(proto.path) actions.run( executable = protoc, @@ -53,6 +71,7 @@ def _proto_gen_swagger_impl(ctx): return struct( files=depset( _run_proto_gen_swagger( + ctx, direct_proto_srcs = proto.direct_sources, transitive_proto_srcs = ctx.files._well_known_protos + proto.transitive_sources.to_list(), actions = ctx.actions,