├── .bazelci └── presubmit.yml ├── .gitignore ├── AUTHORS ├── BUILD ├── CONTRIBUTING.md ├── CONTRIBUTORS ├── LICENSE.txt ├── README.md ├── WORKSPACE ├── generate_workspace.bzl ├── generate_workspace ├── BUILD └── src │ ├── main │ └── java │ │ └── com │ │ └── google │ │ └── devtools │ │ └── build │ │ └── workspace │ │ ├── BUILD │ │ ├── GenerateWorkspace.java │ │ ├── GenerateWorkspaceOptions.java │ │ ├── maven │ │ ├── Aether.java │ │ ├── ArtifactBuilder.java │ │ ├── ArtifactResolver.java │ │ ├── BUILD │ │ ├── DefaultModelResolver.java │ │ ├── GraphSerializer.java │ │ ├── MavenJarRule.java │ │ ├── Resolver.java │ │ ├── Rule.java │ │ └── VersionResolver.java │ │ └── output │ │ ├── AbstractWriter.java │ │ ├── BUILD │ │ ├── BzlWriter.java │ │ └── WorkspaceWriter.java │ └── test │ └── java │ └── com │ └── google │ └── devtools │ └── build │ └── workspace │ ├── BUILD │ ├── GenerateWorkspaceOptionsTest.java │ ├── maven │ ├── AetherGraphTraverserTest.java │ ├── BUILD │ ├── GraphSerializerTest.java │ ├── ResolverTest.java │ ├── RuleTest.java │ └── VersionResolverTest.java │ └── output │ ├── BUILD │ ├── BzlWriterTest.java │ └── WorkspaceWriterTest.java ├── third_party ├── BUILD ├── aether │ ├── LICENSE.html │ ├── aether-api-1.0.0.v20140518.jar │ ├── aether-connector-basic-1.0.0.v20140518.jar │ ├── aether-impl-1.0.0.v20140518.jar │ ├── aether-spi-1.0.0.v20140518.jar │ ├── aether-transport-classpath-1.0.0.v20140518.jar │ ├── aether-transport-file-1.0.0.v20140518.jar │ ├── aether-transport-http-1.0.0.v20140518.jar │ ├── aether-transport-wagon-1.0.0.v20140518.jar │ └── aether-util-1.0.0.v20140518.jar ├── jcommander │ ├── BUILD │ ├── LICENSE │ └── jcommander-1.71 │ │ └── jcommander-1.71.jar └── maven_model │ ├── LICENSE │ ├── maven-aether-provider-3.2.3.jar │ ├── maven-model-3.2.3.jar │ ├── maven-model-builder-3.2.3.jar │ └── maven-repository-metadata-3.2.3.jar └── transitive_maven_jar ├── BUILD ├── generate_workspace_deploy.jar └── transitive_maven_jar.bzl /.bazelci/presubmit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | platforms: 3 | ubuntu1404: 4 | build_targets: 5 | - "..." 6 | test_targets: 7 | - "..." 8 | ubuntu1604: 9 | build_targets: 10 | - "..." 11 | test_targets: 12 | - "..." 13 | macos: 14 | build_targets: 15 | - "..." 16 | test_targets: 17 | - "..." 18 | windows: 19 | build_targets: 20 | - "..." 21 | test_targets: 22 | - "..." 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | bazel-* 3 | .idea/ 4 | *.iml 5 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This the official list of Bazel authors for copyright purposes. 2 | # This file is distinct from the CONTRIBUTORS files. 3 | # See the latter for an explanation. 4 | 5 | # Names should be added to this file as: 6 | # Name or Organization 7 | # The email address is not required for organizations. 8 | 9 | Google Inc. 10 | -------------------------------------------------------------------------------- /BUILD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/BUILD -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Want to contribute? Great! First, read this page (including the small print at the end). 2 | 3 | ### Before you contribute 4 | **Before we can use your code, you must sign the 5 | [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) 6 | (CLA)**, which you can do online. 7 | 8 | The CLA is necessary mainly because you own the copyright to your changes, 9 | even after your contribution becomes part of our codebase, so we need your 10 | permission to use and distribute your code. We also need to be sure of 11 | various other things — for instance that you'll tell us if you know that 12 | your code infringes on other people's patents. You don't have to sign 13 | the CLA until after you've submitted your code for review and a member has 14 | approved it, but you must do it before we can put your code into our codebase. 15 | 16 | Before you start working on a larger contribution, you should get in touch 17 | with us first. Use the issue tracker to explain your idea so we can help and 18 | possibly guide you. 19 | 20 | ### Code reviews and other contributions. 21 | **All submissions, including submissions by project members, require review.** 22 | 23 | Create a GitHub pull request and we will review it as soon as possible. 24 | 25 | ### The small print 26 | 27 | Contributions made by corporations are covered by a different agreement than 28 | the one above, the 29 | [Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate). 30 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # People who have agreed to one of the CLAs and can contribute patches. 2 | # The AUTHORS file lists the copyright holders; this file 3 | # lists people. For example, Google employees are listed here 4 | # but not in AUTHORS, because Google holds the copyright. 5 | # 6 | # https://developers.google.com/open-source/cla/individual 7 | # https://developers.google.com/open-source/cla/corporate 8 | # 9 | # Names should be added to this file as: 10 | # Name 11 | 12 | Alex Humesky 13 | Carmi Grushko 14 | Damien Martin-Guillerez 15 | Dmitry Komanov 16 | Francois-Rene Rideau 17 | Han-Wen Nienhuys 18 | Janak Ramakrishnan 19 | Kristina Chodorow 20 | Laszlo Csomor 21 | Lukacs Berki 22 | Nathan Harmata 23 | Paul Gross 24 | Petros Eskinder 25 | Philipp Wollermann 26 | Rohit Saboo 27 | Stein Eldar Johnsen 28 | Ulf Adams 29 | wjywbs 30 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | 3 | This project is deprecated. Use [build-deps](https://github.com/johnynek/bazel-deps) instead. 4 | 5 | [![Build status](https://badge.buildkite.com/3d265f4a4ef0aa6c54208278c5062491bb074298069d30b051.svg)](https://buildkite.com/bazel/migration-tooling-postsubmit) 6 | 7 | # Migration tooling 8 | 9 | This repository contains tools used for migrating existing projects to Bazel. 10 | 11 | ## Maven-to-Bazel 12 | 13 | To migrate a Maven project to Bazel, build: 14 | 15 | ``` 16 | bazel run //generate_workspace -- --maven_project=/path/to/maven/project 17 | ``` 18 | 19 | This will create a file `generate_workspace.bzl`. Copy it to your workspace 20 | and add the following to your WORKSPACE file: 21 | 22 | ``` python 23 | load("//:generate_workspace.bzl", "generated_maven_jars") 24 | generated_maven_jars() 25 | ``` 26 | 27 | Then you can access any of the jars in `generate_workspace.bzl`. 28 | 29 | Optionally, add the following to a BUILD file: 30 | 31 | ``` python 32 | load("//:generate_workspace.bzl", "generated_java_libraries") 33 | generated_java_libraries() 34 | ``` 35 | 36 | Then you can access any of the Java library targets in `generate_workspace.bzl`, 37 | which export each jar's dependencies as well as the jar itself. 38 | 39 | ## `transitive_maven_jar` 40 | 41 | The `transitive_maven_jar` repository rule exposes the specified Maven jars, as well as their transitive dependencies under one target. This alleviates the need to run 42 | `generate_workspace` whenever dependencies change. However, it comes at the cost of re-fetching dependencies. 43 | 44 | As a prerequisite for use, you must have bazel 0.5.2 or later installed. In addition, add the following to your `WORKSPACE` file: 45 | 46 | ```python 47 | http_archive( 48 | name = "trans_maven_jar", 49 | url = "https://github.com/bazelbuild/migration-tooling/archive/master.zip", 50 | type = "zip", 51 | strip_prefix = "migration-tooling-master", 52 | ) 53 | 54 | load("@trans_maven_jar//transitive_maven_jar:transitive_maven_jar.bzl", "transitive_maven_jar") 55 | 56 | ``` 57 | 58 | Now, within your `WORKSPACE` file, you can define your external maven dependencies as follows 59 | 60 | ```python 61 | transitive_maven_jar( 62 | name = "dependencies", 63 | artifacts = [ 64 | "something:something:4.0", 65 | "otherthing:otherthing:3.2", 66 | ... 67 | ] 68 | ) 69 | 70 | load("@dependencies//:generate_workspace.bzl", "generated_maven_jars") 71 | generated_maven_jars() 72 | ``` 73 | The `transitive_maven_jar` rule will resolve the transitive dependencies for the specified artifacts and then it will generate a `generate_workspace.bzl` which you must load in your `WORKSPACE` file. 74 | 75 | ## Code 76 | This code was inspired by the [aether examples](https://github.com/eclipse/aether-demo/blob/322fa556494335faaf3ad3b7dbe8f89aaaf6222d/aether-demo-snippets/src/main/java/org/eclipse/aether/examples/GetDependencyTree.java) for walking maven dependencies. 77 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | load("//:generate_workspace.bzl", "generated_maven_jars") 2 | generated_maven_jars() 3 | 4 | -------------------------------------------------------------------------------- /generate_workspace.bzl: -------------------------------------------------------------------------------- 1 | # The following dependencies were calculated from: 2 | # 3 | # generate_workspace -a org.apache.maven:maven-artifact:3.5.0 -a org.apache.maven:maven-aether-provider:3.3.9 -a org.eclipse.aether:aether-util:1.1.0 -a com.google.guava:guava:20.0 -a org.powermock:powermock-module-junit4:1.6.6 -a com.google.code.findbugs:jsr305:3.0.1 -a org.codehaus.plexus:plexus-utils:jar:3.0.24 -a org.codehaus.plexus:plexus-component-annotations:1.7.1 -a org.codehaus.plexus:plexus-interpolation:1.24 -a org.mockito:mockito-all:1.9.5 -a junit:junit:4.4 -a com.google.truth:truth:0.30 -a org.apache.httpcomponents:httpcore:4.4.6 -a org.apache.httpcomponents:httpclient:4.5.3 4 | 5 | 6 | def generated_maven_jars(): 7 | native.maven_jar( 8 | name = "com_google_code_findbugs_jsr305", 9 | artifact = "com.google.code.findbugs:jsr305:3.0.1", 10 | ) 11 | 12 | 13 | # org.apache.httpcomponents:httpclient:jar:4.5.3 got requested version 14 | native.maven_jar( 15 | name = "org_apache_httpcomponents_httpcore", 16 | artifact = "org.apache.httpcomponents:httpcore:4.4.6", 17 | ) 18 | 19 | 20 | # org.powermock:powermock-core:jar:1.6.6 21 | # org.powermock:powermock-module-junit4-common:jar:1.6.6 got requested version 22 | native.maven_jar( 23 | name = "org_powermock_powermock_reflect", 24 | artifact = "org.powermock:powermock-reflect:1.6.6", 25 | sha1 = "3fa5d0acee85c5662102ab2ef7a49bbb5a56bae5", 26 | ) 27 | 28 | 29 | # org.apache.httpcomponents:httpclient:jar:4.5.3 30 | native.maven_jar( 31 | name = "commons_codec_commons_codec", 32 | artifact = "commons-codec:commons-codec:1.9", 33 | sha1 = "9ce04e34240f674bc72680f8b843b1457383161a", 34 | ) 35 | 36 | 37 | native.maven_jar( 38 | name = "org_apache_maven_maven_aether_provider", 39 | artifact = "org.apache.maven:maven-aether-provider:3.3.9", 40 | ) 41 | 42 | 43 | native.maven_jar( 44 | name = "org_powermock_powermock_module_junit4", 45 | artifact = "org.powermock:powermock-module-junit4:1.6.6", 46 | ) 47 | 48 | 49 | native.maven_jar( 50 | name = "org_apache_maven_maven_artifact", 51 | artifact = "org.apache.maven:maven-artifact:3.5.0", 52 | ) 53 | 54 | 55 | native.maven_jar( 56 | name = "com_google_truth_truth", 57 | artifact = "com.google.truth:truth:0.30", 58 | ) 59 | 60 | 61 | # com.google.truth:truth:jar:0.30 62 | native.maven_jar( 63 | name = "com_google_errorprone_error_prone_annotations", 64 | artifact = "com.google.errorprone:error_prone_annotations:2.0.8", 65 | sha1 = "54e2d56cb157df08cbf183149bcf50c9f5151ed4", 66 | ) 67 | 68 | 69 | native.maven_jar( 70 | name = "org_codehaus_plexus_plexus_interpolation", 71 | artifact = "org.codehaus.plexus:plexus-interpolation:1.24", 72 | ) 73 | 74 | 75 | # org.powermock:powermock-reflect:jar:1.6.6 76 | native.maven_jar( 77 | name = "org_objenesis_objenesis", 78 | artifact = "org.objenesis:objenesis:2.4", 79 | sha1 = "2916b6c96b50c5b3ec4452ed99401db745aabb27", 80 | ) 81 | 82 | 83 | # com.google.truth:truth:jar:0.30 wanted version 4.10 84 | native.maven_jar( 85 | name = "junit_junit", 86 | artifact = "junit:junit:4.4", 87 | ) 88 | 89 | 90 | # org.powermock:powermock-module-junit4-common:jar:1.6.6 91 | native.maven_jar( 92 | name = "org_powermock_powermock_core", 93 | artifact = "org.powermock:powermock-core:1.6.6", 94 | sha1 = "8085fae46f60d7ff960f1cc711359c00b35c5887", 95 | ) 96 | 97 | 98 | native.maven_jar( 99 | name = "org_codehaus_plexus_plexus_component_annotations", 100 | artifact = "org.codehaus.plexus:plexus-component-annotations:1.7.1", 101 | ) 102 | 103 | 104 | native.maven_jar( 105 | name = "org_codehaus_plexus_plexus_utils", 106 | artifact = "org.codehaus.plexus:plexus-utils:3.0.24", 107 | ) 108 | 109 | 110 | # org.apache.httpcomponents:httpclient:jar:4.5.3 111 | native.maven_jar( 112 | name = "commons_logging_commons_logging", 113 | artifact = "commons-logging:commons-logging:1.2", 114 | sha1 = "4bfc12adfe4842bf07b657f0369c4cb522955686", 115 | ) 116 | 117 | 118 | # junit:junit:jar:4.12 119 | # junit:junit:jar:4.12 got requested version 120 | native.maven_jar( 121 | name = "org_hamcrest_hamcrest_core", 122 | artifact = "org.hamcrest:hamcrest-core:1.3", 123 | sha1 = "42a25dc3219429f0e5d060061f71acb49bf010a0", 124 | ) 125 | 126 | 127 | native.maven_jar( 128 | name = "org_eclipse_aether_aether_util", 129 | artifact = "org.eclipse.aether:aether-util:1.1.0", 130 | ) 131 | 132 | 133 | # org.powermock:powermock-module-junit4:jar:1.6.6 134 | native.maven_jar( 135 | name = "org_powermock_powermock_module_junit4_common", 136 | artifact = "org.powermock:powermock-module-junit4-common:1.6.6", 137 | sha1 = "6302c934d03f76fa348ec91c603e11ce05b61f44", 138 | ) 139 | 140 | 141 | native.maven_jar( 142 | name = "org_apache_httpcomponents_httpclient", 143 | artifact = "org.apache.httpcomponents:httpclient:4.5.3", 144 | ) 145 | 146 | 147 | native.maven_jar( 148 | name = "org_mockito_mockito_all", 149 | artifact = "org.mockito:mockito-all:1.9.5", 150 | ) 151 | 152 | 153 | # org.apache.maven:maven-artifact:jar:3.5.0 154 | native.maven_jar( 155 | name = "org_apache_commons_commons_lang3", 156 | artifact = "org.apache.commons:commons-lang3:3.5", 157 | sha1 = "6c6c702c89bfff3cd9e80b04d668c5e190d588c6", 158 | ) 159 | 160 | 161 | # org.powermock:powermock-core:jar:1.6.6 162 | native.maven_jar( 163 | name = "org_javassist_javassist", 164 | artifact = "org.javassist:javassist:3.22.0-CR2", 165 | sha1 = "44eaf0990dea92f4bca4b9931b2239c0e8756ee7", 166 | ) 167 | 168 | 169 | # org.eclipse.aether:aether-util:jar:1.1.0 170 | native.maven_jar( 171 | name = "org_eclipse_aether_aether_api", 172 | artifact = "org.eclipse.aether:aether-api:1.1.0", 173 | sha1 = "05dd291e788f50dfb48822dab29defc16ad70860", 174 | ) 175 | 176 | 177 | # com.google.truth:truth:jar:0.30 wanted version 19.0 178 | native.maven_jar( 179 | name = "com_google_guava_guava", 180 | artifact = "com.google.guava:guava:20.0", 181 | ) 182 | 183 | 184 | 185 | 186 | def generated_java_libraries(): 187 | native.java_library( 188 | name = "com_google_code_findbugs_jsr305", 189 | visibility = ["//visibility:public"], 190 | exports = ["@com_google_code_findbugs_jsr305//jar"], 191 | ) 192 | 193 | 194 | native.java_library( 195 | name = "org_apache_httpcomponents_httpcore", 196 | visibility = ["//visibility:public"], 197 | exports = ["@org_apache_httpcomponents_httpcore//jar"], 198 | ) 199 | 200 | 201 | native.java_library( 202 | name = "org_powermock_powermock_reflect", 203 | visibility = ["//visibility:public"], 204 | exports = ["@org_powermock_powermock_reflect//jar"], 205 | runtime_deps = [ 206 | ":org_objenesis_objenesis", 207 | ], 208 | ) 209 | 210 | 211 | native.java_library( 212 | name = "commons_codec_commons_codec", 213 | visibility = ["//visibility:public"], 214 | exports = ["@commons_codec_commons_codec//jar"], 215 | ) 216 | 217 | 218 | native.java_library( 219 | name = "org_apache_maven_maven_aether_provider", 220 | visibility = ["//visibility:public"], 221 | exports = ["@org_apache_maven_maven_aether_provider//jar"], 222 | ) 223 | 224 | 225 | native.java_library( 226 | name = "org_powermock_powermock_module_junit4", 227 | visibility = ["//visibility:public"], 228 | exports = ["@org_powermock_powermock_module_junit4//jar"], 229 | runtime_deps = [ 230 | ":junit_junit", 231 | ":org_hamcrest_hamcrest_core", 232 | ":org_javassist_javassist", 233 | ":org_objenesis_objenesis", 234 | ":org_powermock_powermock_core", 235 | ":org_powermock_powermock_module_junit4_common", 236 | ":org_powermock_powermock_reflect", 237 | ], 238 | ) 239 | 240 | 241 | native.java_library( 242 | name = "org_apache_maven_maven_artifact", 243 | visibility = ["//visibility:public"], 244 | exports = ["@org_apache_maven_maven_artifact//jar"], 245 | runtime_deps = [ 246 | ":org_apache_commons_commons_lang3", 247 | ":org_codehaus_plexus_plexus_utils", 248 | ], 249 | ) 250 | 251 | 252 | native.java_library( 253 | name = "com_google_truth_truth", 254 | visibility = ["//visibility:public"], 255 | exports = ["@com_google_truth_truth//jar"], 256 | runtime_deps = [ 257 | ":com_google_errorprone_error_prone_annotations", 258 | ":com_google_guava_guava", 259 | ":junit_junit", 260 | ], 261 | ) 262 | 263 | 264 | native.java_library( 265 | name = "com_google_errorprone_error_prone_annotations", 266 | visibility = ["//visibility:public"], 267 | exports = ["@com_google_errorprone_error_prone_annotations//jar"], 268 | ) 269 | 270 | 271 | native.java_library( 272 | name = "org_codehaus_plexus_plexus_interpolation", 273 | visibility = ["//visibility:public"], 274 | exports = ["@org_codehaus_plexus_plexus_interpolation//jar"], 275 | ) 276 | 277 | 278 | native.java_library( 279 | name = "org_objenesis_objenesis", 280 | visibility = ["//visibility:public"], 281 | exports = ["@org_objenesis_objenesis//jar"], 282 | ) 283 | 284 | 285 | native.java_library( 286 | name = "junit_junit", 287 | visibility = ["//visibility:public"], 288 | exports = ["@junit_junit//jar"], 289 | runtime_deps = [ 290 | ":org_hamcrest_hamcrest_core", 291 | ], 292 | ) 293 | 294 | 295 | native.java_library( 296 | name = "org_powermock_powermock_core", 297 | visibility = ["//visibility:public"], 298 | exports = ["@org_powermock_powermock_core//jar"], 299 | runtime_deps = [ 300 | ":org_javassist_javassist", 301 | ":org_objenesis_objenesis", 302 | ":org_powermock_powermock_reflect", 303 | ], 304 | ) 305 | 306 | 307 | native.java_library( 308 | name = "org_codehaus_plexus_plexus_component_annotations", 309 | visibility = ["//visibility:public"], 310 | exports = ["@org_codehaus_plexus_plexus_component_annotations//jar"], 311 | ) 312 | 313 | 314 | native.java_library( 315 | name = "org_codehaus_plexus_plexus_utils", 316 | visibility = ["//visibility:public"], 317 | exports = ["@org_codehaus_plexus_plexus_utils//jar"], 318 | ) 319 | 320 | 321 | native.java_library( 322 | name = "commons_logging_commons_logging", 323 | visibility = ["//visibility:public"], 324 | exports = ["@commons_logging_commons_logging//jar"], 325 | ) 326 | 327 | 328 | native.java_library( 329 | name = "org_hamcrest_hamcrest_core", 330 | visibility = ["//visibility:public"], 331 | exports = ["@org_hamcrest_hamcrest_core//jar"], 332 | ) 333 | 334 | 335 | native.java_library( 336 | name = "org_eclipse_aether_aether_util", 337 | visibility = ["//visibility:public"], 338 | exports = ["@org_eclipse_aether_aether_util//jar"], 339 | runtime_deps = [ 340 | ":org_eclipse_aether_aether_api", 341 | ], 342 | ) 343 | 344 | 345 | native.java_library( 346 | name = "org_powermock_powermock_module_junit4_common", 347 | visibility = ["//visibility:public"], 348 | exports = ["@org_powermock_powermock_module_junit4_common//jar"], 349 | runtime_deps = [ 350 | ":junit_junit", 351 | ":org_javassist_javassist", 352 | ":org_objenesis_objenesis", 353 | ":org_powermock_powermock_core", 354 | ":org_powermock_powermock_reflect", 355 | ], 356 | ) 357 | 358 | 359 | native.java_library( 360 | name = "org_apache_httpcomponents_httpclient", 361 | visibility = ["//visibility:public"], 362 | exports = ["@org_apache_httpcomponents_httpclient//jar"], 363 | runtime_deps = [ 364 | ":commons_codec_commons_codec", 365 | ":commons_logging_commons_logging", 366 | ":org_apache_httpcomponents_httpcore", 367 | ], 368 | ) 369 | 370 | 371 | native.java_library( 372 | name = "org_mockito_mockito_all", 373 | visibility = ["//visibility:public"], 374 | exports = ["@org_mockito_mockito_all//jar"], 375 | ) 376 | 377 | 378 | native.java_library( 379 | name = "org_apache_commons_commons_lang3", 380 | visibility = ["//visibility:public"], 381 | exports = ["@org_apache_commons_commons_lang3//jar"], 382 | ) 383 | 384 | 385 | native.java_library( 386 | name = "org_javassist_javassist", 387 | visibility = ["//visibility:public"], 388 | exports = ["@org_javassist_javassist//jar"], 389 | ) 390 | 391 | 392 | native.java_library( 393 | name = "org_eclipse_aether_aether_api", 394 | visibility = ["//visibility:public"], 395 | exports = ["@org_eclipse_aether_aether_api//jar"], 396 | ) 397 | 398 | 399 | native.java_library( 400 | name = "com_google_guava_guava", 401 | visibility = ["//visibility:public"], 402 | exports = ["@com_google_guava_guava//jar"], 403 | ) 404 | 405 | 406 | -------------------------------------------------------------------------------- /generate_workspace/BUILD: -------------------------------------------------------------------------------- 1 | java_binary( 2 | name = "generate_workspace", 3 | main_class = "com.google.devtools.build.workspace.GenerateWorkspace", 4 | visibility = ["//visibility:public"], 5 | runtime_deps = ["//generate_workspace/src/main/java/com/google/devtools/build/workspace"], 6 | ) -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "workspace", 3 | srcs = glob(["*.java"]), 4 | visibility = ["//generate_workspace:__subpackages__"], 5 | deps = [ 6 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 7 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/output", 8 | "//third_party:aether", 9 | "//third_party:com_google_guava_guava", 10 | "//third_party/jcommander", 11 | "//third_party:maven_model", 12 | ], 13 | ) 14 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace; 16 | 17 | import com.beust.jcommander.JCommander; 18 | import com.beust.jcommander.ParameterException; 19 | import com.google.common.collect.Lists; 20 | import com.google.devtools.build.workspace.maven.DefaultModelResolver; 21 | import com.google.devtools.build.workspace.maven.Resolver; 22 | import com.google.devtools.build.workspace.maven.Rule; 23 | import com.google.devtools.build.workspace.output.AbstractWriter; 24 | import com.google.devtools.build.workspace.output.BzlWriter; 25 | import com.google.devtools.build.workspace.output.WorkspaceWriter; 26 | import java.io.IOException; 27 | import java.lang.invoke.MethodHandles; 28 | import java.nio.file.Paths; 29 | import java.util.List; 30 | import java.util.Set; 31 | import java.util.logging.Logger; 32 | 33 | /** Generates a WORKSPACE file for Bazel from other types of dependency trackers. */ 34 | public class GenerateWorkspace { 35 | 36 | private static final Logger logger = 37 | Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); 38 | 39 | private final Resolver resolver; 40 | private final List inputs; 41 | private final AbstractWriter resultWriter; 42 | 43 | public static void main(String[] args) throws InterruptedException { 44 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 45 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 46 | try { 47 | optionParser.parse(args); 48 | } catch (ParameterException e) { 49 | System.err.println("Unable to parse options: " + e.getLocalizedMessage()); 50 | optionParser.usage(); 51 | return; 52 | } 53 | if (options.mavenProjects.isEmpty() && options.artifacts.isEmpty()) { 54 | optionParser.usage(); 55 | return; 56 | } 57 | 58 | try { 59 | GenerateWorkspace workspaceFileGenerator = 60 | new GenerateWorkspace( 61 | args, 62 | options.outputDir, 63 | options.directToWorkspace, 64 | options.repositories, 65 | options.aliases); 66 | workspaceFileGenerator.generateFromPom(options.mavenProjects, options.scopes); 67 | workspaceFileGenerator.generateFromArtifacts(options.artifacts); 68 | workspaceFileGenerator.writeResults(); 69 | } catch (IOException e) { 70 | logger.severe(e.getMessage()); 71 | System.exit(1); 72 | } 73 | } 74 | 75 | private GenerateWorkspace( 76 | String[] args, 77 | String outputDirStr, 78 | boolean directToWorkspace, 79 | List repositories, 80 | List aliases) 81 | throws IOException { 82 | DefaultModelResolver defaultModelResolver = new DefaultModelResolver(repositories); 83 | this.resolver = new Resolver(defaultModelResolver, aliases); 84 | this.inputs = Lists.newArrayList(); 85 | this.resultWriter = 86 | directToWorkspace 87 | ? new WorkspaceWriter(args, outputDirStr) 88 | : new BzlWriter(args, outputDirStr); 89 | } 90 | 91 | private void generateFromPom(List projects, Set scopes) { 92 | for (String project : projects) { 93 | String pomFile = resolver.resolvePomDependencies(getAbsolute(project), scopes); 94 | if (pomFile != null) { 95 | inputs.add(pomFile); 96 | } 97 | } 98 | } 99 | 100 | private void generateFromArtifacts(List artifacts) { 101 | for (String artifactCoord : artifacts) { 102 | inputs.add(artifactCoord); 103 | resolver.resolveArtifact(artifactCoord); 104 | } 105 | } 106 | 107 | private String getAbsolute(String path) { 108 | return Paths.get(System.getProperty("user.dir")).resolve(path).toString(); 109 | } 110 | 111 | private void writeResults() { 112 | resultWriter.write(resolver.getRules()); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspaceOptions.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace; 16 | 17 | import com.beust.jcommander.IStringConverter; 18 | import com.beust.jcommander.Parameter; 19 | import com.beust.jcommander.ParameterException; 20 | import com.beust.jcommander.Parameters; 21 | import com.beust.jcommander.converters.CommaParameterSplitter; 22 | import com.beust.jcommander.converters.IParameterSplitter; 23 | import com.google.common.collect.Sets; 24 | import com.google.devtools.build.workspace.maven.ArtifactBuilder; 25 | import com.google.devtools.build.workspace.maven.ArtifactBuilder.InvalidArtifactCoordinateException; 26 | import com.google.devtools.build.workspace.maven.Rule; 27 | import java.util.ArrayList; 28 | import java.util.Arrays; 29 | import java.util.List; 30 | import java.util.Set; 31 | import org.eclipse.aether.artifact.Artifact; 32 | import org.eclipse.aether.util.artifact.JavaScopes; 33 | 34 | /** Command-line options for generate_workspace tool. */ 35 | @Parameters(separators = "=") 36 | public class GenerateWorkspaceOptions { 37 | 38 | private static final String MIN_VERSION = "0"; 39 | 40 | @Parameter(names = "--help", description = "This message.", help = true) 41 | private boolean help; 42 | 43 | @Parameter( 44 | names = {"--maven_project", "-m"}, 45 | description = "Directory containing a Maven project." 46 | ) 47 | public List mavenProjects = new ArrayList<>(); 48 | 49 | @Parameter( 50 | names = {"--repositories", "-r"}, 51 | splitter = CommaParameterSplitter.class, 52 | description = "List of remote maven repositories to query for artifacts." 53 | ) 54 | public List repositories = new ArrayList<>(); 55 | 56 | @Parameter( 57 | names = {"--artifact", "-a"}, 58 | splitter = NoSplitter.class, 59 | description = "Maven artifact coordinates (e.g. groupId:artifactId:version)." 60 | ) 61 | public List artifacts = new ArrayList<>(); 62 | 63 | @Parameter( 64 | names = {"--output_dir", "-o"}, 65 | description = 66 | "Output directory to write the output file(s). If unspecified, uses the" 67 | + " current directory." 68 | ) 69 | public String outputDir = ""; 70 | 71 | @Parameter( 72 | names = {"--direct-to-ws"}, 73 | description = 74 | "Write generated rules to files named WORKSPACE and BUILD, respectively." 75 | + " If not specified, generate_workspace will write generated rules to a .bzl" 76 | + " file that can be loaded from hand-written WORKSPACE and BUILD files." 77 | ) 78 | public boolean directToWorkspace = false; 79 | 80 | @Parameter( 81 | names = {"--scope"}, 82 | description = "Maven scope(s) in to look up dependencies in. May be repeated to list scopes." 83 | ) 84 | public Set scopes = 85 | Sets.newHashSet(JavaScopes.COMPILE, JavaScopes.PROVIDED, JavaScopes.TEST, JavaScopes.RUNTIME); 86 | 87 | @Parameter( 88 | names = {"--declare"}, 89 | description = 90 | "Reuse a repository that is already defined elsewhere. For example, " 91 | + "--declare=org.mockito:mockito-all=mockito will use @mockito instead of " 92 | + "@org_mockito_mockito_all for references to Mockito. You can also leave off the " 93 | + "\"=mockito\" to use the default generated name (--declare=org.mockito:mockito-all " 94 | + "will use @org_mockito_mockito_all for references). If this option is specified, it " 95 | + "is assumed that you already have the repository defined somewhere else, so a " 96 | + "maven_jar is not created for it.", 97 | listConverter = AliasSplitter.class 98 | ) 99 | public List aliases = new ArrayList<>(); 100 | 101 | /** 102 | * Jcommander defaults to splitting each parameter by comma. For example, 103 | * --a=group:artifact:[x1,x2] is parsed as two items 'group:artifact:[x1' and 'x2]', instead of 104 | * the intended 'group:artifact:[x1,x2]' 105 | * 106 | *

