pax_global_header00006660000000000000000000000064143447456710014531gustar00rootroot0000000000000052 comment=a59330abeeb34651faf3a0b3a3737d91d38c9be4 tools.deps-0.16.1264/000077500000000000000000000000001434474567100141445ustar00rootroot00000000000000tools.deps-0.16.1264/.clj-kondo/000077500000000000000000000000001434474567100161025ustar00rootroot00000000000000tools.deps-0.16.1264/.clj-kondo/config.edn000066400000000000000000000001011434474567100200270ustar00rootroot00000000000000{:skip-comments true :linters {:unused-binding {:level :off}}} tools.deps-0.16.1264/.github/000077500000000000000000000000001434474567100155045ustar00rootroot00000000000000tools.deps-0.16.1264/.github/PULL_REQUEST_TEMPLATE000066400000000000000000000012451434474567100207100ustar00rootroot00000000000000Hi! Thanks for your interest in contributing to this project. Clojure contrib projects do not use GitHub issues or pull requests, and require a signed Contributor Agreement. If you would like to contribute, please read more about the CA and sign that first (this can be done online). Then go to this project's issue tracker in JIRA to create tickets, update tickets, or submit patches. For help in creating tickets and patches, please see: - Contributing FAQ: https://clojure.org/dev - Signing the CA: https://clojure.org/dev/contributor_agreement - Creating Tickets: https://clojure.org/dev/creating_tickets - Developing Patches: https://clojure.org/dev/developing_patches tools.deps-0.16.1264/.github/workflows/000077500000000000000000000000001434474567100175415ustar00rootroot00000000000000tools.deps-0.16.1264/.github/workflows/maven.yml000066400000000000000000000005251434474567100213740ustar00rootroot00000000000000name: Java CI on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3.1.0 - name: Set up JDK 1.8 uses: actions/setup-java@v3.6.0 with: java-version: 8 distribution: 'temurin' cache: 'maven' - name: Build with Maven run: mvn package --file pom.xml tools.deps-0.16.1264/.gitignore000066400000000000000000000001541434474567100161340ustar00rootroot00000000000000*.iml .idea/ .calva/ .lsp/ target/ .nrepl* .cpcache .lein* project.clj .clj-kondo/.cache test-out/ .vscode/ tools.deps-0.16.1264/CHANGELOG.md000066400000000000000000000475631434474567100157740ustar00rootroot00000000000000Changelog =========== *Also see [Tools and installer changelog](https://github.com/clojure/brew-install/blob/1.10.3/CHANGELOG.md)* * next * Change :deps alias to point to new tools.deps.cli * 0.16.1260 on Dec 9, 2022 * First release as tools.deps * 0.15.1254 on Nov 14, 2022 * Fix typo in generated checksum policy pom * 0.15.1250 on Nov 14, 2022 * TDEPS-101 Added support in :mvn/repos map to set release and snapshot policies * 0.15.1244 on Oct 24, 2022 * During prep, by default don't prep current project * Improve error when missing local dep directory is missing * 0.15.1237 on Oct 23, 2022 * TDEPS-219 Fixed `-X:deps find-versions` doesn't find Maven versions that start with a letter * Add :n option to `-X:deps find-versions` and default to 8 * During clojure.tools.cli.api/prep, use :exec-args of alias being prepped, if present * During clojure.tools.cli.api/prep, also prep current project if needed * Fix bad invocation of deps/prep-libs! in clojure.tools.cli.api/prep * Update deps to latest * 0.14.1222 on Aug 5, 2022 * TDEPS-228 Add support for auto inferred Sourcehut git urls * Update aws-api, Maven, etc dep versions * 0.14.1212 on Jun 20, 2022 * Tweak printing of git coord summary * Update to tools.gitlibs 2.4.181 * 0.14.1205 on Jun 16, 2022 * In `find-versions`, include git sha * Update to tools.gitlibs 2.4.176 * 0.14.1200 on Jun 16, 2022 * Fix regression with `clj -X:deps find-versions` from 0.14.1185 * 0.14.1194 on Jun 12, 2022 * Set root dir context when prepping libs * 0.14.1189 on Jun 11, 2022 * Fix bug in create-basis from TDEPS-213 * 0.14.1185 on Jun 9, 2022 * TDEPS-213 Add `-X:deps aliases` to list available aliases * TDEPS-226 More nunanced error handling for s3 downloads * Better error message when git url can't be inferred * 0.14.1178 on Apr 22, 2022 * TDEPS-153 More fixes for concurrency issues in maven downloads * TDEPS-225 Add clojure.tools.deps.alpha.tree/calc-trace api * 0.14.1173 on Apr 5, 2022 * Change default Clojure version to 1.11.1 in root deps.edn * 0.13.1168 on Mar 25, 2022 * Change default Clojure version to 1.11.0 in root deps.edn * 0.12.1162 on Mar 21, 2022 * TDEPS-153 Fix concurrency issues in maven downloads * 0.12.1158 on Feb 28, 2022 * Fix error message when git url missing or not inferred * Pass :exec-fn and :exec-args to -X/-T even when using -Scp * 0.12.1153 on Feb 21, 2022 * TDEPS-222 Make Clojure dependency in pom a compile dependency, not provided * 0.12.1148 on Feb 11, 2022 * TDEPS-203 In `-X:deps prep` - now takes basis settings, including aliases * TDEPS-197 `-X:deps git-resolve-tags` - now resolves to :git/tag and :git/sha * `-X:deps tree` - now takes basis settings * `-X:deps mvn-pom` - now takes basis settings * `-X:deps list` - put license abbreviation list in a resource and load on demand * 0.12.1135 on Feb 2, 2022 * TDEPS-216 - Built-in :deps alias should remove project paths from classpath * Improve error if git sha is not found in git repo * Improve prep error if transtive dep's prep function is unresolvable * Dep updates for aws deps * 0.12.1120 on Jan 26, 2022 * Bump transitive deps due to CVEs * 0.12.1109 on Jan 4, 2022 * TDEPS-207 Stop saving S3 transporter in session cache to avoid deadlock * 0.12.1104 on Dec 23, 2021 * TDEPS-215 More tweaks to lazy loading * TDEPS-207 Possible fix to deadlock in version range resolver session caching * 0.12.1098 on Dec 22, 2021 * TDEPS-215 Fix race condition during parallel loading of S3TransporterFactory * Update maven-core to 3.8.4 * Update aws deps to latest * 0.12.1090 on Dec 8, 2021 * Don't track non-existent deps.edn manifest files of deps proejcts * Update to aws-api 0.8.536 * 0.12.1084 on Dec 1, 2021 * Add license :format :edn option to clj -X:deps list * 0.12.1080 on Nov 30, 2021 * Add license info to clj -X:deps list * 0.12.1076 on Nov 18, 2021 * Improve error handling on unknown tool * 0.12.1071 on Nov 8, 2021 * Update to tools.gitlibs 2.4.172 * 0.12.1067 on Nov 4, 2021 * Update deps to latest * Add -X:deps list * 0.12.1063 on Oct 29, 2021 * TDEPS-83 Add support for finding manifests of libs * 0.12.1058 on Oct 22, 2021 * TDEPS-210 Update specs * 0.12.1053 on Oct 12, 2021 * TDEPS-209 Include only jar files in classpath from Maven artifacts * 0.12.1048 on Sep 17, 2021 * Fix nested cache usage for local poms * 0.12.1041 on Sep 17, 2021 * Move back to older version of Maven resolver 1.6.3 to match Maven core 3.8.2 * Move to latest version of aws api libs * 0.12.1036 on Aug 30, 2021 * Fix bad type hint * 0.12.1030 on Aug 23, 2021 * Fix javadoc on clojure.tools.cli.api/basis * 0.12.1026 on Aug 17, 2021 * Update all deps * 0.12.1019 on Aug 10, 2021 * Load and cache Maven settings once for perf * Cache version range resolution results for perf * 0.12.1013 on Aug 9, 2021 * TDEPS-199 Use default http-client in S3 transporter * Cache S3 transporter for a repo * Fixed session cache to work properly across threads / binding stacks for better perf * Replace specific maven version range requests with non-range request to reduce repo metadata lookups * 0.12.1003 on July 19, 2021 * slurp-deps returns nil on non-existent file * Add missing multimethods for jar files libs * TDEPS-187 Rework how tools and exec args are resolved * 0.12.994 on July 15, 2021 * For clj -X:deps pom, compute deps from basis :libs, not original :deps * Fix help/doc and help/dir to better handle requiring unloaded nses * 0.12.985 on July 9, 2021 * clojure.tools.cli.api * NEW functions: find-versions, prep, basis * clojure.tools.cli.help * NEW functions: doc, dir * clojure.tools.deps.alpha * NEW create-basis * git deps * Infer :git/url from git lib name * Support :git/tag + prefix :git/sha (must point to same commit) * Support for -T and tools * 0.11.935 on June 25, 2021 * Don't compute local repo path at load time * 0.11.931 on June 10, 2021 * TDEPS-179 - Fix incorrect classpath when :classpath-overrides removes path * 0.11.926 on June 6, 2021 * Fix reflection warning * 0.11.922 on May 20, 2021 * TDEPS-178 - Update to latest Maven deps (resolver 1.7.0, core 1.8.3) * See https://maven.apache.org/docs/3.8.1/release-notes.html for CVE details * 0.11.918 on May 11, 2021 * TDEPS-177 - Use server id, not server name to select Maven mirror * Update to latest tools.gitlibs to 2.3.167 * 0.11.910 on Apr 3, 2021 * Bump dep version for tools.gitlibs to 2.2.152 * 0.11.905 on Mar 12, 2021 * Bump dep version for tools.gitlibs to 2.1.144 * 0.11.901 on Mar 10, 2021 * Bump dep version for tools.gitlibs * Update root deps.edn clojure version to 1.10.3 * 0.10.895 on Mar 10, 2021 * Bump dep versions for tools.gitlibs, tools.cli, and aws to latest * 0.10.889 on Mar 3, 2021 * Update to tools.gitlibs 2.0.109 (shell out to git) * 0.9.884 on Feb 23, 2021 * Cache pom model reading for improved performance on pom deps * git-resolve-tags will update the existing sha if it doesn't match the tag or is invalid * Re-add deprecated method removed in 0.9.871 * 0.9.876 on Feb 17, 2021 * TDEPS-56 - New format for .main and .jvm files to address word splitting * 0.9.871 on Feb 8, 2021 * Print warning if :paths or :extra-paths refers to directory not under the project root. Will eventually error. * 0.9.863 on Jan 26, 2021 * Update defualt clojure version in deps.edn resource file to 1.10.2 * 0.9.859 on Jan 26, 2021 * TDEPS-176 - Improve error message for missing git relationship * 0.9.857 on Dec 7, 2020 * Fix bug that saved trace.edn when using -Stree * 0.9.853 on Dec 6, 2020 * More tree printing options and support for -Stree * 0.9.847 on Dec 2, 2020 * Add new clj -X:deps tree printer * Bump aws api deps * 0.9.840 on Nov 23, 2020 * When resolving pom models, use System properties so jdk profile activation works * Update specs to cover alias changes * 0.9.833 on Oct 21, 2020 * Fixed issue where -Spom had stopped paying attention to -A dep changes * 0.9.828 on Oct 20, 2020 * TDEPS-169 mvn-install should extract and install pom inside jar file * `-X:deps tree` program should use project basis, not injected basis * 0.9.821 on Oct 10, 2020 * Bump to latest deps for maven-resolver and aws api * Read deps.edn to be tolerant of unknown tagged literals in alias data * 0.9.816 on Oct 5, 2020 * Fix issues with transitive orphan handling when finding newer versions during expansion * 0.9.810 on Sep 24, 2020 * Fix issue with merging non-map alias args * TDEPS-167 - Handle absolute resource paths in pom deps * 0.9.799 on Sep 16, 2020 * Fix classpath ordering for paths and libs * 0.9.795 on Sep 11, 2020 * More work on -X:deps mvn-pom support * 0.9.790 on Sep 10, 2020 * TDEPS-155 - Better error handling for a variety of bad coordinate cases * Re-add -R, -C, and -Spom support * 0.9.782 on Sep 4, 2020 * Add new argmap keys: :ns-default, :ns-aliases * Deprecate :deps/:paths in tool argmap to :replace-deps/:replace-paths * Move deps programs to new clojure.tools.cli.api namespace * Always order repositories central, then clojars, then others * Bump to tools.gitlibs 1.0.100 * 0.9.763 on Aug 9, 2020 * TDEPS-161 Fix regression with tree printing * 0.9.759 on Aug 7, 2020 * Bump to tools.gitlibs 1.0.96 (see TDEPS-160) * 0.9.755 on July 30, 2020 * TDEPS-157 Fix regression with groupId getting overwritten when syncing existing pom * TDEPS-159 Cut orphaned children of previously selected version after expansion * 0.9.751 on July 30, 2020 * Fixed docstring for make-classpath-map * 0.9.745 on July 22, 2020 * Added new execution mode to execute a function that takes an argmap via -X * Added new calc-basis api * Added support for using data stored in aliases as :paths * Added explicit "tool" step to cover :deps and :paths replacement, which can be passed via alias -T (functionality existed previously but was only exposed via -A alias) * Added new program clojure.tools.deps.alpha.tools.install/install for local jar install * Improved -Spom fix to TDEPS-152 to properly include the srcDirectory on either gen or sync in -Spom * Removed tools.deps.alpha.reader - most functions have migrated to tools.deps.alpha (some API changes as well) * Deprecated use of unqualified lib names in deps.edn - will continue to work but will generate warnings * 0.8.709 on July 17, 2020 * Rework exclusion handling when exclusion sets differ for same lib/version * 0.8.702 on July 15, 2020 * During version selection, prefer same version with fewer exclusions * 0.8.695 on June 11, 2020 * TDEPS-152 - Fix bad addition of in pom gen * TDEPS-155 - Add error checking for missing :mvn/version * Bump versions of tools.gitlibs and tools.cli * 0.8.677 on Feb 14, 2020 * TDEPS-150 - Fix regression in supporting -Scp flag (avoid resolving deps) * TDEPS-148 - Fix incorrect path resolution for git/local dep without deps.edn * 0.8.661 on Jan 30, 2020 * New: concurrent downloading of deps and metadata * Fix regression in -Spom no longer populating from 0.8.573 * Fix manifest type lookup for git deps after coordinate resolution * 0.8.640 on Jan 20, 2020 * Added tests for pom deps and gen pom * 0.8.633 on Jan 17, 2020 * Fix regression with reading pom models with dep set from 0.8.624 * Fix regression breaking pom gen from 0.8.624 * 0.8.624 on Jan 16, 2020 * New s3 transporter, replacing old s3 repo access * Bump all dep versions * 0.8.599 on Nov 19, 2019 * TDEPS-127 - Include pom resource directories in dep paths * TDEPS-140 - Use Maven server HTTP header properties * 0.8.591 on Nov 17, 2019 * Add tracing * TDEPS-143 - Fix pom gen in combination with aliases does not respect alias modifications * 0.8.584 on Nov 4, 2019 * TDEPS-142 - Fix :paths replacement doesn't work when :deps replacement used in alias * 0.8.578 on Oct 18, 2019 * Fix bugs in script.make-classpath2 * 0.8.573 on Oct 17, 2019 * Deprecate script.generate-manifest in favor of generate-manifest2, reuse more of make-classpath2 * 0.8.567 on Oct 17, 2019 * Rework impl of :deps and :paths in aliases, deprecate script.make-classpath in favor of script.make-classpath2 and added tests * nil repo configs will be ignored (can remove default repos by declaring nil) * 0.8.559 on Oct 15, 2019 * TDEPS-138 - add tools.deps.alpha.reader/user-deps-location function * TDEPS-29 - fix -Spom adding unnecessary newlines in Java 9+ * Add :deps and :paths to aliases to "replace" main :deps and :paths * 0.7.549 on Sep 17, 2019 * Fix: spec error for :local/root and missing required key :sha for git coords * 0.7.541 on Aug 9, 2019 * Fix: pom deps should include only compile and runtime deps * Fix: remove slf4j-nop as dep - let consumers choose * 0.7.537 on Aug 9, 2019 * Fix: exclusions were not canonicalized and may fail to match and exclude * Perf: cache Maven resources and use Maven repository cache * 0.7.527 on July 17, 2019 * Deprecate and warn for clojure.tools.deps.alpha.reader/clojure-env * TDEPS-134 - use Maven mirrors * Change unknown aliases from error to warning * 0.7.516 on June 29, 2019 * Add ctda.reader/default-deps to duplicate the deps.edn file logic in clj * 0.7.511 on June 29, 2019 * Fix regression on default clojure version in install * 0.7.505 on June 28, 2019 * TDEPS-52 Embed install deps.edn, fix path gen on deps with no paths * TDEPS-96 Generate pom source path relative to transitive root dir * TDEPS-88 Resolve meaning of -Srepro (include install deps, ignore ~/.clojure) * 0.6.496 on Mar 16, 2019 * TDEPS-74 Fix resolution of relative paths in transitive local deps * TDEPS-20 Support Maven proxy settings * 0.6.488 on Feb 13, 2019 * TDEPS-114 Canonicalize Maven RELEASE or LATEST version marker * Add error handling for unresolvable Maven version * 0.6.480 on Jan 4, 2019 * TDEPS-112 Make exclusions classifier aware * 0.6.474 on Jan 2, 2019 * Error handling improvements when Maven artifact is not found * Error handling improvements for invalid deps.edn * TDEPS-50, TDEPS-109 Fixed handling of Maven classifiers * Specify classifier in lib name: groupId/artifactId$classifier * :classifier in coordinate map will now error * TDEPS-79, TDEPS-109 fix infinite loop in resolving deps tree * TDEPS-107 canonicalized exclusion groupIds in pom gen * 0.5.460 on Oct 17, 2018 * Use newer version of aws-maven under s3-wagon-private * 0.5.452 on Sept 15, 2018 * TDEPS-92 error and report on unknown alias key * TDEPS-12 add support for multiple classifiers in libs * TDEPS-95 fix bug preventing :default-deps from working * 0.5.442 on July 19, 2018 * TDEPS-85 error on unknown aliases * 0.5.435 on May 11, 2018 * TDEPS-9 support Maven deps in authenticated repositories * Use embedded pom to traverse transitive deps for a local dep jar * 0.5.425 on Apr 13, 2018 * TDEPS-73 detect invalid deps.edn file and error * TDEPS-61 use Clojars CDN repo * TDEPS-26 include transitive runtime deps in addition to compile deps * 0.5.417 on Mar 23, 2018 * TDEPS-59 clear cached jvm and main opts if stale * 0.5.410 on Mar 16, 2018 * TDEPS-54 add -Sdeps and -A support to -Spom * TDEPS-55 fix -Spom for xml file with comment before root node * TDEPS-40 clean up log dependencies * Update to tools.gitlibs 0.2.64 * 0.5.398 on Feb 22, 2018 * Update dependency versions to latest * 0.5.393 on Feb 21, 2018 * Change call to clojure -Senv to -Sdescribe * 0.5.388 on Feb 20, 2018 * Better error if cache dir can't be created * API additions and refactoring * 0.5.373 on Feb 10, 2018 * Add tools.deps.alpha/lib-location method * Load all extensions in tools.deps.alpha * Add support in make-classpath for skipping classpath and lib writing * 0.5.351 on Feb 2, 2018 * Alias support for main, jvm opts, and generic aliases * TDEPS-38 Fix issues with merging non-maps at top-level * Automatically add src/main/clojure as a source path in pom manifest reader * 0.5.342 on Jan 23, 2018 * TDEPS-19 Add support for command line deps config data * Add print-tree script * Fix bug with git deps with :deps/root * 0.5.323 on Jan 18, 2018 * Remove stray debug print in -Spom * Fix source paths in pom manifest reader * 0.5.317 on Jan 18, 2018 * TDEPS-24 Major changes to expansion and version resolution * TDEPS-32 git extension should use :deps/root if specified * Change error handling to dump stack on unexpected exception * Add pom file reader for local and git deps * TDEPS-34 Emit exclusions and classifiers in pom gen * Tighten git sha comparison rules * 0.4.295 on Jan 10, 2018 * Disallow prefix sha in git coord * TDEPS-28 - -Spom - now supports -R and -C aliases (for top-level deps) * TDEPS-18 - Internal refactoring for script arg handling * 0.4.277 on Jan 8, 2018 * Add code for resolve-tags command * Git deps now use :sha and :tag rather than :rev * TDEPS-27 - pom gen reported warning when run on Java 9 * Less confusing errors when a git dep has no deps.edn * 0.3.260 on Jan 4, 2018 * TDEPS-25 - pom gen will now sync repositories * Update to latest version of gitlibs * 0.3.254 on Jan 3, 2018 * Refactored gitlibs out into library * 0.3.231 on Dec 21, 2017 * Insert deps config at front of config chain rather than back * Make deps manifest reader tolerant of missing deps.edn in project * 0.3.225 on Dec 21, 2017 * Fix bug in cache dir configuration * 0.3.220 on Dec 20, 2017 * Added support for git deps - see docs for details * Print warnings and messages to stderr rather than stdout * 0.2.196 on Dec 7, 2017 * Local deps should use full deps file chain, not just project deps * Change default clojars url back * 0.2.190 on Dec 2, 2017 * Change default clojars url to use the CDN * Fix bug in :local/root for jar manifests * 0.2.183 on Nov 8, 2017 * Improve error handling when switching on coordinate and manifest types * Close pom reader before writing during pom gen sync * 0.2.173 on Oct 31, 2017 * TDEPS-14 - Canonicalize lib symbol format * 0.2.167 on Oct 26, 2017 * Add s3 Maven repo support * 0.2.162 on Oct 24, 2017 * Add pom gen/sync * 0.2.155 on Oct 6, 2017 * Overhaul provider extensions * Implement local provider deps project support * 0.2.130 on Sep 21, 2017 * Always treat libs-file as stale * 0.2.122 on Sep 21, 2017 * Ignore reserved "deps" namespace when dispatching on coord type * Avoid duplicating cache logic in makecp * 0.2.116 on Sep 20, 2017 * New strategy for coordinate specification and dispatch * 0.1.108 on Sep 19, 2017 * Remove -P classpath overrides option handling * 0.1.103 on Sep 19, 2017 * Bug fixes for :paths and :extra-paths * 0.1.85 on Sep 15, 2017 * TDEPS-11 - Lift provider attributes up to top-level with namespace qualifiers * Use platform-specific character when creating classpaths * Add top-level :paths and make-classpath :extra-paths * 0.1.78 on Sep 12, 2017 * TDEPS-10 - Change makecp to take a list of config files to be merged left to right rather than just a user and project level file. Changed args to be named rather than positional to help with script evolution. * 0.1.73 on Aug 31, 2017 * Combine user and project deps.edn with `merge-with merge` rather than `merge` * 0.1.68 on Aug 25, 2017 * Top dep coords take priority over transitive deps * 0.1.62 on Aug 24, 2017 * Omit scope and optional attributes on expanded Maven deps * Handle exclusions in resolve-deps * 0.1.56 on Aug 22, 2017 * Add specs * Add provider-specific version comparison * Add Maven version comparison * Report exclusions in Maven coords * 0.1.40 on Aug 14, 2017 * makecp now takes an initial argument that is the system deps file to avoid all implicit dirs * 0.1.35 on Aug 14, 2017 * Load prototype :file provider in addition to the :mvn provider * clj script has been deprecated and moved to the brew-install repo (but is still here for the moment) * 0.1.29 on Aug 1, 2017 * Modify clj script to check whether ~/.clojure/clj.props has changed and if so, re-run install-clj * TDEPS-2 Overhauled makecp error handling * Make rlwrap usage dependent on availability * Rename deptools.cp to clj.cp * 0.1.14 on Jul 24, 2017 * Initial release tools.deps-0.16.1264/CONTRIBUTING.md000066400000000000000000000007371434474567100164040ustar00rootroot00000000000000This is a [Clojure contrib] project. Under the Clojure contrib [guidelines], this project cannot accept pull requests. All patches must be submitted via [JIRA]. See [Contributing] on the Clojure website for more information on how to contribute. [Clojure contrib]: https://clojure.org/community/contrib_libs [Contributing]: https://clojure.org/community/contributing [JIRA]: https://clojure.atlassian.net/browse/TDEPS [guidelines]: https://clojure.org/community/contrib_howto tools.deps-0.16.1264/LICENSE000066400000000000000000000263741434474567100151650ustar00rootroot00000000000000Eclipse Public License - v 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. tools.deps-0.16.1264/README.md000066400000000000000000000077271434474567100154400ustar00rootroot00000000000000tools.deps ======================================== A functional API for transitive dependency graph expansion and the creation of classpaths. # Rationale Clojure "endeavors to be a general-purpose language suitable in those areas where Java is suitable" (from [Rationale](https://clojure.org/about/rationale)). To effectively target the JVM platform, Clojure needs to provide ready access to Java libraries, ideally in a way suited for dynamic development. In practice, this means meeting the JVM platform in two places: * the classpath used when invoking JVM processes (and/or URLClassLoaders) * transitive dependency download and resolution from Maven repositories tools.deps aims to provide a functional API to access these capabilities. tools.deps makes it simple and easy to interactively consume JVM libraries, without dragging in unrelated concerns of building programs or project management. (It should also be a useful shared resource for future work on project and build tools.) tools.deps will support package installers for Clojure (e.g. brew, apt-get, etc) to provide a path for Clojure installation and ongoing Clojure development. The Clojure 1.9 release for the first time required multiple artifacts to run Clojure (clojure, spec.alpha, and core.specs.alpha) and thus the issues of transitive dependency are now immediately in front of a Clojure user in the first minute. Maven-artifacts-first orientation of current tooling has created great rigidity and friction for dev processes - making it hard to e.g. work with libs not yet building/publishing artifacts (new users!), working on speculative changes w/o artifacts, working on mutual changes across multiple libs, give control to a 3rd party tool to manage shared dependencies, and to directly leverage git which is now widely used as a source of truth for code lifecycles. Also see: * [Getting Started](https://clojure.org/guides/getting_started) * [Deps and CLI Guide](https://clojure.org/guides/deps_and_cli) * [Deps and CLI Reference](https://clojure.org/reference/deps_and_cli) * [Dependency Heaven](http://cdn.cognitect.com/presentations/2017/dependency_heaven.pdf) from EuroClojure 2017 - [video](https://youtube.com/watch?v=sStlTye-Kjk) * [Projects that use or work with tools.deps and clj](https://github.com/clojure/tools.deps.alpha/wiki/Tools) * [Tool implementation and installers](https://github.com/clojure/brew-install) # Release Information Latest release: 0.16.1260 * [All released versions](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22tools.deps%22) [deps.edn](https://clojure.org/guides/deps_and_cli) dependency information: ``` org.clojure/tools.deps {:mvn/version "0.16.1260"} ``` [Leiningen](https://github.com/technomancy/leiningen/) dependency information: ``` [org.clojure/tools.deps "0.16.1260"] ``` [Maven](https://maven.apache.org) dependency information: ``` org.clojure tools.deps 0.16.1260 ``` # API For info on using tools.deps as a library, see: * [API Docs](https://clojure.github.io/tools.deps) # Developer Information * [GitHub project](https://github.com/clojure/tools.deps) * [How to contribute](https://clojure.org/community/contributing) * [Bug Tracker](https://clojure.atlassian.net/browse/TDEPS) * [Continuous Integration](https://build.clojure.org/job/tools.deps/) * [Compatibility Test Matrix](https://build.clojure.org/job/tools.deps-test-matrix/) # Copyright and License Copyright © 2017-2022 Rich Hickey, Alex Miller, and contributors All rights reserved. The use and distribution terms for this software are covered by the [Eclipse Public License 1.0] which can be found in the file LICENSE at the root of this distribution. By using this software in any fashion, you are agreeing to be bound by the terms of this license. You must not remove this notice, or any other, from this software. [Eclipse Public License 1.0]: https://opensource.org/licenses/eclipse-1.0.php tools.deps-0.16.1264/VERSION_TEMPLATE000077500000000000000000000000271434474567100165110ustar00rootroot000000000000000.16.GENERATED_VERSION tools.deps-0.16.1264/deps.edn000066400000000000000000000036641434474567100156000ustar00rootroot00000000000000{:paths ["src/main/clojure" "src/main/resources"] :deps { org.clojure/clojure {:mvn/version "1.10.3"} org.apache.maven.resolver/maven-resolver-api {:mvn/version "1.8.2"} org.apache.maven.resolver/maven-resolver-spi {:mvn/version "1.8.2"} org.apache.maven.resolver/maven-resolver-impl {:mvn/version "1.8.2"} org.apache.maven.resolver/maven-resolver-util {:mvn/version "1.8.2"} org.apache.maven.resolver/maven-resolver-connector-basic {:mvn/version "1.8.2"} org.apache.maven.resolver/maven-resolver-transport-file {:mvn/version "1.8.2"} org.apache.maven.resolver/maven-resolver-transport-http {:mvn/version "1.8.2"} org.apache.maven/maven-resolver-provider {:mvn/version "3.8.6"} org.apache.maven/maven-core {:mvn/version "3.8.6" exclusions [commons-io/commons-io com.google.guava/guava]} commons-io/commons-io {:mvn/version "2.11.0"} ;; update transitive dep due to CVE-2021-29425 com.google.guava/guava {:mvn/version "31.1-android"} ;; update transitive dep due to CVE-2020-8908 org.clojure/data.xml {:mvn/version "0.2.0-alpha8"} org.clojure/tools.gitlibs {:mvn/version "2.4.181"} org.clojure/tools.cli {:mvn/version "1.0.214"} com.cognitect.aws/api {:mvn/version "0.8.612"} com.cognitect.aws/endpoints {:mvn/version "1.1.12.321"} com.cognitect.aws/s3 {:mvn/version "822.2.1145.0"} javax.inject/javax.inject {:mvn/version "1"} } :aliases { ;; clj -M:lint :lint {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2022.10.14"}} :main-opts ["-m" "clj-kondo.main" "--lint" "src/main/clojure" "--lint" "src/test/clojure"]} ;; clj -M:cve :cve {:extra-deps {io.github.clj-holmes/clj-watson {:git/tag "v4.1.0" :git/sha "e3da1b6"}} :jvm-opts ["--illegal-access=deny"] :main-opts ["-m" "clj-watson.cli" "scan" "-p" "deps.edn"]} ;; clj -M:outdated :outdated {:extra-deps {com.github.liquidz/antq {:mvn/version "RELEASE"}} :main-opts ["-m" "antq.core"]} } } tools.deps-0.16.1264/pom.xml000066400000000000000000000143031434474567100154620ustar00rootroot00000000000000 4.0.0 tools.deps 0.16.1264 tools.deps org.clojure pom.contrib 1.1.0 puredanger Alex Miller true 1.10.3 1.8.2 3.8.6 1.10.3 org.clojure clojure ${clojure.version} org.apache.maven.resolver maven-resolver-api ${resolverVersion} org.apache.maven.resolver maven-resolver-spi ${resolverVersion} org.apache.maven.resolver maven-resolver-impl ${resolverVersion} org.apache.maven.resolver maven-resolver-util ${resolverVersion} org.apache.maven.resolver maven-resolver-connector-basic ${resolverVersion} org.apache.maven.resolver maven-resolver-transport-file ${resolverVersion} org.apache.maven.resolver maven-resolver-transport-http ${resolverVersion} org.apache.maven maven-resolver-provider ${mavenVersion} org.apache.maven maven-core ${mavenVersion} commons-io commons-io com.google.guava guava commons-io commons-io 2.11.0 com.google.guava guava 31.1-android org.slf4j slf4j-nop 1.7.36 test org.clojure data.xml 0.2.0-alpha8 org.clojure tools.gitlibs 2.4.181 org.clojure tools.cli 1.0.214 com.cognitect.aws api 0.8.612 com.cognitect.aws endpoints 1.1.12.321 com.cognitect.aws s3 822.2.1145.0 javax.inject javax.inject 1 src/main/resources true org.apache.maven.plugins maven-resources-plugin 3.1.0 com.theoryinpractise clojure-maven-plugin 1.7.1 true ${clojure.warnOnReflection} true clojure-compile none clojure-test test test scm:git:git@github.com:clojure/tools.deps.git scm:git:git@github.com:clojure/tools.deps.git git@github.com:clojure/tools.deps.git v0.16.1264 clojars https://clojars.org/repo/ tools.deps-0.16.1264/script/000077500000000000000000000000001434474567100154505ustar00rootroot00000000000000tools.deps-0.16.1264/script/version000077500000000000000000000005401434474567100170620ustar00rootroot00000000000000#!/usr/bin/env bash set -e version_template=`cat VERSION_TEMPLATE` commit_count=`git rev-list HEAD --count` if [[ "$version_template" =~ ^[0-9]+\.[0-9]+\.GENERATED_VERSION(-[a-zA-Z0-9]+)?$ ]]; then echo ${version_template/GENERATED_VERSION/$commit_count} else echo "Invalid version template string: $version_template" >&2 exit -1 fi tools.deps-0.16.1264/src/000077500000000000000000000000001434474567100147335ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/000077500000000000000000000000001434474567100156575ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/clojure/000077500000000000000000000000001434474567100173225ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/clojure/clojure/000077500000000000000000000000001434474567100207655ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/clojure/clojure/tools/000077500000000000000000000000001434474567100221255ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps.clj000066400000000000000000001204631434474567100235600ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns clojure.tools.deps (:require [clojure.java.io :as jio] [clojure.set :as set] [clojure.string :as str] [clojure.tools.deps.util.concurrent :as concurrent] [clojure.tools.deps.util.dir :as dir] [clojure.tools.deps.util.io :as io] [clojure.tools.deps.util.session :as session] [clojure.tools.deps.extensions :as ext] [clojure.walk :as walk]) (:import [clojure.lang EdnReader$ReaderException] [clojure.lang PersistentQueue] [java.io File InputStreamReader BufferedReader] [java.lang ProcessBuilder ProcessBuilder$Redirect] [java.util List])) ;(set! *warn-on-reflection* true) ;;;; deps.edn reading (defn- io-err ^Throwable [fmt ^File f] (let [path (.getAbsolutePath f)] (ex-info (format fmt path) {:path path}))) (defn- slurp-edn-map "Read the file specified by the path-segments, slurp it, and read it as edn." [^File f] (let [val (try (io/slurp-edn f) (catch EdnReader$ReaderException e (throw (io-err (str (.getMessage e) " (%s)") f))) (catch RuntimeException t (if (str/starts-with? (.getMessage t) "EOF while reading") (throw (io-err "Error reading edn, delimiter unmatched (%s)" f)) (throw (io-err (str "Error reading edn. " (.getMessage t) " (%s)") f)))))] (if (map? val) val (throw (io-err "Expected edn map in: %s" f))))) ;; all this canonicalization is deprecated and will eventually be removed (defn- canonicalize-sym ([s] (canonicalize-sym s nil)) ([s file-name] (if (simple-symbol? s) (let [cs (as-> (name s) n (symbol n n))] (io/printerrln "DEPRECATED: Libs must be qualified, change" s "=>" cs (if file-name (str "(" file-name ")") "")) cs) s))) (defn- canonicalize-exclusions [{:keys [exclusions] :as coord} file-name] (if (seq (filter simple-symbol? exclusions)) (assoc coord :exclusions (mapv #(canonicalize-sym % file-name) exclusions)) coord)) (defn- canonicalize-dep-map [deps-map file-name] (when deps-map (reduce-kv (fn [acc lib coord] (let [new-lib (if (simple-symbol? lib) (canonicalize-sym lib file-name) lib) new-coord (canonicalize-exclusions coord file-name)] (assoc acc new-lib new-coord))) {} deps-map))) (defn- canonicalize-all-syms ([deps-edn] (canonicalize-all-syms deps-edn nil)) ([deps-edn file-name] (walk/postwalk (fn [x] (if (map? x) (reduce (fn [xr k] (if-let [xm (get xr k)] (assoc xr k (canonicalize-dep-map xm file-name)) xr)) x #{:deps :default-deps :override-deps :extra-deps :classpath-overrides}) x)) deps-edn))) (defn slurp-deps "Read a single deps.edn file from disk and canonicalize symbols, return a deps map. If the file doesn't exist, returns nil." [^File dep-file] (when (.exists dep-file) (-> dep-file slurp-edn-map (canonicalize-all-syms (.getPath dep-file))))) (defn root-deps "Read the root deps.edn resource from the classpath at the path clojure/tools/deps/deps.edn" [] (let [url (jio/resource "clojure/tools/deps/deps.edn")] (io/read-edn (BufferedReader. (InputStreamReader. (.openStream url)))))) (defn user-deps-path "Use the same logic as clj to calculate the location of the user deps.edn. Note that it's possible no file may exist at this location." [] (let [config-env (System/getenv "CLJ_CONFIG") xdg-env (System/getenv "XDG_CONFIG_HOME") home (System/getProperty "user.home") config-dir (cond config-env config-env xdg-env (str xdg-env File/separator "clojure") :else (str home File/separator ".clojure"))] (str config-dir File/separator "deps.edn"))) (defn find-edn-maps "Finds and returns standard deps edn maps in a map with keys :root-edn, :user-edn, :project-edn If no project-edn is supplied, use the deps.edn in current directory" ([] (find-edn-maps nil)) ([project-edn-file] (let [user-loc (jio/file (user-deps-path)) project-loc (jio/file (if project-edn-file project-edn-file (str dir/*the-dir* File/separator "deps.edn")))] (cond-> {:root-edn (root-deps)} (.exists user-loc) (assoc :user-edn (slurp-deps user-loc)) (.exists project-loc) (assoc :project-edn (slurp-deps project-loc)))))) (defn- merge-or-replace "If maps, merge, otherwise replace" [& vals] (when (some identity vals) (reduce (fn [ret val] (if (and (map? ret) (map? val)) (merge ret val) (or val ret))) nil vals))) (defn merge-edns "Merge multiple deps edn maps from left to right into a single deps edn map." [deps-edn-maps] (apply merge-with merge-or-replace (remove nil? deps-edn-maps))) ;;;; Aliases ;; per-key binary merge-with rules (def ^:private last-wins (comp last #(remove nil? %) vector)) (def ^:private append (comp vec concat)) (def ^:private append-unique (comp vec distinct concat)) (def ^:private merge-alias-rules {:deps merge ;; FUTURE: remove :replace-deps merge ;; formerly :deps :extra-deps merge :override-deps merge :default-deps merge :classpath-overrides merge :paths append-unique ;; FUTURE: remove :replace-paths append-unique ;; formerly :paths :extra-paths append-unique :jvm-opts append :main-opts last-wins :exec-fn last-wins :exec-args merge-or-replace :ns-aliases merge :ns-default last-wins}) (defn- choose-rule [alias-key val] (or (merge-alias-rules alias-key) (if (map? val) merge (fn [_v1 v2] v2)))) (defn- merge-alias-maps "Like merge-with, but using custom per-alias-key merge function" [& ms] (reduce #(reduce (fn [m [k v]] (update m k (choose-rule k v) v)) %1 %2) {} ms)) (defn combine-aliases "Find, read, and combine alias maps identified by alias keywords from a deps edn map into a single args map." [edn-map alias-kws] (->> alias-kws (map #(get-in edn-map [:aliases %])) (apply merge-alias-maps))) (defn lib-location "Find the file path location of where a lib/coord would be located if procured without actually doing the procuring!" [lib coord deps-config] (ext/lib-location lib coord deps-config)) ;;;; expand-deps ;; exclusions tree (defn- excluded? [exclusions path lib] (let [lib-name (first (str/split (name lib) #"\$")) base-lib (symbol (namespace lib) lib-name)] (loop [search path] (when (seq search) (if (get-in exclusions [search base-lib]) true (recur (pop search))))))) (defn- update-excl "Update exclusions and cut based on whether this is a new lib/version, a new instance of an existing lib/version, or not including." [lib use-coord coord-id use-path include reason exclusions cut] (let [coord-excl (when-let [e (:exclusions use-coord)] (set e))] (cond ;; if adding new lib/version, include all non-excluded children include (if (nil? coord-excl) {:exclusions' exclusions, :cut' cut, :child-pred (constantly true)} {:exclusions' (assoc exclusions use-path coord-excl) :cut' (assoc cut [lib coord-id] coord-excl) :child-pred (fn [lib] (not (contains? coord-excl lib)))}) ;; if seeing same lib/ver again, narrow exclusions to intersection of prior and new. ;; only include new unexcluded children (old excl set minus new excl set) ;; as others were already enqueued when first added (= reason :same-version) (let [exclusions' (if (seq coord-excl) (assoc exclusions use-path coord-excl) exclusions) cut-coord (get cut [lib coord-id]) ;; previously cut from this lib, so were not enqueued new-cut (set/intersection coord-excl cut-coord) enq-only (set/difference cut-coord new-cut)] {:exclusions' exclusions' :cut' (assoc cut [lib coord-id] new-cut) :child-pred (set enq-only)}) :else ;; otherwise, no change {:exclusions' exclusions, :cut' cut}))) ;; version map ;; {lib {:versions {coord-id coord} ;; all version coords ;; :paths {coord-id #{paths}} ;; paths to coord-ids ;; :select coord-id ;; current selection ;; :top true} ;; if selection is top dep (defn- add-version "Add a new version of a lib to the version map" [vmap lib coord path coord-id] (-> (or vmap {}) (assoc-in [lib :versions coord-id] coord) (update-in [lib :paths] (fn [coord-paths] (merge-with into {coord-id #{path}} coord-paths))))) (defn- select-version "Mark a particular coord as selected in version map" [vmap lib coord-id top?] (update-in vmap [lib] merge (cond-> {:select coord-id} top? (assoc :top true)))) (defn- selected-version "Get currently selected version of lib" [vmap lib] (get-in vmap [lib :select])) (defn- selected-coord "Get currently selected coord of lib" [vmap lib] (get-in vmap [lib :versions (selected-version vmap lib)])) (defn- selected-paths "Get paths to selected coord of lib" [vmap lib] (get-in vmap [lib :paths (selected-version vmap lib)])) (defn- parent-missing? "Is any part of the parent path missing from the selected lib/versions? This can happen if a newer version was found, orphaning previously selected children." [vmap parent-path] (when (seq parent-path) (loop [path parent-path] (if (seq path) (let [lib (last path) check-path (vec (butlast path)) {:keys [paths select]} (get vmap lib)] (if (contains? (get paths select) check-path) (recur check-path) true)) false)))) (defn- deselect-orphans "For the given paths, deselect any libs whose only selected version paths are in omitted-paths" [vmap omitted-paths] (reduce-kv (fn [ret lib {:keys [select paths]}] (let [lib-paths (get paths select)] ;; if every selected path for this lib has omitted paths as prefixes, deselect (if (every? (fn [p] (some #(= % (take (count %) p)) omitted-paths)) lib-paths) (update-in ret [lib] dissoc :select) ret))) vmap vmap)) (defn- dominates? "Is new-coord newer than old-coord?" [lib new-coord old-coord config] (pos? (ext/compare-versions lib new-coord old-coord config))) (defn- include-coord? "This is the key decision-making function when considering a lib/coord node in the traversal graph. It returns :include (whether to include this lib/coord), a :reason why it was included or not, and an updated :vmap (may have new version added and/or new selected version for a lib)" [vmap lib coord coord-id path exclusions config] (cond ;; lib is a top dep and this is it => select (empty? path) {:include true, :reason :new-top-dep, :vmap (-> vmap (add-version lib coord path coord-id) (select-version lib coord-id true))} ;; lib is excluded in this path => omit (excluded? exclusions path lib) {:include false, :reason :excluded, :vmap vmap} ;; lib is a top dep and this isn't it => omit (get-in vmap [lib :top]) {:include false, :reason :use-top, :vmap vmap} ;; lib's parent path is not included => omit (parent-missing? vmap path) {:include false, :reason :parent-omitted, :vmap vmap} ;; new lib or no selection => select (not (selected-version vmap lib)) {:include true, :reason :new-dep, :vmap (-> vmap (add-version lib coord path coord-id) (select-version lib coord-id false))} ;; existing lib, same version => omit (but update vmap, may need to enqueue newly unexcluded children) (= coord-id (selected-version vmap lib)) {:include false, :reason :same-version, :vmap (add-version vmap lib coord path coord-id)} ;; existing lib, newer version => select (dominates? lib coord (selected-coord vmap lib) config) {:include true, :reason :newer-version, :vmap (-> vmap (add-version lib coord path coord-id) (deselect-orphans (set (map #(conj % lib) (selected-paths vmap lib)))) (select-version lib coord-id false))} ;; existing lib, older version => omit :else {:include false, :reason :older-version, :vmap vmap})) (defn- canonicalize-deps [deps config] (reduce (fn [m [lib coord]] (conj m (ext/canonicalize lib coord config))) [] deps)) (defn- trace+ "Add an entry to the trace if needed" [trace? trace parents lib coord use-coord coord-id override-coord include reason] (when trace? (let [entry (cond-> {:path parents, :lib lib, :coord use-coord, :orig-coord coord, :coord-id coord-id :include include, :reason reason} override-coord (assoc :override-coord override-coord))] (conj trace entry)))) (defn- next-path [pendq q on-error] (let [[fchild & rchildren] pendq] (if fchild {:path fchild, :pendq rchildren, :q' q} (let [next-q (peek q) q' (pop q)] (if (map? next-q) (let [{:keys [pend-children ppath child-pred]} next-q result @pend-children] (when (instance? Throwable result) (on-error result)) (next-path (->> result (filter (fn [[lib _coord]] (child-pred lib))) (map #(conj ppath %))) q' on-error)) {:path next-q, :q' q'}))))) (defn- expand-deps "Dep tree expansion, returns version map" [deps default-deps override-deps config executor trace?] (letfn [(err-handler [throwable] (do (concurrent/shutdown-on-error executor) (throw ^Throwable throwable))) (children-task [lib use-coord use-path child-pred] {:pend-children (let [{:deps/keys [manifest root]} use-coord] (dir/with-dir (if root (jio/file root) dir/*the-dir*) (concurrent/submit-task executor #(try (canonicalize-deps (ext/coord-deps lib use-coord manifest config) config) (catch Throwable t t))))) :ppath use-path :child-pred child-pred})] (loop [pendq nil ;; a resolved child-lookup thunk to look at first q (into (PersistentQueue/EMPTY) (map vector deps)) ;; queue of nodes or child-lookups version-map nil ;; track all seen versions of libs and which version is selected exclusions nil ;; tracks exclusions marked in the tree cut nil ;; tracks cuts made of child nodes based on exclusions trace []] ;; trace expansion (let [{:keys [path pendq q']} (next-path pendq q err-handler)] (if path (let [[lib coord] (peek path) parents (pop path) use-path (conj parents lib) override-coord (get override-deps lib) choose-coord (cond override-coord override-coord coord coord :else (get default-deps lib)) use-coord (merge choose-coord (ext/manifest-type lib choose-coord config)) coord-id (ext/dep-id lib use-coord config) {:keys [include reason vmap]} (include-coord? version-map lib use-coord coord-id parents exclusions config) ;_ (println "loop" lib coord-id "include=" include "reason=" reason) {:keys [exclusions' cut' child-pred]} (update-excl lib use-coord coord-id use-path include reason exclusions cut) new-q (if child-pred (conj q' (children-task lib use-coord use-path child-pred)) q')] (recur pendq new-q vmap exclusions' cut' (trace+ trace? trace parents lib coord use-coord coord-id override-coord include reason))) (cond-> version-map trace? (with-meta {:trace {:log trace, :vmap version-map, :exclusions exclusions}}))))))) (defn- cut-orphans "Remove any selected lib that does not have a selected parent path" [version-map] (reduce-kv (fn [vmap lib {:keys [select]}] (if (nil? select) (dissoc vmap lib) vmap)) version-map version-map)) (defn- lib-paths "Convert version map to lib map" [version-map] (reduce-kv (fn [ret lib {:keys [select versions paths]}] (let [coord (get versions select) parent-paths (get paths select) parents (->> parent-paths (map last) (remove nil?) vec)] (assoc ret lib (cond-> coord (seq parents) (assoc :dependents parents) (seq parent-paths) (assoc :parents parent-paths))))) {} version-map)) (defn- download-libs [executor lib-map config] (let [lib-futs (reduce-kv (fn [fs lib coord] (let [fut (concurrent/submit-task executor #(try (ext/coord-paths lib coord (:deps/manifest coord) config) (catch Throwable t t)))] (assoc fs lib fut))) {} lib-map)] (reduce-kv (fn [lm lib fut] (let [result @fut] (if (instance? Throwable result) (do (concurrent/shutdown-on-error executor) (throw ^Throwable result)) (assoc-in lm [lib :paths] result)))) lib-map lib-futs))) (defn resolve-deps "Takes a deps configuration map and resolves the transitive dependency graph from the initial set of deps. args-map is a map with several keys (all optional) that can modify the results of the transitive expansion: :extra-deps - a map from lib to coord of deps to add to the main deps :override-deps - a map from lib to coord of coord to use instead of those in the graph :default-deps - a map from lib to coord of deps to use if no coord specified :trace - boolean. If true, the returned lib map will have metadata with :trace log :threads - long. If provided, sets the number of concurrent download threads Returns a lib map (map of lib to coordinate chosen)." {:arglists '([deps-map args-map])} ([deps-map args-map] (let [{:keys [extra-deps default-deps override-deps threads trace]} args-map n (or threads concurrent/processors) executor (concurrent/new-executor n) deps (merge (:deps deps-map) extra-deps) version-map (-> deps (canonicalize-deps deps-map) (expand-deps default-deps override-deps deps-map executor trace) cut-orphans) lib-map (lib-paths version-map) lib-map' (download-libs executor lib-map deps-map)] (with-meta lib-map' (meta version-map)))) ;; deprecated arity, retained for backwards compatibility ([deps-map args-map settings] (resolve-deps deps-map (merge args-map settings)))) (defn- make-tree [lib-map] (let [{roots false, nonroots true} (group-by #(-> % val :dependents boolean) lib-map)] (loop [q (into (PersistentQueue/EMPTY) roots) remaining nonroots tree {}] (let [[lib coord :as node] (peek q) q' (pop q)] (if node (let [{children true, not-used false} (group-by #(-> % val :dependents set (contains? lib)) remaining)] (recur (into q' children) not-used (assoc tree lib (assoc coord :children (map key children))))) tree))))) (defn print-tree "Print lib-map tree to the console" [lib-map] (let [tree (make-tree lib-map)] (letfn [(print-node [lib indent] (let [{:keys [children] :as coord} (get tree lib)] (println (str indent (ext/coord-summary lib coord))) (doseq [child-lib children] (print-node child-lib (str indent " ")))))] (doseq [[lib coord] tree :when (-> coord :dependents nil?)] (print-node lib ""))))) (defn- chase-key "Given an aliases set and a keyword k, return a flattened vector of path entries for that k, resolving recursively if needed, or nil." [aliases k] (let [path-coll (get aliases k)] (when (seq path-coll) (into [] (mapcat #(if (string? %) [[% {:path-key k}]] (chase-key aliases %))) path-coll)))) (defn- flatten-paths [{:keys [paths aliases] :as deps-edn-map} {:keys [extra-paths] :as classpath-args}] (let [aliases' (assoc aliases :paths paths :extra-paths extra-paths)] (into [] (comp (mapcat #(chase-key aliases' %)) (remove nil?)) [:extra-paths :paths]))) (defn- validate-paths [paths] (doto paths (->> (map first) (run! #(when (not (dir/sub-path? (jio/file %))) (io/printerrln "WARNING: Use of :paths external to the project has been deprecated, please remove:" %)))))) (defn- tree-paths "Given a lib map, return a vector of all vector paths to included libs in the tree. Libs are often included at multiple paths." [lib-map] (loop [paths [] [lib & libs] (keys lib-map)] (if lib (let [parent-paths (:parents (get lib-map lib))] (recur (reduce (fn [paths parent-path] (conj paths (conj parent-path lib))) paths parent-paths) libs)) paths))) (defn- sort-paths "Given a vector of lib paths, sort in canonical order - top of tree to bottom, alpha sort at same level" [lib-paths] (->> lib-paths sort (sort-by count) vec)) (defn- flatten-libs [lib-map {:keys [classpath-overrides] :as classpath-args}] (let [override-libs (if classpath-overrides (reduce-kv (fn [lm lib path] (if (contains? lm lib) (if (str/blank? path) ;; classpath-override removes lib (dissoc lm lib) ;; override path for lib (assoc-in lm [lib :paths] [path])) lm)) lib-map classpath-overrides) lib-map) lib-order (->> override-libs tree-paths sort-paths (map peek) distinct) lib-paths (mapcat #(map vector (get-in override-libs [% :paths]) (repeat {:lib-name %})) lib-order)] lib-paths)) (defn make-classpath-map "Takes a merged deps edn map and a lib map. Extracts the paths for each chosen lib coordinate, and assembles a classpath map. The classpath-args is a map with keys that can be used to modify the classpath building operation: :extra-paths - extra classpath paths to add to the classpath :classpath-overrides - a map of lib to path, where path is used instead of the coord's paths Returns a map: :classpath map of path entry (string) to a map describing where its from, either a :lib-name or :path-key entry. :classpath-roots coll of the classpath keys in classpath order" [deps-edn-map lib-map classpath-args] (let [flat-paths (->> classpath-args (flatten-paths deps-edn-map) validate-paths) flat-libs (flatten-libs lib-map classpath-args) all-paths (concat flat-paths flat-libs) cp (mapv first all-paths) cp-map (reduce (fn [m [path-str src]] (assoc m path-str src)) {} all-paths)] {:classpath-roots cp :classpath cp-map})) (defn join-classpath "Takes a coll of string classpath roots and creates a platform sensitive classpath" [roots] (str/join File/pathSeparator roots)) (defn make-classpath "Takes a lib map, and a set of explicit paths. Extracts the paths for each chosen lib coordinate, and assembles a classpath string using the system path separator. The classpath-args is a map with keys that can be used to modify the classpath building operation: :extra-paths - extra classpath paths to add to the classpath :classpath-overrides - a map of lib to path, where path is used instead of the coord's paths Returns the classpath as a string." {:deprecated "0.9.745"} [lib-map paths classpath-args] (-> (make-classpath-map {:paths paths} lib-map classpath-args) :classpath-roots join-classpath)) (defn tool "Transform project edn for tool by applying tool args (keys = :paths, :deps) and returning an updated project edn." [project-edn tool-args] (let [{:keys [replace-deps replace-paths deps paths]} tool-args] (cond-> project-edn (or deps replace-deps) (merge {:deps (merge deps replace-deps)}) (or paths replace-paths) (merge {:paths (vec (concat paths replace-paths))})))) (defn- qualify-fn "Compute function symbol based on fn, ns-aliases, and ns-default" [fsym {:keys [ns-aliases ns-default] :as x}] (when (and fsym (not (symbol? fsym))) (throw (ex-info (format "Expected function symbol: %s" fsym) {}))) (when fsym (if (qualified-ident? fsym) (let [nsym (get ns-aliases (symbol (namespace fsym)))] (if nsym (symbol (str nsym) (name fsym)) fsym)) (if ns-default (symbol (str ns-default) (str fsym)) (throw (ex-info (format "Unqualified function can't be resolved: %s" fsym) {})))))) (defn- exec-prep! "Exec the prep command in the command-args coll. Redirect stdout/stderr to this process, wait for the process to complete, and return the exit code. Exit code 1 indicates the prep function could not be resolved." [^File dir classpath f args] ;; java -cp clojure.main -e '(do (if-let [resolved-f (requiring-resolve 'f)] (resolved-f nil) (System/exit 1)) nil)' (let [command-args ["java" "-cp" classpath "clojure.main" "-e" (str "(do (if-let [resolved-f (requiring-resolve '" f ")] (resolved-f " (pr-str args) ") (System/exit 1)) nil)")] ;;_ (apply println (map #(if (str/includes? % " ") (str "\"" % "\"") %) command-args)) proc-builder (doto (ProcessBuilder. ^List command-args) (.directory dir) (.redirectOutput ProcessBuilder$Redirect/INHERIT) (.redirectError ProcessBuilder$Redirect/INHERIT)) proc (.start proc-builder)] (.waitFor proc))) (declare create-basis) (defn prep-libs! "Takes a lib map and looks for unprepped libs, optionally prepping them. Options: :action - what to do when an unprepped lib is found, one of: :prep - if unprepped, prep :force - prep regardless of whether already prepped :error (default) - don't prep, error :current - boolean, default = false. Whether to prep current project :log - print to console based on log level (default, no logging): :info - print only when prepping :debug - :info + print for each lib considered" [lib-map {:keys [action current log] :or {current false}} config] (let [local-dir (.getAbsolutePath (dir/canonicalize (jio/file "."))) unprepped (reduce-kv (fn [ret lib {:deps/keys [root manifest] :as coord}] (if-let [{f :fn, :keys [alias ensure exec-args]} (ext/prep-command lib coord manifest config)] (let [ensure-dir (when ensure (jio/file root ensure)) unprepped (and ensure (not (.exists ^File ensure-dir)))] (when (#{:debug} log) (println lib "-" (if unprepped "unprepped" "prepped"))) (if (or (= action :force) (and unprepped (= action :prep))) (do (when (#{:info :debug} log) (println "Prepping" lib "in" root)) (let [root-dir (jio/file root)] (dir/with-dir root-dir (let [basis (create-basis {:project :standard ;; deps.edn at root :extra {:aliases {:deps/TOOL {:replace-deps {} :replace-paths ["."]}}} :aliases [:deps/TOOL alias]}) cp (join-classpath (:classpath-roots basis)) qual-f (qualify-fn f (get-in basis [:aliases alias])) exit (exec-prep! root-dir cp qual-f exec-args)] (cond (zero? exit) ret (= exit 1) (throw (ex-info (format "Prep function could not be resolved: %s" qual-f) {:lib lib})) :else (throw (ex-info (format "Error building %s" lib) {:lib lib :exit exit}))))))) (if unprepped (conj (or ret []) lib) ret))) (do (when (#{:debug} log) (println lib "- no prep")) ret))) nil (cond-> lib-map current (assoc (symbol "current project") {:local/root local-dir :deps/manifest :deps :deps/root local-dir})))] (when unprepped (throw (ex-info (format "The following libs must be prepared before use: %s" unprepped) {:unprepped unprepped}))))) (defn calc-basis "Calculates and returns the runtime basis from a master deps edn map, modifying resolve-deps and make-classpath args as needed. master-edn - a master deps edn map args - an optional map of arguments to constituent steps, keys: :resolve-args - map of args to resolve-deps, with possible keys: :extra-deps :override-deps :default-deps :threads - number of threads to use during deps resolution :trace - flag to record a trace log :classpath-args - map of args to make-classpath-map, with possible keys: :extra-paths :classpath-overrides Returns the runtime basis, which is the initial deps edn map plus these keys: :resolve-args - the resolve args passed in, if any :classpath-args - the classpath args passed in, if any :libs - lib map, per resolve-deps :classpath - classpath map per make-classpath-map :classpath-roots - vector of paths in classpath order" ([master-edn] (calc-basis master-edn nil)) ([master-edn {:keys [resolve-args classpath-args] :as argmaps}] (session/with-session (let [libs (resolve-deps master-edn resolve-args) cp (make-classpath-map master-edn libs classpath-args)] (merge master-edn {:libs libs} cp argmaps))))) ;(defn runtime-basis ; "Load the runtime execution basis context and return it." ; [] ; (when-let [f (jio/file (System/getProperty "clojure.basis"))] ; (if (and f (.exists f)) ; {:basis (slurp-deps f)} ; (throw (IllegalArgumentException. "No basis declared in clojure.basis system property"))))) (defn- choose-deps [requested standard-fn] (cond (= :standard requested) (standard-fn) (string? requested) (-> requested jio/file dir/canonicalize slurp-deps) (or (nil? requested) (map? requested)) requested :else (throw (ex-info (format "Unexpected dep source: %s" (pr-str requested)) {:requested requested})))) (defn create-edn-maps "Create a set of edn maps from the standard dep sources and return them in a map with keys :root :user :project :extra" [{:keys [root user project extra] :as params :or {root :standard, user :standard, project :standard}}] (let [root-edn (choose-deps root #(root-deps)) user-edn (choose-deps user #(-> (user-deps-path) jio/file dir/canonicalize slurp-deps)) project-edn (choose-deps project #(-> "deps.edn" jio/file dir/canonicalize slurp-deps)) extra-edn (choose-deps extra (constantly nil))] (cond-> {} root-edn (assoc :root root-edn) user-edn (assoc :user user-edn) project-edn (assoc :project project-edn) extra-edn (assoc :extra extra-edn)))) (defn create-basis "Create a basis from a set of deps sources and a set of aliases. By default, use root, user, and project deps and no argmaps (essentially the same classpath you get by default from the Clojure CLI). Each dep source value can be :standard, a string path, a deps edn map, or nil. Sources are merged in the order - :root, :user, :project, :extra. Aliases refer to argmaps in the merged deps that will be supplied to the basis subprocesses (tool, resolve-deps, make-classpath-map). The following subprocess argmap args can be provided: Key Subproc Description :replace-deps tool Replace project deps :replace-paths tool Replace project paths :extra-deps resolve-deps Add additional deps :override-deps resolve-deps Override coord of dep :default-deps resolve-deps Provide coord if missing :extra-paths make-classpath-map Add additional paths :classpath-overrides make-classpath-map Replace lib path in cp Options: :root - dep source, default = :standard :user - dep source, default = :standard :project - dep source, default = :standard (\"./deps.edn\") :extra - dep source, default = nil :aliases - coll of aliases of argmaps to apply to subprocesses Returns a runtime basis, which is the initial merged deps edn map plus these keys: :resolve-args - the resolve args passed in, if any :classpath-args - the classpath args passed in, if any :libs - lib map, per resolve-deps :classpath - classpath map per make-classpath-map :classpath-roots - vector of paths in classpath order" [{:keys [aliases] :as params}] (let [{root-edn :root user-edn :user project-edn :project extra-edn :extra} (create-edn-maps params) edn-maps [root-edn user-edn project-edn extra-edn] alias-data (->> edn-maps (map :aliases) (remove nil?) (apply merge-with merge)) argmap-data (->> aliases (remove nil?) (map #(get alias-data %))) argmap (apply merge-alias-maps argmap-data) project-tooled-edn (tool project-edn argmap) master-edn (merge-edns [root-edn user-edn project-tooled-edn extra-edn])] (calc-basis master-edn {:resolve-args argmap :classpath-args argmap}))) ;; Load extensions (load "/clojure/tools/deps/extensions/maven") (load "/clojure/tools/deps/extensions/local") (load "/clojure/tools/deps/extensions/git") (load "/clojure/tools/deps/extensions/deps") (load "/clojure/tools/deps/extensions/pom") (comment (require '[clojure.tools.deps.util.maven :as mvn]) (def ex-svc (concurrent/new-executor 2)) (calc-basis {:mvn/repos mvn/standard-repos :paths ["src" "test"] :deps {'org.clojure/clojure {:mvn/version "1.9.0"} 'org.clojure/core.memoize {:mvn/version "0.5.8"}} :aliases {:x {:extra-paths ["a" "b"]}}} {:classpath-args {:extra-paths ["a" "b"]}}) (expand-deps {'org.clojure/clojure {:mvn/version "1.9.0"}} nil nil {:mvn/repos mvn/standard-repos} ex-svc true) (expand-deps {'org.apache.xmlgraphics/batik-transcoder {:mvn/version "1.7"}} nil nil {:mvn/repos mvn/standard-repos} ex-svc true) (expand-deps {'org.clojure/clojure {:mvn/version "1.9.0"} 'org.clojure/core.memoize {:mvn/version "0.5.8"}} nil nil {:mvn/repos mvn/standard-repos} ex-svc true) (expand-deps {'org.clojure/clojure {:mvn/version "1.9.0"} 'org.clojure/clojurescript {:mvn/version "1.9.946"} 'reagent/reagent {:mvn/version "0.6.0"}} nil nil {:mvn/repos mvn/standard-repos} ex-svc true) (expand-deps {'org.clojure/core.async {:mvn/version "0.3.426"} 'reagent/reagent {:mvn/version "0.6.0"}} nil nil {:mvn/repos mvn/standard-repos} ex-svc true) (expand-deps {'org.clojure/tools.deps {:mvn/version "0.4.277"}} nil nil {:mvn/repos mvn/standard-repos} ex-svc true) (calc-basis {:deps {'org.clojure/clojure {:mvn/version "1.10.3"} 'com.datomic/ion {:mvn/version "0.9.50"}, 'software.amazon.awscdk/codebuild {:mvn/version "1.115.0"}} :mvn/repos (merge mvn/standard-repos {"datomic-cloud" {:url "s3://datomic-releases-1fc2183a/maven/releases"}})} nil) (print-tree (resolve-deps {:deps {'org.clojure/clojure {:mvn/version "1.8.0"} 'org.clojure/core.memoize {:mvn/version "0.5.8"}} :mvn/repos mvn/standard-repos} nil)) (make-classpath-map {:paths ["src"]} (resolve-deps {:deps {'org.clojure/clojure {:mvn/version "1.9.0-alpha17"} 'org.clojure/core.memoize {:mvn/version "0.5.8"}} :mvn/repos mvn/standard-repos} nil) {:extra-paths ["test"]}) (require 'clojure.pprint) (clojure.pprint/pprint (resolve-deps {:deps {'org.clojure/tools.analyzer.jvm {:mvn/version "0.6.9"}} :mvn/repos mvn/standard-repos} nil)) (clojure.pprint/pprint (resolve-deps {:deps {'cheshire/cheshire {:mvn/version "5.7.0"}} :mvn/repos mvn/standard-repos} nil)) ;; top deps win (clojure.pprint/pprint (resolve-deps {:deps {'org.clojure/clojure {:mvn/version "1.2.0"} 'cheshire/cheshire {:mvn/version "5.8.0"}} :mvn/repos mvn/standard-repos} nil)) ;; deps replacement (clojure.pprint/pprint (resolve-deps {:deps {'cheshire/cheshire {:mvn/version "5.8.0"}} :mvn/repos mvn/standard-repos} {:deps {'org.clojure/tools.gitlibs {:mvn/version "0.2.64"}}})) ;; deps addition (clojure.pprint/pprint (resolve-deps {:deps {'cheshire/cheshire {:mvn/version "5.8.0"}} :mvn/repos mvn/standard-repos} {:extra-deps {'org.clojure/tools.gitlibs {:mvn/version "0.2.64"}}})) ;; validate paths (make-classpath-map {:paths ["../foo/src"]} (resolve-deps {:deps {} :mvn/repos mvn/standard-repos} nil) nil) ;; override-deps (make-classpath-map {:paths ["src"]} (resolve-deps {:deps {'org.clojure/core.memoize {:mvn/version "0.5.8"}} :mvn/repos mvn/standard-repos} {:override-deps {'org.clojure/clojure {:mvn/version "1.3.0"}}}) nil) (make-classpath-map {:paths ["src"]} (resolve-deps {:deps {'org.clojure/tools.deps {:mvn/version "0.1.40"} 'org.clojure/clojure {:mvn/version "1.9.0-alpha17"}} :mvn/repos mvn/standard-repos} nil) nil) ;; extra paths (make-classpath-map {:paths ["src"]} (resolve-deps {:deps {'org.clojure/clojure {:mvn/version "1.10.0"}} :mvn/repos mvn/standard-repos} nil) {:extra-paths ["extra"]}) ;; classpath overrides (make-classpath-map {} (resolve-deps {:deps {'org.clojure/tools.deps {:mvn/version "0.1.40"} 'org.clojure/clojure {:mvn/version "1.9.0-alpha17"}} :mvn/repos mvn/standard-repos} nil) '{:classpath-overrides {org.clojure/clojure "foo"}}) (resolve-deps {:deps '{org.clojure/clojure {:mvn/version "1.9.0"} org.clojure/clojurescript {:mvn/version "1.9.946"} reagent/reagent {:mvn/version "0.6.0"}} :mvn/repos mvn/standard-repos} nil) ;; pom not in cp (make-classpath-map {:paths ["src"]} (resolve-deps {:deps {'org.apache.jena/apache-jena-libs {:mvn/version "4.2.0" :extension "pom"}} :mvn/repos mvn/standard-repos} nil) nil) ;; err case (resolve-deps {:deps {'bogus/bogus {:mvn/version "1.2.3"}} :mvn/repos mvn/standard-repos} nil) (resolve-deps {:deps {'bogus/bogus "1.2.3"} :mvn/repos mvn/standard-repos} nil) (require '[clojure.tools.deps.extensions.git] '[clojure.tools.deps.extensions.deps]) (resolve-deps {:deps {'foo/bar {:git/url "https://github.com/clojure/core.async.git" :sha "ecea2539a724a415b15e50f12815b4ab115cfd35"}}} nil) (time (do (session/with-session (resolve-deps {:deps {'com.google.cloud/google-cloud-monitoring {:mvn/version "1.78.0"}} :mvn/repos (merge mvn/standard-repos {"datomic-cloud" {:url "s3://datomic-releases-1fc2183a.s3-us-east-1.amazonaws.com/maven/releases"}})} nil)) nil)) ) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/000077500000000000000000000000001434474567100230605ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/extensions.clj000066400000000000000000000202021434474567100257450ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.extensions (:require [clojure.java.io :as jio] [clojure.set :as set])) ;; Helper for autodetect of manifest type ;; vector to control ordering (def manifest-types ["deps.edn" :deps, "pom.xml" :pom ;; "project.clj" :lein ]) (defn detect-manifest "Given a directory, detect the manifest type and return the manifest info." [dir] (loop [[file-name manifest-type & others] manifest-types] (when file-name (let [f (jio/file dir file-name)] (if (and (.exists f) (.isFile f)) {:deps/manifest manifest-type, :deps/root dir} (recur others)))))) ;; Methods switching on coordinate type (defmulti coord-type-keys "Takes a coordinate type and returns valid set of keys indicating that coord type" (fn [type] type)) (defmethod coord-type-keys :default [type] #{}) (defn procurer-types "Returns set of registerd procurer types (results may change if procurer methods are registered)." [] (disj (-> (.getMethodTable ^clojure.lang.MultiFn coord-type-keys) keys set) :default)) (defn coord-type "Determine the coordinate type of the coordinate, based on the self-published procurer keys from coord-type-keys." [coord] (when (map? coord) (let [exts (procurer-types) coord-keys (-> coord keys set) matches (reduce (fn [ms type] (cond-> ms (seq (set/intersection (coord-type-keys type) coord-keys)) (conj type))) [] exts)] (case (count matches) 0 (throw (ex-info (format "Coord of unknown type: %s" (pr-str coord)) {:coord coord})) 1 (first matches) (throw (ex-info (format "Coord type is ambiguous: %s" (pr-str coord)) {:coord coord})))))) (defmulti lib-location "Takes a coordinate and returns the location where the lib would be installed locally. Location keys: :base local repo base directory path :path path within base dir :type coordinate type" (fn [lib coord config] (coord-type coord))) (defmulti canonicalize "Takes a lib and coordinate and returns a canonical form. For example, a Maven coordinate might resolve LATEST to a version or a Git coordinate might resolve a partial sha to a full sha. Returns [lib coord]." (fn [lib coord config] (coord-type coord))) (defmethod canonicalize :default [lib coord config] [lib coord]) (defmulti dep-id "Returns an identifier value that can be used to detect a lib/coord cycle while expanding deps. This will only be called after canonicalization so it can rely on the canonical form." (fn [lib coord config] (coord-type coord))) (defn- throw-bad-coord [lib coord] (if (map? coord) (let [type (coord-type coord)] (if (nil? type) (throw (ex-info (str "No coordinate type found for library " lib " in coordinate " (pr-str coord)) {:lib lib :coord coord})) (throw (ex-info (str "Coordinate type " type " not loaded for library " lib " in coordinate " (pr-str coord)) {:lib lib :coord coord})))) (throw (ex-info (str "Bad coordinate for library " lib ", expected map: " (pr-str coord)) {:lib lib :coord coord})))) (defmethod dep-id :default [lib coord config] (throw-bad-coord lib coord)) (defmulti manifest-type "Takes a lib, a coord, and the root config. Dispatch based on the coordinate type. Detect and return the manifest type and location for this coordinate." (fn [lib coord config] (coord-type coord))) (defmethod manifest-type :default [lib coord config] (throw-bad-coord lib coord)) (defmulti coord-summary "Takes a coord, and returns a concise description, used when printing tree" (fn [lib coord] (coord-type coord))) (defmethod coord-summary :default [lib coord] (str lib " " (coord-type coord))) (defmulti license-info "Return map of license info (:name and :url) or nil if unknown" (fn [lib coord config] (coord-type coord))) (defmethod license-info :default [lib coord config] nil) ;; Version comparison, either within or across coordinate types (defmulti compare-versions "Given two coordinates, use this as a comparator returning a negative number, zero, or positive number when coord-x is logically 'less than', 'equal to', or 'greater than' coord-y. The dispatch occurs on the type of x and y." (fn [lib coord-x coord-y config] [(coord-type coord-x) (coord-type coord-y)])) (defmethod compare-versions :default [lib coord-x coord-y config] (throw (ex-info (str "Unable to compare versions for " lib ": " (pr-str coord-x) " and " (pr-str coord-y)) {:lib lib :coord-x coord-x :coord-y coord-y}))) ;; Find coords (defmulti find-versions "Return a coll of coords based on a lib and a partial coord" (fn [lib coord coord-type config] coord-type)) (defmethod find-versions :default [lib coord coord-type config] (throw-bad-coord lib coord)) (defn find-all-versions "Find versions across all registered procurer types and return first that finds some. Returns coll of coordinates for this lib (based on lib and partial coordinate)." [lib coord config] (some #(find-versions lib coord % config) (procurer-types))) ;; Methods switching on manifest type (defn- throw-bad-manifest [lib coord manifest-type] (if manifest-type (throw (ex-info (str "Manifest type " manifest-type " not loaded for " lib " in coordinate " (pr-str coord)) {:lib lib :coord coord})) (throw (ex-info (str "Manifest file not found for " lib " in coordinate " (pr-str coord)) {:lib lib :coord coord})))) (defmulti coord-deps "Return coll of immediate [lib coord] external deps for this library." (fn [lib coord manifest-type config] manifest-type)) (defmethod coord-deps :default [lib coord manifest-type config] (throw-bad-manifest lib coord manifest-type)) (defmulti coord-paths "Return coll of classpath roots for this library on disk." (fn [lib coord manifest-type config] manifest-type)) (defmethod coord-paths :default [lib coord manifest-type config] (throw-bad-manifest lib coord manifest-type)) (defmulti manifest-file "Return path to manifest file (if any). If this file is updated, causes the cache to be recomputed." (fn [lib coord manifest-type config] manifest-type)) (defmethod manifest-file :default [lib coord manifest-type config] (throw-bad-manifest lib coord manifest-type)) (defmulti license-info-mf "Return map of license info (:name and :url) or nil if unknown based on the manifest." (fn [lib coord manifest-type config] manifest-type)) (defmethod license-info-mf :default [lib coord manifest-type config] nil) (defmulti coord-usage "Return usage info map for this library with the following optional keys: :ns-default - default namespace symbol :ns-aliases - map of alias to namespace symbol" (fn [lib coord manifest-type config] manifest-type)) (defmethod coord-usage :default [lib coord manifest-type config] (throw-bad-manifest lib coord manifest-type)) (defmulti prep-command "Return prep command for this library with the following keys: :alias - alias to use when invoking (keyword) :fn - function to invoke in alias (symbol) :ensure - relative path in repo to ensure exists after prep" (fn [lib coord manifest-type config] manifest-type)) (defmethod prep-command :default [lib coord manifest-type config] (throw-bad-manifest lib coord manifest-type)) (comment (require '[clojure.tools.deps.util.maven :as maven]) (binding [*print-namespace-maps* false] (run! prn (find-all-versions 'io.github.clojure/tools.deps.alpha nil {:mvn/repos maven/standard-repos}))) (binding [*print-namespace-maps* false] (run! prn (find-all-versions 'org.clojure/tools.deps.alpha nil {:mvn/repos maven/standard-repos}))) )tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/extensions/000077500000000000000000000000001434474567100252575ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/extensions/deps.clj000066400000000000000000000046541434474567100267150ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.extensions.deps (:require [clojure.java.io :as jio] [clojure.tools.deps :as deps] [clojure.tools.deps.extensions :as ext] [clojure.tools.deps.util.dir :as dir] [clojure.tools.deps.util.io :as io] [clojure.tools.deps.util.session :as session]) (:import [java.io File])) (set! *warn-on-reflection* true) (defn- deps-map [config dir] (let [f (jio/file dir "deps.edn")] (session/retrieve {:deps :map :file (.getAbsolutePath f)} ;; session key #(if (.exists f) (deps/merge-edns [(deps/root-deps) (deps/slurp-deps f)]) (deps/root-deps))))) (defmethod ext/coord-deps :deps [_lib {:keys [deps/root] :as _coord} _mf config] (dir/with-dir (jio/file root) (seq (:deps (deps-map config root))))) (defmethod ext/coord-paths :deps [_lib {:keys [deps/root] :as _coord} _mf config] (dir/with-dir (jio/file root) (->> (:paths (deps-map config root)) (map #(dir/canonicalize (jio/file %))) (map #(do (when (not (dir/sub-path? %)) (io/printerrln "WARNING: Deprecated use of path" % "external to project" root)) %)) (map #(.getCanonicalPath ^File %)) vec))) (defmethod ext/manifest-file :deps [_lib {:keys [deps/root] :as _coord} _mf _config] (let [manifest (jio/file root "deps.edn")] (when (.exists manifest) (.getAbsolutePath manifest)))) (defmethod ext/coord-usage :deps [lib {:keys [deps/root] :as _coord} manifest-type config] (dir/with-dir (jio/file root) (:tools/usage (deps-map config root)))) (defmethod ext/prep-command :deps [lib {:keys [deps/root] :as _coord} manifest-type config] (dir/with-dir (jio/file root) (let [external-deps (deps-map config root)] (when-let [prep-info (:deps/prep-lib external-deps)] (let [exec-args (-> external-deps :aliases (get (:alias prep-info)) :exec-args)] (cond-> prep-info exec-args (assoc :exec-args exec-args)))))))tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/extensions/git.clj000066400000000000000000000177441434474567100265510ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.extensions.git (:require [clojure.java.io :as jio] [clojure.tools.deps.extensions :as ext] [clojure.tools.gitlibs :as gitlibs])) (def ^:private git-services {:github {:service #"^(?:com|io).github.([^.]+)$" :url "https://github.com/%s/%s.git"} :gitlab {:service #"^(?:com|io).gitlab.([^.]+)$" :url "https://gitlab.com/%s/%s.git"} :bitbucket {:service #"^(?:org|io).bitbucket.([^.]+)$" :url "https://bitbucket.org/%s/%s.git"} :beanstalk {:service #"^(?:com|io).beanstalkapp.([^.]+)$" :url "https://%s.git.beanstalkapp.com/%s.git"} :sourcehut {:service #"^ht.sr.([^.]+)$" :url "https://git.sr.ht/~%s/%s"}}) (defn auto-git-url "Create url from lib name, ie: io.github.foo/bar => https://github.com/foo/bar.git or return nil if not a name that can be auto converted to a url." [lib] (let [group (namespace lib) project (name lib)] (some (fn [{:keys [service url]}] (when-let [matches (re-matches service group)] (format url (second matches) project))) (vals git-services)))) (defn full-sha? [sha] (boolean (and sha (= 40 (count sha))))) (defmethod ext/coord-type-keys :git [_type] #{:git/url :git/sha :git/tag :sha}) (defn- coord-err ^Throwable [msg lib coord] (ex-info msg {:lib lib :coord coord})) (defn- make-standard [coord url sha tag] (-> (cond-> coord url (assoc :git/url url) sha (assoc :git/sha sha) tag (assoc :git/tag tag)) (dissoc :sha :tag))) (defmethod ext/canonicalize :git [lib {unsha :sha untag :tag :git/keys [url sha tag] :as coord} _config] (when (nil? (namespace lib)) (throw (coord-err (format "Invalid lib name: %s" lib) lib coord))) (when (and unsha sha) (throw (coord-err (format "git coord has both :sha and :git/sha for %s" lib) lib coord))) (when (and untag tag) (throw (coord-err (format "git coord has both :tag and :git/tag for %s" tag) lib coord))) (let [canon-sha (or sha unsha) canon-tag (or tag untag) canon-url (or url (auto-git-url lib))] (when (nil? canon-url) (throw (coord-err (format "Failed to infer git url for: %s" lib) lib coord))) (when (and canon-tag (not (some #{canon-tag} (gitlibs/tags canon-url)))) (throw (coord-err (format "Library %s has invalid tag: %s" lib canon-tag) lib coord))) (if canon-sha (if canon-tag (let [full-sha (if (full-sha? canon-sha) canon-sha (gitlibs/resolve canon-url canon-sha))] (when-not (= (gitlibs/resolve canon-url canon-sha) (gitlibs/resolve canon-url canon-tag)) (throw (coord-err (format "Library %s has sha and tag that point to different commits" lib) lib coord))) [lib (make-standard coord canon-url full-sha canon-tag)]) (if (full-sha? canon-sha) [lib (make-standard coord canon-url canon-sha canon-tag)] (throw (ex-info (format "Library %s has prefix sha, use full sha or add tag" lib) {:lib lib :coord coord})))) (throw (ex-info (format "Library %s has coord with missing sha" lib) {:lib lib :coord coord}))))) (defn- to-canonical [lib {:git/keys [url sha] :as coord} config] (if (and url (full-sha? sha)) [lib coord] (ext/canonicalize lib coord config))) (defmethod ext/lib-location :git [lib coord config] (let [[lib {:git/keys [sha]}] (to-canonical lib coord config)] {:base (str (gitlibs/cache-dir) "/libs") ;; gitlibs repo location is not in a public API... :path (str lib "/" sha) :type :git})) (defmethod ext/dep-id :git [lib coord config] (let [[_lib {:git/keys [url sha]}] (to-canonical lib coord config)] {:git/url url, :git/sha sha})) (defmethod ext/manifest-type :git [lib coord config] (let [[lib {:git/keys [url sha] :deps/keys [manifest root]}] (to-canonical lib coord config)] (when-not url (throw (ex-info (format ":git/url not found or inferred for %s" lib) {:lib lib :coord coord}))) (let [sha-dir (gitlibs/procure url lib sha)] (if sha-dir (let [root-dir (if root (let [root-file (jio/file root)] (if (.isAbsolute root-file) ;; should be only after coordinate resolution (.getCanonicalPath root-file) (.getCanonicalPath (jio/file sha-dir root-file)))) sha-dir)] (if manifest {:deps/manifest manifest, :deps/root root-dir} (ext/detect-manifest root-dir))) (throw (ex-info (format "Commit not found for %s in repo %s at %s" lib url sha) {:lib lib :coord coord})))))) (defmethod ext/coord-summary :git [lib coord] (let [[lib {:git/keys [url tag sha]}] (to-canonical lib coord nil)] (str lib " " (if tag tag (subs sha 0 7))))) (defmethod ext/license-info :git [lib coord config] (let [coord (merge coord (ext/manifest-type lib coord config))] (ext/license-info-mf lib coord (:deps/manifest coord) config))) ;; 0 if x and y are the same commit ;; negative if x is parent of y (y derives from x) ;; positive if y is parent of x (x derives from y) (defmethod ext/compare-versions [:git :git] [lib x-coord y-coord config] (let [[_ {x-url :git/url, x-sha :git/sha, :as x}] (to-canonical lib x-coord config) [_ {y-url :git/url, y-sha :git/sha, :as y}] (to-canonical lib y-coord config)] (if (= x-sha y-sha) 0 (let [desc (if (= x-url y-url) (or (gitlibs/descendant x-url [x-sha y-sha]) (gitlibs/descendant y-url [x-sha y-sha])) (and (gitlibs/descendant x-url [x-sha y-sha]) (gitlibs/descendant y-url [x-sha y-sha])))] (cond (nil? desc) (throw (ex-info (str "No known ancestor relationship between git versions for " lib "\n" " " x-url " at " x-sha "\n" " " y-url " at " y-sha) {:x x :y y})) (= desc x-sha) 1 (= desc y-sha) -1))))) (defmethod ext/find-versions :git [lib coord _coord-type config] (let [url (or (:git/url coord) (auto-git-url lib))] (when url (try (map (fn [tag] {:git/tag tag :git/sha (subs (gitlibs/commit-sha url tag) 0 7)}) (gitlibs/tags url)) (catch Throwable _ nil))))) (comment (ext/find-versions 'io.github.cognitect-labs/test-runner {} :git nil) (ext/find-versions 'org.clojure/spec.alpha {:git/url "https://github.com/clojure/spec.alpha.git"} :git nil) (ext/lib-location 'foo/foo {:git/url "https://github.com/clojure/core.async.git" :sha "ecea2539a724a415b15e50f12815b4ab115cfd35"} {}) (binding [*print-namespace-maps* false] (run! prn (ext/find-versions 'io.github.clojure/tools.deps.alpha nil :git nil))) ;; error - prefix sha (ext/canonicalize 'org.clojure/spec.alpha {:git/url "https://github.com/clojure/spec.alpha.git" :sha "739c1af5"} nil) (ext/dep-id 'org.clojure/spec.alpha {:git/url "https://github.com/clojure/spec.alpha.git" :sha "739c1af56dae621aedf1bb282025a0d676eff713"} nil) (ext/manifest-type 'org.clojure/spec.alpha {:git/url "https://github.com/clojure/spec.alpha.git" :git/sha "739c1af56dae621aedf1bb282025a0d676eff713"} nil) (ext/compare-versions 'org.clojure/spec.alpha {:git/url "https://github.com/clojure/spec.alpha.git" :git/sha "739c1af56dae621aedf1bb282025a0d676eff713"} {:git/url "git@github.com:clojure/spec.alpha.git" :git/sha "a65fb3aceec67d1096105cab707e6ad7e5f063af"} nil) ) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/extensions/local.clj000066400000000000000000000105441434474567100270470ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.extensions.local (:require [clojure.java.io :as jio] [clojure.string :as str] [clojure.tools.deps.extensions :as ext] [clojure.tools.deps.extensions.pom :as pom] [clojure.tools.deps.util.dir :as dir] [clojure.tools.deps.util.maven :as maven] [clojure.tools.deps.util.session :as session]) (:import [java.io File IOException] [java.net URL] [java.util.jar JarFile JarEntry] ;; maven-builder-support [org.apache.maven.model.building UrlModelSource] [org.apache.maven.model License])) (defmethod ext/coord-type-keys :local [_type] #{:local/root}) (defmethod ext/dep-id :local [lib {:keys [local/root] :as _coord} _config] {:lib lib :root root}) (defn- ensure-file ^File [lib root] (let [f (jio/file root)] (if (.exists f) f (throw (ex-info (format "Local lib %s not found: %s" lib root) {:lib lib :root root}))))) (defmethod ext/canonicalize :local [lib {:keys [local/root] :as coord} _config] (let [canonical-root (.getCanonicalPath (dir/canonicalize (jio/file root)))] (ensure-file lib canonical-root) ;; throw if missing [lib (assoc coord :local/root canonical-root)])) (defmethod ext/lib-location :local [_lib {:keys [local/root]} _config] {:base root :path "" :type :local}) (defmethod ext/find-versions :local [_lib _coord _type _config] nil) (defmethod ext/manifest-type :local [lib {:keys [local/root deps/manifest] :as _coord} _config] (cond manifest {:deps/manifest manifest :deps/root root} (.isFile (ensure-file lib root)) {:deps/manifest :jar, :deps/root root} :else (ext/detect-manifest root))) (defmethod ext/coord-summary :local [lib {:keys [local/root]}] (str lib " " root)) (defmethod ext/license-info :local [lib coord config] (let [coord (merge coord (ext/manifest-type lib coord config))] (ext/license-info-mf lib coord (:deps/manifest coord) config))) (defn find-pom "Find path of pom file in jar file, or nil if it doesn't exist" [^JarFile jar-file] (try (loop [[^JarEntry entry & entries] (enumeration-seq (.entries jar-file))] (when entry (let [name (.getName entry)] (if (and (str/starts-with? name "META-INF/") (str/ends-with? name "pom.xml")) name (recur entries))))) (catch IOException _t nil))) (defmethod ext/coord-deps :jar [lib {:keys [local/root] :as _coord} _manifest config] (let [jar (JarFile. (ensure-file lib root))] (if-let [path (find-pom jar)] (let [url (URL. (str "jar:file:" root "!/" path)) src (UrlModelSource. url) settings (session/retrieve :mvn/settings #(maven/get-settings)) model (pom/read-model src config settings)] (pom/model-deps model)) []))) (defmethod ext/coord-paths :jar [_lib coord _manifest _config] [(:local/root coord)]) (defmethod ext/manifest-file :jar [_lib {:keys [deps/root] :as _coord} _mf _config] nil) (defmethod ext/license-info-mf :jar [lib {:keys [local/root] :as _coord} _mf config] (let [jar (JarFile. (ensure-file lib root))] (when-let [path (find-pom jar)] (let [url (URL. (str "jar:file:" root "!/" path)) src (UrlModelSource. url) settings (session/retrieve :mvn/settings #(maven/get-settings)) model (pom/read-model src config settings) licenses (.getLicenses model) ^License license (when (and licenses (pos? (count licenses))) (first licenses))] (when license (let [name (.getName license) url (.getUrl license)] (when (or name url) (cond-> {} name (assoc :name name) url (assoc :url url))))))))) (defmethod ext/coord-usage :jar [_lib _coord _manifest-type _config] ;; TBD nil) (defmethod ext/prep-command :jar [_lib _coord _manifest-type _config] ;; TBD - could look in jar nil)tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/extensions/maven.clj000066400000000000000000000244211434474567100270620ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.extensions.maven (:require [clojure.java.io :as jio] [clojure.string :as str] [clojure.tools.deps.extensions :as ext] [clojure.tools.deps.util.maven :as maven] [clojure.tools.deps.util.session :as session]) (:import [java.io File] ;; maven-resolver-api [org.eclipse.aether RepositorySystem RepositorySystemSession] [org.eclipse.aether.resolution ArtifactRequest ArtifactDescriptorRequest VersionRangeRequest VersionRequest ArtifactResolutionException ArtifactDescriptorResult] [org.eclipse.aether.version Version] ;; maven-resolver-util [org.eclipse.aether.util.version GenericVersionScheme] [org.apache.maven.settings Settings])) (set! *warn-on-reflection* true) ;; Main extension points for using Maven deps (defmethod ext/coord-type-keys :mvn [_type] #{:mvn/version}) (defn- specific-version [version] (second (re-matches #"^\[([^,]*)]$" version))) (defn- resolve-version-range ;; only call when version is a range [lib {:keys [mvn/version] :as coord} {:keys [mvn/local-repo mvn/repos] :as config}] (let [local-repo (or local-repo @maven/cached-local-repo) system ^RepositorySystem (session/retrieve-local :mvn/system #(maven/make-system)) settings ^Settings (session/retrieve :mvn/settings #(maven/get-settings)) session ^RepositorySystemSession (session/retrieve-local :mvn/session #(maven/make-session system settings local-repo))] (or (session/retrieve {:type :mvn/highest-version lib version} (fn [] (let [artifact (maven/coord->artifact lib coord) req (VersionRangeRequest. artifact (maven/remote-repos repos settings) nil) result (.resolveVersionRange system session req) high-version (and result (.getHighestVersion result))] (when high-version (.toString ^Version high-version))))) (throw (ex-info (str "Unable to resolve " lib " version: " version) {:lib lib :coord coord}))))) (defmethod ext/canonicalize :mvn [lib {:keys [mvn/version] :as coord} {:keys [mvn/repos mvn/local-repo] :as config}] (let [specific (specific-version version)] (cond (contains? #{"RELEASE" "LATEST"} version) (let [local-repo (or local-repo @maven/cached-local-repo) system ^RepositorySystem (session/retrieve-local :mvn/system #(maven/make-system)) settings ^Settings (session/retrieve :mvn/settings #(maven/get-settings)) session ^RepositorySystemSession (session/retrieve-local :mvn/session #(maven/make-session system settings local-repo)) artifact (maven/coord->artifact lib coord) req (VersionRequest. artifact (maven/remote-repos repos settings) nil) result (.resolveVersion system session req)] (if result [lib (assoc coord :mvn/version (.getVersion result))] (throw (ex-info (str "Unable to resolve " lib " version: " version) {:lib lib :coord coord})))) ;; cuts down on version range requests when we're not going to honor it anyways specific [lib (assoc coord :mvn/version specific)] (maven/version-range? version) [lib (assoc coord :mvn/version (resolve-version-range lib coord config))] :else [lib coord]))) (defmethod ext/lib-location :mvn [lib {:keys [mvn/version]} {:keys [mvn/local-repo]}] (let [[group-id artifact-id classifier] (maven/lib->names lib)] {:base (or local-repo @maven/cached-local-repo) :path (.getPath ^File (apply jio/file (concat (str/split group-id #"\.") [artifact-id version]))) :classifier classifier :type :mvn})) (defmethod ext/dep-id :mvn [_lib coord _config] (select-keys coord [:mvn/version])) (defmethod ext/manifest-type :mvn [_lib _coord _config] {:deps/manifest :mvn}) (defmethod ext/coord-summary :mvn [lib {:keys [mvn/version]}] (str lib " " version)) (defn- read-descriptor ^ArtifactDescriptorResult [lib coord {:keys [mvn/repos mvn/local-repo]}] (let [local-repo (or local-repo @maven/cached-local-repo) system ^RepositorySystem (session/retrieve-local :mvn/system #(maven/make-system)) settings ^Settings (session/retrieve :mvn/settings #(maven/get-settings)) session ^RepositorySystemSession (session/retrieve-local :mvn/session #(maven/make-session system settings local-repo)) artifact (maven/coord->artifact lib coord) repos (maven/remote-repos repos settings) req (ArtifactDescriptorRequest. artifact repos nil)] (.readArtifactDescriptor system session req))) (defn- check-version [lib {:keys [mvn/version]}] (when (nil? version) (throw (ex-info (str "No :mvn/version specified for " lib) {})))) (defmethod ext/license-info :mvn [lib coord config] (check-version lib coord) (let [descriptor (read-descriptor lib coord config) props (.getProperties descriptor) name (some-> props (.get "license.0.name")) url (some-> props (.get "license.0.url"))] (when (or name url) (cond-> {} name (assoc :name name) url (assoc :url url))))) (defonce ^:private version-scheme (GenericVersionScheme.)) (defn- parse-version [{version :mvn/version :as _coord}] (.parseVersion ^GenericVersionScheme version-scheme ^String version)) (defmethod ext/compare-versions [:mvn :mvn] [lib coord-x coord-y _config] (check-version lib coord-x) (check-version lib coord-y) (apply compare (map parse-version [coord-x coord-y]))) (defmethod ext/coord-deps :mvn [lib coord _manifest config] (check-version lib coord) (let [descriptor (read-descriptor lib coord config)] (into [] (comp (map maven/dep->data) (filter #(contains? #{"compile" "runtime"} (:scope (second %)))) (remove (comp :optional second)) (map #(update-in % [1] dissoc :scope :optional))) (.getDependencies descriptor)))) (defn- get-artifact [lib coord ^RepositorySystem system ^RepositorySystemSession session mvn-repos] (check-version lib coord) (try (let [artifact (maven/coord->artifact lib coord) req (ArtifactRequest. artifact mvn-repos nil) result (.resolveArtifact system session req)] (cond (.isResolved result) (.. result getArtifact getFile getAbsolutePath) (.isMissing result) (throw (ex-info (str "Unable to download: [" lib (pr-str (:mvn/version coord)) "]") {:lib lib :coord coord})) :else (throw (first (.getExceptions result))))) (catch ArtifactResolutionException e (throw (ex-info (.getMessage e) {:lib lib, :coord coord}))))) (defmethod ext/coord-paths :mvn [lib {:keys [extension] :or {extension "jar"} :as coord} _manifest {:keys [mvn/repos mvn/local-repo]}] (check-version lib coord) (when (contains? #{"jar"} extension) (let [local-repo (or local-repo @maven/cached-local-repo) system ^RepositorySystem (session/retrieve-local :mvn/system #(maven/make-system)) settings ^Settings (session/retrieve :mvn/settings #(maven/get-settings)) session ^RepositorySystemSession (session/retrieve-local :mvn/session #(maven/make-session system settings local-repo)) mvn-repos (maven/remote-repos repos settings)] [(get-artifact lib coord system session mvn-repos)]))) (defmethod ext/manifest-file :mvn [_lib {:keys [deps/root] :as _coord} _mf _config] nil) (defmethod ext/find-versions :mvn [lib _coord _coord-type {:keys [mvn/repos mvn/local-repo]}] (let [local-repo (or local-repo maven/default-local-repo) system ^RepositorySystem (session/retrieve-local :mvn/system #(maven/make-system)) settings ^Settings (session/retrieve :mvn/settings #(maven/get-settings)) session ^RepositorySystemSession (session/retrieve-local :mvn/session #(maven/make-session system settings local-repo)) artifact (maven/coord->artifact lib {:mvn/version "(,]"}) req (VersionRangeRequest. artifact (maven/remote-repos repos settings) nil) result (.resolveVersionRange system session req) versions (.getVersions result)] (when (seq versions) (into [] (map (fn [v] {:mvn/version (.toString ^Version v)}) versions))))) (defmethod ext/coord-usage :mvn [lib {:keys [deps/root]} manifest-type config] ;; TBD - could look in jar, could download well-known classifier nil) (defmethod ext/prep-command :mvn [lib {:keys [deps/root]} manifest-type config] ;; TBD - could look in jar, could download well-known classifier nil) (comment (ext/lib-location 'org.clojure/clojure {:mvn/version "1.8.0"} {}) (binding [*print-namespace-maps* false] (run! prn (ext/find-versions 'org.clojure/clojure nil :mvn {:mvn/repos maven/standard-repos}))) ;; given a dep, find the child deps (ext/coord-deps 'org.clojure/clojure {:mvn/version "1.9.0-alpha17"} :mvn {:mvn/repos maven/standard-repos}) (ext/coord-deps 'cider/cider-nrepl {:mvn/version "0.17.0-SNAPSHOT"} :mvn {:mvn/repos maven/standard-repos}) (ext/canonicalize 'joda-time/joda-time {:mvn/version "[2.2,)"} {:mvn/repos maven/standard-repos}) ;; give a dep, download just that dep (not transitive - that's handled by the core algorithm) (ext/coord-paths 'org.clojure/clojure {:mvn/version "1.9.0-alpha17"} :mvn {:mvn/repos maven/standard-repos}) ;; get specific classifier (ext/coord-paths 'org.jogamp.gluegen/gluegen-rt$natives-linux-amd64 {:mvn/version "2.3.2"} :mvn {:mvn/repos maven/standard-repos}) (parse-version {:mvn/version "1.1.0"}) (ext/compare-versions 'org.clojure/clojure {:mvn/version "1.1.0-alpha10"} {:mvn/version "1.1.0-beta1"} {}) (ext/coord-deps 'org.clojure/clojure {:mvn/version "1.10.0-master-SNAPSHOT"} :mvn {:mvn/repos (merge maven/standard-repos {"sonatype-oss-public" {:url "https://oss.sonatype.org/content/groups/public/"}})}) (def rr (maven/remote-repo ["sonatype-oss-public" {:url "https://oss.sonatype.org/content/groups/public/"}]))) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/extensions/pom.clj000066400000000000000000000142411434474567100265460ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.extensions.pom (:require [clojure.java.io :as jio] [clojure.string :as str] [clojure.tools.deps.extensions :as ext] [clojure.tools.deps.util.maven :as maven] [clojure.tools.deps.util.session :as session]) (:import [java.io File] [java.util Properties] ;; maven-model [org.apache.maven.model Model Dependency Exclusion] ;; maven-model-builder [org.apache.maven.model.building DefaultModelBuildingRequest DefaultModelBuilderFactory ModelSource FileModelSource] [org.apache.maven.model.resolution ModelResolver] ;; maven-resolver-impl [org.eclipse.aether.internal.impl DefaultRemoteRepositoryManager] ;; maven-model [org.apache.maven.model Resource License] ;; maven-core [org.apache.maven.project ProjectModelResolver ProjectBuildingRequest$RepositoryMerging] )) (set! *warn-on-reflection* true) (defn- model-resolver ^ModelResolver [{:keys [mvn/repos mvn/local-repo]} settings] (let [local-repo (or local-repo @maven/cached-local-repo) locator (maven/make-locator) system (maven/make-system locator) session (maven/make-session system settings local-repo) repo-mgr (doto (DefaultRemoteRepositoryManager.) (.initService locator)) repos (maven/remote-repos repos settings)] (ProjectModelResolver. session nil system repo-mgr repos ProjectBuildingRequest$RepositoryMerging/REQUEST_DOMINANT nil))) (defn read-model ^Model [^ModelSource source config settings] (let [props (Properties.) _ (.putAll props (System/getProperties)) _ (.setProperty props "project.basedir" ".") req (doto (DefaultModelBuildingRequest.) (.setModelSource source) (.setModelResolver (model-resolver config settings)) (.setSystemProperties props)) builder (.newInstance (DefaultModelBuilderFactory.)) result (.build builder req)] (.getEffectiveModel result))) (defn read-model-file ^Model [^File file config] (let [settings (session/retrieve :mvn/settings #(maven/get-settings))] (session/retrieve {:pom :model :file (.getAbsolutePath file)} ;; session key #(read-model (FileModelSource. file) config settings)))) (defn- model-exclusions->data [exclusions] (when (and exclusions (pos? (count exclusions))) (into #{} (map (fn [^Exclusion exclusion] (symbol (.getGroupId exclusion) (.getArtifactId exclusion)))) exclusions))) (defn- is-compile [^Dependency dep] (contains? #{"compile" "runtime"} (.getScope dep))) (defn- model-dep->data [^Dependency dep] (let [scope (.getScope dep) optional (.isOptional dep) exclusions (model-exclusions->data (.getExclusions dep)) artifact-id (.getArtifactId dep) classifier (.getClassifier dep)] [(symbol (.getGroupId dep) (if (str/blank? classifier) artifact-id (str artifact-id "$" classifier))) (cond-> {:mvn/version (.getVersion dep)} scope (assoc :scope scope) optional (assoc :optional true) (seq exclusions) (assoc :exclusions exclusions))])) (defn model-deps [^Model model] (->> (.getDependencies model) (filter is-compile) (map model-dep->data))) (defmethod ext/coord-deps :pom [_lib {:keys [deps/root] :as _coord} _mf config] (let [pom (jio/file root "pom.xml") model (read-model-file pom config)] (model-deps model))) (defmethod ext/coord-paths :pom [lib {:keys [deps/root] :as _coord} _mf config] (let [pom (jio/file root "pom.xml") model (read-model-file pom config) ;; Maven core 3.8.2 returns an absolute directory here, which is a breaking regression ;; from previous versions (see https://issues.apache.org/jira/browse/MNG-7218). ;; Working around this with conditional code that deals with either absolute or relative. ;; When MNG-7218 is fixed and deps bumped, might be able to revert the absolute path here. src-dir (jio/file (.. model getBuild getSourceDirectory)) src-path (if (.isAbsolute src-dir) (.getCanonicalPath src-dir) (.getCanonicalPath (jio/file root src-dir))) srcs (into [src-path (.getCanonicalPath (jio/file root "src/main/clojure"))] (for [^Resource resource (.. model getBuild getResources)] (let [dir (jio/file (.getDirectory resource))] (when dir (if (.isAbsolute dir) (.getCanonicalPath dir) (.getCanonicalPath (jio/file root dir)))))))] (->> srcs (remove nil?) distinct))) (defmethod ext/manifest-file :pom [_lib {:keys [deps/root] :as _coord} _mf _config] (.getAbsolutePath (jio/file root "pom.xml"))) (defmethod ext/license-info-mf :pom [lib {:keys [deps/root] :as _coord} _mf config] (let [pom (jio/file root "pom.xml") model (read-model-file pom config) licenses (.getLicenses model) ^License license (when (and licenses (pos? (count licenses))) (first licenses))] (when license (let [name (.getName license) url (.getUrl license)] (when (or name url) (cond-> {} name (assoc :name name) url (assoc :url url))))))) (defmethod ext/coord-usage :pom [lib {:keys [deps/root]} manifest-type config] ;; TBD nil) (defmethod ext/prep-command :pom [lib {:keys [deps/root]} manifest-type config] ;; TBD nil) (comment (ext/coord-deps 'org.clojure/core.async {:deps/root "../core.async" :deps/manifest :pom} :pom {:mvn/repos maven/standard-repos}) (ext/coord-paths 'org.clojure/core.async {:deps/root "../core.async" :deps/manifest :pom} :pom {:mvn/repos maven/standard-repos}) ) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/gen/000077500000000000000000000000001434474567100236315ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/gen/pom.clj000066400000000000000000000231701434474567100251210ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.gen.pom (:require [clojure.java.io :as jio] [clojure.data.xml :as xml] [clojure.data.xml.tree :as tree] [clojure.data.xml.event :as event] [clojure.zip :as zip] [clojure.tools.deps.util.maven :as maven] [clojure.tools.deps.util.io :refer [printerrln]]) (:import [java.io File Reader] [clojure.data.xml.node Element])) (set! *warn-on-reflection* true) (xml/alias-uri 'pom "http://maven.apache.org/POM/4.0.0") (defn- to-dep [[lib {:keys [mvn/version exclusions optional] :as coord}]] (let [[group-id artifact-id classifier] (maven/lib->names lib)] (if version (cond-> [::pom/dependency [::pom/groupId group-id] [::pom/artifactId artifact-id] [::pom/version version]] classifier (conj [::pom/classifier classifier]) (seq exclusions) (conj [::pom/exclusions (map (fn [excl] [::pom/exclusion [::pom/groupId (or (namespace excl) (name excl))] [::pom/artifactId (name excl)]]) exclusions)]) optional (conj [::pom/optional "true"])) (printerrln "Skipping coordinate:" coord)))) (defn- gen-deps [deps] [::pom/dependencies (map to-dep deps)]) (defn- gen-source-dir [path] [::pom/sourceDirectory path]) (defn- to-repo-policy [parent-tag {:keys [enabled update checksum]}] [parent-tag (when (some? enabled) [::pom/enabled (str enabled)]) (when update [::pom/updatePolicy (if (keyword? update) (name update) (str "interval:" update))]) (when checksum [::pom/checksumPolicy (name checksum)])]) (defn- to-repo [[name {:keys [url snapshots releases]}]] [::pom/repository [::pom/id name] [::pom/url url] (when releases (to-repo-policy ::pom/releases releases)) (when snapshots (to-repo-policy ::pom/snapshots snapshots))]) (defn- gen-repos [repos] [::pom/repositories (map to-repo repos)]) (defn- gen-pom [{:keys [deps src-paths resource-paths repos group artifact version] :or {version "0.1.0"}}] (let [[path & paths] src-paths] (xml/sexp-as-element [::pom/project {:xmlns "http://maven.apache.org/POM/4.0.0" (keyword "xmlns:xsi") "http://www.w3.org/2001/XMLSchema-instance" (keyword "xsi:schemaLocation") "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"} [::pom/modelVersion "4.0.0"] [::pom/packaging "jar"] [::pom/groupId group] [::pom/artifactId artifact] [::pom/version version] [::pom/name artifact] (gen-deps deps) (when path (when (seq paths) (apply printerrln "Skipping paths:" paths)) [::pom/build (gen-source-dir path)]) (gen-repos repos)]))) (defn- make-xml-element [{:keys [tag attrs] :as node} children] (with-meta (apply xml/element tag attrs children) (meta node))) (defn- xml-update [root tag-path replace-node] (let [z (zip/zipper xml/element? :content make-xml-element root)] (zip/root (loop [[tag & more-tags :as tags] tag-path, parent z, child (zip/down z)] (if child (if (= tag (:tag (zip/node child))) (if (seq more-tags) (recur more-tags child (zip/down child)) (zip/edit child (constantly replace-node))) (if-let [next-sibling (zip/right child)] (recur tags parent next-sibling) (if (seq more-tags) (let [new-parent (zip/append-child parent (xml/sexp-as-element tag)) new-child (zip/rightmost (zip/down new-parent))] (recur more-tags new-child (zip/down new-child))) (zip/append-child parent replace-node)))) (if (seq more-tags) (let [new-parent (zip/append-child parent (xml/sexp-as-element tag)) new-child (zip/rightmost (zip/down new-parent))] (recur more-tags new-child (zip/down new-child))) (zip/append-child parent replace-node))))))) (defn- replace-deps [pom deps] (xml-update pom [::pom/dependencies] (xml/sexp-as-element (gen-deps deps)))) (defn- replace-paths [pom [path & paths]] (if path (do (when (seq paths) (apply printerrln "Skipping paths:" paths)) (xml-update pom [::pom/build ::pom/sourceDirectory] (xml/sexp-as-element (gen-source-dir path)))) pom)) (defn- replace-repos [pom repos] (if (seq repos) (xml-update pom [::pom/repositories] (xml/sexp-as-element (gen-repos repos))) pom)) (defn- replace-lib [pom lib] (if lib (-> pom (xml-update [::pom/groupId] (xml/sexp-as-element [::pom/groupId (namespace lib)])) (xml-update [::pom/artifactId] (xml/sexp-as-element [::pom/artifactId (name lib)])) (xml-update [::pom/name] (xml/sexp-as-element [::pom/name (name lib)]))) pom)) (defn- replace-version [pom version] (if version (xml-update pom [::pom/version] (xml/sexp-as-element [::pom/version version])) pom)) (defn- parse-xml [^Reader rdr] (let [roots (tree/seq-tree event/event-element event/event-exit? event/event-node (xml/event-seq rdr {:include-node? #{:element :characters :comment} :skip-whitespace true}))] (first (filter #(instance? Element %) (first roots))))) (defn- resolve-path-ref "Recursively resolve path refs to a coll of paths. Path refs may be: string - a path keyword - a path alias or the special alias, :paths coll of the above" [path-ref {:keys [paths aliases] :as edn-map}] (let [alias-map (merge aliases {:paths paths})] (loop [acc [] [fpath & rpaths] [path-ref]] (cond (nil? fpath) acc (string? fpath) (recur (conj acc fpath) rpaths) (keyword? fpath) (let [res (get alias-map fpath)] (if (coll? res) (recur acc (concat res rpaths)) (recur acc (conj res rpaths)))) (coll? fpath) (recur acc (concat rpaths fpath)))))) (defn- libs->deps "Convert libmap to root deps" [libs] (reduce-kv (fn [ret lib {:keys [dependents] :as coord}] (if (seq dependents) ret (assoc ret lib coord))) {} libs)) (defn sync-pom "Creates or synchronizes a pom given a map of :basis and :params. From basis, uses: :deps to build :paths to build :mvn/repos to build (omits maven central, included by default) Params: :target-dir Path to target output directory (required) :src-pom Path to source pom file (optional, default = \"pom.xml\") :lib Symbol of groupId/artifactId (required for new, optional for existing) :version String of project version (optional)" ([{:keys [basis params]}] (let [{:keys [libs paths :mvn/repos]} basis root-deps (libs->deps libs) {:keys [target-dir src-pom lib version] :or {src-pom "pom.xml"}} params resolved-paths (resolve-path-ref paths basis) repos (remove #(= "https://repo1.maven.org/maven2/" (-> % val :url)) repos) pom-file (jio/file src-pom) pom (if (.exists pom-file) (with-open [rdr (jio/reader pom-file)] (-> rdr parse-xml (replace-deps root-deps) (replace-paths resolved-paths) (replace-repos repos) (replace-lib lib) (replace-version version))) (gen-pom (cond-> {:deps root-deps :src-paths resolved-paths :repos repos :group (namespace lib) :artifact (name lib)} version (assoc :version version)))) target-pom (jio/file target-dir "pom.xml")] (spit target-pom (xml/indent-str pom)))) ;; deprecated arity ([{:keys [deps paths :mvn/repos] :as deps-edn} ^File dir] (let [artifact-name (.. dir getCanonicalFile getName) resolved-paths (resolve-path-ref paths deps-edn) src-pom (jio/file dir "pom.xml")] (sync-pom {:basis {:deps deps :libs deps :paths resolved-paths :mvn/repos repos} :params (merge {:target-dir (.getCanonicalPath dir)} (if (.exists src-pom) {:src-pom (.getCanonicalPath src-pom)} {:lib (symbol artifact-name artifact-name)}))})))) (comment (require '[clojure.tools.deps.alpha :as deps]) (let [{:keys [install-edn user-edn project-edn]} (deps/find-edn-maps) edn (deps/merge-edns [install-edn user-edn project-edn]) basis (deps/calc-basis edn)] (sync-pom basis (jio/file "."))) (let [{:keys [install-edn user-edn project-edn]} (deps/find-edn-maps) edn (deps/merge-edns [install-edn user-edn project-edn]) basis (deps/calc-basis edn)] (sync-pom {:basis basis :params {:src-pom "../../tmp/pom2.xml" :target-dir "../../tmp" :lib 'foo/bar :version "1.2.3"}})) ) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/script/000077500000000000000000000000001434474567100243645ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/script/generate_manifest2.clj000066400000000000000000000060071434474567100306230ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.script.generate-manifest2 (:require [clojure.java.io :as jio] [clojure.tools.cli :as cli] [clojure.tools.deps :as deps] [clojure.tools.deps.gen.pom :as pom] [clojure.tools.deps.script.parse :as parse] [clojure.tools.deps.script.make-classpath2 :as makecp] [clojure.tools.deps.util.io :refer [printerrln]]) (:import [clojure.lang IExceptionInfo])) (def ^:private opts [[nil "--config-user PATH" "User deps.edn location"] [nil "--config-project PATH" "Project deps.edn location"] [nil "--config-data EDN" "Final deps.edn data to treat as the last deps.edn file" :parse-fn parse/parse-config] [nil "--gen TYPE" "manifest type to generate" :parse-fn keyword] ["-R" "--resolve-aliases ALIASES" "Concatenated resolve-deps alias names" :parse-fn parse/parse-kws] ["-C" "--makecp-aliases ALIASES" "Concatenated make-classpath alias names" :parse-fn parse/parse-kws] ["-A" "--repl-aliases ALIASES" "Concatenated repl alias names" :parse-fn parse/parse-kws]]) (defn -main "Main entry point for generating a manifest file. Required: --config-user PATH - User deps.edn location --config-project PATH - Project deps.edn location --config-data={...} - deps.edn as data --gen TYPE - manifest type to generate (currently only pom) Options: -Raliases - concated resolve-deps alias names, applied to the :deps -Aaliases - concatenated generic alias names" [& args] (let [{:keys [options errors]} (cli/parse-opts args opts)] (when (seq errors) (run! println errors) (System/exit 1)) (let [{:keys [gen config-user config-project]} options] (try (let [mod-map (makecp/run-core (merge options {:install-deps (deps/root-deps) :user-deps (makecp/read-deps config-user) :project-deps (makecp/read-deps config-project)})) ;; treat all transitive deps as top-level deps updated-deps (reduce-kv (fn [m lib {:keys [dependents] :as coord}] (if (seq dependents) m (assoc m lib coord))) {} (:libs mod-map))] (pom/sync-pom (merge mod-map {:deps updated-deps}) (jio/file "."))) (catch Throwable t (printerrln "Error generating" (name gen) "manifest:" (.getMessage t)) (when-not (instance? IExceptionInfo t) (.printStackTrace t)) (System/exit 1)))))) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/script/make_classpath2.clj000066400000000000000000000260101434474567100301160ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.script.make-classpath2 (:require [clojure.java.io :as jio] [clojure.pprint :as pprint] [clojure.string :as str] [clojure.tools.cli :as cli] [clojure.tools.deps :as deps] [clojure.tools.deps.extensions :as ext] [clojure.tools.deps.tool :as tool] [clojure.tools.deps.util.io :as io :refer [printerrln]] [clojure.tools.deps.script.parse :as parse] [clojure.tools.deps.tree :as tree]) (:import [clojure.lang IExceptionInfo])) (def ^:private opts [;; deps.edn inputs [nil "--config-user PATH" "User deps.edn location"] [nil "--config-project PATH" "Project deps.edn location"] [nil "--config-data EDN" "Final deps.edn data to treat as the last deps.edn file" :parse-fn parse/parse-config] ;; tool args to resolve [nil "--tool-mode" "Tool mode (-T), may optionally supply tool-name or tool-aliases"] [nil "--tool-name NAME" "Tool name"] ;; output files [nil "--libs-file PATH" "Libs cache file to write"] [nil "--cp-file PATH" "Classpatch cache file to write"] [nil "--jvm-file PATH" "JVM options file"] [nil "--main-file PATH" "Main options file"] [nil "--manifest-file PATH" "Manifest list file"] [nil "--basis-file PATH" "Basis file"] [nil "--skip-cp" "Skip writing .cp and .libs files"] ;; aliases ["-R" "--resolve-aliases ALIASES" "Concatenated resolve-deps alias names" :parse-fn parse/parse-kws] ["-C" "--makecp-aliases ALIASES" "Concatenated make-classpath alias names" :parse-fn parse/parse-kws] ["-A" "--repl-aliases ALIASES" "Concatenated repl alias names" :parse-fn parse/parse-kws] ["-M" "--main-aliases ALIASES" "Concatenated main option alias names" :parse-fn parse/parse-kws] ["-X" "--exec-aliases ALIASES" "Concatenated exec alias names" :parse-fn parse/parse-kws] ["-T" "--tool-aliases ALIASES" "Concatenated tool alias names" :parse-fn parse/parse-kws] ;; options [nil "--trace" "Emit trace log to trace.edn"] [nil "--threads THREADS" "Threads for concurrent downloads"] [nil "--tree" "Print deps tree to console"]]) (defn parse-opts "Parse the command line opts to make-classpath" [args] (cli/parse-opts args opts)) (defn check-aliases "Check that all aliases are known and warn if aliases are undeclared" [deps aliases] (when-let [unknown (seq (remove #(contains? (:aliases deps) %) (distinct aliases)))] (printerrln "WARNING: Specified aliases are undeclared and are not being used:" (vec unknown)))) (defn resolve-tool-args "Resolves the tool by name to the coord + usage data. Returns the proper alias args as if the tool was specified as an alias." [tool-name config] (if-let [{:keys [lib coord]} (tool/resolve-tool tool-name)] (let [manifest-type (ext/manifest-type lib coord config) coord' (merge coord manifest-type) {:keys [ns-default ns-aliases]} (ext/coord-usage lib coord' (:deps/manifest coord') config)] {:replace-deps {lib coord'} :replace-paths ["."] :ns-default ns-default :ns-aliases ns-aliases}) (throw (ex-info (str "Unknown tool: " tool-name) {:tool tool-name})))) (defn run-core "Run make-classpath script from/to data (no file stuff). Returns: {;; Main outputs: :libs lib-map ;; from resolve-deps, .libs file :cp classpath ;; from make-classpath, .cp file :main main-opts ;; effective main opts, .main file :jvm jvm-opts ;; effective jvm opts, .jvm file :trace trace-log ;; from resolve-deps, if requested, trace.edn file ;; Intermediate/source data: :deps merged-deps ;; effective merged :deps :paths local-paths ;; from make-classpath, just effective local paths ;; and any other qualified keys from top level merged deps }" [{:keys [install-deps user-deps project-deps config-data ;; all deps.edn maps tool-mode tool-name tool-resolver ;; -T options resolve-aliases makecp-aliases main-aliases exec-aliases repl-aliases tool-aliases skip-cp threads trace tree] :as _opts}] (when (and main-aliases exec-aliases) (throw (ex-info "-M and -X cannot be used at the same time" {}))) (let [pretool-edn (deps/merge-edns [install-deps user-deps project-deps config-data]) ;; tool use - :deps/:paths/:replace-deps/:replace-paths in project if needed tool-args (cond tool-name (tool-resolver tool-name pretool-edn) tool-mode {:replace-deps {} :replace-paths ["."]}) tool-edn (when tool-args {:aliases {:deps/TOOL tool-args}}) ;; :deps/TOOL is a synthetic deps.edn combining the tool definition and usage ;; it is injected at the end of the deps chain and added as a pseudo alias ;; the effects are seen in the basis but this pseduo alias should not escape combined-tool-args (deps/combine-aliases (deps/merge-edns [pretool-edn tool-edn]) (concat main-aliases exec-aliases repl-aliases tool-aliases (when tool-edn [:deps/TOOL]))) project-deps (deps/tool project-deps combined-tool-args) ;; calc basis merge-edn (deps/merge-edns [install-deps user-deps project-deps config-data (when tool-edn tool-edn)]) ;; recalc to get updated project-deps combined-exec-aliases (concat main-aliases exec-aliases repl-aliases tool-aliases (when tool-edn [:deps/TOOL])) _ (check-aliases merge-edn (concat resolve-aliases makecp-aliases combined-exec-aliases)) resolve-argmap (deps/combine-aliases merge-edn (concat resolve-aliases combined-exec-aliases)) resolve-args (cond-> resolve-argmap threads (assoc :threads (Long/parseLong threads)) trace (assoc :trace trace) tree (assoc :trace true)) cp-args (deps/combine-aliases merge-edn (concat makecp-aliases combined-exec-aliases)) exec-argmap (deps/combine-aliases merge-edn combined-exec-aliases) execute-args (select-keys exec-argmap [:ns-default :ns-aliases :exec-fn :exec-args]) execute-args (let [arg-kw (:exec-args execute-args)] (if (keyword? arg-kw) (assoc execute-args :exec-args (get-in merge-edn [:aliases arg-kw])) execute-args)) basis (if skip-cp (when (pos? (count execute-args)) {:execute-args execute-args}) (deps/calc-basis merge-edn (cond-> {} resolve-args (assoc :resolve-args resolve-args) cp-args (assoc :classpath-args cp-args) execute-args (assoc :execute-args execute-args)))) ;; check for unprepped libs _ (deps/prep-libs! (:libs basis) {:action :error} basis) ;; determine manifest files to add to cache check manifests (->> (for [[lib coord] (:libs basis)] (let [mf (ext/manifest-type lib coord basis)] (ext/manifest-file lib coord (:deps/manifest mf) basis))) (remove nil?) seq) ;; handle jvm and main opts jvm (seq (get exec-argmap :jvm-opts)) main (seq (get exec-argmap :main-opts))] (when (and main repl-aliases) (io/printerrln "WARNING: Use of :main-opts with -A is deprecated. Use -M instead.")) (cond-> basis jvm (assoc :jvm jvm) ;; FUTURE: narrow this to (and main main-aliases) main (assoc :main main) manifests (assoc :manifests manifests)))) (defn read-deps [name] (when (not (str/blank? name)) (let [f (jio/file name)] (when (.exists f) (deps/slurp-deps f))))) (defn write-lines [lines file] (if lines (io/write-file file (apply str (interleave lines (repeat "\n")))) (let [jf (jio/file file)] (when (.exists jf) (.delete jf))))) (defn run "Run make-classpath script. See -main for details." [{:keys [config-user config-project libs-file cp-file jvm-file main-file basis-file manifest-file skip-cp trace tree] :as opts}] (let [opts' (merge opts {:install-deps (deps/root-deps) :user-deps (read-deps config-user) :project-deps (read-deps config-project) :tool-resolver resolve-tool-args}) {:keys [libs classpath-roots jvm main manifests] :as basis} (run-core opts') trace-log (-> libs meta :trace)] (when trace (spit "trace.edn" (binding [*print-namespace-maps* false] (with-out-str (pprint/pprint trace-log))))) (when tree (-> trace-log tree/trace->tree (tree/print-tree nil))) (when-not skip-cp (io/write-file libs-file (binding [*print-namespace-maps* false] (pr-str libs))) (io/write-file cp-file (-> classpath-roots deps/join-classpath))) (io/write-file basis-file (binding [*print-namespace-maps* false] (pr-str basis))) (write-lines jvm jvm-file) (write-lines main main-file) (write-lines manifests manifest-file))) (defn -main "Main entry point for make-classpath script. Options: --config-user=path - user deps.edn file (usually ~/.clojure/deps.edn) --config-project=path - project deps.edn file (usually ./deps.edn) --config-data={...} - deps.edn as data (from -Sdeps) --tool-mode - flag for tool mode --tool-name - name of tool to run --libs-file=path - libs cache file to write --cp-file=path - cp cache file to write --jvm-file=path - jvm opts file to write --main-file=path - main opts file to write --manifest-file=path - manifest list file to write --basis-file=path - basis file to write -Rresolve-aliases - concatenated resolve-deps alias names -Cmakecp-aliases - concatenated make-classpath alias names -Mmain-aliases - concatenated main-opt alias names -Aaliases - concatenated repl alias names -Xaliases - concatenated exec alias names -Taliases - concatenated tool alias names Resolves the dependencies and updates the lib, classpath, etc files. The libs file is at /.libs The cp file is at /.cp The main opts file is at /.main (if needed) The jvm opts file is at /.jvm (if needed) The manifest file is at /.manifest (if needed)" [& args] (try (let [{:keys [options errors]} (parse-opts args)] (when (seq errors) (run! println errors) (System/exit 1)) (run options)) (catch Throwable t (printerrln "Error building classpath." (.getMessage t)) (when-not (instance? IExceptionInfo t) (.printStackTrace t)) (System/exit 1)))) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/script/parse.clj000066400000000000000000000026051434474567100261730ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.script.parse (:require [clojure.java.io :as jio] [clojure.string :as str] [clojure.edn :as edn] [clojure.tools.deps :as deps]) (:import [java.io File])) (defn parse-files "Parses a string of comma-delimited files into a collection of Files, filtering only those that exist." [s] (->> (str/split s #",") (map jio/file) (filter #(.exists ^File %)))) (defn parse-kws "Parses a concatenated string of keywords into a collection of keywords Ex: (parse-kws \":a:b:c\") ;; returns: (:a :b :c)" [s] (->> (str/split (or s "") #":") (remove str/blank?) (map #(if-let [i (str/index-of % \/)] (keyword (subs % 0 i) (subs % (inc i))) (keyword %))))) (defn parse-config "Parses a string of edn into a deps map." [s] (#'deps/canonicalize-all-syms ;; to be removed in the future (edn/read-string {:default tagged-literal} s))) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/script/print_tree.clj000066400000000000000000000027441434474567100272400ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.script.print-tree (:require [clojure.tools.deps :as deps] [clojure.tools.deps.util.io :as io :refer [printerrln]] [clojure.tools.cli :as cli]) (:import [clojure.lang IExceptionInfo])) (def ^:private opts [[nil "--libs-file PATH" "Libs cache file to write"]]) (defn run "Run print-tree script. See -main for details." [{:keys [libs-file] :as _options}] (let [lib-map (io/slurp-edn libs-file)] (deps/print-tree lib-map))) (defn -main "Main entry point for print-tree script. Required: --libs-file=path - libs file Prints the tree from libs file" [& args] (try (let [{:keys [options errors]} (cli/parse-opts args opts)] (when (seq errors) (run! println errors) (System/exit 1)) (run options)) (catch Throwable t (printerrln "Error printing tree." (.getMessage t)) (when-not (instance? IExceptionInfo t) (.printStackTrace t)) (System/exit 1)))) (comment (run {:libs-file "foo.libs"}) ) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/script/resolve_tags.clj000066400000000000000000000062471434474567100275640ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.script.resolve-tags (:require [clojure.java.io :as jio] [clojure.pprint :as pp] [clojure.walk :as walk] [clojure.tools.deps :as deps] [clojure.tools.deps.extensions.git :as git] [clojure.tools.deps.util.io :refer [printerrln]] [clojure.tools.gitlibs :as gitlibs] [clojure.tools.cli :as cli]) (:import [clojure.lang IExceptionInfo])) (def ^:private opts [[nil "--deps-file PATH" "deps.edn file to update"]]) (defn- resolve-git-dep [counter lib {untag :tag, unsha :sha, :git/keys [url tag sha] :as git-coord}] (let [the-url (or url (git/auto-git-url lib)) the-tag (or tag untag) the-sha (or sha unsha)] (if the-tag (let [new-sha (gitlibs/resolve the-url the-tag)] (if (= the-sha new-sha) git-coord ;; no change (do (printerrln "Resolved" the-tag "=>" new-sha "in" the-url) (swap! counter inc) (cond-> {:git/tag the-tag :git/sha (subs new-sha 0 7)} url (assoc :git/url url))))) git-coord))) (defn- resolve-git-deps [counter deps-map] (let [f (partial resolve-git-dep counter)] (walk/postwalk (fn [node] (if (map? node) (reduce-kv (fn [new-deps k v] (if (and (symbol? k) (map? v) (contains? (->> v keys (map namespace) set) "git")) (assoc new-deps k (resolve-git-dep counter k v)) new-deps)) node node) node)) deps-map))) (defn exec [{:keys [deps-file]}] (try (let [deps-map (deps/slurp-deps (jio/file deps-file)) counter (atom 0)] (printerrln "Resolving git tags in" deps-file "...") (let [resolved-map (resolve-git-deps counter deps-map)] (if (zero? @counter) (printerrln "No unresolved tags found.") (spit deps-file (with-out-str (with-bindings {#'pp/*print-right-margin* 100 #'pp/*print-miser-width* 80 #'*print-namespace-maps* false} (pp/pprint resolved-map))))))) (catch Throwable t (printerrln "Error resolving tags." (.getMessage t)) (when-not (instance? IExceptionInfo t) (.printStackTrace t)) (System/exit 1)))) (defn -main "Main entry point for resolve-tags script. Required: --deps-file deps.edn - deps.edn files in which to resolve git tags Read deps.edn, find git coordinates with :tag but without :sha, resolve those tags to shas, and over-write the deps.edn." [& args] (let [{:keys [options]} (cli/parse-opts args opts)] (exec options))) (comment (-main "--deps-file" "deps.edn") ) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/specs.clj000066400000000000000000000142171434474567100246740ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns clojure.tools.deps.specs (:require [clojure.spec.alpha :as s])) ;;;; generic types (s/def ::lib symbol?) (s/def ::path string?) (s/def ::alias keyword?) ;;;; coordinates ;; generic coord attributes (s/def :deps/root ::path) (s/def :deps/manifest keyword?) (s/def :deps/exclusions (s/coll-of ::lib)) (s/def :deps/coord (s/keys :opt [:deps/root :deps/manifest] :opt-un [:deps/exclusions])) ;; maven coords (s/def :mvn/version string?) (s/def :mvn/coord (s/merge :deps/coord (s/keys :req [:mvn/version]))) ;; local coords (s/def :local/root string?) (s/def :local/coord (s/merge :deps/coord (s/keys :req [:local/root]))) ;; git coords (s/def :git/url string?) (s/def :git/sha string?) (s/def :git/tag string?) (s/def :git/coord (s/merge :deps/coord (s/keys :opt [:git/url :git/sha :git/tag]))) ;; should this become a multispec? (s/def ::coord (s/nilable (s/or :mvn :mvn/coord :local :local/coord :git :git/coord))) (s/def ::path-ref (s/or :path ::path :alias ::alias)) (s/def :aliased/paths (s/coll-of ::path-ref :kind vector? :into [])) ;; tool args ;; ::replace-deps - map of lib to coordinate to replace the (s/def ::tool-args (s/keys :opt-un [::replace-deps ::replace-paths ::deps ::paths])) (s/def ::replace-deps (s/map-of ::lib ::coord)) (s/def ::replace-paths :aliased/paths) ;; resolve-deps args - used to modify the expanded deps tree ;; ::extra-deps - map of lib to coordinate added to the initial deps collection ;; ::override-deps - map of lib to coordinate to use instead of the coord found during expansion ;; ::default-deps - map of lib to coordinate to use if no coord is specified in extension (s/def ::resolve-args (s/keys :opt-un [::extra-deps ::override-deps ::default-deps])) (s/def ::extra-deps (s/map-of ::lib ::coord)) (s/def ::override-deps (s/map-of ::lib ::coord)) (s/def ::default-deps (s/map-of ::lib ::coord)) (s/def ::threads pos-int?) (s/def ::trace boolean?) ;; make-classpath args - used when constructing the classpath ;; ::classpath-overrides - map of lib to path to use instead of the artifact found during resolution ;; ::extra-paths - collection of extra paths to add to the classpath in addition to ::paths (s/def ::classpath-args (s/keys :opt-un [::classpath-overrides ::extra-paths])) (s/def ::classpath-overrides (s/map-of ::lib ::path)) (s/def ::extra-paths :aliased/paths) ;; exec args - used when executing a function with -X or -T ;; ::exec-args - map of default function args ;; ::exec-fn - default function symbol ;; ::ns-default - default namespace to use when resolving functions ;; ::ns-aliases - map of alias to namespace to use when resolving functions (s/def ::exec-args (s/keys :opt-un [::exec-args ::exec-fn ::ns-default ::ns-aliases])) (s/def ::exec-args (s/nilable map?)) (s/def ::ns-default simple-symbol?) (s/def ::ns-aliases (s/map-of simple-symbol? simple-symbol?)) ;; deps map (format of the deps.edn file) (s/def ::paths :aliased/paths) (s/def ::deps (s/map-of ::lib ::coord)) (s/def ::aliases (s/map-of ::alias any?)) (s/def ::deps-map (s/keys :opt-un [::paths ::deps ::aliases] :opt [:mvn/repos :mvn/local-repo :tools/usage :deps/prep-lib])) ;; lib map ;; a map of lib to resolved coordinate (a coord with a ::path) and dependent info (s/def ::dependents (s/coll-of ::lib)) (s/def ::resolved-coord (s/merge ::coord (s/keys :opt-un [:aliased/paths ::dependents]))) (s/def ::lib-map (s/map-of ::lib ::resolved-coord)) ;; classpath (s/def ::classpath string?) ;; Procurers ;; Maven (s/def :mvn/repos (s/map-of ::repo-id ::repo)) (s/def ::repo-id string?) (s/def ::repo (s/nilable (s/keys :opt-un [::url :mvn/releases :mvn/snapshots]))) (s/def ::url string?) (s/def :mvn-repo/enabled boolean?) (s/def :mvn-repo/update (s/or :policy #{:daily :always :never} :interval int?)) (s/def :mvn-repo/checksum #{:warn :fail :ignore}) (s/def :mvn/repo-policy (s/keys :opt-un [:mvn-repo/enabled :mvn-repo/update :mvn-repo/checksum])) (s/def :mvn/releases :mvn/repo-policy) (s/def :mvn/snapshots :mvn/repo-policy) (s/def :mvn/local-repo string?) ;; Tool usage (s/def :tools/usage (s/keys :opt-un [::ns-default ::ns-aliases])) ;; Prep lib (s/def :deps/prep-lib (s/keys :req-un [:prep/ensure ::alias :prep/fn])) (s/def :prep/ensure ::path) (s/def :prep/fn symbol?) ;; API (s/fdef clojure.tools.deps/resolve-deps :args (s/cat :deps ::deps-map :options ::resolve-args) :ret ::lib-map) (s/fdef clojure.tools.deps/make-classpath-map :args (s/cat :deps ::deps-map, :libs ::lib-map, :classpath-args ::claspath-args) :ret map?) (s/fdef clojure.tools.deps/make-classpath :args (s/cat :libs ::lib-map, :paths ::paths, :classpath-args ::classpath-args) :ret string?) (comment ;; some scratch code to recursively check every deps.edn under ;; a root directory whether it's valid against the specs (require '[clojure.spec.test.alpha :as stest] '[clojure.tools.deps :as deps]) (import '[java.nio.file Files Paths FileVisitor FileVisitResult]) (stest/instrument (stest/enumerate-namespace 'clojure.tools.deps)) (Files/walkFileTree (Paths/get "../" (into-array String [])) (reify FileVisitor (postVisitDirectory [_ dir ex] FileVisitResult/CONTINUE) (preVisitDirectory [_ dir attrs] FileVisitResult/CONTINUE) (visitFileFailed [_ f ex] FileVisitResult/CONTINUE) (visitFile [_ f attrs] (when (.endsWith (str f) "/deps.edn") (print "Checking" (str f)) (let [v (s/valid? ::deps-map (#'deps/slurp-edn-map (.toFile f)))] (println ":" v) (when-not v (s/explain ::deps-map (#'deps/slurp-edn-map (.toFile f)))))) FileVisitResult/CONTINUE))) ) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/tool.clj000066400000000000000000000054431434474567100245350ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns clojure.tools.deps.tool (:require [clojure.java.io :as jio] [clojure.pprint :as pprint] [clojure.string :as str] [clojure.tools.deps :as deps] [clojure.tools.deps.extensions :as ext] [clojure.tools.deps.util.io :as io]) (:import [java.io File])) (defn- tool-dir ^File [] (jio/file (.getParentFile (jio/file (deps/user-deps-path))) "tools")) (defn- tool-file "Create File location for tool name" ^File [tool] (jio/file (tool-dir) (str tool ".edn"))) (defn install-tool "Procure the lib+coord, install the tool to the user tools dir (with lib, coord)" [lib coord as] (let [{:keys [root-edn user-edn]} (deps/find-edn-maps) master-edn (deps/merge-edns [root-edn user-edn]) deps-info (ext/manifest-type lib coord master-edn) f (tool-file as)] ;; procure (ext/coord-paths lib (merge coord deps-info) (:deps/manifest deps-info) master-edn) ;; ensure tool dir (.mkdirs (.getParentFile f)) ;; write tool file (spit f (with-out-str (binding [*print-namespace-maps* false pprint/*print-right-margin* 100] (pprint/pprint {:lib lib :coord coord})))))) (defn resolve-tool "Resolve a tool by name, look up and return: {:lib lib :coord coord} Or nil if unknown." [tool] (let [f (tool-file tool)] (when (.exists f) (io/slurp-edn f)))) (defn usage "Resolve a tool and return it's usage data, which may be nil. Throws ex-info if tool is unknown." [tool] (if-let [{:keys [lib coord]} (resolve-tool tool)] (let [{:keys [root-edn user-edn]} (deps/find-edn-maps) config (deps/merge-edns [root-edn user-edn]) [lib coord] (ext/canonicalize lib coord config) manifest-type (ext/manifest-type lib coord config)] (ext/coord-usage lib (merge coord manifest-type) (:deps/manifest manifest-type) config)) (throw (ex-info (str "Unknown tool: " tool) {:tool tool})))) (defn list-tools "Return seq of available tool names" [] (->> (.listFiles (tool-dir)) (filter #(.isFile ^File %)) (map #(.getName ^File %)) (filter #(str/ends-with? % ".edn")) (map #(subs % 0 (- (count %) 4))) sort)) (defn remove-tool "Removes tool installation, if it exists. Returns true if it exists and was deleted." [tool] (let [f (tool-file tool)] (when (.exists f) (.delete f))))tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/tree.clj000066400000000000000000000116461434474567100245210ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns clojure.tools.deps.tree (:require [clojure.walk :as walk] [clojure.tools.deps :as deps] [clojure.tools.deps.extensions :as ext])) ;; Data manipulation (defn trace->tree "Convert a deps trace data structure into a deps tree. A deps tree has the structure of the full dependency expansion. Each node of the tree is a map from lib to coord-info with at least these keys: :lib - library symbol :coord - the coord map that was used (may not be the original coord if replaced due to default-deps or override-deps) :include - boolean of whether this node is included in the returned deps :reason - why the node was or was not included :children - vector of child nodes" [trace] (let [{:keys [log]} trace] (loop [[{:keys [lib path reason] :as step} & steps] log i 0 tree {}] (if step (let [nstep (assoc step :step i) full-path (conj path lib) tree-path (interleave (repeat :children) full-path) tree' (if (= reason :newer-version) (walk/postwalk (fn [v] (if (and (map? v) (contains? v lib) (-> v lib :include)) (assoc v lib (merge (get v lib) {:include false, :reason :superseded})) v)) tree) tree)] (recur steps (inc i) (assoc-in tree' tree-path nstep))) tree)))) (defn calc-trace "Like calc-basis, but create and return the dep expansion trace. The trace can be passed to trace->tree to get tree data. The opts map includes the same opts accepted by clojure.tools.deps/create-basis. By default, uses the root, user, and project deps and no argmaps (essentially the same classpath you get by default from the Clojure CLI). Each dep source value can be :standard, a string path, a deps edn map, or nil. Sources are merged in the order - :root, :user, :project, :extra. Aliases refer to argmaps in the merged deps that will be supplied to the basis subprocesses (tool, resolve-deps, make-classpath-map). Options: :root - dep source, default = :standard :user - dep source, default = :standard :project - dep source, default = :standard (\"./deps.edn\") :extra - dep source, default = nil :aliases - coll of aliases of argmaps to apply to subprocesses" ([] (calc-trace nil)) ([opts] (let [{:keys [extra aliases]} opts trace-opts (merge opts {:extra (assoc-in extra [:aliases :__TRACE__ :trace] true)} {:aliases (conj (or aliases []) :__TRACE__)})] (-> trace-opts deps/create-basis :libs meta :trace)))) ;; Printing (defn- space [n] (apply str (repeat n \space))) (defn- print-node [{:keys [lib coord include reason]} indented {:keys [hide-libs]}] (when (and lib (or (= reason :new-top-dep) (not (contains? hide-libs lib)))) (let [pre (space indented) summary (ext/coord-summary lib coord)] (println (case reason :new-top-dep (str pre summary) (:new-dep :same-version) (str pre ". " summary) :newer-version (str pre ". " summary " " reason) (:use-top :older-version :excluded :parent-omitted :superseded) ;; :superseded is internal here (str pre "X " summary " " reason) ;; fallthrough, unknown reason (str pre "? " summary include reason)))))) (defn print-tree "Print the tree to the console. Options: :indent Indent spacing (default = 2) :hide-libs Set of libs to ignore as deps under top deps, default = #{org.clojure/clojure}" ([tree {:keys [indent] :or {indent 2} :as opts}] (print-tree tree (- 0 indent) opts)) ([{:keys [children] :as tree} indented opts] (let [opts' (merge {:indent 2, :hide-libs '#{org.clojure/clojure}} opts)] (print-node tree indented opts') (doseq [child (sort-by :step (vals children))] (print-tree child (+ indented (:indent opts')) opts'))))) (comment (require '[clojure.tools.deps.util.io :as io]) (-> "/Users/alex.miller/tmp/20201124/trace.edn" io/slurp-edn trace->tree (print-tree {})) (-> "/Users/alex.miller/code/tools.deps/trace.edn" io/slurp-edn trace->tree (print-tree {})) (-> "/Users/alex.miller/tmp/20201022/trace.edn" io/slurp-edn trace->tree (print-tree {})) (let [log (:log (io/slurp-edn "/Users/alex.miller/tmp/20201124/trace.edn"))] (distinct (map :reason log))) )tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/util/000077500000000000000000000000001434474567100240355ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/util/concurrent.clj000066400000000000000000000026351434474567100267170ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.util.concurrent (:import [java.util.concurrent Callable Future ThreadFactory ExecutorService Executors TimeUnit])) (set! *warn-on-reflection* true) (defonce thread-factory (let [counter (atom 0)] (reify ThreadFactory (newThread [_ r] (doto (Thread. r) (.setName (format "tools.deps worker %s" (swap! counter inc))) (.setDaemon true)))))) (defn new-executor ^ExecutorService [^long n] (Executors/newFixedThreadPool n ^ThreadFactory thread-factory)) (def processors (long (.availableProcessors (Runtime/getRuntime)))) (defn submit-task ^Future [^ExecutorService executor f] (let [bindings (get-thread-bindings) task #(do (push-thread-bindings bindings) (f))] (.submit executor ^Callable task))) (defn shutdown-on-error [^ExecutorService executor] (.shutdownNow executor) (.awaitTermination executor 1 TimeUnit/SECONDS)) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/util/dir.clj000066400000000000000000000043311434474567100253060ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.util.dir (:require [clojure.java.io :as jio]) (:import [java.io File] [java.nio.file Files Path])) (set! *warn-on-reflection* true) (def ^:dynamic *the-dir* "Thread-local directory context for resolving relative directories. Defaults to current directory. Should always hold an absolute directory java.io.File, never null." (jio/file (System/getProperty "user.dir"))) (defn canonicalize "Make canonical File in terms of the current directory context. f may be either absolute or relative." ^File [^File f] (.getCanonicalFile (if (.isAbsolute f) f (jio/file *the-dir* f)))) (defmacro with-dir "Push directory into current directory context for execution of body." [^File dir & body] `(binding [*the-dir* (canonicalize ~dir)] ~@body)) (defn- same-file? "If a file can't be read (most common reason is directory does not exist), then treat this as not the same file (ie unknown)." [^Path p1 ^Path p2] (try (Files/isSameFile p1 p2) (catch Exception _ false))) (defn sub-path? "True if the path is a sub-path of the current directory context. path may be either absolute or relative. Will return true if path has a parent that is the current directory context, false otherwise. Handles relative paths, .., ., etc. The sub-path does not need to exist on disk (but the current directory context must)." [^File path] (if (nil? path) false (let [root-path (.toPath ^File *the-dir*)] (loop [check-path (.toPath (canonicalize path))] (cond (nil? check-path) false (same-file? root-path check-path) true :else (recur (.getParent check-path))))))) ;; DEPRECATED (defn as-canonical ^File [^File dir] (canonicalize dir))tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/util/io.clj000066400000000000000000000040261434474567100251400ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.util.io (:require [clojure.edn :as edn] [clojure.java.io :as jio] [clojure.string :as str]) (:import [java.io Reader FileReader PushbackReader])) (defonce ^:private nl (System/getProperty "line.separator")) (defn printerrln "println to *err*" [& msgs] (binding [*out* *err* *print-readably* nil] (pr (str (str/join " " msgs) nl)) (flush))) (defn read-edn "Read the edn file from the specified `reader`. This file should contain a single edn value. Empty files return nil. The reader will be read to EOF and closed." [^Reader reader] (let [EOF (Object.)] (with-open [rdr (PushbackReader. reader)] (let [val (edn/read {:default tagged-literal :eof EOF} rdr)] (if (identical? EOF val) nil (if (not (identical? EOF (edn/read {:eof EOF} rdr))) (throw (ex-info "Invalid file, expected edn to contain a single value." {})) val)))))) (defn slurp-edn "Read the edn file specified by f, a string or File. An empty file will return nil." [f] (read-edn (FileReader. (jio/file f)))) (defn write-file "Write the string s to file f. Creates parent directories for f if they don't exist." [f s] (let [the-file (jio/file f) parent (.getParentFile the-file)] (when-not (.exists parent) (when-not (.mkdirs parent) (let [parent-name (.getCanonicalPath parent)] (throw (ex-info (str "Can't create directory: " parent-name) {:dir parent-name}))))) (spit the-file s))) (comment (slurp-edn "deps.edn") ) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/util/maven.clj000066400000000000000000000300441434474567100256360ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.util.maven (:require [clojure.java.io :as jio] [clojure.string :as str] [clojure.tools.deps.util.io :refer [printerrln]] clojure.tools.deps.util.s3-transporter) (:import ;; maven-resolver-api [org.eclipse.aether RepositorySystem RepositorySystemSession DefaultRepositoryCache DefaultRepositorySystemSession ConfigurationProperties] [org.eclipse.aether.artifact Artifact DefaultArtifact] [org.eclipse.aether.repository LocalRepository Proxy RemoteRepository RemoteRepository$Builder RepositoryPolicy] [org.eclipse.aether.graph Dependency Exclusion] [org.eclipse.aether.transfer TransferListener TransferEvent] ;; maven-resolver-spi [org.eclipse.aether.spi.connector RepositoryConnectorFactory] [org.eclipse.aether.spi.connector.transport TransporterFactory] [org.eclipse.aether.spi.locator ServiceLocator] ;; maven-resolver-impl [org.eclipse.aether.impl DefaultServiceLocator] ;; maven-resolver-connector-basic [org.eclipse.aether.connector.basic BasicRepositoryConnectorFactory] ;; maven-resolver-transport-file [org.eclipse.aether.transport.file FileTransporterFactory] ;; maven-resolver-transport-http [org.eclipse.aether.transport.http HttpTransporterFactory] ;; maven-aether-provider [org.apache.maven.repository.internal MavenRepositorySystemUtils] ;; maven-resolver-util [org.eclipse.aether.util.repository AuthenticationBuilder DefaultProxySelector DefaultMirrorSelector] ;; maven-core [org.apache.maven.settings DefaultMavenSettingsBuilder Settings Server Mirror] ;; maven-settings-builder [org.apache.maven.settings.building DefaultSettingsBuilderFactory] ;; plexus-utils [org.codehaus.plexus.util.xml Xpp3Dom] )) (set! *warn-on-reflection* true) ;; Remote repositories (def standard-repos {"central" {:url "https://repo1.maven.org/maven2/"} "clojars" {:url "https://repo.clojars.org/"}}) (defn- set-settings-builder [^DefaultMavenSettingsBuilder default-builder settings-builder] (doto (.. default-builder getClass (getDeclaredField "settingsBuilder")) (.setAccessible true) (.set default-builder settings-builder))) (defn get-settings ^Settings [] (.buildSettings (doto (DefaultMavenSettingsBuilder.) (set-settings-builder (.newInstance (DefaultSettingsBuilderFactory.)))))) (defn- select-mirror ^RemoteRepository [^Settings settings ^RemoteRepository repo] (let [mirrors (.getMirrors settings) selector (DefaultMirrorSelector.)] (run! (fn [^Mirror mirror] (.add selector (.getId mirror) (.getUrl mirror) (.getLayout mirror) false (.getMirrorOf mirror) (.getMirrorOfLayouts mirror))) mirrors) (.getMirror selector repo))) (defn- select-proxy ^Proxy [^Settings settings ^RemoteRepository repo] (->> (.getProxies settings) (keep (fn [^org.apache.maven.settings.Proxy proxy-setting] (when (.isActive proxy-setting) (.. (DefaultProxySelector.) (add (Proxy. (.getProtocol proxy-setting) (.getHost proxy-setting) (.getPort proxy-setting) (.. (AuthenticationBuilder.) (addUsername (.getUsername proxy-setting)) (addPassword (.getPassword proxy-setting)) build)) (.getNonProxyHosts proxy-setting)) (getProxy repo))))) first)) (defn- repo-policy "Converts repo policy map to RepositoryPolicy. :enabled - is enabled (default = true) :update - one of :daily (default), :always, :never, or an interval in minutes :checksum - one of :warn (default), :fail, :ignore" [name {:keys [enabled update checksum] :or {enabled true, update :daily, checksum :warn}}] (RepositoryPolicy. enabled (case update :daily RepositoryPolicy/UPDATE_POLICY_DAILY :always RepositoryPolicy/UPDATE_POLICY_ALWAYS :never RepositoryPolicy/UPDATE_POLICY_NEVER (str update)) (case checksum :warn RepositoryPolicy/CHECKSUM_POLICY_WARN :fail RepositoryPolicy/CHECKSUM_POLICY_FAIL :ignore RepositoryPolicy/CHECKSUM_POLICY_IGNORE (throw (ex-info (format "Invalid checksum policy: %s on repository: %s" checksum name) {:name name :enabled enabled :update update :checksum checksum}))))) (defn remote-repo (^RemoteRepository [repo-entry] (remote-repo repo-entry (get-settings))) (^RemoteRepository [[^String name {:keys [url snapshots releases] :as repo-config}] ^Settings settings] (let [builder (RemoteRepository$Builder. name "default" url) maybe-repo (.build builder) mirror (select-mirror settings maybe-repo) ^RemoteRepository remote-repo (or mirror maybe-repo) proxy (select-proxy settings remote-repo) server-id (.getId remote-repo) ^Server server-setting (->> (.getServers settings) (filter #(= server-id (.getId ^Server %))) first)] (-> (cond-> builder snapshots (.setSnapshotPolicy (repo-policy name snapshots)) releases (.setReleasePolicy (repo-policy name releases)) mirror (.setUrl (.getUrl mirror)) server-setting (.setAuthentication (-> (AuthenticationBuilder.) (.addUsername (.getUsername server-setting)) (.addPassword (.getPassword server-setting)) (.addPrivateKey (.getPrivateKey server-setting) (.getPassphrase server-setting)) (.build))) proxy (.setProxy proxy)) (.build)))) ) (defn remote-repos ([repos] (remote-repos repos (get-settings))) ([{:strs [central clojars] :as repos} ^Settings settings] ;; always return central, then clojars, then other repos (->> (concat [["central" central] ["clojars" clojars]] (dissoc repos "central" "clojars")) (remove (fn [[_name config]] (nil? config))) (mapv #(remote-repo % settings))))) ;; Local repository (defn ^:private local-repo-path "Helper to form the path to the default local repo - use `@cached-local-repo` for caching delayed value" [] (.getAbsolutePath (jio/file (System/getProperty "user.home") ".m2" "repository"))) (def default-local-repo "DEPRECATED - use `@cached-local-repo`" (local-repo-path)) (def cached-local-repo "Delayed default local repo lookup for ~/.m2/repository, access with `@cached-local-repo`" (delay (local-repo-path))) (defn make-local-repo ^LocalRepository [^String dir] (LocalRepository. dir)) ;; Maven system and session (defn make-locator ^ServiceLocator [] (let [^DefaultServiceLocator loc (doto (MavenRepositorySystemUtils/newServiceLocator) (.addService RepositoryConnectorFactory BasicRepositoryConnectorFactory) (.addService TransporterFactory FileTransporterFactory) (.addService TransporterFactory HttpTransporterFactory))] (try (let [c (Class/forName "clojure.tools.deps.util.S3TransporterFactory")] (.addService loc TransporterFactory c)) (catch ClassNotFoundException _ (printerrln "Warning: failed to load the S3TransporterFactory class") loc)))) (def the-locator (delay (make-locator))) (defn make-system (^RepositorySystem [] (make-system (make-locator))) (^RepositorySystem [^ServiceLocator locator] (.getService locator RepositorySystem))) (def ^TransferListener console-listener (reify TransferListener (transferStarted [_ event] (let [event ^TransferEvent event resource (.getResource event) name (.getResourceName resource) repo (.getRepositoryId resource)] (printerrln "Downloading:" name "from" repo))) (transferCorrupted [_ event] (printerrln "Download corrupted:" (.. ^TransferEvent event getException getMessage))) (transferFailed [_ event] ;; This happens when Maven can't find an artifact in a particular repo ;; (but still may find it in a different repo), ie this is a common event #_(printerrln "Download failed:" (.. ^TransferEvent event getException getMessage))) (transferInitiated [_ _event]) (transferProgressed [_ _event]) (transferSucceeded [_ _event]))) (defn add-server-config [^DefaultRepositorySystemSession session ^Server server] (when-let [^Xpp3Dom configuration (.getConfiguration server)] (when-let [^Xpp3Dom headers (.getChild configuration "httpHeaders")] (.setConfigProperty session (str ConfigurationProperties/HTTP_HEADERS "." (.getId server)) (into {} (keep (fn [^Xpp3Dom header] (let [name (.getChild header "name") value (.getChild header "value")] (when (and name value) [(.getValue name) (.getValue value)])))) (.getChildren headers "property")))))) (defn make-session (^RepositorySystemSession [^RepositorySystem system local-repo] ;; DEPRECATED (make-session system (get-settings) local-repo)) (^RepositorySystemSession [^RepositorySystem system ^Settings settings local-repo] (let [session (MavenRepositorySystemUtils/newSession) local-repo-mgr (.newLocalRepositoryManager system session (make-local-repo local-repo))] (.setLocalRepositoryManager session local-repo-mgr) (.setTransferListener session console-listener) (.setCache session (DefaultRepositoryCache.)) (doseq [^Server server (.getServers settings)] (add-server-config session server)) session))) (defn exclusions->data [exclusions] (when (and exclusions (pos? (count exclusions))) (into #{} (map (fn [^Exclusion exclusion] (symbol (.getGroupId exclusion) (.getArtifactId exclusion)))) exclusions))) (defn dep->data [^Dependency dep] (let [scope (.getScope dep) optional (.isOptional dep) exclusions (exclusions->data (.getExclusions dep)) ^Artifact artifact (.getArtifact dep) artifact-id (.getArtifactId artifact) classifier (.getClassifier artifact) ext (.getExtension artifact)] [(symbol (.getGroupId artifact) (if (str/blank? classifier) artifact-id (str artifact-id "$" classifier))) (cond-> {:mvn/version (.getVersion artifact)} (not= "jar" ext) (assoc :extension ext) scope (assoc :scope scope) optional (assoc :optional true) (seq exclusions) (assoc :exclusions exclusions))])) (defn lib->names "Split lib symbol into [group-id artifact-id classifier]" [lib] (let [[artifact-id classifier] (str/split (name lib) #"\$")] [(or (namespace lib) artifact-id) artifact-id classifier])) (defn coord->artifact ^Artifact [lib {:keys [mvn/version classifier extension] :or {extension "jar"} :as coord}] (when classifier (throw (ex-info (str "Invalid library spec:\n" (format " %s %s\n" lib (dissoc coord :deps/manifest)) ":classifier in Maven coordinates is no longer supported.\n" "Use groupId/artifactId$classifier in lib names instead.") {:lib lib, :coord coord}))) (let [[group-id artifact-id classifier] (lib->names lib) version (or version "LATEST") artifact (DefaultArtifact. group-id artifact-id classifier extension version)] artifact)) (defn version-range? [version] (boolean (when version (re-find #"\[|\(" version)))) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/util/s3_aws_client.clj000066400000000000000000000030601434474567100272630ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.util.s3-aws-client (:require [cognitect.aws.client.api :as aws] [cognitect.aws.credentials :as creds])) (defn- aws-creds-provider [user pw] (reify creds/CredentialsProvider (fetch [_] {:aws/access-key-id user :aws/secret-access-key pw}))) (defn- get-bucket-loc [config bucket] (let [s3-client (aws/client (merge {:region "us-east-1"} config)) resp (try (aws/invoke s3-client {:op :GetBucketLocation :request {:Bucket bucket}}) (catch Throwable _ nil)) region (:LocationConstraint resp)] (cond (nil? region) nil (= region "") "us-east-1" :else region))) (defn new-s3-client [user pw region bucket] (let [cred-provider (when (and user pw) (aws-creds-provider user pw)) config (cond-> {:api :s3} cred-provider (assoc :credentials-provider cred-provider)) use-region (or region (get-bucket-loc config bucket) "us-east-1")] (aws/client (assoc config :region use-region))))tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/util/s3_transporter.clj000066400000000000000000000152761434474567100275320ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.util.s3-transporter (:refer-clojure :exclude [peek get]) (:require [clojure.string :as str]) (:import [java.io InputStream OutputStream IOException] [java.net URI] [java.nio ByteBuffer] [org.eclipse.aether RepositorySystemSession] [org.eclipse.aether.repository RemoteRepository AuthenticationContext] [org.eclipse.aether.spi.connector.transport Transporter PeekTask GetTask])) (set! *warn-on-reflection* true) (defn s3-peek "Returns nil if path exists, anomaly category otherwise" [s3-client bucket path] (let [s3-response ((requiring-resolve 'cognitect.aws.client.api/invoke) s3-client {:op :HeadObject, :request {:Bucket bucket, :Key path}})] (:cognitect.anomalies/category s3-response))) (defn stream-copy [^OutputStream os ^InputStream is ^long offset on-read] (let [bb (ByteBuffer/allocate 32768) ba (.array bb)] (when (pos? offset) (let [skipped (.skip is offset)] (when-not (= skipped offset) (throw (IOException. (str "Failed skipping " offset ", only skipped " skipped)))))) (try (loop [] (let [read (.read is ba)] (when (<= 0 read) (.write os ba 0 read) (.rewind bb) (.limit bb read) (on-read bb) (recur)))) (finally (.close is) (.close os))))) (defn s3-get-object [s3-client bucket path ^OutputStream output-stream offset on-read] (let [s3-response ((requiring-resolve 'cognitect.aws.client.api/invoke) s3-client {:op :GetObject, :request {:Bucket bucket, :Key path}}) is ^InputStream (:Body s3-response)] (if is (stream-copy output-stream is offset on-read) (let [{:keys [cognitect.anomalies/category cognitect.http-client/throwable cognitect.anomalies/message]} s3-response] (if (#{:cognitect.anomalies/forbidden :cognitect.anomalies/not-found} category) (throw (ex-info "Artifact not found" {:bucket bucket, :path path, :reason category})) (throw (ex-info (format "Unexpected error downloading artifact from %s" bucket) {:bucket bucket, :path path, :reason category} throwable))))))) ;; s3://BUCKET/PATH?region=us-east-1 (defn parse-url [^RemoteRepository repo] (let [u (URI/create (.getUrl repo)) host (.getHost u) path (str/join "/" (remove str/blank? (str/split (.getPath u) #"/"))) query (.getQuery u) kvs (when query (str/split query #"&")) {:strs [region]} (reduce (fn [m kv] (let [[k v] (str/split kv #"=")] (assoc m k v))) {} kvs)] {:bucket host, :region region, :repo-path path})) (let [lock (Object.)] (defn- dynaload-s3-client [client-atom user pw region bucket] (locking lock (require 'clojure.tools.deps.util.s3-aws-client)) (let [f (requiring-resolve 'clojure.tools.deps.util.s3-aws-client/new-s3-client)] (swap! client-atom #(if % % (f user pw region bucket))) @client-atom))) (defn new-transporter [^RepositorySystemSession session ^RemoteRepository repository] (let [auth-context (AuthenticationContext/forRepository session repository) user (when auth-context (.get auth-context AuthenticationContext/USERNAME)) pw (when auth-context (.get auth-context AuthenticationContext/PASSWORD)) on-close #(when auth-context (.close auth-context)) {:keys [bucket region repo-path]} (parse-url repository) s3-client-holder (atom nil)] ;; defer creation till needed (reify Transporter (^void peek [_ ^PeekTask peek-task] (let [path (.. peek-task getLocation toString) full-path (str repo-path "/" path) s3-client (dynaload-s3-client s3-client-holder user pw region bucket) res (s3-peek s3-client bucket full-path)] (when res (throw (ex-info "Artifact not found" {:bucket bucket, :path path, :reason res}))))) (^void get [_ ^GetTask get-task] (let [path (.. get-task getLocation toString) full-path (str repo-path "/" path) offset (.getResumeOffset get-task) os (.newOutputStream get-task (> offset 0)) listener (.getListener get-task) s3-client (dynaload-s3-client s3-client-holder user pw region bucket)] (.transportStarted listener offset -1) (s3-get-object s3-client bucket full-path os offset #(.transportProgressed listener %)))) (classify [_ throwable] (if (#{:cognitect.anomalies/forbidden :cognitect.anomalies/not-found} (-> throwable ex-data :reason)) Transporter/ERROR_NOT_FOUND Transporter/ERROR_OTHER)) ;;(put [_ ^PutTask put-task]) ;; not supported (close [_] (when on-close (on-close)))))) (comment (require '[cognitect.aws.client.api :as aws] 'clojure.repl) ;; use ambient creds (def s3-client (aws/client {:api :s3 :region :us-east-1})) (def resp (aws/invoke s3-client {:op :GetObject :request {:Bucket "datomic-releases-1fc2183a" :Key "maven/releases/com/datomic/ion/0.9.35/ion-0.9.35.pom"}})) (aws/invoke s3-client {:op :GetBucketLocation :request {:Bucket "datomic-releases-1fc2183a"}}) (aws/invoke s3-client {:op :GetObject :request {:Bucket "datomic-releases-1fc2183a" :Key "/maven/releases/com/datomic/ion/0.9.35/ion-0.9.35.pom"}}) (s3-peek s3-client "datomic-releases-1fc2183a" "/maven/releases/com/datomic/ion/0.9.35/ion-0.9.35.pom") (with-open [os (java.io.FileOutputStream. "download.pom")] (s3-get-object s3-client "datomic-releases-1fc2183a" "/maven/releases/com/datomic/ion/0.9.35/ion-0.9.35.pom" os 0 #(println "read data" %))) (def ann (s3-peek s3-client "datomic-releases-1fc2183a" "/maven/releases/com/datomic/ion/0.9.35/ion-0.9.35.foo")) (aws/ops s3-client) (aws/invoke s3-client {:op :GetBucketAcl, :request {:Bucket "datomic-releases-1fc2183a"}}) (aws/validate-requests s3-client true) (aws/request-spec-key s3-client :GetObject) (clojure.repl/doc :cognitect.aws.s3/GetObjectRequest) (aws/doc s3-client :cognitect.aws.s3/GetBucketLocation) (clojure.repl/doc aws/request-spec-key) ) tools.deps-0.16.1264/src/main/clojure/clojure/tools/deps/util/session.clj000066400000000000000000000032451434474567100262160ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns ^{:skip-wiki true} clojure.tools.deps.util.session "Maintains session resources during or across runs of the resolver" (:import [java.util.concurrent ConcurrentMap ConcurrentHashMap] [java.util.function Function])) (def session (ConcurrentHashMap.)) ;; should never be nil (defn retrieve "Read the current value of key from the session. If absent, and if-absent-fn is supplied, invoke the fn, set it in the session (if there is one), and return the value." ([key] (.get ^ConcurrentMap session key)) ([key if-absent-fn] (.computeIfAbsent ^ConcurrentMap session key (reify Function (apply [_f _k] (if-absent-fn)))))) (defn retrieve-local "Like retrieve, but scoped to a thread-specific key, so never shared across threads." ([key] (retrieve {:thread (.getId (Thread/currentThread)) :key key})) ([key if-absent-fn] (retrieve {:thread (.getId (Thread/currentThread)) :key key} if-absent-fn))) (defmacro with-session "Create a new empty session and execute the body" [& body] `(let [prior# session] (alter-var-root #'session (constantly (ConcurrentHashMap.))) (try ~@body (finally (alter-var-root #'session (constantly prior#)))))) tools.deps-0.16.1264/src/main/java/000077500000000000000000000000001434474567100166005ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/java/clojure/000077500000000000000000000000001434474567100202435ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/java/clojure/tools/000077500000000000000000000000001434474567100214035ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/java/clojure/tools/deps/000077500000000000000000000000001434474567100223365ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/java/clojure/tools/deps/util/000077500000000000000000000000001434474567100233135ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/java/clojure/tools/deps/util/S3TransporterFactory.java000066400000000000000000000040601434474567100302370ustar00rootroot00000000000000/* * Copyright (c) Rich Hickey. All rights reserved. * The use and distribution terms for this software are covered by the * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) * which can be found in the file epl-v10.html at the root of this distribution. * By using this software in any fashion, you are agreeing to be bound by * the terms of this license. * You must not remove this notice, or any other, from this software. */ package clojure.tools.deps.util; import javax.inject.Named; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.spi.connector.transport.Transporter; import org.eclipse.aether.spi.connector.transport.TransporterFactory; import org.eclipse.aether.spi.locator.Service; import org.eclipse.aether.spi.locator.ServiceLocator; import clojure.java.api.Clojure; import clojure.lang.IFn; import org.eclipse.aether.transfer.NoTransporterException; /** * Transporter factory for repositories using the s3 protocol. */ @Named("s3") public final class S3TransporterFactory implements TransporterFactory, Service { private static class DelayedInstance { private static final IFn NEW_TRANSPORTER; static { IFn REQUIRE = Clojure.var("clojure.core", "require"); REQUIRE.invoke(Clojure.read("clojure.tools.deps.util.s3-transporter")); NEW_TRANSPORTER = Clojure.var("clojure.tools.deps.util.s3-transporter", "new-transporter"); } } private S3TransporterFactory() {} public void initService(ServiceLocator locator) { } public Transporter newInstance(RepositorySystemSession session, RemoteRepository repository) throws NoTransporterException { String protocol = repository.getProtocol(); if("s3".equals(protocol)) { return (Transporter) DelayedInstance.NEW_TRANSPORTER.invoke(session, repository); } else { throw new NoTransporterException(repository); } } public float getPriority() { return 5.0f; } } tools.deps-0.16.1264/src/main/resources/000077500000000000000000000000001434474567100176715ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/resources/clojure/000077500000000000000000000000001434474567100213345ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/resources/clojure/tools/000077500000000000000000000000001434474567100224745ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/resources/clojure/tools/deps/000077500000000000000000000000001434474567100234275ustar00rootroot00000000000000tools.deps-0.16.1264/src/main/resources/clojure/tools/deps/deps.edn000066400000000000000000000007341434474567100250560ustar00rootroot00000000000000{ :paths ["src"] :deps { org.clojure/clojure {:mvn/version "1.11.1"} } :aliases { :deps {:replace-paths [] :replace-deps {org.clojure/tools.deps.cli {:mvn/version "0.9.10"}} :ns-default clojure.tools.deps.cli.api :ns-aliases {help clojure.tools.deps.cli.help}} :test {:extra-paths ["test"]} } :mvn/repos { "central" {:url "https://repo1.maven.org/maven2/"} "clojars" {:url "https://repo.clojars.org/"} } } tools.deps-0.16.1264/src/main/resources/clojure/tools/deps/license-abbrev.edn000066400000000000000000000026151434474567100270040ustar00rootroot00000000000000;; Map of "name found in the wild" => abbreviated name ;; not exhaustive, just trying to catch 80% ;; useful resource: https://github.com/spdx/license-list-data {"3-Clause BSD License" "BSD-3-Clause-Attribution" "Apache 2.0" "Apache-2.0" "Apache License 2.0" "Apache-2.0" "Apache License Version 2.0" "Apache-2.0" "Apache License, Version 2.0" "Apache-2.0" "Apache Software License - Version 2.0" "Apache-2.0" "Apache v2" "Apache-2.0" "BSD 3-Clause License" "BSD-3-Clause-Attribution" "Eclipse Public License" "EPL-1.0" "Eclipse Public License (EPL)" "EPL-1.0" "Eclipse Public License - v 1.0" "EPL-1.0" "Eclipse Public License 1.0" "EPL-1.0" "Eclipse Public License, Version 1.0" "EPL-1.0" "Eclipse Public License 2.0" "EPL-2.0" "Eclipse Public License version 2" "EPL-2.0" "GNU Affero General Public License (AGPL) version 3.0" "AGPL-3.0" "GNU General Public License, version 2 (GPL2), with the classpath exception" "GPL-2.0-with-classpath-exception" "GNU General Public License, version 2 with the GNU Classpath Exception" "GPL-2.0-with-classpath-exception" "GNU General Public License, version 2" "GPL-2.0" "GNU Lesser General Public License (LGPL)" "LGPL" "JSON License" "JSON" "MIT License" "MIT" "MIT license" "MIT" "Mozilla Public License" "MPL" "The Apache Software License, Version 2.0" "Apache-2.0" "The BSD 3-Clause License (BSD3)" "BSD-3-Clause-Attribution" "The MIT License" "MIT"}tools.deps-0.16.1264/src/test/000077500000000000000000000000001434474567100157125ustar00rootroot00000000000000tools.deps-0.16.1264/src/test/clojure/000077500000000000000000000000001434474567100173555ustar00rootroot00000000000000tools.deps-0.16.1264/src/test/clojure/clojure/000077500000000000000000000000001434474567100210205ustar00rootroot00000000000000tools.deps-0.16.1264/src/test/clojure/clojure/tools/000077500000000000000000000000001434474567100221605ustar00rootroot00000000000000tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/000077500000000000000000000000001434474567100231135ustar00rootroot00000000000000tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/extensions/000077500000000000000000000000001434474567100253125ustar00rootroot00000000000000tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/extensions/faken.clj000066400000000000000000000042771434474567100271020ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns clojure.tools.deps.extensions.faken (:require [clojure.string :as str] [clojure.tools.deps.extensions :as ext]) (:import ;; maven-resolver-util [org.eclipse.aether.util.version GenericVersionScheme])) ;; Fake Maven extension for testing dependency resolution ;; Use the functions to construct a faux Maven repo ;; {lib {coord [dep1 ...]}} (def ^:dynamic repo {}) (defmacro with-libs [libs & body] `(binding [repo ~libs] ~@body)) (defmethod ext/coord-type-keys :fkn [_type] #{:fkn/version}) (defmethod ext/dep-id :fkn [_lib coord _config] (select-keys coord [:fkn/version])) (defmethod ext/manifest-type :fkn [_lib _coord _config] {:deps/manifest :fkn}) (defonce ^:private version-scheme (GenericVersionScheme.)) (defn- parse-version [{version :fkn/version :as _coord}] (.parseVersion ^GenericVersionScheme version-scheme ^String version)) (defmethod ext/compare-versions [:fkn :fkn] [_lib coord-x coord-y _config] (apply compare (map parse-version [coord-x coord-y]))) (defmethod ext/coord-deps :fkn [lib coord _manifest config] (remove (fn [[lib {:keys [optional]}]] optional) (get-in repo [lib (ext/dep-id lib coord config)]))) (defn make-path [lib {:keys [fkn/version]}] (let [[n c] (str/split (name lib) #"\$")] (str "REPO/" (namespace lib) "/" n "/" version "/" n (if c (str "-" c) "") "-" version ".jar"))) (defmethod ext/coord-paths :fkn [lib coord _manifest _config] [(make-path lib coord)]) (defmethod ext/find-versions :fkn [_lib _coord _type _config] nil) (comment (with-libs {'a/a {{:fkn/version "0.1.2"} [['b/b {:fkn/version "1.2.3"}]]} 'b/b {{:fkn/version "1.2.3"} nil}} (ext/coord-deps 'a/a {:fkn/version "0.1.2"} :fkn nil)) )tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/extensions/test_git.clj000066400000000000000000000107421434474567100276320ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns clojure.tools.deps.extensions.test-git (:require [clojure.test :refer [deftest is are]] [clojure.tools.deps.extensions :as ext] [clojure.tools.deps.extensions.git :as git]) (:import [clojure.lang ExceptionInfo])) (deftest auto-git-url (are [url lib] (= url (git/auto-git-url lib)) "https://github.com/clojure/tools.deps.git" 'io.github.clojure/tools.deps "https://github.com/clojure/tools.deps.git" 'com.github.clojure/tools.deps "https://gitlab.com/clojure/tools.deps.git" 'io.gitlab.clojure/tools.deps "https://gitlab.com/clojure/tools.deps.git" 'com.gitlab.clojure/tools.deps "https://bitbucket.org/clojure/tools.deps.git" 'io.bitbucket.clojure/tools.deps "https://bitbucket.org/clojure/tools.deps.git" 'org.bitbucket.clojure/tools.deps "https://git.sr.ht/~foo/bar" 'ht.sr.foo/bar)) (deftest full-sha (is (true? (git/full-sha? "f7443aa3ad854d5ab351f7ea327d6b161c5f3850"))) (is (false? (git/full-sha? "f7443aa")))) (deftest canonicalize ;; infer url (is (= ['io.github.clojure/tools.deps {:git/url "https://github.com/clojure/tools.deps.git" :git/sha "9bf5778dc26dd5018dbf04fc8e7dbb32ddc4036c"}] (ext/canonicalize 'io.github.clojure/tools.deps {:git/sha "9bf5778dc26dd5018dbf04fc8e7dbb32ddc4036c"} {}))) ;; standardize sha (is (= ['io.github.clojure/tools.deps {:git/url "https://github.com/clojure/tools.deps.git" :git/sha "9bf5778dc26dd5018dbf04fc8e7dbb32ddc4036c"}] (ext/canonicalize 'io.github.clojure/tools.deps {:sha "9bf5778dc26dd5018dbf04fc8e7dbb32ddc4036c"} {}))) ;; standardize sha/tag (is (= ['io.github.clojure/tools.deps {:git/url "https://github.com/clojure/tools.deps.git" :git/sha "c2a3bbe9df5f574c8af17f07d18b75198194d26e" :git/tag "tools.deps.alpha-0.5.317"}] (ext/canonicalize 'io.github.clojure/tools.deps {:sha "c2a3bbe" :tag "tools.deps.alpha-0.5.317"} {})))) (deftest canonicalize-errors ;; unknown coord type (is (thrown-with-msg? ExceptionInfo #"Coord of unknown type" (ext/canonicalize 'io.github.clojure/tools.deps {} {}))) ;; can't infer :git/url and none specified (is (thrown-with-msg? ExceptionInfo #"Failed to infer git url for: org.clojure/tools.deps" (ext/canonicalize 'org.clojure/tools.deps {:git/sha "9bf5778dc26dd5018dbf04fc8e7dbb32ddc4036c"} {}))) ;; both :sha and :git/sha (is (thrown-with-msg? ExceptionInfo #"git coord has both :sha and :git/sha for io.github.clojure/tools.deps" (ext/canonicalize 'io.github.clojure/tools.deps {:sha "9bf5778dc26dd5018dbf04fc8e7dbb32ddc4036c" :git/sha "9bf5778dc26dd5018dbf04fc8e7dbb32ddc4036c"} {}))) ;; lib must be qualified (is (thrown-with-msg? ExceptionInfo #"Invalid lib name: tools.deps" (ext/canonicalize 'tools.deps {:git/url "https://github.com/clojure/tools.deps.git"} {}))) ;; require full sha if no tag (is (thrown-with-msg? ExceptionInfo #"Library io.github.clojure/tools.deps has prefix sha, use full sha or add tag" (ext/canonicalize 'io.github.clojure/tools.deps {:git/sha "9bf5778"} {}))) ;; require at least prefix sha with tag (is (thrown-with-msg? ExceptionInfo #"Library io.github.clojure/tools.deps has coord with missing sha" (ext/canonicalize 'io.github.clojure/tools.deps {:git/tag "tools.deps.alpha-0.5.317"} {}))) ;; sha/tag must point to same commit (is (thrown-with-msg? ExceptionInfo #"Library io.github.clojure/tools.deps has sha and tag that point to different commits" (ext/canonicalize 'io.github.clojure/tools.deps {:git/tag "tools.deps.alpha-0.5.317" :git/sha "9bf5778"} {}))) ;; tag must be a tag (is (thrown-with-msg? ExceptionInfo #"Library io.github.clojure/tools.deps has invalid tag" (ext/canonicalize 'io.github.clojure/tools.deps {:git/tag "9bf5778" :git/sha "9bf5778"} {}))) ) (comment (canonicalize) )tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/gen/000077500000000000000000000000001434474567100236645ustar00rootroot00000000000000tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/gen/test_pom.clj000066400000000000000000000037351434474567100262200ustar00rootroot00000000000000(ns clojure.tools.deps.gen.test-pom (:require [clojure.test :refer [deftest is]] [clojure.java.io :as jio] [clojure.string :as str] [clojure.tools.deps.gen.pom :as gen-pom] [clojure.tools.deps :as deps]) (:import [java.io File])) ;; simple check that pom gen is working - gen a pom.xml from tda's deps.edn (deftest test-pom-gen (let [temp-dir (.getParentFile (File/createTempFile "dummy" nil)) pom (jio/file temp-dir "pom.xml") {:keys [root-edn user-edn project-edn]} (deps/find-edn-maps) master-edn (deps/merge-edns [root-edn user-edn project-edn])] (.delete pom) (gen-pom/sync-pom master-edn temp-dir) (is (.exists pom)) (is (not (str/blank? (slurp pom)))))) ;; check that optional deps are marked optional (deftest test-optional (let [temp-dir (.getParentFile (File/createTempFile "dummy" nil)) pom (jio/file temp-dir "pom.xml")] (.delete pom) (gen-pom/sync-pom '{:deps {org.clojure/core.async {:mvn/version "1.1.587" :optional true}}} temp-dir) (is (.exists pom)) (let [generated (slurp pom)] (is (str/includes? generated "core.async")) (is (str/includes? generated "true"))))) (deftest test-add-src-dir (let [temp-dir (.getParentFile (File/createTempFile "dummy" nil)) pom (jio/file temp-dir "pom.xml")] (.delete pom) (spit pom "\n\n 4.0.0\n foo\n foo\n 0.1.0\n foo\n") (gen-pom/sync-pom (deps/root-deps) temp-dir) (let [new-pom (slurp pom)] (is (str/includes? new-pom "")) (is (str/includes? new-pom "src"))))) tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/script/000077500000000000000000000000001434474567100244175ustar00rootroot00000000000000tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/script/test_make_classpath2.clj000066400000000000000000000276531434474567100312260ustar00rootroot00000000000000(ns clojure.tools.deps.script.test-make-classpath2 (:require [clojure.test :refer [deftest is]] [clojure.tools.deps.script.make-classpath2 :as mc] [clojure.java.io :as jio])) (def install-data {:paths ["src"] :deps {'org.clojure/clojure {:mvn/version "1.10.1"}} :aliases {:test {:extra-paths ["test"]}} :mvn/repos {"central" {:url "https://repo1.maven.org/maven2/"} "clojars" {:url "https://repo.clojars.org/"}}}) (defn submap? "Is m1 a subset of m2?" [m1 m2] (if (and (map? m1) (map? m2)) (every? (fn [[k v]] (and (contains? m2 k) (submap? v (get m2 k)))) m1) (= m1 m2))) (deftest outside-project (let [basis (mc/run-core {:install-deps install-data})] (is (submap? {:libs {'org.clojure/clojure {:mvn/version "1.10.1"} 'org.clojure/spec.alpha {:mvn/version "0.2.176"} 'org.clojure/core.specs.alpha {:mvn/version "0.2.44"}}} basis)))) (deftest in-project (let [basis (mc/run-core {:install-deps install-data :project-deps {:deps {'org.clojure/clojure {:mvn/version "1.9.0"}}}})] (is (submap? {:libs {'org.clojure/clojure {:mvn/version "1.9.0"} 'org.clojure/spec.alpha {:mvn/version "0.1.143"} 'org.clojure/core.specs.alpha {:mvn/version "0.1.24"}}} basis)))) ;; alias :e with :extra-deps extends the project deps (deftest extra-deps (let [basis (mc/run-core {:install-deps install-data :project-deps {:deps {'org.clojure/clojure {:mvn/version "1.9.0"}} :aliases {:e {:extra-deps {'org.clojure/test.check {:mvn/version "0.9.0"}}}}} :repl-aliases [:e]})] (is (submap? {:resolve-args {:extra-deps {'org.clojure/test.check {:mvn/version "0.9.0"}}} :libs {'org.clojure/clojure {:mvn/version "1.9.0"} 'org.clojure/spec.alpha {:mvn/version "0.1.143"} 'org.clojure/core.specs.alpha {:mvn/version "0.1.24"} 'org.clojure/test.check {:mvn/version "0.9.0"}}} basis)))) ;; alias :t with :replace-deps replaces the project deps (deftest tool-deps (doseq [k [:deps :replace-deps]] ;; FUTURE - remove :deps here (will warn for now) (let [basis (mc/run-core {:install-deps install-data :project-deps {:deps {'org.clojure/clojure {:mvn/version "1.9.0"}} :aliases {:t {k {'org.clojure/test.check {:mvn/version "0.9.0"}}}}} :repl-aliases [:t]})] (is (submap? {:paths ["src"] :deps {'org.clojure/test.check {:mvn/version "0.9.0"}} :libs {'org.clojure/clojure {:mvn/version "1.10.1"} 'org.clojure/spec.alpha {:mvn/version "0.2.176"} 'org.clojure/core.specs.alpha {:mvn/version "0.2.44"} 'org.clojure/test.check {:mvn/version "0.9.0"}}} basis))))) ;; alias :o with :override-deps overrides the version to use (deftest override-deps (let [basis (mc/run-core {:install-deps install-data :project-deps {:aliases {:o {:override-deps {'org.clojure/clojure {:mvn/version "1.6.0"}}}}} :repl-aliases [:o]})] (is (submap? {:resolve-args {:override-deps {'org.clojure/clojure {:mvn/version "1.6.0"}}} :libs {'org.clojure/clojure {:mvn/version "1.6.0"}}} basis)))) (defn select-cp [classpath key] (->> classpath (filter #(contains? (val %) key)) (apply conj {}))) ;; paths and deps in alias replace (deftest alias-paths-and-deps (doseq [p [:paths :replace-paths] ;; FUTURE - remove :paths, :deps here (will warn for now) d [:deps :replace-deps]] (let [basis (mc/run-core {:install-deps install-data :project-deps {:paths ["a" "b"] :aliases {:q {p ["a" "c"] d {'org.clojure/clojure {:mvn/version "1.6.0"}}}}} :repl-aliases [:q]})] (is (submap? {:paths ["a" "c"] :deps {'org.clojure/clojure {:mvn/version "1.6.0"}}} basis)) (is (= #{"a" "c"} (-> basis :classpath (select-cp :path-key) keys set)))))) ;; paths replace in chain (deftest paths-replace (let [basis (mc/run-core {:install-deps install-data :user-deps {:paths ["x"]} :project-deps {:paths ["y"]} :config-data {:paths ["z"]}})] (is (submap? {:paths ["z"]} basis)) (is (= #{"z"} (-> basis :classpath (select-cp :path-key) keys set))))) ;; :paths in alias replaces, multiple alias :paths will be combined (deftest alias-paths-replace (doseq [p [:paths :replace-paths]] ;; FUTURE - remove :paths here (will warn for now) (let [basis (mc/run-core {:install-deps install-data :user-deps {:aliases {:p {p ["x" "y"]}}} :project-deps {:aliases {:q {p ["z"]}}} :repl-aliases [:p :q]})] (is (submap? {:paths ["x" "y" "z"]} basis)) (is (= #{"x" "y" "z"} (-> basis :classpath (select-cp :path-key) keys set)))))) ;; :extra-paths add (deftest extra-paths-add (let [basis (mc/run-core {:install-deps install-data :user-deps {:aliases {:p {:extra-paths ["x" "y"]}}} :project-deps {:aliases {:q {:extra-paths ["z"]}}} :repl-aliases [:p :q]})] (is (submap? {:paths ["src"] :classpath-args {:extra-paths ["x" "y" "z"]}} basis)) (is (= #{"src" "x" "y" "z"} (-> basis :classpath (select-cp :path-key) keys set))))) ;; java opts in aliases are additive (deftest jvm-opts-add (let [basis (mc/run-core {:install-deps install-data :user-deps {:aliases {:j1 {:jvm-opts ["-server" "-Xms100m"]}}} :project-deps {:aliases {:j2 {:jvm-opts ["-Xmx200m"]}}} :repl-aliases [:j1 :j2]})] (is (= ["-server" "-Xms100m" "-Xmx200m"] (:jvm basis))))) ;; main opts replace (deftest main-opts-replace (let [basis (mc/run-core {:install-deps install-data :user-deps {:aliases {:m1 {:main-opts ["a" "b"]}}} :project-deps {:aliases {:m2 {:main-opts ["c"]}}} :repl-aliases [:m1 :m2]})] (is (= ["c"] (:main basis))))) ;; local manifests returned (deftest manifest-local (let [basis (mc/run-core {:install-deps install-data :project-deps {:deps {'io.github.clojure/data.json {:git/sha "f367490" :git/tag "v2.4.0"} 'io.github.clojure/data.codec {:git/sha "8ef09db", :git/tag "data.codec-0.1.1", :deps/manifest :pom}}}})] ;; returns a manifest for both projects (deps.edn and pom.xml respectively) (is (= 2 (count (:manifests basis)))))) ;; repositories should be retained for generate-manifest2's use (deftest repo-config-retained (let [basis (mc/run-core {:install-deps install-data})] ;; install-data has central and clojars (is (= #{"central" "clojars"} (-> basis :mvn/repos keys set))))) ;; skip-cp flag prevents resolve-deps/make-classpath (deftest skip-cp-flag (let [basis (mc/run-core {:install-deps install-data :project-deps {:deps {'org.clojure/clojure {:mvn/version "1.10.0"}}} :skip-cp true})] (is (nil? basis)))) ;; skip-cp flag still passes exec-args for -X or -T (deftest skip-cp-exec (let [basis (mc/run-core {:install-deps install-data :project-deps {:deps {'org.clojure/clojure {:mvn/version "1.10.0"}} :aliases {:x {:exec-fn 'clojure.core/prn :exec-args {:a 1}}}} :exec-aliases [:x] :skip-cp true})] (is (= {:execute-args {:exec-fn 'clojure.core/prn :exec-args {:a 1}}} basis)))) (deftest removing-deps (let [basis (mc/run-core {:install-deps install-data :user-deps {:aliases {:remove-clojure {:classpath-overrides '{org.clojure/clojure nil org.clojure/spec.alpha nil org.clojure/core.specs.alpha nil}}}} :repl-aliases [:remove-clojure]})] (is (= 3 (count (:libs basis)))) ;; lib set is not changed by classpath-overrides (is (= ["src"] (:classpath-roots basis))) (is (= {"src" {:path-key :paths}} (:classpath basis))))) (deftest tool-alias (let [{:keys [libs classpath-roots classpath]} (mc/run-core {:install-deps install-data :user-deps {:aliases {:t {:extra-deps {'org.clojure/data.json {:mvn/version "2.0.1"}}}}} :project-deps {:deps {'cheshire/cheshire {:mvn/version "5.10.0"}}} :tool-aliases [:t] :tool-mode true}) paths (filter #(get-in classpath [% :path-key]) classpath-roots)] ;; includes tool dep and not project deps (is (contains? libs 'org.clojure/data.json)) (is (not (contains? libs 'cheshire/cheshire))) ;; paths only contains project root dir (is (= 1 (count paths))) (is (= (.getCanonicalPath (jio/file (first paths))) (.getCanonicalPath (jio/file ".")))))) ;; clj -T a/fn (deftest tool-bare (let [{:keys [libs classpath-roots classpath resolved-function]} (mc/run-core {:install-deps install-data :user-deps {} :project-deps {:deps {'cheshire/cheshire {:mvn/version "5.10.0"}}} :tool-mode true}) paths (filter #(get-in classpath [% :path-key]) classpath-roots)] (is (not (contains? libs 'cheshire/cheshire))) (is (= 1 (count paths))) (is (= (.getCanonicalPath (jio/file (first paths))) (.getCanonicalPath (jio/file ".")))))) ;; clj -Tfoo (deftest tool-by-name (let [{:keys [libs classpath-roots classpath execute-args]} (mc/run-core {:install-deps install-data :user-deps {} :project-deps {:deps {'cheshire/cheshire {:mvn/version "5.10.0"}}} :tool-mode true :tool-name "foo" :tool-resolver {"foo" {:replace-deps {'org.clojure/data.json {:mvn/version "2.0.1"}} :replace-paths ["."] :ns-default 'a.b}}}) paths (filter #(get-in classpath [% :path-key]) classpath-roots)] ;; execute-args in basis (is (= {:ns-default 'a.b} execute-args)) ;; tool deps, not project deps (is (not (contains? libs 'cheshire/cheshire))) (is (contains? libs 'org.clojure/data.json)) ;; ., not project paths (is (= (map #(.getCanonicalPath (jio/file %)) ["."]) (map #(.getCanonicalPath (jio/file %)) paths))))) ;; clj -T:a:b (deftest tool-with-aliases (let [{:keys [libs classpath-roots classpath]} (mc/run-core {:install-deps install-data :user-deps {} :project-deps {:deps {'cheshire/cheshire {:mvn/version "5.10.0"}} :aliases {:a {:replace-paths ["x"]} :b {:replace-paths ["y"]}}} :tool-mode true :tool-aliases [:a :b]}) paths (filter #(get-in classpath [% :path-key]) classpath-roots)] ;; tool deps, not project deps (is (not (contains? libs 'cheshire/cheshire))) (is (= (map #(.getCanonicalPath (jio/file %)) ["x" "y" "."]) (map #(.getCanonicalPath (jio/file %)) paths))))) (comment (clojure.test/run-tests) ) tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/test_deps.clj000066400000000000000000000471331434474567100256070ustar00rootroot00000000000000(ns clojure.tools.deps.test-deps (:require [clojure.java.io :as jio] [clojure.test :refer [deftest is are testing]] [clojure.tools.deps :as deps] [clojure.tools.deps.extensions :as ext] [clojure.tools.deps.extensions.faken :as fkn] [clojure.tools.deps.util.dir :as dir] [clojure.tools.deps.util.maven :as mvn]) (:import [java.io File])) (deftest test-slurp-deps-on-nonexistent-file (is (nil? (deps/slurp-deps (File. "NONEXISTENT_FILE"))))) (deftest test-merge-or-replace (are [vals ret] (= ret (apply #'deps/merge-or-replace vals)) [nil nil] nil [nil {:a 1}] {:a 1} [{:a 1} nil] {:a 1} [{:a 1 :b 1} {:a 2 :c 3} {:c 4 :d 5}] {:a 2 :b 1 :c 4 :d 5} [nil 1] 1 [1 nil] 1 [1 2] 2)) (deftest test-merge-edns (is (= (deps/merge-edns [{:deps {'a {:v 1}, 'b {:v 1}} :a/x {:a 1} :a/y "abc"} {:deps {'b {:v 2}, 'c {:v 3}} :a/x {:b 1} :a/y "def"} nil]) {:deps {'a {:v 1}, 'b {:v 2}, 'c {:v 3}} :a/x {:a 1, :b 1} :a/y "def"}))) (deftest merge-alias-maps (are [m1 m2 out] (= out (#'deps/merge-alias-maps m1 m2)) {} {} {} {} {:extra-deps {:a 1}} {:extra-deps {:a 1}} {:extra-deps {:a 1 :b 1}} {:extra-deps {:b 2}} {:extra-deps {:a 1 :b 2}} {} {:default-deps {:a 1}} {:default-deps {:a 1}} {:default-deps {:a 1 :b 1}} {:default-deps {:b 2}} {:default-deps {:a 1 :b 2}} {} {:override-deps {:a 1}} {:override-deps {:a 1}} {:override-deps {:a 1 :b 1}} {:override-deps {:b 2}} {:override-deps {:a 1 :b 2}} {} {:extra-paths ["a" "b"]} {:extra-paths ["a" "b"]} {:extra-paths ["a" "b"]} {:extra-paths ["c" "d"]} {:extra-paths ["a" "b" "c" "d"]} {} {:jvm-opts ["-Xms100m" "-Xmx200m"]} {:jvm-opts ["-Xms100m" "-Xmx200m"]} {:jvm-opts ["-Xms100m" "-Xmx200m"]} {:jvm-opts ["-Dfoo=bar"]} {:jvm-opts ["-Xms100m" "-Xmx200m" "-Dfoo=bar"]} {} {:main-opts ["foo.bar" "1"]} {:main-opts ["foo.bar" "1"]} {:main-opts ["foo.bar" "1"]} {:main-opts ["foo.baz" "2"]} {:main-opts ["foo.baz" "2"]})) (def repo ;; "real" {'org.clojure/clojure {{:fkn/version "1.9.0"} [['org.clojure/spec.alpha {:fkn/version "0.1.124"}] ['org.clojure/core.specs.alpha {:fkn/version "0.1.10"}]]} 'org.clojure/spec.alpha {{:fkn/version "0.1.124"} nil {:fkn/version "0.1.1"} nil} 'org.clojure/core.specs.alpha {{:fkn/version "0.1.10"} nil} ;; testing various scenarios 'e1/a {{:fkn/version "1"} [['e1/b {:fkn/version "1"}] ['e1/c {:fkn/version "2"}]]} 'e1/b {{:fkn/version "1"} [['e1/c {:fkn/version "1"}]]} 'e1/c {{:fkn/version "1"} nil {:fkn/version "2"} nil} 'opt/a {{:fkn/version "1"} [['opt/b {:fkn/version "1" :optional true}] ['opt/c {:fkn/version "1"}]]} 'opt/b {{:fkn/version "1"} nil} 'opt/c {{:fkn/version "1"} nil}}) (deftest test-top-optional-included (fkn/with-libs repo (is (= (set (keys (deps/resolve-deps {:deps {'opt/b {:fkn/version "1"}}} nil))) #{'opt/b})))) (deftest test-transitive-optional-not-included (fkn/with-libs repo (is (= (set (keys (deps/resolve-deps {:deps {'opt/a {:fkn/version "1"}}} nil))) #{'opt/a 'opt/c})))) (deftest test-basic-expand (fkn/with-libs repo (is (= (set (keys (deps/resolve-deps {:deps {'org.clojure/clojure {:fkn/version "1.9.0"}}} nil))) #{'org.clojure/clojure 'org.clojure/spec.alpha 'org.clojure/core.specs.alpha})))) (deftest test-top-dominates (fkn/with-libs repo ;; dependent dep decides version (is (= (-> {:deps {'org.clojure/clojure {:fkn/version "1.9.0"}}} (deps/resolve-deps nil) (get 'org.clojure/spec.alpha) :fkn/version) "0.1.124")) ;; top dep wins (is (= (-> {:deps {'org.clojure/clojure {:fkn/version "1.9.0"} 'org.clojure/spec.alpha {:fkn/version "0.1.1"}}} (deps/resolve-deps nil) (get 'org.clojure/spec.alpha) :fkn/version) "0.1.1")))) (deftest test-override-deps (fkn/with-libs repo ;; override dep wins (is (= (-> {:deps {'org.clojure/clojure {:fkn/version "1.9.0"}}} (deps/resolve-deps {:override-deps {'org.clojure/spec.alpha {:fkn/version "0.1.1"}}}) (get 'org.clojure/spec.alpha) :fkn/version) "0.1.1")))) (deftest test-default-deps (fkn/with-libs repo ;; default dep wins if none provided (is (= (-> {:deps {'org.clojure/clojure nil}} (deps/resolve-deps {:default-deps {'org.clojure/clojure {:fkn/version "2.0.0"}}}) (get 'org.clojure/clojure) :fkn/version) "2.0.0")))) (defn libs->lib-ver [libmap] (reduce-kv (fn [lib-ver lib coord] (assoc lib-ver (-> lib name keyword) (:fkn/version coord))) {} libmap)) ;; +a1 -> +b1 -> -c1 ;; -> +c2 (deftest test-dep-choice (fkn/with-libs repo (= (->> (deps/resolve-deps {:deps {'e1/a {:fkn/version "1"}}} nil) libs->lib-ver) {:a 1, :b 1, :c 2}))) ;; -> +a1 -> +d1 ;; -> +b1 -> -e1 -> -d2 ;; -> +c1 -> +e2 (deftest test-dep-parent-missing (fkn/with-libs {'ex/a {{:fkn/version "1"} [['ex/d {:fkn/version "1"}]]} 'ex/b {{:fkn/version "1"} [['ex/e {:fkn/version "1"}]]} 'ex/c {{:fkn/version "1"} [['ex/e {:fkn/version "2"}]]} 'ex/d {{:fkn/version "1"} nil {:fkn/version "2"} nil} 'ex/e {{:fkn/version "1"} [['ex/d {:fkn/version "2"}]] {:fkn/version "2"} nil}} (let [r (->> (deps/resolve-deps {:deps {'ex/a {:fkn/version "1"} 'ex/b {:fkn/version "1"} 'ex/c {:fkn/version "1"}}} nil) libs->lib-ver)] (is (= r {:a "1", :b "1", :c "1", :d "1", :e "2"}))))) ;; +a1 -> +b1 -> +x2 -> +y1 ;; +c1 -> -x1 -> -z1 (deftest test-dep-choice2 (fkn/with-libs {'ex/a {{:fkn/version "1"} [['ex/b {:fkn/version "1"}]]} 'ex/b {{:fkn/version "1"} [['ex/x {:fkn/version "2"}]]} 'ex/c {{:fkn/version "1"} [['ex/x {:fkn/version "1"}]]} 'ex/x {{:fkn/version "2"} [['ex/y {:fkn/version "1"}]] {:fkn/version "1"} [['ex/z {:fkn/version "1"}]]} 'ex/y {{:fkn/version "1"} nil} 'ex/z {{:fkn/version "1"} nil}} (is (= {:a "1", :b "1", :c "1", :x "2", :y "1"} (let [res (deps/resolve-deps {:deps {'ex/a {:fkn/version "1"}, 'ex/c {:fkn/version "1"}}} nil)] (libs->lib-ver res)))))) ;; c1 included via both a and b, with exclusions in one branch and without in the other ;; should always include d1 ;; +a1 -> +c1 (excl d) -> d1 ;; +b1 -> +c1 -> +d1 (deftest test-dep-same-version-different-exclusions (fkn/with-libs {'ex/a {{:fkn/version "1"} [['ex/c {:fkn/version "1" :exclusions ['ex/d]}]]} 'ex/b {{:fkn/version "1"} [['ex/c {:fkn/version "1"}]]} 'ex/c {{:fkn/version "1"} [['ex/d {:fkn/version "1"}]]} 'ex/d {{:fkn/version "1"} nil}} (is (= {:a "1", :b "1", :c "1", :d "1"} (libs->lib-ver (deps/resolve-deps {:deps {'ex/a {:fkn/version "1"}, 'ex/b {:fkn/version "1"}}} nil)) (libs->lib-ver (deps/resolve-deps {:deps {'ex/b {:fkn/version "1"}, 'ex/a {:fkn/version "1"}}} nil)))))) ;; +a1 -> +b1 -> -c1 -> a1 ;; -> +c2 -> a1 (deftest test-circular-deps (fkn/with-libs {'ex/a {{:fkn/version "1"} [['ex/b {:fkn/version "1"}] ['ex/c {:fkn/version "2"}]]} 'ex/b {{:fkn/version "1"} [['ex/c {:fkn/version "1"}]]} 'ex/c {{:fkn/version "1"} [['ex/a {:fkn/version "1"}]] {:fkn/version "2"} [['ex/a {:fkn/version "1"}]]}} (is (= {:a "1", :b "1", :c "2"} (let [res (deps/resolve-deps {:deps {'ex/a {:fkn/version "1"}}} nil)] (libs->lib-ver res)))))) ;; +a1 -> -d1 -> -e1 ;; +b1 -> +c1 -> +d2 ;; e1 is found and selected due to d1, then cut when d2 is found (deftest test-cut-previously-selected-child (fkn/with-libs {'ex/a {{:fkn/version "1"} [['ex/d {:fkn/version "1"}]]} 'ex/b {{:fkn/version "1"} [['ex/c {:fkn/version "1"}]]} 'ex/c {{:fkn/version "1"} [['ex/d {:fkn/version "2"}]]} 'ex/d {{:fkn/version "1"} [['ex/e {:fkn/version "1"}]] {:fkn/version "2"} nil} 'ex/e {{:fkn.version "1"} nil}} (is (= {:a "1", :b "1", :c "1", :d "2"} (let [res (deps/resolve-deps {:deps {'ex/a {:fkn/version "1"} 'ex/b {:fkn/version "1"}}} nil)] (libs->lib-ver res)))))) ;; +a1 -> -d1 -> -e1 -> -f1 ;; +b1 -> +c1 -> +g1 -> +d2 -> +e2 ;; e1 is found and selected due to d1, then cut when d2 is found (deftest test-cut-previously-selected-child-2 (fkn/with-libs {'ex/a {{:fkn/version "1"} [['ex/d {:fkn/version "1"}]]} 'ex/b {{:fkn/version "1"} [['ex/c {:fkn/version "1"}]]} 'ex/c {{:fkn/version "1"} [['ex/g {:fkn/version "1"}]]} 'ex/d {{:fkn/version "1"} [['ex/e {:fkn/version "1"}]] {:fkn/version "2"} [['ex/e {:fkn/version "2"}]]} 'ex/e {{:fkn/version "1"} [['ex/f {:fkn/version "1"}]] {:fkn/version "2"} nil} 'ex/f {{:fkn/version "1"} nil} 'ex/g {{:fkn/version "1"} [['ex/d {:fkn/version "2"}]]}} (is (= {:a "1", :b "1", :c "1", :d "2", :e "2", :g "1"} (let [res (deps/resolve-deps {:deps {'ex/a {:fkn/version "1"} 'ex/b {:fkn/version "1"}}} nil)] (libs->lib-ver res)))))) ;; +a -> +b -> -x2 -> -y2 -> -z2 ;; -> +c -> +d -> +x3 -> +y2 -> +z2 ;; -> -x1 -> -y1 -> -z1 ;; include all of x3/y3/z3 (deftest test-multi-version-discovery (fkn/with-libs {'ex/a {{:fkn/version "1"} [['ex/b {:fkn/version "1"}] ['ex/c {:fkn/version "1"}] ['ex/x {:fkn/version "1"}]]} 'ex/b {{:fkn/version "1"} [['ex/x {:fkn/version "2"}]]} 'ex/c {{:fkn/version "1"} [['ex/d {:fkn/version "1"}]]} 'ex/d {{:fkn/version "1"} [['ex/x {:fkn/version "3"}]]} 'ex/x {{:fkn/version "1"} [['ex/y {:fkn/version "1"}]] {:fkn/version "2"} [['ex/y {:fkn/version "2"}]] {:fkn/version "3"} [['ex/y {:fkn/version "2"}]]} 'ex/y {{:fkn/version "1"} [['ex/z {:fkn/version "1"}]] {:fkn/version "2"} [['ex/z {:fkn/version "2"}]]} 'ex/z {{:fkn/version "1"} nil {:fkn/version "2"} nil}} (is (= {:a "1", :b "1", :c "1", :d "1", :x "3", :y "2", :z "2"} (let [res (deps/resolve-deps {:deps {'ex/a {:fkn/version "1"}}} nil)] (libs->lib-ver res)))))) (def ^:dynamic ^File *test-dir*) (defmacro with-test-dir [& body] `(let [name# (-> clojure.test/*testing-vars* last symbol str) dir# (jio/file "test-out" name#)] (.delete dir#) (.mkdirs dir#) (binding [*test-dir* dir#] ~@body))) (deftest test-local-root (with-test-dir (let [base (.getCanonicalFile *test-dir*)] (jio/make-parents *test-dir* "b/deps.edn") (testing "a relative local root canonicalizes relative to parent dep" (binding [dir/*the-dir* base] (is (= ['ex/b {:local/root (.getPath (.getCanonicalFile (File. base "b")))}] (ext/canonicalize 'ex/b {:local/root "b"} {}))))) (testing "an absolute local root canonicalizes to itself" (binding [dir/*the-dir* base] (let [abs-b (.getAbsolutePath (jio/file *test-dir* "b"))] (is (= ['ex/b {:local/root abs-b}] (ext/canonicalize 'ex/b {:local/root abs-b} {}))))))))) ;; simple check that pom resolution is working - load tda itself as pom dep (deftest test-local-pom (is (seq (deps/resolve-deps {:deps {'c/tda {:local/root "." :deps/manifest :pom}} :mvn/repos mvn/standard-repos} nil)))) (def install-data {:paths ["src"] :deps {'org.clojure/clojure {:mvn/version "1.10.1"}} :aliases {:test {:extra-paths ["test"]}} :mvn/repos {"central" {:url "https://repo1.maven.org/maven2/"} "clojars" {:url "https://repo.clojars.org/"}}}) (deftest calc-basis (let [{:keys [libs classpath] :as basis} (deps/calc-basis install-data)] ;; basis is superset of merged deps (is (= install-data (select-keys basis (keys install-data)))) ;; lib map contains transitive deps (is (= (set (keys libs)) #{'org.clojure/clojure 'org.clojure/spec.alpha 'org.clojure/core.specs.alpha})) ;; classpath has all deps and src path (is (= (set (vals classpath)) #{{:lib-name 'org.clojure/clojure} {:lib-name 'org.clojure/spec.alpha} {:lib-name 'org.clojure/core.specs.alpha} {:path-key :paths}})) (is (contains? (set (keys classpath)) "src")))) (defn select-cp [classpath key] (->> classpath (filter #(contains? (val %) key)) (apply conj {}))) (deftest calc-basis-extra-deps (let [ra {:extra-deps {'org.clojure/tools.deps.alpha {:mvn/version "0.8.677"}}} {:keys [resolve-args libs]} (deps/calc-basis install-data {:resolve-args ra})] ;; basis contains resolve-args (is (= resolve-args ra)) ;; libs has extra deps and transitive deps (let [expanded-deps (-> libs keys set)] (is (< 4 (count expanded-deps))) (is (contains? expanded-deps 'org.clojure/tools.deps.alpha))))) (deftest calc-basis-override-deps (let [ra {:extra-deps {'org.clojure/clojure {:mvn/version "1.6.0"}}} {:keys [resolve-args libs]} (deps/calc-basis install-data {:resolve-args ra})] ;; basis contains resolve-args (is (= resolve-args ra)) ;; libs has extra deps and transitive deps (is (= (get-in libs ['org.clojure/clojure :mvn/version]) "1.6.0")))) (deftest calc-basis-extra-paths (let [cpa {:extra-paths ["x" "y"]} {:keys [classpath-args classpath]} (deps/calc-basis install-data {:classpath-args cpa})] ;; basis contains classpath-args (is (= classpath-args cpa)) ;; classpath has extra paths (is (= {"src" {:path-key :paths}, "x" {:path-key :extra-paths}, "y" {:path-key :extra-paths}} (select-cp classpath :path-key))))) (deftest calc-basis-classpath-overrides (let [cpa {:classpath-overrides {'org.clojure/clojure "foo"}} {:keys [classpath-args classpath]} (deps/calc-basis install-data {:classpath-args cpa})] ;; basis contains classpath-args (is (= classpath-args cpa)) ;; classpath has replaced path (is (= (get classpath "foo") {:lib-name 'org.clojure/clojure})))) (deftest optional-deps-included (let [master-edn (merge install-data '{:deps {org.clojure/clojure {:mvn/version "1.10.1"} org.clojure/core.async {:mvn/version "1.1.587" :optional true}}}) {:keys [libs]} (deps/calc-basis master-edn)] ;; libs contains optional dep (is (= (get-in libs ['org.clojure/core.async :mvn/version]) "1.1.587")))) ;(update-excl [lib use-coord coord-id use-path include reason exclusions cut]) (deftest test-update-excl ;; new lib/version, no exclusions (let [ret (#'deps/update-excl 'a {:mvn/version "1"} {:mvn/version "1"} '[b a] true :new-version nil nil)] (is (= {:exclusions' nil, :cut' nil} (select-keys ret [:exclusions' :cut']))) (is (not (nil? (:child-pred ret))))) ;; new lib/version, with exclusions (let [ret (#'deps/update-excl 'a {:mvn/version "1" :exclusions ['c]} {:mvn/version "1"} '[b a] true :new-version nil nil)] (is (= {:exclusions' '{[b a] #{c}}, :cut' '{[a {:mvn/version "1"}] #{c}}} (select-keys ret [:exclusions' :cut']))) (is (not (nil? (:child-pred ret))))) ;; same lib/version, fewer excludes ;; a (excl c) ;; b -> a -> c1 (let [excl '{[a] #{c}} ret (#'deps/update-excl 'a {:mvn/version "1"} {:mvn/version "1"} '[b a] false :same-version excl '{[a {:mvn/version "1"}] #{c}})] (is (= {:exclusions' excl, :cut' '{[a #:mvn{:version "1"}] nil}} (select-keys ret [:exclusions' :cut']))) ;; remove cut (let [pred (:child-pred ret)] (is (true? (boolean (pred 'c)))))) ;; same lib/version, subset excludes ;; a (excl c d) ;; b -> a (excl c) (let [excl '{[a] #{c d}} cut '{[a {:mvn/version "1"}] #{c d}} ret (#'deps/update-excl 'a '{:mvn/version "1" :exclusions [c]} {:mvn/version "1"} '[b a] false :same-version excl cut)] (is (= {:exclusions' '{[a] #{c d}, [b a] #{c}}, :cut' '{[a {:mvn/version "1"}] #{c}}} (select-keys ret [:exclusions' :cut']))) (let [pred (:child-pred ret)] (is (false? (boolean (pred 'c)))) ;; already enqueued (is (true? (boolean (pred 'd)))))) ;; newly enqueueable due to smaller exclusion set ;; same lib/version, same excludes ;; a (excl c) ;; b -> a (excl c) (let [excl '{[a] #{c}} cut '{[a {:mvn/version "1"}] #{c}} ret (#'deps/update-excl 'a {:mvn/version "1" :exclusions ['c]} {:mvn/version "1"} '[b a] false :same-version excl cut)] (is (= {:exclusions' (assoc excl '[b a] '#{c}), :cut' cut} (select-keys ret [:exclusions' :cut']))) ;; no change in cut (let [pred (:child-pred ret)] (is (false? (boolean (pred 'c)))))) ;; same lib/version, more excludes ;; a (excl c) ;; b -> a (excl c, d) (let [excl '{[a] #{c}} cut '{[a {:mvn/version "1"}] #{c}} ret (#'deps/update-excl 'a '{:mvn/version "1" :exclusions [c d]} {:mvn/version "1"} '[b a] false :same-version excl cut)] (is (= {:exclusions' '{[a] #{c}, [b a] #{c d}}, :cut' cut} (select-keys ret [:exclusions' :cut']))) ;; no change in cut (let [pred (:child-pred ret)] ;; everything already enqueued (is (false? (boolean (pred 'c)))) (is (false? (boolean (pred 'd))))))) ;; +x1 -> -a1 -> +b2 ;; +z1 -> +y1 -> +a2 -> -b1 (or +b1, but at least a consistent result) ;; TDEPS-58 (deftest test-dep-ordering (fkn/with-libs {'ex/a {{:fkn/version "1"} [['ex/b {:fkn/version "2"}]] {:fkn/version "2"} [['ex/b {:fkn/version "1"}]]} 'ex/b {{:fkn/version "1"} nil {:fkn/version "2"} nil} 'ex/x {{:fkn/version "1"} [['ex/a {:fkn/version "1"}]]} 'ex/y {{:fkn/version "1"} [['ex/a {:fkn/version "2"}]]} 'ex/z {{:fkn/version "1"} [['ex/y {:fkn/version "1"}]]}} (is (= (let [res (deps/resolve-deps {:deps {'ex/x {:fkn/version "1"}, 'ex/z {:fkn/version "1"}}} nil)] (reduce-kv #(assoc %1 (-> %2 name keyword) (:fkn/version %3)) {} res)) (let [res (deps/resolve-deps {:deps {'ex/z {:fkn/version "1"}, 'ex/x {:fkn/version "1"}}} nil)] (reduce-kv #(assoc %1 (-> %2 name keyword) (:fkn/version %3)) {} res)))))) (deftest test-create-basis (fkn/with-libs {'ex/a {{:fkn/version "1"} nil} 'ex/b {{:fkn/version "1"} nil} 'ex/c {{:fkn/version "1"} nil}} (are [libs params] (= (set libs) (set (keys (:libs (deps/create-basis params))))) ;; check pulling project sources [] {:root nil :user nil :project nil} ['ex/a] {:root {:deps {'ex/a {:fkn/version "1"}}} :user nil :project nil} ['ex/a] {:root nil :user {:deps {'ex/a {:fkn/version "1"}}} :project nil} ['ex/a] {:root nil :user nil :project {:deps {'ex/a {:fkn/version "1"}}}} ['ex/a] {:root nil :user nil :project nil :extra {:deps {'ex/a {:fkn/version "1"}}}} ;; check aliases ['ex/a 'ex/b] {:root nil :project {:deps {'ex/a {:fkn/version "1"}} :aliases {:b {:extra-deps {'ex/b {:fkn/version "1"}}}}} :aliases [:b]})))tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/util/000077500000000000000000000000001434474567100240705ustar00rootroot00000000000000tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/util/dir_test.clj000066400000000000000000000015631434474567100264040ustar00rootroot00000000000000; Copyright (c) Rich Hickey. All rights reserved. ; The use and distribution terms for this software are covered by the ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) ; which can be found in the file epl-v10.html at the root of this distribution. ; By using this software in any fashion, you are agreeing to be bound by ; the terms of this license. ; You must not remove this notice, or any other, from this software. (ns clojure.tools.deps.util.dir-test (:require [clojure.tools.deps.util.dir :as dir] [clojure.test :refer [deftest is]]) (:import [java.io File])) (deftest test-canonicalize (let [base (.getCanonicalFile (File. "."))] (binding [dir/*the-dir* base] (let [abs (File. "/a/b")] (is (= abs (dir/canonicalize abs))) (is (= (File. base "xyz") (dir/canonicalize (File. "xyz"))))))))tools.deps-0.16.1264/src/test/clojure/clojure/tools/deps/util/test_s3_transporter.clj000066400000000000000000000031221434474567100306070ustar00rootroot00000000000000(ns clojure.tools.deps.util.test-s3-transporter (:require [clojure.test :refer [are deftest]] [clojure.tools.deps.util.s3-transporter :as s3t] [clojure.tools.deps.util.maven :as mvn]) (:import [java.io File] [java.net URI] [org.eclipse.aether.spi.connector.transport Transporter GetTask TransportListener])) (set! *warn-on-reflection* true) (deftest test-parse (are [u r b p] (= (merge {:region nil, :bucket nil, :repo-path nil} (s3t/parse-url (mvn/remote-repo [nil {:url u}]))) {:region r :bucket b :repo-path p}) "s3://BUCKET/PATH1/PATH2" nil "BUCKET" "PATH1/PATH2" "s3://BUCKET/PATH1/PATH2?region=REGION" "REGION" "BUCKET" "PATH1/PATH2")) (defn downloader [repo url path] (let [system (mvn/make-system) settings (mvn/get-settings) session (mvn/make-session system settings "/Users/alex/.m2/repository") remote-repo (mvn/remote-repo [repo {:url url}]) transporter (s3t/new-transporter session remote-repo) task (GetTask. (URI/create path)) temp (File/createTempFile "dload-" nil)] (.setDataFile task temp) (.setListener task (proxy [TransportListener] [] (transportStarted [_ _]) (transportProgressed [_]))) (.get ^Transporter transporter task) (slurp temp))) (comment (downloader "datomic" "s3://datomic-releases-1fc2183a/maven/releases" "com/datomic/ion/0.9.35/ion-0.9.35.pom") (downloader "datomic" "s3://datomic-releases-1fc2183a/maven/releases?region=us-east-1" "com/datomic/ion/0.9.35/ion-0.9.35.pom") )