For more information: http://jcommander.org/#_splitting 107 | */ 108 | private static class NoSplitter implements IParameterSplitter { 109 | @Override 110 | public List split(String value) { 111 | return Arrays.asList(value); 112 | } 113 | } 114 | 115 | private static class AliasSplitter implements IStringConverter { 116 | 117 | @Override 118 | public Rule convert(String s) { 119 | if (s.contains("=")) { 120 | return getMapping(s); 121 | } 122 | 123 | // Alternatively, maybe this is just a coordinate that's declared elsewhere. 124 | return new Rule(getArtifact(s)); 125 | } 126 | 127 | private Artifact getArtifact(String coordinate) { 128 | if (coordinate.split(":").length == 2) { 129 | // Add a version. 130 | coordinate = coordinate + ":" + MIN_VERSION; 131 | } 132 | Artifact artifact; 133 | try { 134 | artifact = ArtifactBuilder.fromCoords(coordinate); 135 | } catch (InvalidArtifactCoordinateException e) { 136 | throw new ParameterException( 137 | "Invalid format for alias: " + coordinate + ": " + e.getLocalizedMessage()); 138 | } 139 | return artifact; 140 | } 141 | 142 | private Rule getMapping(String s) { 143 | String[] parts = s.split("="); 144 | if (parts.length != 2) { 145 | throw new ParameterException( 146 | "Invalid format for alias: " + s + ", expected groupId:artifactId=repository_name"); 147 | } 148 | return new Rule(getArtifact(parts[0]), parts[1]); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/Aether.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | 18 | import static java.util.stream.Collectors.toList; 19 | 20 | import com.google.common.collect.Lists; 21 | import java.util.List; 22 | import org.apache.maven.repository.internal.MavenRepositorySystemUtils; 23 | import org.eclipse.aether.DefaultRepositorySystemSession; 24 | import org.eclipse.aether.RepositorySystem; 25 | import org.eclipse.aether.RepositorySystemSession; 26 | import org.eclipse.aether.artifact.Artifact; 27 | import org.eclipse.aether.collection.CollectRequest; 28 | import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; 29 | import org.eclipse.aether.graph.Dependency; 30 | import org.eclipse.aether.graph.DependencyFilter; 31 | import org.eclipse.aether.impl.DefaultServiceLocator; 32 | import org.eclipse.aether.repository.LocalRepository; 33 | import org.eclipse.aether.repository.RemoteRepository; 34 | import org.eclipse.aether.resolution.DependencyRequest; 35 | import org.eclipse.aether.resolution.DependencyResolutionException; 36 | import org.eclipse.aether.resolution.DependencyResult; 37 | import org.eclipse.aether.resolution.VersionRangeRequest; 38 | import org.eclipse.aether.resolution.VersionRangeResolutionException; 39 | import org.eclipse.aether.resolution.VersionRangeResult; 40 | import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; 41 | import org.eclipse.aether.spi.connector.transport.TransporterFactory; 42 | import org.eclipse.aether.transport.file.FileTransporterFactory; 43 | import org.eclipse.aether.transport.http.HttpTransporterFactory; 44 | import org.eclipse.aether.util.artifact.JavaScopes; 45 | import org.eclipse.aether.util.filter.DependencyFilterUtils; 46 | import org.eclipse.aether.util.graph.manager.ClassicDependencyManager; 47 | import org.eclipse.aether.version.Version; 48 | 49 | /** 50 | * Facade around aether. This class is used to make various requests to the aether subsystem. 51 | */ 52 | public class Aether { 53 | 54 | static final String MAVEN_CENTRAL_URL = "https://repo1.maven.org/maven2/"; 55 | 56 | RepositorySystem repositorySystem; 57 | 58 | RepositorySystemSession repositorySystemSession; 59 | 60 | List remoteRepositories; 61 | 62 | private Aether(RepositorySystem repositorySystem, 63 | RepositorySystemSession session, List remoteRepositories) { 64 | this.repositorySystem = repositorySystem; 65 | this.repositorySystemSession = session; 66 | this.remoteRepositories = remoteRepositories; 67 | } 68 | 69 | public void addRemoteRepository(RemoteRepository repo) { 70 | this.remoteRepositories.add(repo); 71 | } 72 | 73 | public List getRemoteRepositories() { 74 | return this.remoteRepositories; 75 | } 76 | 77 | /** Given an artifacts requests a version range for it. */ 78 | List requestVersionRange(Artifact artifact) throws VersionRangeResolutionException { 79 | VersionRangeRequest rangeRequest = new VersionRangeRequest(artifact, remoteRepositories, null); 80 | VersionRangeResult result = repositorySystem.resolveVersionRange(repositorySystemSession, rangeRequest); 81 | return result.getVersions().stream().map(Version::toString).collect(toList()); 82 | } 83 | 84 | /** 85 | * Creates a CollectRequest, i.e. a request to collect transitive dependencies and to build 86 | * a dependency graph from them. It accomplishes this through a list of direct dependencies. 87 | */ 88 | CollectRequest createCollectRequest( 89 | List directDependencies, List managedDependencies) { 90 | return new CollectRequest(directDependencies, managedDependencies, remoteRepositories); 91 | } 92 | 93 | /** 94 | * Creates a DependencyRequest, i.e. a request to resolve transitive dependencies, from 95 | * a collect request. 96 | */ 97 | //TODO(petros): add some means to add exclusions. 98 | DependencyRequest createDependencyRequest(CollectRequest collectRequest, DependencyFilter filter) { 99 | return new DependencyRequest(collectRequest, filter); 100 | } 101 | 102 | DependencyRequest createDependencyRequest(CollectRequest collectRequest) { 103 | DependencyFilter compileFilter = DependencyFilterUtils.classpathFilter(JavaScopes.COMPILE); 104 | return createDependencyRequest(collectRequest, compileFilter); 105 | } 106 | 107 | /** 108 | * Given a dependency request, this makes the call to aether to transitively resolve the 109 | * dependencies. 110 | */ 111 | DependencyResult requestDependencyResolution(DependencyRequest dependencyRequest) 112 | throws DependencyResolutionException { 113 | return repositorySystem.resolveDependencies(repositorySystemSession, dependencyRequest); 114 | } 115 | 116 | /** TODO(petros): this is a hack until I replace the existing Resolver. */ 117 | static Aether defaultOption() { 118 | return new Aether.Builder().build(); 119 | } 120 | 121 | static Aether.Builder builder() { 122 | return new Aether.Builder(); 123 | } 124 | 125 | /** Builder class for convenience and flexibility. */ 126 | static class Builder { 127 | private List remoteRepositories; 128 | private RepositorySystem repositorySystem; 129 | private RepositorySystemSession repositorySystemSession; 130 | 131 | Builder() { 132 | remoteRepositories = Lists.newArrayList(Utilities.mavenCentralRepository()); 133 | repositorySystem = Utilities.newRepositorySystem(); 134 | repositorySystemSession = Utilities.newRepositorySession(repositorySystem); 135 | } 136 | 137 | Builder remoteRepos(List remoteRepositories) { 138 | this.remoteRepositories = remoteRepositories; 139 | return this; 140 | } 141 | 142 | /** 143 | * Provide Repository System Sessions and RepositorySystems together since 144 | * Repository sessions are associated to a particular to a Repository System. 145 | */ 146 | Builder systemSession(RepositorySystemSession session, RepositorySystem system) { 147 | this.repositorySystemSession = session; 148 | this.repositorySystem = system; 149 | return this; 150 | } 151 | 152 | Aether build() { 153 | return new Aether(repositorySystem, repositorySystemSession, remoteRepositories); 154 | } 155 | } 156 | 157 | /** 158 | * A set of utility methods for creating repository systems, repository system sessions and 159 | * remote repositories. 160 | */ 161 | static class Utilities { 162 | 163 | /* Creates a new aether repository system. */ 164 | static RepositorySystem newRepositorySystem() { 165 | DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); 166 | locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); 167 | locator.addService(TransporterFactory.class, FileTransporterFactory.class); 168 | locator.addService(TransporterFactory.class, HttpTransporterFactory.class); 169 | return locator.getService(RepositorySystem.class); 170 | } 171 | 172 | /** 173 | * Aether and its components are designed to be stateless. All configurations and state 174 | * are provided through the RepositorySystemSession. 175 | * 176 | * TODO(petros): Separate this out into its own class. 177 | * This is the most intricate element of Aether. 178 | * There are various settings that are useful to us. 179 | * Specifically, these are the (1) LocalRepositoryManager, (2) DependencyManager, 180 | * (3) DependencyGraphTransformer, (4) TransferListener, (5) ProxySelector 181 | */ 182 | static RepositorySystemSession newRepositorySession(RepositorySystem system) { 183 | DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); 184 | 185 | // TODO(petros): Decide on where to cache things. 186 | LocalRepository localRepository = new LocalRepository("target/local-repo"); 187 | session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepository)); 188 | 189 | session.setDependencyManager(new ClassicDependencyManager()); 190 | return session; 191 | } 192 | 193 | /** Creates an instance of the maven central repository */ 194 | static RemoteRepository mavenCentralRepository() { 195 | return new RemoteRepository.Builder( "central", "default", MAVEN_CENTRAL_URL).build(); 196 | } 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/ArtifactBuilder.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | import org.apache.maven.model.Dependency; 18 | import org.eclipse.aether.artifact.Artifact; 19 | import org.eclipse.aether.artifact.DefaultArtifact; 20 | 21 | 22 | /* Builds Aether/Maven artifacts */ 23 | public class ArtifactBuilder { 24 | 25 | /** Builds a Maven artifact from a set of Maven coordinates */ 26 | public static Artifact fromCoords(String artifactCoords) throws InvalidArtifactCoordinateException { 27 | try { 28 | return new DefaultArtifact(artifactCoords); 29 | } catch (IllegalArgumentException e) { 30 | throw new InvalidArtifactCoordinateException(e.getMessage()); 31 | } 32 | } 33 | 34 | /** Builds a Maven artifact from a set of Maven coordinates */ 35 | public static Artifact fromCoords(String groupId, String artifactId, String versionSpec) 36 | throws InvalidArtifactCoordinateException { 37 | String artifactCoords = String.format("%s:%s:%s", groupId, artifactId, versionSpec); 38 | return fromCoords(artifactCoords); 39 | } 40 | 41 | /** 42 | * Builds a Maven artifact from a dependency. Note, this is a org.apache.maven.model.Dependency 43 | * and not the Dependency defined by aether. 44 | */ 45 | public static Artifact fromMavenDependency(Dependency dep, VersionResolver versionResolver) 46 | throws InvalidArtifactCoordinateException { 47 | String version = 48 | versionResolver.resolveVersion(dep.getGroupId(), dep.getArtifactId(), dep.getVersion()); 49 | String mavenCoordinate = String.format("%s:%s:%s", dep.getGroupId(), dep.getArtifactId(), version); 50 | return fromCoords(mavenCoordinate); 51 | } 52 | 53 | /** Exception thrown if an artifact coordinate cannot be parsed */ 54 | public static class InvalidArtifactCoordinateException extends Exception { 55 | InvalidArtifactCoordinateException(String message) { 56 | super(message); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/ArtifactResolver.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | 18 | import static java.util.stream.Collectors.toList; 19 | 20 | import java.lang.invoke.MethodHandles; 21 | import java.util.List; 22 | import java.util.function.Function; 23 | import java.util.logging.Logger; 24 | import org.eclipse.aether.artifact.DefaultArtifact; 25 | import org.eclipse.aether.collection.CollectRequest; 26 | import org.eclipse.aether.graph.Dependency; 27 | import org.eclipse.aether.graph.DependencyNode; 28 | import org.eclipse.aether.resolution.DependencyRequest; 29 | import org.eclipse.aether.resolution.DependencyResolutionException; 30 | import org.eclipse.aether.resolution.DependencyResult; 31 | import org.eclipse.aether.util.artifact.JavaScopes; 32 | 33 | /** 34 | * Resolves transitive dependencies of maven artifacts using aether. 35 | */ 36 | public class ArtifactResolver { 37 | private final Aether aether; 38 | private final List managedDependencies; 39 | private final static Logger logger = Logger.getLogger( 40 | MethodHandles.lookup().lookupClass().getName()); 41 | 42 | //TODO(petros): add support for managed dependencies, exclusions, and aliases. 43 | public ArtifactResolver(Aether aether, List managedDependencies) { 44 | this.aether = aether; 45 | this.managedDependencies = managedDependencies; 46 | } 47 | 48 | /** 49 | * Given a set of coordinates, resolves the transitive dependencies, and then returns the root 50 | * node to the resolved dependency graph. The root node is a sentinel node with direct edges 51 | * on the artifacts users declared explicit on. 52 | */ 53 | public DependencyNode resolveArtifacts(List artifactCoords) { 54 | List directDependencies = createDirectDependencyList(artifactCoords); 55 | CollectRequest collectRequest = 56 | aether.createCollectRequest(directDependencies, managedDependencies); 57 | 58 | DependencyRequest dependencyRequest = aether.createDependencyRequest(collectRequest); 59 | DependencyResult dependencyResult; 60 | try { 61 | dependencyResult = aether.requestDependencyResolution(dependencyRequest); 62 | } catch (DependencyResolutionException e) { 63 | //FIXME(petros): This is very fragile. If one artifact doesn't resolve, no artifacts resolve. 64 | logger.warning("Unable to resolve transitive dependencies: " + e.getMessage()); 65 | return null; 66 | } 67 | // root is a sentinel node whose direct children are the requested artifacts. 68 | return dependencyResult.getRoot(); 69 | } 70 | 71 | /* Given a list of artifacts, constructs a lists of Aether Dependencies */ 72 | private List createDirectDependencyList(List artifactCoords) { 73 | Function coordinateToDependencyNode = 74 | a -> new Dependency(new DefaultArtifact(a), JavaScopes.COMPILE); 75 | return artifactCoords.stream().map(coordinateToDependencyNode).collect(toList()); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "maven", 3 | srcs = glob(["*.java"]), 4 | visibility = ["//generate_workspace/src:__subpackages__"], 5 | runtime_deps = [ 6 | "//third_party:org_codehaus_plexus_plexus_interpolation", 7 | "//third_party:org_codehaus_plexus_plexus_utils", 8 | ], 9 | deps = [ 10 | "//third_party:aether", 11 | "//third_party:com_google_code_findbugs_jsr305", 12 | "//third_party:com_google_guava_guava", 13 | "//third_party:maven_model", 14 | "//third_party:org_apache_httpcomponents_httpclient", 15 | "//third_party:org_apache_httpcomponents_httpcore", 16 | "//third_party:org_apache_maven_maven_aether_provider", 17 | "//third_party:org_apache_maven_maven_artifact", 18 | ], 19 | ) 20 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/DefaultModelResolver.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | import static com.google.devtools.build.workspace.maven.Rule.MAVEN_CENTRAL_URL; 18 | import static java.util.stream.Collectors.toList; 19 | 20 | import com.google.common.base.Joiner; 21 | import com.google.common.collect.Maps; 22 | import java.io.IOException; 23 | import java.lang.invoke.MethodHandles; 24 | import java.net.HttpURLConnection; 25 | import java.net.MalformedURLException; 26 | import java.net.URL; 27 | import java.net.URLConnection; 28 | import java.util.ArrayList; 29 | import java.util.Collection; 30 | import java.util.List; 31 | import java.util.Map; 32 | import java.util.Set; 33 | import java.util.logging.Logger; 34 | import java.util.stream.Collectors; 35 | import org.apache.maven.model.Model; 36 | import org.apache.maven.model.Parent; 37 | import org.apache.maven.model.Repository; 38 | import org.apache.maven.model.building.*; 39 | import org.apache.maven.model.profile.DefaultProfileSelector; 40 | import org.apache.maven.model.resolution.ModelResolver; 41 | import org.apache.maven.model.resolution.UnresolvableModelException; 42 | import org.eclipse.aether.artifact.Artifact; 43 | import org.eclipse.aether.repository.RemoteRepository; 44 | 45 | /** Resolver to find the repository a given Maven artifact should be fetched from. */ 46 | public class DefaultModelResolver implements ModelResolver { 47 | 48 | private static final Logger logger = 49 | Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); 50 | private static final Repository MAVEN_CENTRAL = new Repository(); 51 | 52 | static { 53 | MAVEN_CENTRAL.setId("central"); 54 | MAVEN_CENTRAL.setName("default"); 55 | MAVEN_CENTRAL.setUrl(MAVEN_CENTRAL_URL); 56 | } 57 | 58 | private final Set repositories; 59 | private final Map ruleNameToModelSource; 60 | private final DefaultModelBuilder modelBuilder; 61 | private final Aether aether; 62 | private final VersionResolver versionResolver; 63 | 64 | public DefaultModelResolver() { 65 | this(new ArrayList<>()); 66 | } 67 | 68 | public DefaultModelResolver(Collection repositoryUrls) { 69 | this( 70 | Aether.builder() 71 | .remoteRepos( 72 | repositoryUrls 73 | .stream() 74 | .map( 75 | (String url) -> 76 | new RemoteRepository.Builder("user-defined repository", "default", url) 77 | .build()) 78 | .collect(Collectors.toList())) 79 | .build(), 80 | repositoryUrls 81 | .stream() 82 | .map( 83 | (String url) -> { 84 | Repository r = new Repository(); 85 | r.setId(url); 86 | r.setUrl(url); 87 | return r; 88 | }) 89 | .collect(Collectors.toSet()), 90 | Maps.newHashMap(), 91 | new DefaultModelBuilderFactory() 92 | .newInstance() 93 | .setProfileSelector(new DefaultProfileSelector())); 94 | } 95 | 96 | private DefaultModelResolver( 97 | Aether aether, 98 | Set repositories, 99 | Map ruleNameToModelSource, 100 | DefaultModelBuilder modelBuilder) { 101 | this.repositories = repositories; 102 | this.ruleNameToModelSource = ruleNameToModelSource; 103 | this.modelBuilder = modelBuilder; 104 | this.aether = aether; 105 | this.versionResolver = new VersionResolver(aether); 106 | } 107 | 108 | public ModelSource resolveModel(Artifact artifact) throws UnresolvableModelException { 109 | return resolveModel(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()); 110 | } 111 | 112 | @Override 113 | public ModelSource resolveModel(String groupId, String artifactId, String version) 114 | throws UnresolvableModelException { 115 | String ruleName = Rule.name(groupId, artifactId); 116 | if (ruleNameToModelSource.containsKey(ruleName)) { 117 | return ruleNameToModelSource.get(ruleName); 118 | } 119 | for (Repository repository : repositories) { 120 | UrlModelSource modelSource = 121 | getModelSource(repository.getUrl(), groupId, artifactId, version); 122 | if (modelSource != null) { 123 | return modelSource; 124 | } 125 | } 126 | 127 | List attemptedUrls = repositories.stream().map(Repository::getUrl).collect(toList()); 128 | throw new UnresolvableModelException( 129 | "Could not find any repositories that knew how to " 130 | + "resolve " 131 | + groupId 132 | + ":" 133 | + artifactId 134 | + ":" 135 | + version 136 | + " (checked " 137 | + Joiner.on(", ").join(attemptedUrls) 138 | + ")", 139 | groupId, 140 | artifactId, 141 | version); 142 | } 143 | 144 | // TODO(kchodorow): make this work with local repositories. 145 | private UrlModelSource getModelSource( 146 | String url, String groupId, String artifactId, String version) 147 | throws UnresolvableModelException { 148 | try { 149 | version = versionResolver.resolveVersion(groupId, artifactId, version); 150 | } catch (ArtifactBuilder.InvalidArtifactCoordinateException e) { 151 | throw new UnresolvableModelException( 152 | "Unable to resolve version", groupId, artifactId, version, e); 153 | } 154 | try { 155 | if (!url.endsWith("/")) { 156 | url += "/"; 157 | } 158 | URL urlUrl = 159 | new URL( 160 | url 161 | + groupId.replaceAll("\\.", "/") 162 | + "/" 163 | + artifactId 164 | + "/" 165 | + version 166 | + "/" 167 | + artifactId 168 | + "-" 169 | + version 170 | + ".pom"); 171 | if (pomFileExists(urlUrl)) { 172 | UrlModelSource urlModelSource = new UrlModelSource(urlUrl); 173 | ruleNameToModelSource.put(Rule.name(groupId, artifactId), urlModelSource); 174 | return urlModelSource; 175 | } 176 | } catch (MalformedURLException e) { 177 | throw new UnresolvableModelException( 178 | "Bad URL " + url + ": " + e.getMessage(), groupId, artifactId, version, e); 179 | } 180 | return null; 181 | } 182 | 183 | private boolean pomFileExists(URL url) { 184 | try { 185 | URLConnection urlConnection = url.openConnection(); 186 | if (!(urlConnection instanceof HttpURLConnection)) { 187 | return false; 188 | } 189 | 190 | HttpURLConnection connection = (HttpURLConnection) urlConnection; 191 | connection.setRequestMethod("HEAD"); 192 | connection.setInstanceFollowRedirects(true); 193 | connection.connect(); 194 | 195 | int code = connection.getResponseCode(); 196 | if (code == 200) { 197 | return true; 198 | } 199 | } catch (IOException e) { 200 | // Something went wrong, fall through. 201 | } 202 | return false; 203 | } 204 | 205 | // For compatibility with older versions of ModelResolver which don't have this method, 206 | // don't add @Override. 207 | public ModelSource resolveModel(Parent parent) throws UnresolvableModelException { 208 | return resolveModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()); 209 | } 210 | 211 | // For compatibility with older versions of ModelResolver which don't have this method, 212 | // don't add @Override. 213 | public void addRepository(Repository repository) { 214 | repositories.add(repository); 215 | } 216 | 217 | @Override 218 | public void addRepository(Repository repository, boolean replace) { 219 | addRepository(repository); 220 | } 221 | 222 | @Override 223 | public ModelResolver newCopy() { 224 | return new DefaultModelResolver(aether, repositories, ruleNameToModelSource, modelBuilder); 225 | } 226 | 227 | public VersionResolver getVersionResolver() { 228 | return this.versionResolver; 229 | } 230 | 231 | /** Adds a user-specified repository to the list. */ 232 | public void addUserRepository(String url) { 233 | Repository repository = new Repository(); 234 | repository.setUrl(url); 235 | repository.setId("user-defined repository"); 236 | repository.setName("default"); 237 | addRepository(repository); 238 | this.aether.addRemoteRepository( 239 | new RemoteRepository.Builder("user-defined repository", "default", url).build()); 240 | } 241 | 242 | public boolean putModelSource(String groupId, String artifactId, ModelSource modelSource) { 243 | String key = Rule.name(groupId, artifactId); 244 | if (!ruleNameToModelSource.containsKey(key)) { 245 | ruleNameToModelSource.put(key, modelSource); 246 | return true; 247 | } 248 | return false; 249 | } 250 | 251 | public Model getEffectiveModel(ModelSource modelSource) { 252 | DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); 253 | request.setModelResolver(this); 254 | request.setModelSource(modelSource); 255 | Model model; 256 | try { 257 | ModelBuildingResult result = modelBuilder.build(request); 258 | model = result.getEffectiveModel(); 259 | } catch (ModelBuildingException | IllegalArgumentException e) { 260 | // IllegalArg can be thrown if the parent POM cannot be resolved. 261 | logger.warning( 262 | "Unable to resolve Maven model from " 263 | + modelSource.getLocation() 264 | + ": " 265 | + e.getMessage()); 266 | return null; 267 | } 268 | return model; 269 | } 270 | 271 | public Model getRawModel(FileModelSource fileModelSource) { 272 | DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); 273 | request.setModelResolver(this); 274 | request.setModelSource(fileModelSource); 275 | Model model; 276 | try { 277 | ModelBuildingResult result = modelBuilder.build(request); 278 | model = result.getRawModel(); 279 | } catch (ModelBuildingException | IllegalArgumentException e) { 280 | // IllegalArg can be thrown if the parent POM cannot be resolved. 281 | logger.warning( 282 | "Unable to resolve raw Maven model from " 283 | + fileModelSource.getLocation() 284 | + ": " 285 | + e.getMessage()); 286 | return null; 287 | } 288 | return model; 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/GraphSerializer.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | import com.google.common.collect.Maps; 18 | import com.google.common.collect.Sets; 19 | import com.google.common.graph.GraphBuilder; 20 | import com.google.common.graph.MutableGraph; 21 | import org.eclipse.aether.graph.DependencyNode; 22 | import org.eclipse.aether.graph.DependencyVisitor; 23 | 24 | import java.util.Map; 25 | import java.util.Set; 26 | 27 | /** 28 | * Serializes a resolved dependency graph into a set of Bazel Build Rules. 29 | */ 30 | public class GraphSerializer { 31 | 32 | public static Set generateBuildRules(DependencyNode root) { 33 | MutableGraph graph = GraphBuilder.directed().allowsSelfLoops(false).build(); 34 | DependencyVisitor visitor = new AetherGraphTraverser(graph); 35 | root.getChildren().forEach(c -> c.accept(visitor)); 36 | return graph.nodes(); 37 | } 38 | } 39 | 40 | /** 41 | * Performs a depth first traversal of aether's dependency node graph, and 42 | * constructs a guava graph representation of the aether graph, with each 43 | * node being a Rule object. 44 | */ 45 | class AetherGraphTraverser implements DependencyVisitor { 46 | private final Set visited; 47 | private final MutableGraph ruleGraph; 48 | private final Map nodeRuleMap; 49 | 50 | AetherGraphTraverser(MutableGraph ruleGraph) { 51 | this.visited = Sets.newHashSet(); 52 | this.ruleGraph = ruleGraph; 53 | this.nodeRuleMap = Maps.newHashMap(); 54 | } 55 | 56 | @Override 57 | public boolean visitEnter(DependencyNode dependencyNode) { 58 | if (dependencyNode == null || dependencyNode.getDependency().isOptional()) { 59 | return false; 60 | } 61 | MavenJarRule rule = getRule(dependencyNode); 62 | boolean isFirstVisit = visited.add(rule); 63 | if (!isFirstVisit) { 64 | return false; 65 | } 66 | for (DependencyNode child : dependencyNode.getChildren()) { 67 | MavenJarRule childRule = getRule(child); 68 | ruleGraph.putEdge(rule, childRule); 69 | } 70 | return true; 71 | } 72 | 73 | @Override 74 | /* Adds parent and child pointers to nodes for later use by serializer. */ 75 | public boolean visitLeave(DependencyNode dependencyNode) { 76 | MavenJarRule rule = getRule(dependencyNode); 77 | ruleGraph.successors(rule).forEach(r -> r.addParent(rule)); 78 | ruleGraph.successors(rule).forEach(rule::addDependency); 79 | return true; 80 | } 81 | 82 | /** 83 | * Given a dependency node, either fetches a cached Rule object or 84 | * constructs a new one. 85 | */ 86 | private MavenJarRule getRule(DependencyNode node) { 87 | MavenJarRule rule = nodeRuleMap.get(node); 88 | if (rule != null) { 89 | return rule; 90 | } 91 | rule = new MavenJarRule(node); 92 | nodeRuleMap.put(node, rule); 93 | ruleGraph.addNode(rule); 94 | return rule; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/MavenJarRule.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | import static java.util.stream.Collectors.toList; 18 | 19 | import com.google.common.base.Joiner; 20 | import com.google.common.collect.Sets; 21 | import java.util.List; 22 | import java.util.Objects; 23 | import java.util.Set; 24 | import org.eclipse.aether.artifact.Artifact; 25 | import org.eclipse.aether.graph.DependencyNode; 26 | import org.eclipse.aether.repository.RemoteRepository; 27 | 28 | /** 29 | * A struct representing the fields of maven_jar to be written to the WORKSPACE file. 30 | */ 31 | //TODO(petros): refactor existing resolvers to use this class rather than Rule. 32 | //TODO(petros): Implement the SHA1 and aliasing. 33 | public class MavenJarRule implements Comparable { 34 | 35 | private final DependencyNode node; 36 | private final Set parents; 37 | private final Set dependencies; 38 | 39 | public MavenJarRule(DependencyNode node) { 40 | this.node = node; 41 | this.parents = Sets.newHashSet(); 42 | this.dependencies = Sets.newHashSet(); 43 | } 44 | 45 | public void addParent(MavenJarRule parent) { 46 | addParent(parent.toMavenArtifactString()); 47 | } 48 | 49 | public void addParent(String parent) { 50 | parents.add(parent); 51 | } 52 | 53 | public Set getParents() { 54 | return parents; 55 | } 56 | 57 | public void addDependency(MavenJarRule dependency) { 58 | addDependency(dependency.name()); 59 | } 60 | 61 | public void addDependency(String dependency) { 62 | dependencies.add(dependency); 63 | } 64 | 65 | public Set getDependencies() { 66 | return dependencies; 67 | } 68 | 69 | private String artifactId() { 70 | return node.getArtifact().getArtifactId(); 71 | } 72 | 73 | private String groupId() { 74 | return node.getArtifact().getGroupId(); 75 | } 76 | 77 | public String version() { 78 | return node.getArtifact().getVersion(); 79 | } 80 | 81 | /** 82 | * A unique name for this artifact to use in maven_jar's name attribute. 83 | */ 84 | public String name() { 85 | return name(groupId(), artifactId()); 86 | } 87 | 88 | /** 89 | * A unique name for this artifact to use in maven_jar's name attribute. 90 | */ 91 | public static String name(String groupId, String artifactId) { 92 | return groupId.replaceAll("[.-]", "_") + "_" + artifactId.replaceAll("[.-]", "_"); 93 | } 94 | 95 | public Artifact getArtifact() { 96 | return node.getArtifact(); 97 | } 98 | 99 | public String toMavenArtifactString() { 100 | return groupId() + ":" + artifactId() + ":" + version(); 101 | } 102 | 103 | /** Checks if the dependency node possesses a remote repository other than maven central */ 104 | public boolean hasCustomRepository() { 105 | List repositories = node.getRepositories(); 106 | if (repositories == null || repositories.isEmpty() || repositories.size() > 1) { 107 | return false; 108 | } 109 | return repositories.get(0).equals(Aether.Utilities.mavenCentralRepository()); 110 | } 111 | 112 | public String getRepository() { 113 | return Joiner.on(',').join( 114 | node.getRepositories().stream().map(RemoteRepository::getUrl).collect(toList())); 115 | } 116 | 117 | @Override 118 | public String toString() { 119 | return node.getArtifact().toString(); 120 | } 121 | 122 | @Override 123 | public boolean equals(Object o) { 124 | if (this == o) { 125 | return true; 126 | } 127 | if (o == null || getClass() != o.getClass()) { 128 | return false; 129 | } 130 | 131 | MavenJarRule rule = (MavenJarRule) o; 132 | 133 | return Objects.equals(groupId(), rule.groupId()) 134 | && Objects.equals(artifactId(), rule.artifactId()); 135 | } 136 | 137 | @Override 138 | public int hashCode() { 139 | return Objects.hash(groupId(), artifactId()); 140 | } 141 | 142 | @Override 143 | public int compareTo(MavenJarRule o) { 144 | return name().compareTo(o.name()); 145 | } 146 | 147 | public boolean aliased() { 148 | //TODO(petros) implement this 149 | return false; 150 | } 151 | 152 | public String getSha1() { 153 | //TODO(petros) implement this 154 | return null; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/Resolver.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | import static com.google.devtools.build.workspace.maven.ArtifactBuilder.InvalidArtifactCoordinateException; 18 | 19 | import com.google.common.annotations.VisibleForTesting; 20 | import com.google.common.collect.Maps; 21 | import com.google.common.collect.Sets; 22 | import com.google.common.io.CharStreams; 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.io.InputStreamReader; 27 | import java.lang.invoke.MethodHandles; 28 | import java.net.HttpURLConnection; 29 | import java.net.URL; 30 | import java.nio.charset.Charset; 31 | import java.util.*; 32 | import java.util.logging.Logger; 33 | import javax.annotation.Nullable; 34 | import org.apache.maven.artifact.versioning.DefaultArtifactVersion; 35 | import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 36 | import org.apache.maven.artifact.versioning.VersionRange; 37 | import org.apache.maven.model.*; 38 | import org.apache.maven.model.building.DefaultModelProcessor; 39 | import org.apache.maven.model.building.FileModelSource; 40 | import org.apache.maven.model.building.ModelSource; 41 | import org.apache.maven.model.io.DefaultModelReader; 42 | import org.apache.maven.model.locator.DefaultModelLocator; 43 | import org.apache.maven.model.resolution.UnresolvableModelException; 44 | import org.eclipse.aether.artifact.Artifact; 45 | import org.eclipse.aether.util.artifact.JavaScopes; 46 | 47 | /** Resolves Maven dependencies. */ 48 | public class Resolver { 49 | 50 | private static final Logger logger = 51 | Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); 52 | private static final String TOP_LEVEL_ARTIFACT = "pom.xml"; 53 | 54 | /** 55 | * The set of scopes whose artifacts are pulled into the transitive dependency tree. See 56 | * https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html for more 57 | * details on how maven handles this. 58 | */ 59 | private static final Set INHERITED_SCOPES = 60 | Sets.newHashSet(JavaScopes.COMPILE, JavaScopes.RUNTIME); 61 | 62 | private static String unversionedCoordinate(Dependency dependency) { 63 | return dependency.getGroupId() + ":" + dependency.getArtifactId(); 64 | } 65 | 66 | private static String unversionedCoordinate(Exclusion exclusion) { 67 | return exclusion.getGroupId() + ":" + exclusion.getArtifactId(); 68 | } 69 | 70 | private final DefaultModelResolver modelResolver; 71 | 72 | // Mapping of maven_jar name to Rule. 73 | private final Map deps; 74 | private final Map restriction; 75 | 76 | private final VersionResolver versionResolver; 77 | 78 | @VisibleForTesting 79 | public Resolver( 80 | DefaultModelResolver modelResolver, VersionResolver versionResolver, List aliases) { 81 | this.versionResolver = versionResolver; 82 | this.deps = Maps.newHashMap(); 83 | this.restriction = Maps.newHashMap(); 84 | this.modelResolver = modelResolver; 85 | aliases.forEach(alias -> addArtifact(alias, TOP_LEVEL_ARTIFACT)); 86 | } 87 | 88 | public Resolver(DefaultModelResolver resolver, List aliases) { 89 | this(resolver, resolver.getVersionResolver(), aliases); 90 | } 91 | 92 | /** Returns all maven_jars. */ 93 | public Collection getRules() { 94 | return deps.values(); 95 | } 96 | 97 | /** 98 | * Given a local path to a Maven project, this attempts to find the transitive dependencies of the 99 | * project. 100 | * 101 | * @param projectPath The path to search for Maven projects. 102 | * @param scopes The scopes to look up dependencies in. 103 | */ 104 | public String resolvePomDependencies(String projectPath, Set scopes) { 105 | DefaultModelProcessor processor = new DefaultModelProcessor(); 106 | processor.setModelLocator(new DefaultModelLocator()); 107 | processor.setModelReader(new DefaultModelReader()); 108 | File pom = processor.locatePom(new File(projectPath)); 109 | FileModelSource pomSource = new FileModelSource(pom); 110 | // First resolve the model source locations. 111 | resolveSourceLocations(pomSource); 112 | // Next, fully resolve the models. 113 | Model model = modelResolver.getEffectiveModel(pomSource); 114 | if (model != null) { 115 | traverseDeps(model, scopes, Sets.newHashSet(), null); 116 | } 117 | return pom.getAbsolutePath(); 118 | } 119 | 120 | /** Resolves an artifact as a root of a dependency graph. */ 121 | public void resolveArtifact(String artifactCoord) { 122 | Artifact artifact; 123 | ModelSource modelSource; 124 | try { 125 | artifact = ArtifactBuilder.fromCoords(artifactCoord); 126 | modelSource = modelResolver.resolveModel(artifact); 127 | } catch (UnresolvableModelException | InvalidArtifactCoordinateException e) { 128 | logger.warning(e.getMessage()); 129 | return; 130 | } 131 | 132 | Rule rule = new Rule(artifact); 133 | rule.setRepository(modelSource.getLocation()); 134 | rule.setSha1(downloadSha1(rule)); 135 | deps.put(rule.name(), rule); // add the artifact rule to the workspace 136 | Model model = modelResolver.getEffectiveModel(modelSource); 137 | if (model != null) { 138 | traverseDeps(model, Sets.newHashSet(), Sets.newHashSet(), rule); 139 | } 140 | } 141 | 142 | /** 143 | * Resolves all dependencies from a given "model source," which could be either a URL or a local 144 | * file. 145 | */ 146 | @VisibleForTesting 147 | void traverseDeps(Model model, Set scopes, Set exclusions, Rule parent) { 148 | logger.info( 149 | "\tDownloading pom for " 150 | + model.getGroupId() 151 | + ":" 152 | + model.getArtifactId() 153 | + ":" 154 | + model.getVersion()); 155 | for (Repository repo : model.getRepositories()) { 156 | modelResolver.addRepository(repo); 157 | } 158 | 159 | if (model.getDependencyManagement() != null) { 160 | // Dependencies described in the DependencyManagement section of the pom override all others, 161 | // so resolve them first. 162 | for (Dependency dependency : model.getDependencyManagement().getDependencies()) { 163 | restriction.put( 164 | Rule.name(dependency.getGroupId(), dependency.getArtifactId()), 165 | dependency.getVersion()); 166 | } 167 | } 168 | for (Dependency dependency : model.getDependencies()) { 169 | addDependency(dependency, model, scopes, exclusions, parent); 170 | } 171 | } 172 | 173 | private void addDependency( 174 | Dependency dependency, 175 | Model model, 176 | Set topLevelScopes, 177 | Set exclusions, 178 | @Nullable Rule parent) { 179 | String scope = dependency.getScope(); 180 | // DependencyManagement dependencies don't have scope. 181 | if (scope != null) { 182 | if (parent == null) { 183 | // Top-level scopes get pulled in based on the user-provided scopes. 184 | if (!topLevelScopes.contains(scope)) { 185 | return; 186 | } 187 | } else { 188 | // TODO (bazel-devel): Relabel the scope of transitive dependencies so that they match how 189 | // maven relabels them as described here: 190 | // https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html 191 | if (!INHERITED_SCOPES.contains(scope)) { 192 | return; 193 | } 194 | } 195 | } 196 | if (dependency.isOptional()) { 197 | return; 198 | } 199 | if (exclusions.contains(unversionedCoordinate(dependency))) { 200 | return; 201 | } 202 | try { 203 | Rule artifactRule = 204 | new Rule(ArtifactBuilder.fromMavenDependency(dependency, versionResolver)); 205 | HashSet localDepExclusions = Sets.newHashSet(exclusions); 206 | dependency 207 | .getExclusions() 208 | .forEach(exclusion -> localDepExclusions.add(unversionedCoordinate(exclusion))); 209 | 210 | boolean isNewDependency = addArtifact(artifactRule, model.toString()); 211 | if (isNewDependency) { 212 | ModelSource depModelSource = 213 | modelResolver.resolveModel( 214 | dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion()); 215 | if (depModelSource != null) { 216 | artifactRule.setRepository(depModelSource.getLocation()); 217 | artifactRule.setSha1(downloadSha1(artifactRule)); 218 | Model depModel = modelResolver.getEffectiveModel(depModelSource); 219 | if (depModel != null) { 220 | traverseDeps(depModel, topLevelScopes, localDepExclusions, artifactRule); 221 | } 222 | } else { 223 | logger.warning("Could not get a model for " + dependency); 224 | } 225 | } 226 | 227 | if (parent == null) { 228 | addArtifact(artifactRule, TOP_LEVEL_ARTIFACT); 229 | } else { 230 | parent.addDependency(artifactRule); 231 | parent.getDependencies().addAll(artifactRule.getDependencies()); 232 | } 233 | } catch (UnresolvableModelException | InvalidArtifactCoordinateException e) { 234 | logger.warning( 235 | "Could not resolve dependency " 236 | + dependency.getGroupId() 237 | + ":" 238 | + dependency.getArtifactId() 239 | + ":" 240 | + dependency.getVersion() 241 | + ": " 242 | + e.getMessage()); 243 | } 244 | } 245 | 246 | /** Find the POM files for a given pom's parent(s) and submodules. */ 247 | private void resolveSourceLocations(FileModelSource fileModelSource) { 248 | Model model = modelResolver.getRawModel(fileModelSource); 249 | if (model == null) { 250 | return; 251 | } 252 | 253 | // Self. 254 | Parent parent = model.getParent(); 255 | if (model.getGroupId() == null) { 256 | model.setGroupId(parent.getGroupId()); 257 | } 258 | if (!modelResolver.putModelSource(model.getGroupId(), model.getArtifactId(), fileModelSource)) { 259 | return; 260 | } 261 | 262 | // Parent. 263 | File pomDirectory = new File(fileModelSource.getLocation()).getParentFile(); 264 | if (parent != null && !parent.getArtifactId().equals(model.getArtifactId())) { 265 | File parentPom; 266 | try { 267 | parentPom = new File(pomDirectory, parent.getRelativePath()).getCanonicalFile(); 268 | } catch (IOException e) { 269 | logger.warning( 270 | "Unable to get canonical path of " + pomDirectory + " and " + parent.getRelativePath()); 271 | return; 272 | } 273 | if (parentPom.exists()) { 274 | resolveSourceLocations(new FileModelSource(parentPom)); 275 | } 276 | } 277 | 278 | // Submodules. 279 | for (String module : model.getModules()) { 280 | resolveSourceLocations(new FileModelSource(new File(pomDirectory, module + "/pom.xml"))); 281 | } 282 | } 283 | 284 | /** 285 | * Adds the artifact to the map of deps, if it is not already there. Returns if the artifact was 286 | * newly added. If the artifact was in the list at a different version, adds an comment about the 287 | * desired version. 288 | */ 289 | private boolean addArtifact(Rule dependency, String parent) { 290 | String artifactName = dependency.name(); 291 | if (deps.containsKey(artifactName)) { 292 | Rule existingDependency = deps.get(artifactName); 293 | // Check that the versions are the same. 294 | if (!existingDependency.version().equals(dependency.version())) { 295 | existingDependency.addParent(parent + " wanted version " + dependency.version()); 296 | } else { 297 | existingDependency.addParent(parent + " got requested version"); 298 | } 299 | return false; 300 | } 301 | 302 | updateVersion(artifactName, dependency); 303 | deps.put(artifactName, dependency); 304 | dependency.addParent(parent); 305 | return true; 306 | } 307 | 308 | /** TODO: this should be removed once this uses Maven's own version resolution. */ 309 | private void updateVersion(String artifactName, Rule dependency) { 310 | VersionRange versionRange; 311 | if (!restriction.containsKey(artifactName)) { 312 | return; 313 | } 314 | String versionRestriction = restriction.get(artifactName); 315 | try { 316 | versionRange = VersionRange.createFromVersionSpec(versionRestriction); 317 | } catch (InvalidVersionSpecificationException e) { 318 | logger.warning( 319 | "Error parsing version " + versionRestriction + ": " + e.getLocalizedMessage()); 320 | // So that this isn't logged over and over. 321 | restriction.remove(artifactName); 322 | return; 323 | } 324 | if (!versionRange.containsVersion(new DefaultArtifactVersion(dependency.version()))) { 325 | try { 326 | dependency.setVersion( 327 | versionResolver.resolveVersion( 328 | dependency.groupId(), dependency.artifactId(), versionRestriction)); 329 | } catch (InvalidArtifactCoordinateException e) { 330 | logger.warning("Error setting version: " + e.getLocalizedMessage()); 331 | } 332 | } 333 | } 334 | 335 | static String getSha1Url(String url, String extension) { 336 | return url.replaceAll(".pom$", "." + extension + ".sha1"); 337 | } 338 | 339 | /** Downloads the SHA-1 for the given artifact. */ 340 | private String downloadSha1(Rule rule) { 341 | String sha1Url = getSha1Url(rule.getUrl(), rule.getArtifact().getExtension()); 342 | try { 343 | InputStream in = httpGet(sha1Url); 344 | return extractSha1(CharStreams.toString(new InputStreamReader(in, Charset.defaultCharset()))); 345 | } catch (IOException e) { 346 | logger.warning("Failed to download the sha1 at " + sha1Url); 347 | } 348 | return null; 349 | } 350 | 351 | static String extractSha1(String sha1Contents) { 352 | return sha1Contents.split("\\s+")[0]; 353 | } 354 | 355 | protected InputStream httpGet(String url) throws IOException { 356 | HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); 357 | connection.setInstanceFollowRedirects(true); 358 | connection.connect(); 359 | return connection.getInputStream(); 360 | } 361 | } 362 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/Rule.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | import com.google.common.base.Preconditions; 18 | import com.google.common.collect.Sets; 19 | import org.eclipse.aether.artifact.Artifact; 20 | 21 | import javax.annotation.Nullable; 22 | import java.lang.invoke.MethodHandles; 23 | import java.util.Objects; 24 | import java.util.Set; 25 | import java.util.logging.Logger; 26 | 27 | /** 28 | * A struct representing the fields of maven_jar to be written to the WORKSPACE file. 29 | */ 30 | //TODO(petros): Kill this after refactoring resolvers. 31 | public final class Rule implements Comparable { 32 | private final static Logger logger = Logger.getLogger( 33 | MethodHandles.lookup().lookupClass().getName()); 34 | static final String MAVEN_CENTRAL_URL = "https://repo1.maven.org/maven2/"; 35 | 36 | private final Artifact artifact; 37 | @Nullable 38 | private final String alias; 39 | private final Set parents; 40 | private final Set exclusions; 41 | private final Set dependencies; 42 | private String version; 43 | private String repository; 44 | private String sha1; 45 | 46 | public Rule(Artifact artifact) { 47 | this(artifact, null); 48 | } 49 | 50 | public Rule(Artifact artifact, String alias) { 51 | this.artifact = artifact; 52 | this.version = artifact.getVersion(); 53 | this.parents = Sets.newHashSet(); 54 | this.dependencies = Sets.newTreeSet(); 55 | this.exclusions = Sets.newHashSet(); 56 | this.repository = MAVEN_CENTRAL_URL; 57 | this.alias = alias; 58 | } 59 | 60 | public void addParent(String parent) { 61 | parents.add(parent); 62 | } 63 | 64 | public void addDependency(Rule dependency) { 65 | dependencies.add(dependency); 66 | } 67 | 68 | public Set getDependencies() { 69 | return dependencies; 70 | } 71 | 72 | public String artifactId() { 73 | return artifact.getArtifactId(); 74 | } 75 | 76 | public String groupId() { 77 | return artifact.getGroupId(); 78 | } 79 | 80 | public String version() { 81 | return version; 82 | } 83 | 84 | public void setVersion(String version) { 85 | this.version = version; 86 | } 87 | 88 | /** 89 | * A unique name for this artifact to use in maven_jar's name attribute. 90 | */ 91 | public String name() { 92 | if (alias != null) { 93 | return alias; 94 | } 95 | return Rule.name(groupId(), artifactId()); 96 | } 97 | 98 | /** 99 | * A unique name for this artifact to use in maven_jar's name attribute. 100 | */ 101 | public static String name(String groupId, String artifactId) { 102 | return groupId.replaceAll("[.-]", "_") + "_" + artifactId.replaceAll("[.-]", "_"); 103 | } 104 | 105 | public Artifact getArtifact() { 106 | return artifact; 107 | } 108 | 109 | public String toMavenArtifactString() { 110 | return groupId() + ":" + artifactId() + ":" + version(); 111 | } 112 | 113 | public void setRepository(String url) { 114 | // url is of the form repository/group/artifact/version/artifact-version.pom. Strip off 115 | // everything after repository/. 116 | int uriStart = url.indexOf(getUri()); 117 | if (uriStart == -1) { 118 | // If url is actually a path to a file, it won't match the URL pattern described above. 119 | // However, in that case we also have no way of fetching the artifact, so we'll print a 120 | // warning. 121 | logger.warning(name() + " was defined in " + url 122 | + " which isn't a repository URL, so we couldn't figure out how to fetch " 123 | + toMavenArtifactString() + " in a general way. You will need to set the \"repository\"" 124 | + " attribute manually"); 125 | } else { 126 | this.repository = url.substring(0, uriStart); 127 | } 128 | } 129 | 130 | public void setSha1(String sha1) { 131 | this.sha1 = sha1; 132 | } 133 | 134 | private String getUri() { 135 | return groupId().replaceAll("\\.", "/") + "/" + artifactId() + "/" + version() + "/" 136 | + artifactId() + "-" + version() + ".pom"; 137 | } 138 | 139 | /** 140 | * @return The artifact's URL. 141 | */ 142 | public String getUrl() { 143 | Preconditions.checkState(repository.endsWith("/")); 144 | return repository + getUri(); 145 | } 146 | 147 | public boolean hasCustomRepository() { 148 | return !MAVEN_CENTRAL_URL.equals(repository); 149 | } 150 | 151 | @Override 152 | public boolean equals(Object o) { 153 | if (this == o) { 154 | return true; 155 | } 156 | if (o == null || getClass() != o.getClass()) { 157 | return false; 158 | } 159 | 160 | Rule rule = (Rule) o; 161 | 162 | return Objects.equals(groupId(), rule.groupId()) 163 | && Objects.equals(artifactId(), rule.artifactId()); 164 | } 165 | 166 | @Override 167 | public int hashCode() { 168 | return Objects.hash(groupId(), artifactId()); 169 | } 170 | 171 | @Override 172 | public int compareTo(Rule o) { 173 | return name().compareTo(o.name()); 174 | } 175 | 176 | public Set getParents() { 177 | return parents; 178 | } 179 | 180 | public String getRepository() { 181 | return repository; 182 | } 183 | 184 | public String getSha1() { 185 | return sha1; 186 | } 187 | 188 | public boolean aliased() { 189 | return alias != null; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/maven/VersionResolver.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | import static com.google.devtools.build.workspace.maven.ArtifactBuilder.InvalidArtifactCoordinateException; 18 | 19 | import com.google.common.annotations.VisibleForTesting; 20 | import java.util.List; 21 | import org.eclipse.aether.artifact.Artifact; 22 | import org.eclipse.aether.resolution.VersionRangeResolutionException; 23 | 24 | /** 25 | * Given a Maven coordinate with a version specification resolves the version of the coordinate in a 26 | * similar fashion as Maven. Version specifications can include hard and soft pins as well as various 27 | * forms of version ranges. When given a version range, Maven selects the highest available version. 28 | * For a soft pin, it selects the pinned version or the nearest valid version. 29 | * 30 | * Documentation on Maven's versioning scheme can be found here: 31 | * http://maven.apache.org/enforcer/enforcer-rules/versionRanges.html 32 | */ 33 | class VersionResolver { 34 | 35 | private final Aether aether; 36 | 37 | VersionResolver(Aether aether) { 38 | this.aether = aether; 39 | } 40 | 41 | /** 42 | * Given a maven coordinate and its version specifications, selects the highest version 43 | * if it is a version range or returns the pinned version if is a hard or soft pin. 44 | * For soft pins, if that version does not exist it selects the nearest version. 45 | */ 46 | String resolveVersion(String groupId, String artifactId, String versionSpec) 47 | throws InvalidArtifactCoordinateException { 48 | 49 | List versions; 50 | try { 51 | versions = requestVersionList(groupId, artifactId, versionSpec); 52 | } catch (VersionRangeResolutionException e) { 53 | String errorMessage = 54 | messageForInvalidArtifact(groupId, artifactId, versionSpec, e.getMessage()); 55 | throw new InvalidArtifactCoordinateException(errorMessage); 56 | } 57 | 58 | if (isInvalidRangeResult(versions)) { 59 | String errorMessage = 60 | messageForInvalidArtifact(groupId, artifactId, versionSpec, "Invalid Range Result"); 61 | throw new InvalidArtifactCoordinateException(errorMessage); 62 | } 63 | return selectVersion(versionSpec, versions); 64 | } 65 | 66 | /** 67 | * Given a set of maven coordinates, obtains a list of valid versions in ascending order. 68 | * Note, for soft pinned versions, it interprets it as the following version range: "[version,)" 69 | */ 70 | private List requestVersionList(String groupId, String artifactId, String versionSpec) 71 | throws VersionRangeResolutionException, InvalidArtifactCoordinateException { 72 | String transformedSpec = makeVersionRange(versionSpec); 73 | Artifact artifact = ArtifactBuilder.fromCoords(groupId, artifactId, transformedSpec); 74 | return aether.requestVersionRange(artifact); 75 | } 76 | 77 | /** 78 | * Given a list of potential valid versions (in ascending order), selects the appropriate version 79 | * based on the following heuristic: (1) If it is a version range, it selects the highest version. 80 | * (2) If it is a soft pinned version, it selects the earliest valid version. 81 | */ 82 | private String selectVersion(String versionSpec, List versions) { 83 | int index = (isVersionRange(versionSpec)) ? versions.size() - 1 : 0; 84 | return versions.get(index); 85 | } 86 | 87 | private boolean isInvalidRangeResult(List result) { 88 | return result == null || result.isEmpty(); 89 | } 90 | 91 | /** default error message */ 92 | private static String messageForInvalidArtifact( 93 | String groupId, String artifactId, String versionSpec, String errorMessage) { 94 | return String.format("Unable to find a version for %s:%s:%s due to %s", 95 | groupId, artifactId, versionSpec, errorMessage); 96 | } 97 | 98 | /** 99 | * Crudely checks whether a version specification is a version range. 100 | * Leaves checks for semantic correctness to maven. 101 | * By definition, any range must start with an open bracket or parenthesis. 102 | */ 103 | @VisibleForTesting 104 | static boolean isVersionRange(String versionSpec) { 105 | return versionSpec.charAt(0) == '(' || versionSpec.charAt(0) == '['; 106 | } 107 | 108 | /** 109 | * Transforms all version specifications into a version range. For soft pinned versions like 110 | * "3.0", it transforms it into "[3.0,)" 111 | */ 112 | private static String makeVersionRange(String versionSpec) { 113 | if (isVersionRange(versionSpec)) { 114 | return versionSpec; 115 | } 116 | // is a soft pinned version. 117 | return String.format("[%s,)", versionSpec); 118 | } 119 | 120 | /** 121 | * Creates a VersionResolver with the default Aether settings. 122 | */ 123 | public static VersionResolver defaultResolver() { 124 | return new VersionResolver(Aether.defaultOption()); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/output/AbstractWriter.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.output; 16 | 17 | import com.google.devtools.build.workspace.maven.Rule; 18 | import java.io.PrintStream; 19 | import java.util.Collection; 20 | import java.util.Set; 21 | 22 | /** 23 | * Basic implementation for output writers. 24 | */ 25 | public abstract class AbstractWriter { 26 | public abstract void write(Collection rules); 27 | 28 | private static final String lineSeparator = System.lineSeparator(); 29 | /** 30 | * Writes the list of sources as a comment to outputStream. 31 | */ 32 | void writeHeader(PrintStream outputStream, String[] argv) { 33 | outputStream.println("# The following dependencies were calculated from:"); 34 | outputStream.println("#"); 35 | outputStream.println("# generate_workspace " + String.join(" ", argv)); 36 | outputStream.print(String.format("%n%n")); 37 | } 38 | 39 | protected String formatMavenJar(Rule rule, String ruleName, String indent) { 40 | if (rule.aliased()) { 41 | // If the rule was aliased, then it is already declared somewhere else and we don't need to 42 | // declare it again. 43 | return ""; 44 | } 45 | StringBuilder builder = new StringBuilder(); 46 | String ending = "\"," + lineSeparator; 47 | for (String parent : rule.getParents()) { 48 | builder.append(indent).append("# ").append(parent).append(lineSeparator); 49 | } 50 | builder.append(indent).append(ruleName).append("(" + lineSeparator); 51 | builder.append(indent).append(" name = \"").append(rule.name()).append(ending); 52 | builder.append(indent).append(" artifact = \"").append(rule.toMavenArtifactString()) 53 | .append(ending); 54 | if (rule.hasCustomRepository()) { 55 | builder.append(indent).append(" repository = \"").append(rule.getRepository()) 56 | .append(ending); 57 | } 58 | if (rule.getSha1() != null) { 59 | builder.append(indent).append(" sha1 = \"").append(rule.getSha1()).append(ending); 60 | } 61 | builder.append(indent).append(String.format(")%n%n")); 62 | return builder.toString(); 63 | } 64 | 65 | /** 66 | * Write library rules to depend on the transitive closure of all of these rules. 67 | */ 68 | protected String formatJavaLibrary(Rule rule, String ruleName, String indent) { 69 | StringBuilder builder = new StringBuilder(); 70 | String ending = "\"," + lineSeparator; 71 | builder.append(indent).append(ruleName).append("(" + lineSeparator); 72 | builder.append(indent).append(" name = \"").append(rule.name()).append(ending); 73 | builder.append(indent).append(" visibility = [\"//visibility:public\"]," + lineSeparator); 74 | builder.append(indent).append(" exports = [\"@").append(rule.name()).append("//jar\"]," + lineSeparator); 75 | Set dependencies = rule.getDependencies(); 76 | if (!dependencies.isEmpty()) { 77 | builder.append(indent).append(" runtime_deps = [" + lineSeparator); 78 | for (Rule r : rule.getDependencies()) { 79 | builder.append(indent).append(" \":").append(r.name()).append(ending); 80 | } 81 | builder.append(indent).append(" ]," + lineSeparator); 82 | } 83 | builder.append(indent).append(String.format(")%n%n")); 84 | return builder.toString(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/output/BUILD: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "output", 3 | srcs = glob(["*.java"]), 4 | visibility = ["//generate_workspace/src:__subpackages__"], 5 | deps = [ 6 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 7 | "//third_party:com_google_guava_guava", 8 | ], 9 | ) 10 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/output/BzlWriter.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.output; 16 | 17 | import com.google.common.annotations.VisibleForTesting; 18 | import com.google.devtools.build.workspace.maven.Rule; 19 | 20 | import java.io.FileNotFoundException; 21 | import java.io.IOException; 22 | import java.io.PrintStream; 23 | import java.lang.invoke.MethodHandles; 24 | import java.nio.file.Files; 25 | import java.nio.file.Path; 26 | import java.nio.file.Paths; 27 | import java.util.Collection; 28 | import java.util.logging.Logger; 29 | 30 | /** 31 | * Writes WORKSPACE and BUILD file definitions to a .bzl file. 32 | */ 33 | public class BzlWriter extends AbstractWriter { 34 | 35 | private final static Logger logger = Logger.getLogger( 36 | MethodHandles.lookup().lookupClass().getName()); 37 | 38 | private final String[] argv; 39 | private final Path generatedFile; 40 | 41 | public BzlWriter(String[] argv, String outputDirStr) { 42 | this.argv = argv; 43 | this.generatedFile = Paths.get(outputDirStr).resolve("generate_workspace.bzl"); 44 | } 45 | 46 | @Override 47 | public void write(Collection rules) { 48 | try { 49 | createParentDirectory(generatedFile); 50 | } catch (IOException | NullPointerException e) { 51 | logger.severe("Could not create directories for " + generatedFile + ": " + e.getMessage()); 52 | return; 53 | } 54 | try (PrintStream outputStream = new PrintStream(generatedFile.toFile())) { 55 | writeBzl(outputStream, rules); 56 | } catch (FileNotFoundException e) { 57 | logger.severe("Could not write " + generatedFile + ": " + e.getMessage()); 58 | return; 59 | } 60 | System.err.println("Wrote " + generatedFile.toAbsolutePath()); 61 | } 62 | 63 | private void writeBzl(PrintStream outputStream, Collection rules) { 64 | writeHeader(outputStream, argv); 65 | outputStream.println("def generated_maven_jars():"); 66 | if (rules.isEmpty()) { 67 | outputStream.println(String.format(" pass%n")); 68 | } 69 | for (Rule rule : rules) { 70 | outputStream.println(formatMavenJar(rule, "native.maven_jar", " ")); 71 | } 72 | 73 | outputStream.append(String.format("%n%n")); 74 | 75 | outputStream.println("def generated_java_libraries():"); 76 | if (rules.isEmpty()) { 77 | outputStream.println(String.format(" pass%n")); 78 | } 79 | for (Rule rule : rules) { 80 | outputStream.println(formatJavaLibrary(rule, "native.java_library", " ")); 81 | } 82 | } 83 | 84 | /** Creates parent directories if they don't exist */ 85 | @VisibleForTesting 86 | void createParentDirectory(Path generatedFile) throws IOException { 87 | Path parentDirectory = generatedFile.toAbsolutePath().getParent(); 88 | if (Files.exists(parentDirectory)) { 89 | return; 90 | } 91 | Files.createDirectories(parentDirectory); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /generate_workspace/src/main/java/com/google/devtools/build/workspace/output/WorkspaceWriter.java: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.output; 16 | 17 | import com.google.devtools.build.workspace.maven.Rule; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.io.PrintStream; 22 | import java.lang.invoke.MethodHandles; 23 | import java.nio.file.Files; 24 | import java.nio.file.Path; 25 | import java.nio.file.Paths; 26 | import java.text.SimpleDateFormat; 27 | import java.util.Collection; 28 | import java.util.Date; 29 | import java.util.logging.Logger; 30 | 31 | /** 32 | * Write a set of rules to a WORKSPACE and BUILD file. 33 | */ 34 | public class WorkspaceWriter extends AbstractWriter { 35 | private final static Logger logger = Logger.getLogger( 36 | MethodHandles.lookup().lookupClass().getName()); 37 | 38 | private final String[] args; 39 | private final File workspaceFile; 40 | private final File buildFile; 41 | 42 | public WorkspaceWriter(String[] args, String outputDirStr) throws IOException { 43 | this.args = args; 44 | Path outputDir; 45 | if (outputDirStr.isEmpty()) { 46 | outputDir = Files.createTempDirectory("generate_workspace"); 47 | } else { 48 | outputDir = Paths.get(outputDirStr); 49 | } 50 | String date = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); 51 | File tempWorkspaceFile = outputDir.resolve("WORKSPACE").toFile(); 52 | File tempBuildFile = outputDir.resolve("BUILD").toFile(); 53 | 54 | // Don't overwrite existing files with generated ones. 55 | if (tempWorkspaceFile.exists()) { 56 | workspaceFile = outputDir.resolve(date + ".WORKSPACE").toFile(); 57 | } else { 58 | workspaceFile = tempWorkspaceFile; 59 | } 60 | if (tempBuildFile.exists()) { 61 | buildFile = outputDir.resolve(date + ".BUILD").toFile(); 62 | } else { 63 | buildFile = tempBuildFile; 64 | } 65 | } 66 | 67 | @Override 68 | public void write(Collection rules) { 69 | try (PrintStream workspaceStream = new PrintStream(workspaceFile); 70 | PrintStream buildStream = new PrintStream(buildFile)) { 71 | writeWorkspace(workspaceStream, rules); 72 | writeBuild(buildStream, rules); 73 | } catch (IOException e) { 74 | logger.severe( 75 | "Could not write WORKSPACE and BUILD files to " + buildFile.getParent() + ": " 76 | + e.getMessage()); 77 | return; 78 | } 79 | System.err.println("Wrote:\n" + workspaceFile + "\n" + buildFile); 80 | } 81 | 82 | /** 83 | * Writes all resolved dependencies in WORKSPACE file format to the outputStream. 84 | */ 85 | public void writeWorkspace(PrintStream outputStream, Collection rules) { 86 | writeHeader(outputStream, args); 87 | for (Rule rule : rules) { 88 | outputStream.println(formatMavenJar(rule, "maven_jar", "")); 89 | } 90 | } 91 | 92 | public void writeBuild(PrintStream outputStream, Collection rules) { 93 | writeHeader(outputStream, args); 94 | for (Rule rule : rules) { 95 | outputStream.println(formatJavaLibrary(rule, "java_library", "")); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/BUILD: -------------------------------------------------------------------------------- 1 | java_test( 2 | name = "GenerateWorkspaceOptionsTest", 3 | srcs = ["GenerateWorkspaceOptionsTest.java"], 4 | deps = [ 5 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace", 6 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 7 | "//third_party:com_google_truth_truth", 8 | "//third_party:junit_junit", 9 | "//third_party/jcommander", 10 | ], 11 | ) 12 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/GenerateWorkspaceOptionsTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace; 16 | 17 | import static com.google.common.truth.Truth.assertThat; 18 | 19 | import com.beust.jcommander.JCommander; 20 | import com.google.devtools.build.workspace.maven.Rule; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.junit.runners.JUnit4; 24 | 25 | /** Tests for option parsing. */ 26 | @RunWith(JUnit4.class) 27 | public class GenerateWorkspaceOptionsTest { 28 | @Test 29 | public void equalsSeparator() throws Exception { 30 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 31 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 32 | optionParser.parse("--artifact=foo:bar:1.2.3"); 33 | assertThat(options.artifacts).contains("foo:bar:1.2.3"); 34 | } 35 | 36 | @Test 37 | public void spaceSeparator() throws Exception { 38 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 39 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 40 | optionParser.parse("--artifact", "foo:bar:1.2.3"); 41 | assertThat(options.artifacts).contains("foo:bar:1.2.3"); 42 | } 43 | 44 | @Test 45 | public void noCommaDelimiter() throws Exception { 46 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 47 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 48 | optionParser.parse("--artifact", "foo:bar:[1.2.3,)"); 49 | assertThat(options.artifacts).contains("foo:bar:[1.2.3,)"); 50 | } 51 | 52 | @Test 53 | public void multipleArtifacts() throws Exception { 54 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 55 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 56 | optionParser.parse("--artifact", "a:b1:[1.2,2.0]", "--artifact", "a:b2:[1.0,2.0)"); 57 | assertThat(options.artifacts).containsExactly("a:b1:[1.2,2.0]", "a:b2:[1.0,2.0)"); 58 | } 59 | 60 | @Test 61 | public void repository() throws Exception { 62 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 63 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 64 | optionParser.parse("--repositories", "http://central.maven.org/maven2/"); 65 | assertThat(options.repositories).contains("http://central.maven.org/maven2/"); 66 | } 67 | 68 | @Test 69 | public void multipleRepositories() throws Exception { 70 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 71 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 72 | optionParser.parse( 73 | "--repositories", "http://central.maven.org/maven2/,http://repo.spring.io/libs-milestone/"); 74 | assertThat(options.repositories) 75 | .containsExactly( 76 | "http://central.maven.org/maven2/", "http://repo.spring.io/libs-milestone/"); 77 | } 78 | 79 | @Test 80 | public void alias() throws Exception { 81 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 82 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 83 | optionParser.parse("--declare=a:b=c"); 84 | assertThat(options.aliases).hasSize(1); 85 | Rule aliasedRule = options.aliases.get(0); 86 | assertThat(aliasedRule.name()).isEqualTo("c"); 87 | assertThat(aliasedRule.toMavenArtifactString()).isEqualTo("a:b:0"); 88 | } 89 | 90 | @Test 91 | public void versionedAlias() throws Exception { 92 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 93 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 94 | optionParser.parse("--declare=a:b:1.2.3=c"); 95 | assertThat(options.aliases).hasSize(1); 96 | Rule aliasedRule = options.aliases.get(0); 97 | assertThat(aliasedRule.name()).isEqualTo("c"); 98 | assertThat(aliasedRule.toMavenArtifactString()).isEqualTo("a:b:1.2.3"); 99 | } 100 | 101 | @Test 102 | public void declareDefault() throws Exception { 103 | GenerateWorkspaceOptions options = new GenerateWorkspaceOptions(); 104 | JCommander optionParser = JCommander.newBuilder().addObject(options).build(); 105 | optionParser.parse("--declare=a:b"); 106 | assertThat(options.aliases).hasSize(1); 107 | Rule aliasedRule = options.aliases.get(0); 108 | assertThat(aliasedRule.name()).isEqualTo("a_b"); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/maven/AetherGraphTraverserTest.java: -------------------------------------------------------------------------------- 1 | package com.google.devtools.build.workspace.maven; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.google.common.graph.Graph; 5 | import com.google.common.graph.GraphBuilder; 6 | import com.google.common.graph.MutableGraph; 7 | import org.eclipse.aether.artifact.DefaultArtifact; 8 | import org.eclipse.aether.graph.DefaultDependencyNode; 9 | import org.eclipse.aether.graph.Dependency; 10 | import org.eclipse.aether.graph.DependencyNode; 11 | import org.eclipse.aether.util.artifact.JavaScopes; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.junit.runners.JUnit4; 15 | 16 | import static com.google.common.truth.Truth.assertThat; 17 | 18 | /** 19 | * Tests for {@link AetherGraphTraverser}. 20 | */ 21 | @RunWith(JUnit4.class) 22 | public class AetherGraphTraverserTest { 23 | 24 | @Test 25 | public void testBasicGraphConstruction() { 26 | DependencyNode root = dependencyNode("root:root:1"); 27 | DependencyNode depA = dependencyNode("a:a:1"); 28 | DependencyNode depB = dependencyNode("b:b:1"); 29 | 30 | root.setChildren(ImmutableList.of(depA, depB)); 31 | 32 | MavenJarRule rootRule = new MavenJarRule(root); 33 | MavenJarRule aRule = new MavenJarRule(depA); 34 | MavenJarRule bRule = new MavenJarRule(depB); 35 | 36 | MutableGraph expected = newGraph(); 37 | addEdge(expected, rootRule, aRule); 38 | addEdge(expected, rootRule, bRule); 39 | 40 | // Construct the graph 41 | MutableGraph actual = newGraph(); 42 | AetherGraphTraverser visitor = new AetherGraphTraverser(actual); 43 | root.accept(visitor); 44 | 45 | assertThatGraphsEqual(actual, expected); 46 | } 47 | 48 | /** 49 | * Asserts that when the dependency visitor is accepted by multiple 50 | * nodes, the constructed graph contains nodes and edges from all visits. 51 | */ 52 | @Test 53 | public void testAccumulation() { 54 | DependencyNode rootNodeA = dependencyNode("a:a1:1"); 55 | DependencyNode childNodeA = dependencyNode("a:a2:1"); 56 | DependencyNode rootNodeB = dependencyNode("b:b1:1"); 57 | DependencyNode childNodeB = dependencyNode("b:b2:1"); 58 | 59 | rootNodeA.setChildren(ImmutableList.of(childNodeA)); 60 | rootNodeB.setChildren(ImmutableList.of(childNodeB)); 61 | 62 | MavenJarRule rootRuleA = new MavenJarRule(rootNodeA); 63 | MavenJarRule childRuleA = new MavenJarRule(childNodeA); 64 | MavenJarRule rootRuleB = new MavenJarRule(rootNodeB); 65 | MavenJarRule childRuleB = new MavenJarRule(childNodeB); 66 | 67 | MutableGraph expected = newGraph(); 68 | addEdge(expected, rootRuleA, childRuleA); 69 | addEdge(expected, rootRuleB, childRuleB); 70 | 71 | // Construct the graph 72 | MutableGraph actual = newGraph(); 73 | AetherGraphTraverser visitor = new AetherGraphTraverser(actual); 74 | rootNodeA.accept(visitor); 75 | rootNodeB.accept(visitor); 76 | 77 | assertThatGraphsEqual(actual, expected); 78 | } 79 | 80 | /** 81 | * Tests behavior when there is a duplicate dependency node within the graph, meaning 82 | * two nodes with the same maven coordinate. The generated graph should not contain 83 | * multiple instances of that node. 84 | */ 85 | @Test 86 | public void testDuplicateChildren() { 87 | DependencyNode rootNodeA = dependencyNode("a:a:1"); 88 | DependencyNode rootNodeB = dependencyNode("b:b:1"); 89 | DependencyNode childNode = dependencyNode("c:c:1"); 90 | DependencyNode childNodeDuplicate = dependencyNode("c:c:1"); 91 | 92 | rootNodeA.setChildren(ImmutableList.of(childNode)); 93 | rootNodeB.setChildren(ImmutableList.of(childNode)); 94 | rootNodeA.setChildren(ImmutableList.of(childNodeDuplicate)); 95 | rootNodeB.setChildren(ImmutableList.of(childNodeDuplicate)); 96 | 97 | MavenJarRule rootRuleA = new MavenJarRule(rootNodeA); 98 | MavenJarRule childRule = new MavenJarRule(childNode); 99 | MavenJarRule rootRuleB = new MavenJarRule(rootNodeB); 100 | 101 | MutableGraph expected = newGraph(); 102 | addEdge(expected, rootRuleA, childRule); 103 | addEdge(expected, rootRuleB, childRule); 104 | 105 | // Construct the graph 106 | MutableGraph actual = newGraph(); 107 | AetherGraphTraverser visitor = new AetherGraphTraverser(actual); 108 | rootNodeA.accept(visitor); 109 | rootNodeB.accept(visitor); 110 | 111 | assertThatGraphsEqual(actual, expected); 112 | } 113 | 114 | private void assertThatGraphsEqual(Graph actual, Graph expected) { 115 | assertThat(actual.nodes()).containsExactlyElementsIn(expected.nodes()); 116 | assertThat(actual.edges()).containsExactlyElementsIn(expected.edges()); 117 | } 118 | 119 | private void addEdge(MutableGraph graph, MavenJarRule src, MavenJarRule dst) { 120 | graph.putEdge(src, dst); 121 | src.addDependency(dst); 122 | dst.addParent(src); 123 | } 124 | 125 | /** Helper for creating a dependency node */ 126 | private DependencyNode dependencyNode(String coordinate) { 127 | Dependency dependency = new Dependency(new DefaultArtifact(coordinate), JavaScopes.COMPILE); 128 | return new DefaultDependencyNode(dependency); 129 | } 130 | 131 | private MutableGraph newGraph() { 132 | return GraphBuilder.directed().allowsSelfLoops(false).build(); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/maven/BUILD: -------------------------------------------------------------------------------- 1 | java_test( 2 | name = "RuleTest", 3 | srcs = ["RuleTest.java"], 4 | deps = [ 5 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 6 | "//third_party:com_google_truth_truth", 7 | "//third_party:junit_junit", 8 | ], 9 | ) 10 | 11 | java_test( 12 | name = "ResolverTest", 13 | srcs = ["ResolverTest.java"], 14 | deps = [ 15 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 16 | "//third_party:aether", 17 | "//third_party:com_google_guava_guava", 18 | "//third_party:com_google_truth_truth", 19 | "//third_party:junit_junit", 20 | "//third_party:maven_model", 21 | "//third_party:org_mockito_mockito_all", 22 | ], 23 | ) 24 | 25 | java_test( 26 | name = "AetherGraphTraverserTest", 27 | srcs = ["AetherGraphTraverserTest.java"], 28 | deps = [ 29 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 30 | "//third_party:aether", 31 | "//third_party:com_google_guava_guava", 32 | "//third_party:com_google_truth_truth", 33 | "//third_party:junit_junit", 34 | "//third_party:org_mockito_mockito_all", 35 | ], 36 | ) 37 | 38 | java_test( 39 | name = "GraphSerializerTest", 40 | srcs = ["GraphSerializerTest.java"], 41 | deps = [ 42 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 43 | "//third_party:aether", 44 | "//third_party:com_google_guava_guava", 45 | "//third_party:com_google_truth_truth", 46 | "//third_party:junit_junit", 47 | "//third_party:org_mockito_mockito_all", 48 | ], 49 | ) 50 | 51 | java_test( 52 | name = "VersionResolverTest", 53 | srcs = ["VersionResolverTest.java"], 54 | deps = [ 55 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 56 | "//third_party:aether", 57 | "//third_party:maven_model", 58 | "@com_google_guava_guava//jar", 59 | "@com_google_truth_truth//jar", 60 | "@junit_junit//jar", 61 | "@org_mockito_mockito_all//jar", 62 | ] 63 | ) -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/maven/GraphSerializerTest.java: -------------------------------------------------------------------------------- 1 | package com.google.devtools.build.workspace.maven; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.google.common.collect.Maps; 5 | import org.eclipse.aether.artifact.DefaultArtifact; 6 | import org.eclipse.aether.graph.DefaultDependencyNode; 7 | import org.eclipse.aether.graph.Dependency; 8 | import org.eclipse.aether.graph.DependencyNode; 9 | import org.eclipse.aether.util.artifact.JavaScopes; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.junit.runners.JUnit4; 13 | 14 | import java.util.Arrays; 15 | import java.util.Map; 16 | import java.util.Set; 17 | 18 | import static com.google.common.truth.Truth.assertThat; 19 | 20 | /** 21 | * Tests for {@link AetherGraphTraverser}. 22 | */ 23 | @RunWith(JUnit4.class) 24 | public class GraphSerializerTest { 25 | 26 | /** 27 | * Ensures that the generated rules preserve dependency relations 28 | * (i.e. parent, child sets). This will be used to generate the deps field. 29 | */ 30 | @Test 31 | public void testBasicParentChildRelations() { 32 | DependencyNode sentinel = dependencyNode("dummy:dummy:0"); 33 | DependencyNode parentNode = dependencyNode("a:a:1"); 34 | DependencyNode childNode = dependencyNode("a:2:1"); 35 | 36 | sentinel.setChildren(ImmutableList.of(parentNode)); 37 | parentNode.setChildren(ImmutableList.of(childNode)); 38 | 39 | MavenJarRule parent = new MavenJarRule(parentNode); 40 | MavenJarRule child = new MavenJarRule(childNode); 41 | addDependency(parent, child); 42 | 43 | Set actual = GraphSerializer.generateBuildRules(sentinel); 44 | 45 | assertRuleSetContainsExactly(actual, parent, child); 46 | } 47 | 48 | @Test 49 | public void testMultipleDirectDependencies() { 50 | DependencyNode sentinel = dependencyNode("dummy:dummy:0"); 51 | DependencyNode nodeA = dependencyNode("a:a:1"); 52 | DependencyNode nodeA1 = dependencyNode("a:1:1"); 53 | DependencyNode nodeB = dependencyNode("b:b:1"); 54 | DependencyNode nodeC = dependencyNode("c:c:1"); 55 | 56 | sentinel.setChildren(ImmutableList.of(nodeA, nodeB, nodeC)); 57 | nodeA.setChildren(ImmutableList.of(nodeA1)); 58 | 59 | Set rules = GraphSerializer.generateBuildRules(sentinel); 60 | 61 | MavenJarRule ruleA = new MavenJarRule(nodeA); 62 | MavenJarRule ruleA1 = new MavenJarRule(nodeA1); 63 | MavenJarRule ruleB = new MavenJarRule(nodeB); 64 | MavenJarRule ruleC = new MavenJarRule(nodeC); 65 | addDependency(ruleA, ruleA1); 66 | 67 | assertRuleSetContainsExactly(rules, ruleA, ruleA1, ruleB, ruleC); 68 | } 69 | 70 | @Test 71 | public void testSharedChild() { 72 | DependencyNode sentinel = dependencyNode("dummy:dummy:0"); 73 | DependencyNode nodeA = dependencyNode("a:a:1"); 74 | DependencyNode nodeB = dependencyNode("b:b:1"); 75 | DependencyNode child = dependencyNode("child:child:1"); 76 | 77 | sentinel.setChildren(ImmutableList.of(nodeA, nodeB)); 78 | nodeA.setChildren(ImmutableList.of(child)); 79 | nodeB.setChildren(ImmutableList.of(child)); 80 | 81 | Set rules = GraphSerializer.generateBuildRules(sentinel); 82 | 83 | MavenJarRule ruleA = new MavenJarRule(nodeA); 84 | MavenJarRule ruleB = new MavenJarRule(nodeB); 85 | MavenJarRule childRule = new MavenJarRule(child); 86 | addDependency(ruleA, childRule); 87 | addDependency(ruleB, childRule); 88 | 89 | assertRuleSetContainsExactly(rules, ruleA, ruleB, childRule); 90 | 91 | } 92 | 93 | /** 94 | * Augments the definition of equality between two rules to include 95 | * identical sets of parents and children. 96 | */ 97 | private void assertRuleSetContainsExactly(Set actual, MavenJarRule... rules) { 98 | assertThat(actual).containsExactlyElementsIn(Arrays.asList(rules)); 99 | Map ruleMap = convertSetToMap(actual); 100 | for (MavenJarRule rule : rules) { 101 | MavenJarRule actualRule = ruleMap.get(rule); 102 | assertThat(actualRule.getParents()).containsExactlyElementsIn(rule.getParents()); 103 | assertThat(actualRule.getDependencies()).containsExactlyElementsIn(rule.getDependencies()); 104 | } 105 | } 106 | 107 | private void addDependency(MavenJarRule parent, MavenJarRule child) { 108 | parent.addDependency(child); 109 | child.addParent(parent); 110 | } 111 | 112 | private Map convertSetToMap(Set rules) { 113 | Map map = Maps.newHashMap(); 114 | rules.forEach(rule -> map.put(rule, rule)); 115 | return map; 116 | } 117 | 118 | /** Helper for creating a dependency node */ 119 | private DependencyNode dependencyNode(String coordinate) { 120 | Dependency dependency = new Dependency(new DefaultArtifact(coordinate), JavaScopes.COMPILE); 121 | return new DefaultDependencyNode(dependency); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/maven/ResolverTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | import static com.google.common.collect.Lists.newArrayList; 18 | import static com.google.common.truth.Truth.assertThat; 19 | import static com.google.devtools.build.workspace.maven.ArtifactBuilder.fromCoords; 20 | import static org.mockito.Mockito.mock; 21 | import static org.mockito.Mockito.when; 22 | 23 | import com.google.common.base.Preconditions; 24 | import com.google.common.collect.ImmutableList; 25 | import com.google.common.collect.Sets; 26 | import java.io.ByteArrayInputStream; 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | import java.net.URL; 30 | import java.util.Collection; 31 | import java.util.List; 32 | import java.util.Set; 33 | import java.util.stream.Collectors; 34 | import org.apache.maven.model.Dependency; 35 | import org.apache.maven.model.DependencyManagement; 36 | import org.apache.maven.model.Model; 37 | import org.apache.maven.model.building.UrlModelSource; 38 | import org.eclipse.aether.artifact.DefaultArtifact; 39 | import org.junit.Test; 40 | import org.junit.runner.RunWith; 41 | import org.junit.runners.JUnit4; 42 | 43 | /** Tests for {@link Resolver}. */ 44 | @RunWith(JUnit4.class) 45 | public class ResolverTest { 46 | private static final String GROUP_ID = "x"; 47 | private static final String ARTIFACT_ID = "y"; 48 | private static final List ALIASES = ImmutableList.of(); 49 | 50 | @Test 51 | public void testGetSha1Url() throws Exception { 52 | assertThat(Resolver.getSha1Url("http://example.com/foo.pom", "jar")) 53 | .isEqualTo("http://example.com/foo.jar.sha1"); 54 | assertThat(Resolver.getSha1Url("http://example.com/foo.pom", "aar")) 55 | .isEqualTo("http://example.com/foo.aar.sha1"); 56 | } 57 | 58 | @Test 59 | public void testGetSha1UrlOnlyAtEOL() throws Exception { 60 | assertThat(Resolver.getSha1Url("http://example.pom/foo.pom", "jar")) 61 | .isEqualTo("http://example.pom/foo.jar.sha1"); 62 | } 63 | 64 | @Test 65 | public void testArtifactResolution() throws Exception { 66 | String coords = "x:y:1.2.3"; 67 | DefaultModelResolver modelResolver = mock(DefaultModelResolver.class); 68 | when(modelResolver.resolveModel(fromCoords(coords))) 69 | .thenReturn(new UrlModelSource(new URL("http://repo.foo.org/maven/x/y/1.2.3/y-1.2.3.pom"))); 70 | String httpGetBody = "5fe28b9518e58819180a43a850fbc0dd24b7c050"; 71 | Resolver resolver = 72 | new Resolver(modelResolver, ALIASES) { 73 | protected InputStream httpGet(String url) throws IOException { 74 | return new ByteArrayInputStream(httpGetBody.getBytes()); 75 | } 76 | }; 77 | resolver.resolveArtifact(coords); 78 | 79 | Collection rules = resolver.getRules(); 80 | assertThat(rules).hasSize(1); 81 | Rule rule = rules.iterator().next(); 82 | assertThat(rule.name()).isEqualTo("x_y"); 83 | assertThat(rule.getRepository()).isEqualTo("http://repo.foo.org/maven/"); 84 | assertThat(rule.getSha1()).isEqualTo("5fe28b9518e58819180a43a850fbc0dd24b7c050"); 85 | } 86 | 87 | @Test 88 | public void testExtractSha1() { 89 | assertThat(Resolver.extractSha1("5fe28b9518e58819180a43a850fbc0dd24b7c050")) 90 | .isEqualTo("5fe28b9518e58819180a43a850fbc0dd24b7c050"); 91 | 92 | assertThat(Resolver.extractSha1("5fe28b9518e58819180a43a850fbc0dd24b7c050\n")) 93 | .isEqualTo("5fe28b9518e58819180a43a850fbc0dd24b7c050"); 94 | 95 | assertThat( 96 | Resolver.extractSha1( 97 | "83cd2cd674a217ade95a4bb83a8a14f351f48bd0 /home/maven/repository-staging/to-ibiblio/maven2/antlr/antlr/2.7.7/antlr-2.7.7.jar")) 98 | .isEqualTo("83cd2cd674a217ade95a4bb83a8a14f351f48bd0"); 99 | } 100 | 101 | private Dependency getDependency(String coordinates) { 102 | return getDependency(coordinates, "compile"); 103 | } 104 | 105 | private Dependency getDependency(String coordinates, String scope) { 106 | String[] coordinateArray = coordinates.split(":"); 107 | Preconditions.checkState(coordinateArray.length == 3); 108 | Dependency dependency = new Dependency(); 109 | dependency.setGroupId(coordinateArray[0]); 110 | dependency.setArtifactId(coordinateArray[1]); 111 | dependency.setVersion(coordinateArray[2]); 112 | dependency.setScope(scope); 113 | return dependency; 114 | } 115 | 116 | private Model mockDepManagementModel(String dependencyManagementDep, String normalDep) { 117 | Dependency dmDep = getDependency(dependencyManagementDep); 118 | Dependency dep = getDependency(normalDep); 119 | 120 | Model mockModel = mock(Model.class); 121 | DependencyManagement dependencyManagement = new DependencyManagement(); 122 | dependencyManagement.addDependency(dmDep); 123 | when(mockModel.getDependencyManagement()).thenReturn(dependencyManagement); 124 | when(mockModel.getDependencies()).thenReturn(ImmutableList.of(dep)); 125 | return mockModel; 126 | } 127 | 128 | @Test 129 | public void dependencyManagementWins() throws Exception { 130 | Aether aether = mock(Aether.class); 131 | when(aether.requestVersionRange(fromCoords("a:b:[1.0]"))).thenReturn(newArrayList("1.0")); 132 | when(aether.requestVersionRange(fromCoords("a:b:[2.0,)"))).thenReturn(newArrayList("2.0")); 133 | VersionResolver versionResolver = new VersionResolver(aether); 134 | 135 | Resolver resolver = new Resolver(mock(DefaultModelResolver.class), versionResolver, ALIASES); 136 | resolver.traverseDeps( 137 | mockDepManagementModel("a:b:[1.0]", "a:b:2.0"), 138 | Sets.newHashSet(), 139 | Sets.newHashSet(), 140 | new Rule(new DefaultArtifact("par:ent:1.2.3"))); 141 | Collection rules = resolver.getRules(); 142 | assertThat(rules).hasSize(1); 143 | Rule actual = rules.iterator().next(); 144 | assertThat(actual.version()).isEqualTo("1.0"); 145 | } 146 | 147 | @Test 148 | public void nonConflictingDepManagement() throws Exception { 149 | Aether aether = mock(Aether.class); 150 | when(aether.requestVersionRange(fromCoords("a:b:[1.0,4.0]"))) 151 | .thenReturn(newArrayList("1.0", "2.0", "3.0", "4.0")); 152 | when(aether.requestVersionRange(fromCoords("a:b:[2.0,)"))) 153 | .thenReturn(newArrayList("2.0", "3.0")); 154 | VersionResolver versionResolver = new VersionResolver(aether); 155 | 156 | Resolver resolver = new Resolver(mock(DefaultModelResolver.class), versionResolver, ALIASES); 157 | resolver.traverseDeps( 158 | mockDepManagementModel("a:b:[1.0, 4.0]", "a:b:2.0"), 159 | Sets.newHashSet(), 160 | Sets.newHashSet(), 161 | new Rule(new DefaultArtifact("par:ent:1.2.3"))); 162 | Collection rules = resolver.getRules(); 163 | assertThat(rules).hasSize(1); 164 | Rule actual = rules.iterator().next(); 165 | assertThat(actual.version()).isEqualTo("2.0"); 166 | } 167 | 168 | @Test 169 | public void nonConflictingDepManagementRange() throws Exception { 170 | Aether aether = mock(Aether.class); 171 | when(aether.requestVersionRange(fromCoords("a:b:[1.0,4.0]"))) 172 | .thenReturn(newArrayList("1.0", "1.2", "2.0", "3.0", "4.0")); 173 | when(aether.requestVersionRange(fromCoords("a:b:[1.2,3.0]"))) 174 | .thenReturn(newArrayList("1.2", "2.0", "3.0")); 175 | VersionResolver versionResolver = new VersionResolver(aether); 176 | 177 | Resolver resolver = new Resolver(mock(DefaultModelResolver.class), versionResolver, ALIASES); 178 | resolver.traverseDeps( 179 | mockDepManagementModel("a:b:[1.0,4.0]", "a:b:[1.2,3.0]"), 180 | Sets.newHashSet(), 181 | Sets.newHashSet(), 182 | new Rule(new DefaultArtifact("par:ent:1.2.3"))); 183 | Collection rules = resolver.getRules(); 184 | assertThat(rules).hasSize(1); 185 | Rule actual = rules.iterator().next(); 186 | assertThat(actual.version()).isEqualTo("3.0"); 187 | } 188 | 189 | @Test 190 | public void depManagementDoesntAddDeps() throws Exception { 191 | Aether aether = mock(Aether.class); 192 | when(aether.requestVersionRange(fromCoords("c:d:[2.0,)"))).thenReturn(newArrayList("2.0")); 193 | when(aether.requestVersionRange(fromCoords("a:b:[1.0,)"))) 194 | .thenReturn(newArrayList("1.0", "2.0")); 195 | VersionResolver versionResolver = new VersionResolver(aether); 196 | 197 | Resolver resolver = new Resolver(mock(DefaultModelResolver.class), versionResolver, ALIASES); 198 | resolver.traverseDeps( 199 | mockDepManagementModel("a:b:1.0", "c:d:2.0"), 200 | Sets.newHashSet(), 201 | Sets.newHashSet(), 202 | new Rule(new DefaultArtifact("par:ent:1.2.3"))); 203 | Collection rules = resolver.getRules(); 204 | assertThat(rules).hasSize(1); 205 | Rule actual = rules.iterator().next(); 206 | assertThat(actual.name()).isEqualTo("c_d"); 207 | } 208 | 209 | @Test 210 | public void scopesHonoredForRoot() throws Exception { 211 | Model mockModel = mock(Model.class); 212 | // Only "compile" should go through. 213 | when(mockModel.getDependencies()) 214 | .thenReturn( 215 | ImmutableList.of( 216 | getDependency("a:b:1.0", "compile"), getDependency("c:d:1.0", "test"))); 217 | 218 | Aether aether = mock(Aether.class); 219 | when(aether.requestVersionRange(fromCoords("a:b:[1.0,)"))).thenReturn(newArrayList("1.0")); 220 | when(aether.requestVersionRange(fromCoords("c:d:[1.0,)"))).thenReturn(newArrayList("1.0")); 221 | VersionResolver versionResolver = new VersionResolver(aether); 222 | 223 | Resolver resolver = new Resolver(mock(DefaultModelResolver.class), versionResolver, ALIASES); 224 | 225 | resolver.traverseDeps(mockModel, Sets.newHashSet("compile"), Sets.newHashSet(), null); 226 | Collection rules = resolver.getRules(); 227 | assertThat(rules).hasSize(1); 228 | Rule actual = rules.iterator().next(); 229 | assertThat(actual.name()).isEqualTo("a_b"); 230 | } 231 | 232 | @Test 233 | public void scopesIgnoredForNonRoot() throws Exception { 234 | Model mockModel = mock(Model.class); 235 | // "compile" and "runtime" should go through. 236 | when(mockModel.getDependencies()) 237 | .thenReturn( 238 | ImmutableList.of( 239 | getDependency("a:b:1.0", "compile"), 240 | getDependency("c:d:1.0", "runtime"), 241 | getDependency("e:f:1.0", "test"))); 242 | 243 | Aether aether = mock(Aether.class); 244 | when(aether.requestVersionRange(fromCoords("a:b:[1.0,)"))).thenReturn(newArrayList("1.0")); 245 | when(aether.requestVersionRange(fromCoords("c:d:[1.0,)"))).thenReturn(newArrayList("1.0")); 246 | when(aether.requestVersionRange(fromCoords("e:f:[1.0,)"))).thenReturn(newArrayList("1.0")); 247 | VersionResolver versionResolver = new VersionResolver(aether); 248 | 249 | Resolver resolver = new Resolver(mock(DefaultModelResolver.class), versionResolver, ALIASES); 250 | resolver.traverseDeps( 251 | mockModel, 252 | Sets.newHashSet("compile"), 253 | Sets.newHashSet(), 254 | new Rule(new DefaultArtifact("par:ent:1.2.3"))); 255 | Collection rules = resolver.getRules(); 256 | assertThat(rules).hasSize(2); 257 | Set names = rules.stream().map(rule -> rule.name()).collect(Collectors.toSet()); 258 | assertThat(names).isEqualTo(Sets.newHashSet("a_b", "c_d")); 259 | } 260 | 261 | @Test 262 | public void exclusions() throws Exception { 263 | Model mockModel = mock(Model.class); 264 | when(mockModel.getDependencies()).thenReturn(ImmutableList.of(getDependency("a:b:1.0"))); 265 | 266 | Resolver resolver = new Resolver(mock(DefaultModelResolver.class), ALIASES); 267 | resolver.traverseDeps( 268 | mockModel, 269 | Sets.newHashSet(), 270 | Sets.newHashSet("a:b"), 271 | new Rule(new DefaultArtifact("par:ent:1.2.3"))); 272 | Collection rules = resolver.getRules(); 273 | assertThat(rules).isEmpty(); 274 | } 275 | 276 | @Test 277 | public void aliasWins() throws Exception { 278 | Aether aether = mock(Aether.class); 279 | when(aether.requestVersionRange(fromCoords("a:b:[1.0,)"))).thenReturn(newArrayList("1.0")); 280 | VersionResolver versionResolver = new VersionResolver(aether); 281 | 282 | Rule aliasedRule = new Rule(fromCoords("a:b:0"), "c"); 283 | Model mockModel = mock(Model.class); 284 | when(mockModel.getDependencies()).thenReturn(ImmutableList.of(getDependency("a:b:1.0"))); 285 | 286 | Resolver resolver = 287 | new Resolver( 288 | mock(DefaultModelResolver.class), versionResolver, ImmutableList.of(aliasedRule)); 289 | resolver.traverseDeps( 290 | mockModel, 291 | Sets.newHashSet(), 292 | Sets.newHashSet(), 293 | new Rule(new DefaultArtifact("par:ent:1.2.3"))); 294 | Collection rules = resolver.getRules(); 295 | assertThat(rules).hasSize(2); 296 | rules.iterator().next(); 297 | Rule actualRule = rules.iterator().next(); 298 | assertThat(actualRule).isSameAs(aliasedRule); 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/maven/RuleTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.maven; 16 | 17 | import static com.google.common.truth.Truth.assertThat; 18 | 19 | import org.junit.Test; 20 | import org.junit.runner.RunWith; 21 | import org.junit.runners.JUnit4; 22 | 23 | /** 24 | * Tests for {@link Rule}. 25 | */ 26 | @RunWith(JUnit4.class) 27 | public class RuleTest { 28 | 29 | @Test 30 | public void testUrl() throws Exception { 31 | Rule rule = new Rule(ArtifactBuilder.fromCoords("foo:bar:1.2.3")); 32 | assertThat(rule.getUrl()) 33 | .isEqualTo("https://repo1.maven.org/maven2/foo/bar/1.2.3/bar-1.2.3.pom"); 34 | rule.setRepository("http://myrepo.com/foo/bar/1.2.3/bar-1.2.3.pom"); 35 | assertThat(rule.getUrl()).isEqualTo("http://myrepo.com/foo/bar/1.2.3/bar-1.2.3.pom"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/maven/VersionResolverTest.java: -------------------------------------------------------------------------------- 1 | package com.google.devtools.build.workspace.maven; 2 | 3 | import static com.google.common.collect.Lists.newArrayList; 4 | import static com.google.common.truth.Truth.assertThat; 5 | import static com.google.devtools.build.workspace.maven.VersionResolver.isVersionRange; 6 | import static org.mockito.Matchers.any; 7 | import static org.mockito.Matchers.anyList; 8 | 9 | import com.google.devtools.build.workspace.maven.ArtifactBuilder.InvalidArtifactCoordinateException; 10 | import org.eclipse.aether.artifact.Artifact; 11 | import org.eclipse.aether.resolution.VersionRangeResolutionException; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.junit.runners.JUnit4; 15 | import org.mockito.Mockito; 16 | 17 | /** 18 | * Tests for {@link VersionResolver}. 19 | */ 20 | @RunWith(JUnit4.class) 21 | public class VersionResolverTest { 22 | 23 | /** 24 | * Ensures that an exception is thrown if there is a version range resolution exception. 25 | * This occurs when aether is unable to resolve the version. 26 | */ 27 | @Test(expected = ArtifactBuilder.InvalidArtifactCoordinateException.class) 28 | public void failsOnResolutionException() 29 | throws InvalidArtifactCoordinateException, VersionRangeResolutionException { 30 | Aether aether = Mockito.mock(Aether.class); 31 | 32 | Mockito.when(aether.requestVersionRange(any())) 33 | .thenThrow(new VersionRangeResolutionException(any())); 34 | 35 | VersionResolver resolver = new VersionResolver(aether); 36 | resolver.resolveVersion("something", "something", "1.0"); 37 | } 38 | 39 | /** 40 | * Ensures that an exception is thrown if there is an invalid version range. An invalid version range 41 | * is one which is either (1) equal to null or (2) returns null when asked for highest version. 42 | */ 43 | @Test(expected = ArtifactBuilder.InvalidArtifactCoordinateException.class) 44 | public void failsOnInvalidVersionRange() 45 | throws VersionRangeResolutionException, InvalidArtifactCoordinateException { 46 | Aether aether = Mockito.mock(Aether.class); 47 | 48 | // Using `anyRangeResult()` will ensure that rangeResult.highestVersion() == null. 49 | Mockito.when(aether.requestVersionRange(any())) 50 | .thenReturn(anyList()); 51 | 52 | VersionResolver resolver = new VersionResolver(aether); 53 | resolver.resolveVersion("something", "something", "1.0"); 54 | } 55 | 56 | /** 57 | * Asserts that given a soft pinned version specification, it selects that version, 58 | * and does not get the highest version. "3.4" is an example of a soft pinned version specification. 59 | */ 60 | @Test 61 | public void softPinnedVersion_versionExists() 62 | throws InvalidArtifactCoordinateException, VersionRangeResolutionException { 63 | Aether aether = Mockito.mock(Aether.class); 64 | Artifact artifact = ArtifactBuilder.fromCoords("something:something:[1.0,)"); 65 | Mockito.when(aether.requestVersionRange(artifact)).thenReturn(newArrayList("1.0", "1.2")); 66 | 67 | VersionResolver resolver = new VersionResolver(aether); 68 | String version = 69 | resolver.resolveVersion("something", "something", "1.0"); 70 | assertThat(version).isEqualTo("1.0"); 71 | } 72 | 73 | /** 74 | * Asserts that if a soft pinned version specification DNE, it selects the nearest version. 75 | */ 76 | @Test 77 | public void softPinnedVersion_versionDoesNotExist() 78 | throws InvalidArtifactCoordinateException, VersionRangeResolutionException { 79 | Aether aether = Mockito.mock(Aether.class); 80 | Artifact artifact = ArtifactBuilder.fromCoords("something:something:[1.0,)"); 81 | Mockito.when(aether.requestVersionRange(artifact)).thenReturn(newArrayList("1.2", "2.0", "3.0")); 82 | 83 | VersionResolver resolver = new VersionResolver(aether); 84 | String version = 85 | resolver.resolveVersion("something", "something", "1.0"); 86 | assertThat(version).isEqualTo("1.2"); 87 | } 88 | 89 | /** 90 | * Asserts that the VersionResolver selects the highest version from the list of versions 91 | * provided by aether. 92 | */ 93 | @Test 94 | public void selectsHighestVersion() 95 | throws InvalidArtifactCoordinateException, VersionRangeResolutionException { 96 | Aether aether = Mockito.mock(Aether.class); 97 | Artifact artifact; 98 | 99 | artifact = ArtifactBuilder.fromCoords("com.hello:something:[,)"); 100 | Mockito.when( 101 | aether.requestVersionRange(artifact)).thenReturn(newArrayList("1.0", "1.2", "1.3")); 102 | VersionResolver resolver = new VersionResolver(aether); 103 | String version = resolver.resolveVersion("com.hello", "something", "[,)"); 104 | assertThat(version).isEqualTo("1.3"); 105 | } 106 | 107 | @Test 108 | public void identifiesVersionRange() { 109 | assertThat(isVersionRange("[3]")).isTrue(); 110 | assertThat(isVersionRange("[3,4]")).isTrue(); 111 | assertThat(isVersionRange("[3,4)")).isTrue(); 112 | assertThat(isVersionRange("(3,4)")).isTrue(); 113 | assertThat(isVersionRange("(3,4]")).isTrue(); 114 | assertThat(isVersionRange("(,)")).isTrue(); 115 | assertThat(isVersionRange("[3,)")).isTrue(); 116 | assertThat(isVersionRange("(3,)")).isTrue(); 117 | 118 | assertThat(isVersionRange("3.0")).isFalse(); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/output/BUILD: -------------------------------------------------------------------------------- 1 | java_test( 2 | name = "WorkspaceWriterTest", 3 | srcs = ["WorkspaceWriterTest.java"], 4 | deps = [ 5 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 6 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/output", 7 | "//third_party:aether", 8 | "//third_party:com_google_guava_guava", 9 | "//third_party:com_google_truth_truth", 10 | "//third_party:junit_junit", 11 | ], 12 | ) 13 | 14 | java_test( 15 | name = "BzlWriterTest", 16 | srcs = ["BzlWriterTest.java"], 17 | deps = [ 18 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/maven", 19 | "//generate_workspace/src/main/java/com/google/devtools/build/workspace/output", 20 | "//third_party:aether", 21 | "//third_party:com_google_guava_guava", 22 | "//third_party:com_google_truth_truth", 23 | "//third_party:junit_junit", 24 | "//third_party:org_mockito_mockito_all", 25 | ], 26 | ) 27 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/output/BzlWriterTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.output; 16 | 17 | import static com.google.common.truth.Truth.assertThat; 18 | import static java.util.stream.Collectors.toList; 19 | import static org.mockito.Matchers.any; 20 | import static org.mockito.Mockito.doThrow; 21 | 22 | import com.google.common.collect.ImmutableList; 23 | import com.google.common.io.Files; 24 | import com.google.devtools.build.workspace.maven.Rule; 25 | import java.io.File; 26 | import java.io.IOException; 27 | import java.nio.charset.Charset; 28 | import java.nio.file.Path; 29 | import java.nio.file.Paths; 30 | import java.util.Arrays; 31 | import java.util.List; 32 | import org.eclipse.aether.artifact.DefaultArtifact; 33 | import org.junit.Test; 34 | import org.junit.runner.RunWith; 35 | import org.junit.runners.JUnit4; 36 | import org.mockito.Mockito; 37 | 38 | /** 39 | * Test the .bzl output writer. 40 | */ 41 | @RunWith(JUnit4.class) 42 | public class BzlWriterTest { 43 | 44 | @Test 45 | public void writeEmpty() throws Exception { 46 | BzlWriter writer = new BzlWriter(new String[]{}, System.getenv("TEST_TMPDIR")); 47 | writer.write(createRules()); 48 | String fileContents = Files.toString( 49 | new File(System.getenv("TEST_TMPDIR") + "/generate_workspace.bzl"), 50 | Charset.defaultCharset()); 51 | assertThat(fileContents).contains(String.format("def generated_maven_jars():%n pass%n")); 52 | assertThat(fileContents).contains(String.format("def generated_java_libraries():%n pass%n")); 53 | } 54 | 55 | /** Ensures that it automatically creates output directory if they do not exist */ 56 | @Test 57 | public void automaticallyCreateParentDirectories() throws Exception { 58 | Path outputDirs = Paths.get(System.getenv("TEST_TMPDIR")).resolve("child/dir"); 59 | 60 | BzlWriter writer = new BzlWriter(new String[]{}, outputDirs.toString()); 61 | List rules = createRules("x:y:1.2.3"); 62 | writer.write(rules); 63 | 64 | File generatedFile = new File(outputDirs.resolve("generate_workspace.bzl").toString()); 65 | assert(generatedFile.exists() && !generatedFile.isDirectory()); 66 | } 67 | 68 | /** Ensures that if we throw an IOException, we recover gracefully, and that a bzl file is not generated. */ 69 | @Test 70 | public void unableToAutomaticallyCreateDirectories() throws Exception { 71 | Path outputDirs = Paths.get(System.getenv("TEST_TMPDIR")).resolve("test/ioexception/"); 72 | 73 | BzlWriter writer = Mockito.mock(BzlWriter.class); 74 | doThrow(new IOException("Test exception")).when(writer).createParentDirectory(any()); 75 | 76 | List rules = createRules("x:y:1.2.3"); 77 | writer.write(rules); 78 | 79 | File generatedFile = new File(outputDirs.resolve("generate_workspace.bzl").toString()); 80 | assert(!generatedFile.exists()); 81 | } 82 | 83 | @Test 84 | public void writeRules() throws Exception { 85 | BzlWriter writer = new BzlWriter(new String[]{}, System.getenv("TEST_TMPDIR")); 86 | writer.write(createRules("x:y:1.2.3")); 87 | String fileContents = Files.toString( 88 | new File(System.getenv("TEST_TMPDIR") + "/generate_workspace.bzl"), 89 | Charset.defaultCharset()); 90 | assertThat(fileContents).contains(String.format( 91 | "def generated_maven_jars():%n native.maven_jar(%n" 92 | + " name = \"x_y\",%n" 93 | + " artifact = \"x:y:1.2.3\",%n" 94 | + " )%n")); 95 | assertThat(fileContents).contains(String.format( 96 | "def generated_java_libraries():%n native.java_library(%n" 97 | + " name = \"x_y\",%n" 98 | + " visibility = [\"//visibility:public\"],%n" 99 | + " exports = [\"@x_y//jar\"],%n" 100 | + " )%n")); 101 | } 102 | 103 | @Test 104 | public void writeAlias() throws Exception { 105 | BzlWriter writer = new BzlWriter(new String[]{}, System.getenv("TEST_TMPDIR")); 106 | writer.write(ImmutableList.of(new Rule(new DefaultArtifact("x:y:1.2.3"), "z"))); 107 | String fileContents = Files.toString( 108 | new File(System.getenv("TEST_TMPDIR") + "/generate_workspace.bzl"), 109 | Charset.defaultCharset()); 110 | assertThat(fileContents).doesNotContain("x:y:1.2.3"); 111 | assertThat(fileContents).contains("exports = [\"@z//jar\"],"); 112 | } 113 | 114 | @Test 115 | public void writeCommand() throws Exception { 116 | BzlWriter writer = new BzlWriter(new String[]{"x", "y", "z"}, System.getenv("TEST_TMPDIR")); 117 | writer.write(createRules()); 118 | String fileContents = Files.toString( 119 | new File(System.getenv("TEST_TMPDIR") + "/generate_workspace.bzl"), 120 | Charset.defaultCharset()); 121 | assertThat(fileContents).contains("# generate_workspace x y z"); 122 | } 123 | 124 | private ImmutableList createRules(String ... mavenCoordinates) { 125 | return ImmutableList.copyOf(Arrays.stream(mavenCoordinates) 126 | .map(DefaultArtifact::new) 127 | .map(Rule::new) 128 | .collect(toList())); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /generate_workspace/src/test/java/com/google/devtools/build/workspace/output/WorkspaceWriterTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Bazel Authors. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.devtools.build.workspace.output; 16 | 17 | import static com.google.common.truth.Truth.assertThat; 18 | 19 | import com.google.common.collect.ImmutableSet; 20 | import com.google.common.collect.Sets; 21 | import com.google.devtools.build.workspace.maven.Rule; 22 | 23 | import org.eclipse.aether.artifact.DefaultArtifact; 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.junit.runners.JUnit4; 27 | 28 | import java.io.ByteArrayOutputStream; 29 | import java.io.PrintStream; 30 | import java.nio.charset.Charset; 31 | import java.util.Set; 32 | 33 | /** 34 | * Tests for @{link WorkspaceWriter}. 35 | */ 36 | @RunWith(JUnit4.class) 37 | public class WorkspaceWriterTest { 38 | 39 | public String getWorkspaceFileContent(Set rules) throws Exception { 40 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 41 | PrintStream ps = new PrintStream(baos); 42 | WorkspaceWriter writer = new WorkspaceWriter(new String[]{}, System.getenv("TEST_TMPDIR")); 43 | writer.writeWorkspace(ps, rules); 44 | return baos.toString(String.valueOf(Charset.defaultCharset())); 45 | } 46 | 47 | public String getBuildFileContent(Set rules) throws Exception { 48 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 49 | PrintStream ps = new PrintStream(baos); 50 | WorkspaceWriter writer = new WorkspaceWriter(new String[]{}, System.getenv("TEST_TMPDIR")); 51 | writer.writeBuild(ps, rules); 52 | return baos.toString(String.valueOf(Charset.defaultCharset())); 53 | } 54 | 55 | @Test 56 | public void testHeaders() throws Exception { 57 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 58 | PrintStream ps = new PrintStream(baos); 59 | WorkspaceWriter writer = new WorkspaceWriter( 60 | new String[]{"--artifact=x:y:1.2.3", "--artifact=a:b:3.2.1"}, 61 | System.getenv("TEST_TMPDIR")); 62 | writer.writeWorkspace(ps, Sets.newHashSet()); 63 | assertThat(baos.toString(String.valueOf(Charset.defaultCharset()))).contains( 64 | "# generate_workspace --artifact=x:y:1.2.3 --artifact=a:b:3.2.1"); 65 | } 66 | 67 | @Test 68 | public void testArtifacts() throws Exception { 69 | Set rules = ImmutableSet.of( 70 | new Rule(new DefaultArtifact("x:y:1.2.3"))); 71 | String content = getWorkspaceFileContent(rules); 72 | assertThat(content).contains(String.format("maven_jar(%n" 73 | + " name = \"x_y\",%n" 74 | + " artifact = \"x:y:1.2.3\",%n" 75 | + ")" 76 | )); 77 | } 78 | 79 | @Test 80 | public void testParents() throws Exception { 81 | Rule rule = new Rule(new DefaultArtifact("x:y:1.2.3")); 82 | rule.addParent("some parent"); 83 | Set rules = ImmutableSet.of(rule); 84 | String content = getWorkspaceFileContent(rules); 85 | assertThat(content).contains(String.format("# some parent%n" 86 | + "maven_jar(%n" 87 | + " name = \"x_y\",%n" 88 | + " artifact = \"x:y:1.2.3\",%n" 89 | + ")" 90 | )); 91 | } 92 | 93 | @Test 94 | public void testBuildFile() throws Exception { 95 | Rule rule = new Rule(new DefaultArtifact("x:y:1.2.3")); 96 | Rule dep1 = new Rule(new DefaultArtifact("dep:dep1:4.5.6")); 97 | rule.addDependency(dep1); 98 | Rule dep2 = new Rule(new DefaultArtifact("dep:dep2:7.8.9")); 99 | rule.addDependency(dep2); 100 | Set rules = ImmutableSet.of(rule, dep1, dep2); 101 | String content = getBuildFileContent(rules); 102 | assertThat(content).contains(String.format("java_library(%n" 103 | + " name = \"x_y\",%n" 104 | + " visibility = [\"//visibility:public\"],%n" 105 | + " exports = [\"@x_y//jar\"],%n" 106 | + " runtime_deps = [%n" 107 | + " \":dep_dep1\",%n" 108 | + " \":dep_dep2\",%n" 109 | + " ],%n" 110 | + ")" 111 | )); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /third_party/BUILD: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("//:generate_workspace.bzl", "generated_java_libraries") 4 | 5 | generated_java_libraries() 6 | 7 | java_import( 8 | name = "aether", 9 | jars = [ 10 | "aether/aether-api-1.0.0.v20140518.jar", 11 | "aether/aether-spi-1.0.0.v20140518.jar", 12 | "aether/aether-transport-http-1.0.0.v20140518.jar", 13 | "aether/aether-connector-basic-1.0.0.v20140518.jar", 14 | "aether/aether-transport-classpath-1.0.0.v20140518.jar", 15 | "aether/aether-transport-wagon-1.0.0.v20140518.jar", 16 | "aether/aether-impl-1.0.0.v20140518.jar", 17 | "aether/aether-transport-file-1.0.0.v20140518.jar", 18 | "aether/aether-util-1.0.0.v20140518.jar", 19 | ], 20 | ) 21 | 22 | java_import( 23 | name = "maven_model", 24 | jars = [ 25 | "maven_model/maven-aether-provider-3.2.3.jar", 26 | "maven_model/maven-model-3.2.3.jar", 27 | "maven_model/maven-model-builder-3.2.3.jar", 28 | "maven_model/maven-repository-metadata-3.2.3.jar", 29 | ], 30 | ) 31 | -------------------------------------------------------------------------------- /third_party/aether/LICENSE.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Eclipse Public License - Version 1.0 6 | 23 | 24 | 25 | 26 | 27 | 28 |

Eclipse Public License - v 1.0

29 | 30 |

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE 31 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR 32 | DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS 33 | AGREEMENT.

34 | 35 |

1. DEFINITIONS

36 | 37 |

"Contribution" means:

38 | 39 |

a) in the case of the initial Contributor, the initial 40 | code and documentation distributed under this Agreement, and

41 |

b) in the case of each subsequent Contributor:

42 |

i) changes to the Program, and

43 |

ii) additions to the Program;

44 |

where such changes and/or additions to the Program 45 | originate from and are distributed by that particular Contributor. A 46 | Contribution 'originates' from a Contributor if it was added to the 47 | Program by such Contributor itself or anyone acting on such 48 | Contributor's behalf. Contributions do not include additions to the 49 | Program which: (i) are separate modules of software distributed in 50 | conjunction with the Program under their own license agreement, and (ii) 51 | are not derivative works of the Program.

52 | 53 |

"Contributor" means any person or entity that distributes 54 | the Program.

55 | 56 |

"Licensed Patents" mean patent claims licensable by a 57 | Contributor which are necessarily infringed by the use or sale of its 58 | Contribution alone or when combined with the Program.

59 | 60 |

"Program" means the Contributions distributed in accordance 61 | with this Agreement.

62 | 63 |

"Recipient" means anyone who receives the Program under 64 | this Agreement, including all Contributors.

65 | 66 |

2. GRANT OF RIGHTS

67 | 68 |

a) Subject to the terms of this Agreement, each 69 | Contributor hereby grants Recipient a non-exclusive, worldwide, 70 | royalty-free copyright license to reproduce, prepare derivative works 71 | of, publicly display, publicly perform, distribute and sublicense the 72 | Contribution of such Contributor, if any, and such derivative works, in 73 | source code and object code form.

74 | 75 |

b) Subject to the terms of this Agreement, each 76 | Contributor hereby grants Recipient a non-exclusive, worldwide, 77 | royalty-free patent license under Licensed Patents to make, use, sell, 78 | offer to sell, import and otherwise transfer the Contribution of such 79 | Contributor, if any, in source code and object code form. This patent 80 | license shall apply to the combination of the Contribution and the 81 | Program if, at the time the Contribution is added by the Contributor, 82 | such addition of the Contribution causes such combination to be covered 83 | by the Licensed Patents. The patent license shall not apply to any other 84 | combinations which include the Contribution. No hardware per se is 85 | licensed hereunder.

86 | 87 |

c) Recipient understands that although each Contributor 88 | grants the licenses to its Contributions set forth herein, no assurances 89 | are provided by any Contributor that the Program does not infringe the 90 | patent or other intellectual property rights of any other entity. Each 91 | Contributor disclaims any liability to Recipient for claims brought by 92 | any other entity based on infringement of intellectual property rights 93 | or otherwise. As a condition to exercising the rights and licenses 94 | granted hereunder, each Recipient hereby assumes sole responsibility to 95 | secure any other intellectual property rights needed, if any. For 96 | example, if a third party patent license is required to allow Recipient 97 | to distribute the Program, it is Recipient's responsibility to acquire 98 | that license before distributing the Program.

99 | 100 |

d) Each Contributor represents that to its knowledge it 101 | has sufficient copyright rights in its Contribution, if any, to grant 102 | the copyright license set forth in this Agreement.

103 | 104 |

3. REQUIREMENTS

105 | 106 |

A Contributor may choose to distribute the Program in object code 107 | form under its own license agreement, provided that:

108 | 109 |

a) it complies with the terms and conditions of this 110 | Agreement; and

111 | 112 |

b) its license agreement:

113 | 114 |

i) effectively disclaims on behalf of all Contributors 115 | all warranties and conditions, express and implied, including warranties 116 | or conditions of title and non-infringement, and implied warranties or 117 | conditions of merchantability and fitness for a particular purpose;

118 | 119 |

ii) effectively excludes on behalf of all Contributors 120 | all liability for damages, including direct, indirect, special, 121 | incidental and consequential damages, such as lost profits;

122 | 123 |

iii) states that any provisions which differ from this 124 | Agreement are offered by that Contributor alone and not by any other 125 | party; and

126 | 127 |

iv) states that source code for the Program is available 128 | from such Contributor, and informs licensees how to obtain it in a 129 | reasonable manner on or through a medium customarily used for software 130 | exchange.

131 | 132 |

When the Program is made available in source code form:

133 | 134 |

a) it must be made available under this Agreement; and

135 | 136 |

b) a copy of this Agreement must be included with each 137 | copy of the Program.

138 | 139 |

Contributors may not remove or alter any copyright notices contained 140 | within the Program.

141 | 142 |

Each Contributor must identify itself as the originator of its 143 | Contribution, if any, in a manner that reasonably allows subsequent 144 | Recipients to identify the originator of the Contribution.

145 | 146 |

4. COMMERCIAL DISTRIBUTION

147 | 148 |

Commercial distributors of software may accept certain 149 | responsibilities with respect to end users, business partners and the 150 | like. While this license is intended to facilitate the commercial use of 151 | the Program, the Contributor who includes the Program in a commercial 152 | product offering should do so in a manner which does not create 153 | potential liability for other Contributors. Therefore, if a Contributor 154 | includes the Program in a commercial product offering, such Contributor 155 | ("Commercial Contributor") hereby agrees to defend and 156 | indemnify every other Contributor ("Indemnified Contributor") 157 | against any losses, damages and costs (collectively "Losses") 158 | arising from claims, lawsuits and other legal actions brought by a third 159 | party against the Indemnified Contributor to the extent caused by the 160 | acts or omissions of such Commercial Contributor in connection with its 161 | distribution of the Program in a commercial product offering. The 162 | obligations in this section do not apply to any claims or Losses 163 | relating to any actual or alleged intellectual property infringement. In 164 | order to qualify, an Indemnified Contributor must: a) promptly notify 165 | the Commercial Contributor in writing of such claim, and b) allow the 166 | Commercial Contributor to control, and cooperate with the Commercial 167 | Contributor in, the defense and any related settlement negotiations. The 168 | Indemnified Contributor may participate in any such claim at its own 169 | expense.

170 | 171 |

For example, a Contributor might include the Program in a commercial 172 | product offering, Product X. That Contributor is then a Commercial 173 | Contributor. If that Commercial Contributor then makes performance 174 | claims, or offers warranties related to Product X, those performance 175 | claims and warranties are such Commercial Contributor's responsibility 176 | alone. Under this section, the Commercial Contributor would have to 177 | defend claims against the other Contributors related to those 178 | performance claims and warranties, and if a court requires any other 179 | Contributor to pay any damages as a result, the Commercial Contributor 180 | must pay those damages.

181 | 182 |

5. NO WARRANTY

183 | 184 |

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS 185 | PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 186 | OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, 187 | ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY 188 | OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely 189 | responsible for determining the appropriateness of using and 190 | distributing the Program and assumes all risks associated with its 191 | exercise of rights under this Agreement , including but not limited to 192 | the risks and costs of program errors, compliance with applicable laws, 193 | damage to or loss of data, programs or equipment, and unavailability or 194 | interruption of operations.

195 | 196 |

6. DISCLAIMER OF LIABILITY

197 | 198 |

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT 199 | NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, 200 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING 201 | WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF 202 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 203 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR 204 | DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED 205 | HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

206 | 207 |

7. GENERAL

208 | 209 |

If any provision of this Agreement is invalid or unenforceable under 210 | applicable law, it shall not affect the validity or enforceability of 211 | the remainder of the terms of this Agreement, and without further action 212 | by the parties hereto, such provision shall be reformed to the minimum 213 | extent necessary to make such provision valid and enforceable.

214 | 215 |

If Recipient institutes patent litigation against any entity 216 | (including a cross-claim or counterclaim in a lawsuit) alleging that the 217 | Program itself (excluding combinations of the Program with other 218 | software or hardware) infringes such Recipient's patent(s), then such 219 | Recipient's rights granted under Section 2(b) shall terminate as of the 220 | date such litigation is filed.

221 | 222 |

All Recipient's rights under this Agreement shall terminate if it 223 | fails to comply with any of the material terms or conditions of this 224 | Agreement and does not cure such failure in a reasonable period of time 225 | after becoming aware of such noncompliance. If all Recipient's rights 226 | under this Agreement terminate, Recipient agrees to cease use and 227 | distribution of the Program as soon as reasonably practicable. However, 228 | Recipient's obligations under this Agreement and any licenses granted by 229 | Recipient relating to the Program shall continue and survive.

230 | 231 |

Everyone is permitted to copy and distribute copies of this 232 | Agreement, but in order to avoid inconsistency the Agreement is 233 | copyrighted and may only be modified in the following manner. The 234 | Agreement Steward reserves the right to publish new versions (including 235 | revisions) of this Agreement from time to time. No one other than the 236 | Agreement Steward has the right to modify this Agreement. The Eclipse 237 | Foundation is the initial Agreement Steward. The Eclipse Foundation may 238 | assign the responsibility to serve as the Agreement Steward to a 239 | suitable separate entity. Each new version of the Agreement will be 240 | given a distinguishing version number. The Program (including 241 | Contributions) may always be distributed subject to the version of the 242 | Agreement under which it was received. In addition, after a new version 243 | of the Agreement is published, Contributor may elect to distribute the 244 | Program (including its Contributions) under the new version. Except as 245 | expressly stated in Sections 2(a) and 2(b) above, Recipient receives no 246 | rights or licenses to the intellectual property of any Contributor under 247 | this Agreement, whether expressly, by implication, estoppel or 248 | otherwise. All rights in the Program not expressly granted under this 249 | Agreement are reserved.

250 | 251 |

This Agreement is governed by the laws of the State of New York and 252 | the intellectual property laws of the United States of America. No party 253 | to this Agreement will bring a legal action under this Agreement more 254 | than one year after the cause of action arose. Each party waives its 255 | rights to a jury trial in any resulting litigation.

256 | 257 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /third_party/aether/aether-api-1.0.0.v20140518.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/aether/aether-api-1.0.0.v20140518.jar -------------------------------------------------------------------------------- /third_party/aether/aether-connector-basic-1.0.0.v20140518.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/aether/aether-connector-basic-1.0.0.v20140518.jar -------------------------------------------------------------------------------- /third_party/aether/aether-impl-1.0.0.v20140518.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/aether/aether-impl-1.0.0.v20140518.jar -------------------------------------------------------------------------------- /third_party/aether/aether-spi-1.0.0.v20140518.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/aether/aether-spi-1.0.0.v20140518.jar -------------------------------------------------------------------------------- /third_party/aether/aether-transport-classpath-1.0.0.v20140518.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/aether/aether-transport-classpath-1.0.0.v20140518.jar -------------------------------------------------------------------------------- /third_party/aether/aether-transport-file-1.0.0.v20140518.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/aether/aether-transport-file-1.0.0.v20140518.jar -------------------------------------------------------------------------------- /third_party/aether/aether-transport-http-1.0.0.v20140518.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/aether/aether-transport-http-1.0.0.v20140518.jar -------------------------------------------------------------------------------- /third_party/aether/aether-transport-wagon-1.0.0.v20140518.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/aether/aether-transport-wagon-1.0.0.v20140518.jar -------------------------------------------------------------------------------- /third_party/aether/aether-util-1.0.0.v20140518.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/aether/aether-util-1.0.0.v20140518.jar -------------------------------------------------------------------------------- /third_party/jcommander/BUILD: -------------------------------------------------------------------------------- 1 | licenses(["notice"]) # Apache 2.0. 2 | 3 | java_import( 4 | name = "jcommander", 5 | jars = ["jcommander-1.71/jcommander-1.71.jar"], 6 | visibility = ["//visibility:public"], 7 | ) 8 | -------------------------------------------------------------------------------- /third_party/jcommander/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2012, Cedric Beust 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | 204 | -------------------------------------------------------------------------------- /third_party/jcommander/jcommander-1.71/jcommander-1.71.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/jcommander/jcommander-1.71/jcommander-1.71.jar -------------------------------------------------------------------------------- /third_party/maven_model/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2012, Cedric Beust 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | 204 | -------------------------------------------------------------------------------- /third_party/maven_model/maven-aether-provider-3.2.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/maven_model/maven-aether-provider-3.2.3.jar -------------------------------------------------------------------------------- /third_party/maven_model/maven-model-3.2.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/maven_model/maven-model-3.2.3.jar -------------------------------------------------------------------------------- /third_party/maven_model/maven-model-builder-3.2.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/maven_model/maven-model-builder-3.2.3.jar -------------------------------------------------------------------------------- /third_party/maven_model/maven-repository-metadata-3.2.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/third_party/maven_model/maven-repository-metadata-3.2.3.jar -------------------------------------------------------------------------------- /transitive_maven_jar/BUILD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/transitive_maven_jar/BUILD -------------------------------------------------------------------------------- /transitive_maven_jar/generate_workspace_deploy.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bazelbuild/migration-tooling/36f7b8e7ded991021fe083dea6b736ffedf7404c/transitive_maven_jar/generate_workspace_deploy.jar -------------------------------------------------------------------------------- /transitive_maven_jar/transitive_maven_jar.bzl: -------------------------------------------------------------------------------- 1 | MAX_TIMEOUT = 0x7FFFFFFF 2 | 3 | def _validate_coordinate_length(coordinate): 4 | parts = coordinate.split(":") 5 | return len(parts) >= 2 and len(parts) <= 5 6 | 7 | def _validate_coordinates(rctx): 8 | coordinates = rctx.attr.artifacts 9 | for coord in coordinates: 10 | if _validate_coordinate_length(coord) == False: 11 | fail("Invalid coordinate %s. Generally formatted as \"group:artifact:version\"" % coord) 12 | return True 13 | 14 | def _create_arguments(rctx): 15 | arguments = ['--artifact ' + artifact for artifact in rctx.attr.artifacts] 16 | arguments += ['--repositories ' + ','.join(rctx.attr.repositories)] 17 | return ' '.join(arguments) 18 | 19 | def _execute(rctx, command_string, quiet): 20 | return rctx.execute(["bash", "-c", command_string], timeout = rctx.attr._timeout, quiet = quiet) 21 | 22 | def _transitive_maven_jar_impl(rctx): 23 | _validate_coordinates(rctx) 24 | arguments = _create_arguments(rctx) 25 | quiet = rctx.attr.quiet 26 | 27 | jar_path = rctx.path(rctx.attr._generate_workspace_tool) 28 | 29 | # execute the command 30 | command = "java -jar %s %s" % (jar_path, arguments) 31 | print(command + "\n") 32 | result = _execute(rctx, command, quiet) 33 | rctx.file('%s/BUILD' % rctx.path(''), '', False) 34 | 35 | transitive_maven_jar = repository_rule( 36 | implementation = _transitive_maven_jar_impl, 37 | attrs = { 38 | "artifacts" : attr.string_list(default = [], mandatory = True), 39 | "repositories" : attr.string_list(default = [], mandatory = False), 40 | "quiet" : attr.bool(default = False, mandatory = False), 41 | "_timeout" : attr.int(default = MAX_TIMEOUT), 42 | "_generate_workspace_tool" : attr.label(executable = True, allow_files = True, cfg = "host", default = Label("//transitive_maven_jar:generate_workspace_deploy.jar")) 43 | }, 44 | local = False, 45 | ) 46 | 47 | --------------------------------------------------------------------------------