├── .gitattributes ├── .github └── workflows │ ├── check.yml │ ├── promote.yml │ └── release.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── VERSION ├── VERSION_TEMPLATE ├── deps.edn ├── devel.properties ├── doc └── clojure.1 ├── epl.html ├── script ├── build.clj ├── print_version ├── publish.sh ├── read_versions.sh └── update_version ├── src ├── main │ ├── clojure │ │ └── clojure │ │ │ └── run │ │ │ └── exec.clj │ └── resources │ │ └── clojure │ │ └── install │ │ ├── ClojureTools.psd1 │ │ ├── ClojureTools.psm1 │ │ ├── clj │ │ ├── clojure │ │ ├── clojure.rb │ │ ├── clojure@version.rb │ │ ├── deps.edn │ │ ├── example-deps.edn │ │ ├── install.sh │ │ ├── linux-install.sh │ │ ├── posix-install.sh │ │ ├── tools.edn │ │ └── win-install.ps1 └── test │ └── clojure │ └── clojure │ └── run │ └── test_exec.clj └── stable.properties /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | # Unix Shell Scripts 4 | *.sh text eol=lf 5 | clj text eol=lf 6 | clojure text eol=lf 7 | print_version text eol=lf 8 | update_version text eol=lf 9 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: Check download via setup-clojure 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | os: 7 | description: 'OS to check installation with' 8 | required: true 9 | default: 'ubuntu-latest' 10 | version: 11 | description: 'Version to check installation with' 12 | required: true 13 | default: 'latest' 14 | 15 | jobs: 16 | build: 17 | runs-on: ${{ github.event.inputs.os }} 18 | steps: 19 | - name: Set Github identity 20 | run: | 21 | git config --global user.name clojure-build 22 | git config --global user.email "clojure-build@users.noreply.github.com" 23 | - name: Set up Java 24 | uses: actions/setup-java@v3 25 | with: 26 | java-version: 8 27 | distribution: 'temurin' 28 | - name: Set up Clojure 29 | uses: DeLaGuardo/setup-clojure@13.2 30 | with: 31 | cli: ${{ github.event.inputs.version }} 32 | - name: Check downloaded version 33 | run: clojure --version 34 | - name: Run CLI 35 | run: clojure -M -e nil 36 | 37 | -------------------------------------------------------------------------------- /.github/workflows/promote.yml: -------------------------------------------------------------------------------- 1 | name: Promote dev to stable 2 | 3 | on: [workflow_dispatch] 4 | 5 | permissions: # Exchange the OIDC token (JWT) for a cloud access token 6 | id-token: write # This is required for requesting the JWT 7 | contents: write # This is required for actions/checkout 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: aws-actions/configure-aws-credentials@v2 14 | with: 15 | role-to-assume: arn:aws:iam::173728190221:role/github-CLI-upload 16 | aws-region: us-east-2 17 | - name: Check out 18 | uses: actions/checkout@v3 19 | - name: Set Github identity 20 | run: | 21 | git config --global user.name clojure-build 22 | git config --global user.email "clojure-build@users.noreply.github.com" 23 | - name: Read versions and save for later use 24 | run: | 25 | source script/read_versions.sh 26 | echo "DEVEL_VERSION=$DEVEL_VERSION" >> "$GITHUB_ENV" 27 | echo "DEVEL_SHA=$DEVEL_SHA" >> "$GITHUB_ENV" 28 | echo "STABLE_VERSION=$STABLE_VERSION" >> "$GITHUB_ENV" 29 | echo "STABLE_SHA=$STABLE_SHA" >> "$GITHUB_ENV" 30 | - name: Read versions 31 | run: | 32 | cp devel.properties stable.properties 33 | git add stable.properties 34 | git commit -m "update stable to $DEVEL_VERSION" 35 | git push 36 | - name: Publish new stable version 37 | run: aws s3 cp --only-show-errors "stable.properties" "$S3_BUCKET/install/stable.properties" 38 | env: 39 | S3_BUCKET: ${{ secrets.S3_BUCKET }} 40 | - name: Mark github release as published and latest 41 | run: gh release edit "$DEVEL_VERSION" --prerelease=false --latest 42 | env: 43 | GH_TOKEN: ${{secrets.GH_TOKEN}} 44 | - name: Change brew recipe in tap 45 | run: | 46 | echo "old $STABLE_VERSION" 47 | gh workflow run -R clojure/homebrew-tools promote -r master -f old_version="$STABLE_VERSION" -f old_sha="$STABLE_SHA" -f new_version="$DEVEL_VERSION" -f new_sha="$DEVEL_SHA" 48 | env: 49 | GH_TOKEN: ${{secrets.GH_TOKEN}} 50 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release dev version 2 | 3 | on: [workflow_dispatch] 4 | 5 | permissions: # Exchange the OIDC token (JWT) for a cloud access token 6 | id-token: write # This is required for requesting the JWT 7 | contents: write # This is required for actions/checkout 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: aws-actions/configure-aws-credentials@v2 14 | with: 15 | role-to-assume: arn:aws:iam::173728190221:role/github-CLI-upload 16 | aws-region: us-east-2 17 | - name: Check out 18 | uses: actions/checkout@v3 19 | with: 20 | fetch-depth: 0 21 | - name: Set Github identity 22 | run: | 23 | git config --global user.name clojure-build 24 | git config --global user.email "clojure-build@users.noreply.github.com" 25 | - name: Set up Java 26 | uses: actions/setup-java@v3 27 | with: 28 | java-version: 8 29 | distribution: 'temurin' 30 | - name: Set up Clojure 31 | uses: DeLaGuardo/setup-clojure@13.2 32 | with: 33 | cli: latest 34 | - name: Cache clojure dependencies 35 | uses: actions/cache@v3 36 | with: 37 | path: | 38 | ~/.m2/repository 39 | ~/.gitlibs 40 | key: cljdeps-${{ hashFiles('deps.edn') }} 41 | restore-keys: cljdeps- 42 | - name: Calculate version 43 | run: | 44 | script/update_version 45 | echo "VERSION=$(cat VERSION)" >> "$GITHUB_ENV" 46 | - name: Package release 47 | run: clojure -T:build release 48 | - name: Upload release to site 49 | run: script/publish.sh 50 | env: 51 | S3_BUCKET: ${{ secrets.S3_BUCKET }} 52 | - name: Tag release 53 | run: | 54 | git tag -a "$VERSION" -m "$VERSION" 55 | git push --tags 56 | git push 57 | - name: Upload to github release 58 | run: gh release create "$VERSION" -p -t "$VERSION" "target/clojure@$VERSION.rb" "target/clojure-tools-$VERSION.tar.gz" "target/clojure-tools-$VERSION.tar.gz.sha256" "target/linux-install.sh" "target/posix-install.sh" "target/clojure-tools.zip" "target/win-install.ps1" "target/clojure-tools.zip.sha256" 59 | env: 60 | GH_TOKEN: ${{secrets.GH_TOKEN}} 61 | - name: Publish versioned brew recipe to tap 62 | run: gh workflow run -R clojure/homebrew-tools publish -r master -f "version=$VERSION" 63 | env: 64 | GH_TOKEN: ${{secrets.GH_TOKEN}} 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dependency-reduced-pom.xml 2 | target 3 | .idea/ 4 | clojure-tools.iml 5 | .cpcache/ 6 | *.iml 7 | .nrepl-port 8 | .lsp/ 9 | .clj-kondo/ 10 | .calva/ 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | =========== 3 | 4 | **Also see [tools.deps changelog](https://github.com/clojure/tools.deps.alpha/blob/master/CHANGELOG.md)** 5 | 6 | clj has both stable and prerelease versions. Current and former stable build are listed in **bold** and are (or were) available from the default [brew formula](https://github.com/clojure/brew-install/). Other versions can be obtained using versioned formulas only. 7 | 8 | Prerelease versions: none 9 | 10 | **Current stable version:** 11 | 12 | * **1.12.1.1550 on Jun 3, 2025** 13 | * **`-Sdescribe` - undocumented (prefer using tools.deps APIs instead)** 14 | * **`-Sverbose` - add explicit deps.edn references** 15 | 16 | Older versions (previous stable builds in bold): 17 | 18 | * **1.12.1.1543 on Jun 3, 2025** 19 | * **Update to Clojure 1.12.1** 20 | * **1.12.1.1538 on Jun 2, 2025** 21 | * **Update to Clojure 1.12.1** 22 | * **1.12.0.1530 on Mar 5, 2025** 23 | * **Update to tools.deps 0.23.1512** 24 | * 1.12.0.1523 on Mar 5, 2025 25 | * Also accept file for -Sdeps, and check it for staleness 26 | * Update to tools.deps 0.22.1497 27 | * **1.12.0.1517 on Feb 7, 2025** 28 | * **Update to tools.deps 0.22.1492** 29 | * 1.12.0.1514 on Feb 7, 2025 30 | * Update to tools.deps 0.22.1484 31 | * 1.12.0.1510 on Feb 6, 2025 32 | * Update to tools.deps 0.22.1480 33 | * 1.12.0.1506 on Feb 6, 2025 34 | * Update to tools.deps 0.22.1476 35 | * **1.12.0.1501 on Jan 27, 2025** 36 | * **Update to tools.deps 0.21.1471** 37 | * **1.12.0.1495 on Dec 31, 2024** 38 | * **Echo args with -M deprecation warning for clarity** 39 | * **Update to tools.deps 0.21.1467** 40 | * **1.12.0.1488** on Nov 21, 2024 41 | * **Tweak message when -X or -T function namespace not found** 42 | * **Update to latest tools.tools** 43 | * **Update to latest tools.deps** 44 | * **1.12.0.1479** 45 | * **Default to Clojure 1.12.0** 46 | * **Update to tools.deps 0.21.1449 and tools.deps.cli** 47 | * **1.11.4.1474** 48 | * **Default to Clojure 1.11.4** 49 | * **Update to tools.deps 0.20.1440** 50 | * **1.11.3.1463** 51 | * **Update list of :deps programs in help** 52 | * **Update to latest tools.deps.cli, tools.deps, and tools.build** 53 | * **1.11.3.1456 on Apr 24, 2024** 54 | * **Update to latest tools.deps and tools.deps.cli** 55 | * 1.11.3.1452 on Apr 24, 2024 56 | * Update to Clojure 1.11.3 as default 57 | * **1.11.2.1446 on Mar 8, 2024** 58 | * **Update to tools.deps 0.19.1417** 59 | * **1.11.2.1441 on Mar 8, 2024** 60 | * **Update to tools.tools 0.3.3** 61 | * **Update to Clojure 1.11.2** 62 | * **1.11.1.1435 on Dec 29, 2023** 63 | * **Update to tools.deps 1.18.1394** 64 | * **1.11.1.1429 on Dec 4, 2023** 65 | * **Update to tools.deps 1.18.1374** 66 | * **1.11.1.1420 on Dec 4, 2023** 67 | * **TDEPS-119 Unable to start CLI in write-protected project directory** 68 | * **Update to tools.deps 1.18.1370** 69 | * **Update to tools.tools 0.3.2** 70 | * **1.11.1.1413 on Aug 26, 2023** 71 | * **No changes from prior** 72 | * **1.11.1.1409 on Aug 25, 2023** 73 | * **No changes from prior** 74 | * **1.11.1.1405 on Aug 22, 2023** 75 | * **GitHub releases now contain .sha256 files for binaries** 76 | * **1.11.1.1386 on Aug 14, 2023** 77 | * **Release artifacts are now published to GitHub, and the download archive is used only as a mirror** 78 | * **1.11.1.1369 on Aug 14, 2023** 79 | * **Download and mirroring wip** 80 | * **1.11.1.1365 on Aug 13, 2023** 81 | * **Download and mirroring wip** 82 | * **1.11.1.1347 on May 31, 2023** 83 | * **With -X or -T accept `-` as a trailing argument to read the remainder of args from stdin** 84 | * **On windows installer, hide progress bar on download** 85 | * **Update to tools.deps 0.18.1354** 86 | * **Update to tools.tools 0.3.1** 87 | * **1.11.1.1273 on Apr 3, 2023** 88 | * **Change help text to point to -X:deps mvn-pom instead of -Spom** 89 | * **Switch to tools.deps 0.18.1335** 90 | * **1.11.1.1267 on Mar 31, 2023** 91 | * **Switch to tools.deps 0.18.1331** 92 | * **1.11.1.1262 on Mar 27, 2023** 93 | * **Switch to tools.deps 0.18.1317** 94 | * **1.11.1.1257 on Mar 15, 2023** 95 | * **Switch to tools.deps 0.18.1308** 96 | * **1.11.1.1252 on Mar 6, 2023** 97 | * **Switch to passing exec args via the basis :argmap** 98 | * **Function execution protocol support for -X/-T** 99 | * **Switch to tools.deps 0.17.1297** 100 | * **1.11.1.1237 on Feb 27, 2023** 101 | * **Updates on -R and -C error messages** 102 | * 1.11.1.1234 on Feb 27, 2023 103 | * Remove deprecated support for -R and -C 104 | * Clean up help text around repl supporting init-opts 105 | * Switch to tools.deps 0.16.1285 106 | * **1.11.1.1224** on Feb 12, 2023** 107 | * **Switch to tools.deps 0.16.1281** 108 | * **TDEPS-236 Add rlwrap -m to clj for multiline editing** 109 | * **1.11.1.1208 on Dec 11, 2022** 110 | * **Switch to tools.deps 0.16.1264** 111 | * **TDEPS-234 - Set -XX:-OmitStackTraceInFastThrow always** 112 | * **1.11.1.1200 on Nov 14, 2022** 113 | * **Update to tools.deps.alpha 0.15.1254** 114 | * **Update to tools.tools v0.2.9** 115 | * 1.11.1.1194 on Nov 14, 2022 116 | * Update to tools.deps.alpha 0.15.1250 117 | * **1.11.1.1189 on Nov 2, 2022** 118 | * **TDEPS-233 bash script fixes from stale jar check changes** 119 | * **Add some missing items on help and man page** 120 | * **1.11.1.1182 on Oct 24, 2022** 121 | * **Update to tools.deps.alpha 0.15.1244** 122 | * 1.11.1.1177 on Oct 23, 2022 123 | * Fix bug in posix-install.sh 124 | * 1.11.1.1174 on Oct 23, 2022 125 | * TDEPS-70 - Detect missing jar in classpath and recompute 126 | * TDEPS-200 - Clean up default user deps.edn 127 | * TDEPS-232 - Add more generic posix installer 128 | * Update to tools.deps.alpha 0.15.1237 129 | * **1.11.1.1165 on Sep 18, 2022** 130 | * Extended the env var support to Windows 131 | * 1.11.1.1161 on Sep 16, 2022 132 | * Use `$CLJ_JVM_OPTS` as jvm options on calls to internal tooling (making classpaths etc) 133 | * Use `$JAVA_OPTS` as jvm options on calls to user programs 134 | * **1.11.1.1155 on Aug 5, 2022** 135 | * **Update to tools.deps.alpha 0.14.1222** 136 | * **1.11.1.1149 on Jun 21, 2022** 137 | * **Update to tools.tools 0.2.8** 138 | * 1.11.1.1145 on Jun 20, 2022 139 | * Update to tools.tools 0.2.7 140 | * Update to tools.deps.alpha 0.14.1212 141 | * **1.11.1.1139 on Jun 16, 2022** 142 | * **Update to tools.tools 0.2.6** 143 | * **Update to tools.deps.alpha 0.14.1205** 144 | * 1.11.1.1135 on Jun 16, 2022 145 | * Update to tools.deps.alpha 0.14.1200 146 | * **1.11.1.1129 on Jun 12, 2022** 147 | * **Update to tools.deps.alpha 0.14.1194** 148 | * **1.11.1.1124** on Jun 11, 2022 149 | * **Update to tools.deps.alpha 0.14.1189** 150 | * **1.11.1.1119** on Jun 9, 2022 151 | * **Update to tools.deps.alpha 0.14.1185** 152 | * **1.11.1.1113** on Apr 22, 2022 153 | * **Update to tools.deps.alpha 0.14.1178** 154 | * **Update to tools.build v0.8.1** 155 | * **1.11.1.1105 on Apr 5, 2022** 156 | * **Update to clojure 1.11.1** 157 | * **1.11.0.1100 on Mar 28, 2022** 158 | * **No changes from prior** 159 | * 1.11.0.1097 on Mar 25, 2022 160 | * Update to clojure 1.11.0 161 | * 1.10.3.1093 on Mar 21, 2022 162 | * Update to tools.deps.alpha 0.12.1162 163 | * **1.10.3.1087 on Feb 28, 2022** 164 | * **Update to tools.deps.alpha 0.12.1158** 165 | * **Update to tools.build v0.8.0** 166 | * 1.10.3.1082 on Feb 11, 2022 167 | * Update to tools.deps.alpha 0.12.1148 168 | * **1.10.3.1075 on Feb 2, 2022** 169 | * **Update to tools.deps.alpha 0.12.1135** 170 | * **1.10.3.1069 on Jan 26, 2022** 171 | * **Update to tools.deps.alpha 0.12.1120** 172 | * **Update to tools.tools v0.2.5** 173 | * **Add check to error on invocation of multiple exec functions** 174 | * **1.10.3.1058 on Jan 4, 2022** 175 | * **Update to tools.deps.alpha 0.12.1109** 176 | * 1.10.3.1053 on Dec 23, 2021 177 | * Update to tools.deps.alpha 0.12.1104 178 | * Update to tools.tools 0.2.3 179 | * Build with tools.build 0.7.3 180 | * 1.10.3.1049 on Dec 22, 2021 181 | * Update to tools.deps.alpha 0.12.1098 182 | * **1.10.3.1040 on Dec 1, 2021** 183 | * **Update to tools.deps.alpha 0.12.1084** 184 | * 1.10.3.1036 on Nov 30, 2021 185 | * Update to tools.deps.alpha 0.12.1080 186 | * **1.10.3.1029 on Nov 8, 2021** 187 | * **Update to tools.deps.alpha 0.12.1071** 188 | * **Update to tools.tools 0.2.2** 189 | * **Update to tools.build 0.6.3** 190 | * **1.10.3.1020 on Nov 4, 2021** 191 | * **TDEPS-83 - invalidate cp cache when local manifest is missing** 192 | * **Update to tools.deps.alpha 0.12.1067** 193 | * 1.10.3.1013 on Oct 30, 2021 194 | * Undo: -Stree no longer forces cache recompute 195 | * 1.10.3.1007 on Oct 29, 2021 196 | * TDEPS-83 - invalidate cp cache when local lib manifests are stale 197 | * -Stree no longer forces cache recompute 198 | * Clean up exception handling for -X 199 | * Update to tools.deps.alpha 0.12.1063 200 | * **1.10.3.998 on Oct 26, 2021** 201 | * **Remove `bottle :unneeded` from brew formulas** 202 | * **Update to tools.deps.alpha 0.12.1058** 203 | * **Update to tools.tools v0.2.1** 204 | * **1.10.3.986 on Sept 22, 2021** 205 | * **Rebuild to actually include latest tools.deps.alpha** 206 | * **Update to tools.deps.alpha 0.12.1048** 207 | * **1.10.3.981 on Sept 17, 2021** 208 | * **Update to tools.build v0.5.0** 209 | * 1.10.3.976 on Sept 17, 2021 210 | * Update to tools.deps.alpha 0.12.1041 211 | * **1.10.3.967 on Aug 31, 2021** 212 | * **Undo compilation of exec stub jar** 213 | * 1.10.3.962 on Aug 30, 2021 214 | * Modify build to compile tools.deps entry points and exec stub jar 215 | * Update to tools.deps.alpha 0.12.1036 216 | * 1.10.3.956 on Aug 27, 2021 217 | * Refine exec exceptions for missing namespace vs missing function in namespace 218 | * Update to tools.deps.alpha 0.12.1030 219 | * Build the Clojure CLI with tools.build, instead of Maven 220 | * 1.10.3.949 on Aug 17, 2021 221 | * Update to tools.deps.alpha 0.12.1026 222 | * **1.10.3.943 on Aug 10, 2021** 223 | * **Update to tools.deps.alpha 0.12.1019** 224 | * 1.10.3.939 on Aug 9, 2021 225 | * Update to tools.deps.alpha 0.12.1013 226 | * **1.10.3.933 on July 28, 2021** 227 | * **TDEPS-198 - on -X, don't use System/exit or shutdown-agents (but don't let agent threads block exit)** 228 | * 1.10.3.929 on July 21, 2021 229 | * TDEPS-189 Port -T changes to Windows 230 | * Did some script cleanup in bash 231 | * 1.10.3.920 on July 19, 2021 232 | * Fix regression in -X execution 233 | * 1.10.3.916 on July 19, 2021 234 | * TDEPS-187 - redo how -X and -T get execute arg data 235 | * Update to tools.deps.alpha 0.12.1003 236 | * 1.10.3.912 on July 15, 2021 237 | * On -X success, exit with (shutdown-agents) instead of System/exit 238 | * TDEPS-187 - pass -A aliases along with -Ttool 239 | * 1.10.3.905 on July 9, 2021 240 | * Removing multi-function support from -X and -T for now 241 | * 1.10.3.899 on July 9, 2021 242 | * New tools support 243 | * Added -T 244 | * Update to tools.deps.alpha 0.12.985 245 | * 1.10.3.882 on June 15, 2021 246 | * On -X success, exit with System/exit to avoid hang from futures 247 | * Bind namespace resolution context around -X 248 | * 1.10.3.875 on June 10, 2021 249 | * New: support for specifying multiple functions with -X with -> semantics 250 | * TDEPS-182 - Improve deprecation message to be more accurate 251 | * TDEPS-183 - Fix -Sdescribe output to be valid edn on Windows 252 | * Update to tools.deps.alpha 0.11.931 253 | * **1.10.3.855 on May 25, 2021** 254 | * **Fix bug in applying :jvm-opts flags for -X on Windows** 255 | * **1.10.3.849 on May 20, 2021** 256 | * **Add support for trailing map in -X calls** 257 | * **Update to tools.deps.alpha 0.11.922** 258 | * **1.10.3.839 on May 12, 2021** 259 | * **Fix breakage in linux installer in 1.10.3.833** 260 | * **1.10.3.833 on May 11, 2021** 261 | * **Clean up script variables** 262 | * 1.10.3.829 on May 11, 2021 263 | * Update to tools.deps.alpha 0.11.918 264 | * **1.10.3.822 on Apr 3, 2021** 265 | * **Update to tools.deps.alpha 0.11.910** 266 | * **1.10.3.814 on Mar 11, 2021** 267 | * **Update to tools.deps.alpha 0.11.905** 268 | * 1.10.3.810 on Mar 10, 2021 269 | * Use Clojure 1.10.3 by default 270 | * Update to tools.deps.alpha 0.11.901 271 | * 1.10.2.805 on Mar 10, 2021 272 | * Update to tools.deps.alpha 0.10.895 273 | * 1.10.2.801 on Mar 3, 2021 274 | * Update to tools.deps.alpha 0.10.889 275 | * **1.10.2.796 on Feb 23, 2021** 276 | * **Update to tools.deps.alpha 0.9.884** 277 | * **1.10.2.790 on Feb 19, 2021** 278 | * **Add -version and --version to print Clojure CLI version (to stderr and stdout respectively)** 279 | * 1.10.2.786 on Feb 17, 2021 280 | * TDEPS-56 - fix main-opts and jvm-opts splitting on space 281 | * Update to tools.deps.alpha 0.9.876 282 | * 1.10.2.781 on Feb 8, 2021 283 | * TDEPS-125 - use `JAVA_CMD` if set 284 | * Update to tools.deps.alpha 0.9.871 285 | * **1.10.2.774 on Jan 26, 2021** 286 | * **Change default Clojure dep to 1.10.2** 287 | * **Update to tools.deps.alpha 0.9.863** 288 | * 1.10.1.769 on Jan 26, 2021 289 | * Update to tools.deps.alpha 0.9.859 290 | * **1.10.1.763 on Dec 10, 2020** 291 | * **Set exit code for -X ex-info error** 292 | * **Sync up cli syntax for aliases in help** 293 | * **1.10.1.754 on Dec 7, 2020** 294 | * **Update to tools.deps.alpha 0.9.857** 295 | * **Update Windows scripts for new -Stree format** 296 | * 1.10.1.749 on Dec 6, 2020 297 | * Update -Stree to use new tree printer 298 | * Update to tools.deps.alpha 0.9.853 299 | * 1.10.1.745 on Dec 2, 2020 300 | * Update to tools.deps.alpha 0.9.847 301 | * **1.10.1.739 on Nov 23, 2020** 302 | * **Update to tools.deps.alpha 0.9.840** 303 | * 1.10.1.735 on Oct 30, 2020 304 | * Fix double throw in -X handling 305 | * Error if -A used without an alias 306 | * **1.10.1.727 on Oct 21, 2020** 307 | * **Update to tools.deps.alpha 0.9.833** 308 | * 1.10.1.723 on Oct 20, 2020 309 | * Fix `clj -X:deps tree` adding tools.deps.alpha to tree 310 | * Fix `clj -X:deps mvn-pom` adding tools.deps.alpha to pom deps 311 | * Fix `clj -X:deps git-resolve-tags` not working 312 | * Update to tools.deps.alpha 0.9.828 313 | * **1.10.1.716 on Oct 10, 2020** 314 | * **Make edn reading tolerant of unknown tagged literals** 315 | * **Update to tools.deps.alpha 0.9.821** 316 | * **1.10.1.708 on Oct 7, 2020** 317 | * **Update to tools.deps.alpha 0.9.816** 318 | * **TDEPS-168 - Fix error message handling for -X** 319 | * **1.10.1.697 on Sep 25, 2020** 320 | * **Update to tools.deps.alpha 0.9.810** 321 | * 1.10.1.693 on Sep 21, 2020 322 | * Update windows scripts for latest 323 | * Re-instate -Stree 324 | * Update to tools.deps.alpha 0.9.799 325 | * 1.10.1.681 on Sep 11, 2020 326 | * Reinstate -R, -C, and -Spom as deprecated options 327 | * Update to tools.deps.alpha 0.9.795 328 | * 1.10.1.672 on Sep 4, 2020 329 | * Add -P to prepare (download, cache classpath) without execution 330 | * Enhance -X and -M to support all argmaps 331 | * Enhance -X to support ad hoc function (-F removed) 332 | * Add new argmap keys for -X, :ns-default, :ns-aliases 333 | * Deprecate main args without -M 334 | * Remove -T, -R, -C, -O 335 | * In deps.edn, deprecate :deps/:paths in alias (change to :replace-deps/:replace-paths) 336 | * In deps.edn, change :fn/:args to :exec-fn/:exec-args 337 | * Move -Sdeps, -Spom, -Sresolve-tags into -X:deps invocations 338 | * Update to tools.deps.alpha 0.9.782 339 | * 1.10.1.645 on Aug 9, 2020 340 | * Update to tools.deps.alpha 0.9.763 341 | * 1.10.1.641 on Aug 8, 2020 342 | * Fix clj -X to make :args optional 343 | * 1.10.1.636 on Aug 7, 2020 344 | * Fix clj -X arg handler in Windows 345 | * Update to tools.deps.alpha 0.9.759 346 | * 1.10.1.619 on July 31, 2020 347 | * Error handling on -X :args 348 | * 1.10.1.615 on July 30, 2020 349 | * Add -F function exec 350 | * Update to tools.deps.alpha 0.9.751 351 | * 1.10.1.604 on July 28, 2020 352 | * Fix clj -X arg handler in Windows 353 | * 1.10.1.600 on July 28, 2020 354 | * Fix clj -X handler in Windows 355 | * 1.10.1.596 on July 28, 2020 356 | * Fix clj -X handler 357 | * 1.10.1.590 on July 22, 2020 358 | * Added new execution mode to execute a function that takes an argmap via -X 359 | * Added support for using data stored in aliases as :paths 360 | * Added explicit "tool" step to cover :deps and :paths replacement, which can be passed via alias -T 361 | * Update to tools.deps.alpha 0.9.745 362 | * **1.10.1.561 on July 17, 2020** 363 | * **Update to tools.deps.alpha 0.8.709** 364 | * 1.10.1.554 on July 15, 2020 365 | * Update to tools.deps.alpha 0.8.702 366 | * **1.10.1.547 on June 11, 2020** 367 | * **In Windows impl, use Write-Output when returning values like with -Spath** 368 | * **Update to tools.deps.alpha 0.8.695** 369 | * 1.10.1.524-**1.10.1.536 on Feb 28, 2020** 370 | * Working on release automation, no changes 371 | * **All releases older than this were stable releases** 372 | * 1.10.1.510 on Feb 14, 2020 373 | * Update to tools.deps.alpha 0.8.677 374 | * 1.10.1.507 on Jan 30, 2020 375 | * Update to tools.deps.alpha 0.8.661 376 | * Add -Sthreads option for concurrent downloads 377 | * Use -- to separate dep options and clojure.main options 378 | * 1.10.1.502 on Jan 20, 2020 379 | * Report clj version in clj -h 380 | * Update to tools.deps.alpha 0.8.640 381 | * 1.10.1.496 on Jan 16, 2020 382 | * Update to tools.deps.alpha 0.8.624 383 | * Remove -Xms on tool jvms 384 | * 1.10.1.492 on Nov 25, 2019 385 | * Fix bad condition checking whether to write trace.edn 386 | * 1.10.1.489 on Nov 20, 2019 387 | * Update to tools.deps.alpha 0.8.599 388 | * Join aliases in windows script without spaces 389 | * Added -Strace option 390 | * 1.10.1.483 on Nov 4, 2019 391 | * Update to tools.deps.alpha 0.8.584 392 | * Use homebrew ruby to minimize env conflicts 393 | * 1.10.1.478 on Oct 18, 2019 394 | * Update to tools.deps.alpha 0.8.567 395 | * Report locations of user and project configs in -Sdescribe 396 | * 1.10.1.472 on Oct 15, 2019 397 | * Update to tools.deps.alpha 0.8.559 398 | * 1.10.1.469 on Aug 9, 2019 399 | * Update to tools.deps.alpha 0.7.541 400 | * Add slf4j-nop which was removed from tools.deps.alpha 401 | * 1.10.1.466 on July 17, 2019 402 | * Use min heap setting, not max, on internal tool calls 403 | * Update to tools.deps 0.7.527 404 | * 1.10.1.462 on July 3, 2019 405 | * Rollback deps.edn install changes and install again 406 | * 1.10.1.458 on June 29, 2019 407 | * Update to tools.deps 0.7.511 408 | * 1.10.1.455 on June 28, 2019 409 | * Fix some manpage/help formatting 410 | * TDEPS-131 Fix bug tracker link in man page 411 | * Update to tools.deps 0.7.505 412 | * Stop installing deps.edn, now embedded in tools.deps 413 | * 1.10.1.447 on June 6, 2019 414 | * Add new clj option to man page and clj help 415 | * 1.10.1.445 on June 6, 2019 416 | * Change default Clojure to 1.10.1 417 | * 1.10.0.442 on Mar 16, 2019 418 | * Update to tools.deps.alpha 0.6.496 419 | * Early release of Windows clj 420 | * 1.10.0.414 on Feb 13, 2019 421 | * Update to tools.deps.alpha 0.6.488 422 | * 1.10.0.411 on Jan 4, 2019 423 | * Update to tools.deps.alpha 0.6.480 424 | * 1.10.0.408 on Jan 2, 2019 425 | * Update to tools.deps.alpha 0.6.474 426 | * FIX TDEPS-82 - ensure -Sdescribe doesn't trigger resolution 427 | * 1.10.0.403 on Dec 17, 2018 428 | * Changed default Clojure version to 1.10 429 | * 1.9.0.397 on Oct 17, 2018 430 | * Update to tools.deps.alpha 0.5.460 431 | * 1.9.0.394 on Sept 15, 2018 432 | * Update to tools.deps.alpha 0.5.452 433 | * 1.9.0.391 on July 19, 2018 434 | * FIX TDEPS-77 - fix bad break character in rlwrap 435 | * FIX TDEPS-86 - use non-0 exit code in clj if rlwrap doesn't exist 436 | * FIX TDEPS-87 - change wording describing -Sdeps in help and man 437 | * 1.9.0.381 on May 11, 2018 438 | * FIX TDEPS-76 - use exec for final Java invocation in script 439 | * NEW Convey lib map via Java system property 440 | * 1.9.0.375 on Apr 14, 2018 441 | * FIX TDEPS-61 - switch to use Clojars CDN repo 442 | * FIX TDEPS-71 - better error if Java not installed 443 | * FIX TDEPS-65 - specify permissions on installed files 444 | * 1.9.0.358 on Mar 2, 2018 445 | * FIX linux-install - use mkdir -p to ensure parent dirs are created 446 | * FIX brew install - move man page installation from formula to install.sh 447 | * FIX TDEPS-45 - don't swipe -h flag if main aliases are in effect 448 | * FIX TDEPS-47 - use classpath cache with -Sdeps 449 | * 1.9.0.348 on Feb 23, 2018 450 | * NEW Add --prefix to linux-install (INST-9) 451 | * NEW Add man page to installation (INST-18) 452 | * FIX Fix uberjar construction to avoid overlap of file and directory with same name 453 | * FIX Add missing license file 454 | * 1.9.0.341 on Feb 21, 2018 455 | * CHANGE -Senv to -Sdescribe 456 | * 1.9.0.338 on Feb 20, 2018 457 | * NEW -Senv - print edn for Clojure config, similar to -Sverbose info 458 | * NEW -Scp - provide a custom classpath and ignore classpath gen 459 | * 1.9.0.326 on Feb 2, 2018 460 | * NEW -O - Java option aliases (append if multiple) 461 | * NEW -M - clojure.main option aliases (replace if multiple) 462 | * NEW -A - generic alias can combine any kind of alias and all are applied 463 | * FIX - if multiple alias switches supplied, they combine 464 | * FIX - whitespace in help fixed 465 | * 1.9.0.315 on Jan 23, 2018 466 | * NEW -Stree to print dependency tree 467 | * NEW -Sdeps to supply a deps.edn on the command line as data 468 | * FIX bug with git deps using :deps/root writing File objects to libs files 469 | * 1.9.0.309 on Jan 18, 2018 470 | * NEW -Spom emits dep exclusions and classifier 471 | * NEW pom file reader for local and git deps 472 | * FIX git deps now use :deps/root if specified 473 | * FIX major updates to improve transitive version selection 474 | * ENHANCE git version resolution uses stricter rules in comparison 475 | * ENHANCE dump stack on unexpected errors for debugging 476 | * 1.9.0.302 on Jan 8, 2018 477 | * CHANGE git dep attributes (removed :rev, added :tag and :sha) 478 | * FIX Java 9 warning with -Spom 479 | * NEW -Sresolve-tags 480 | * 1.9.0.297 on Jan 4, 2018 481 | * NEW git deps 482 | * NEW Updated -Spom to include repositories in the pom 483 | * 1.9.0.273 on Dec 8, 2017 484 | * Initial release for 1.9 485 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 1.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial code and documentation 12 | distributed under this Agreement, and 13 | b) in the case of each subsequent Contributor: 14 | i) changes to the Program, and 15 | ii) additions to the Program; 16 | 17 | where such changes and/or additions to the Program originate from and are 18 | distributed by that particular Contributor. A Contribution 'originates' 19 | from a Contributor if it was added to the Program by such Contributor 20 | itself or anyone acting on such Contributor's behalf. Contributions do not 21 | include additions to the Program which: (i) are separate modules of 22 | software distributed in conjunction with the Program under their own 23 | license agreement, and (ii) are not derivative works of the Program. 24 | 25 | "Contributor" means any person or entity that distributes the Program. 26 | 27 | "Licensed Patents" mean patent claims licensable by a Contributor which are 28 | necessarily infringed by the use or sale of its Contribution alone or when 29 | combined with the Program. 30 | 31 | "Program" means the Contributions distributed in accordance with this 32 | Agreement. 33 | 34 | "Recipient" means anyone who receives the Program under this Agreement, 35 | including all Contributors. 36 | 37 | 2. GRANT OF RIGHTS 38 | a) Subject to the terms of this Agreement, each Contributor hereby grants 39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 40 | reproduce, prepare derivative works of, publicly display, publicly 41 | perform, distribute and sublicense the Contribution of such Contributor, 42 | if any, and such derivative works, in source code and object code form. 43 | b) Subject to the terms of this Agreement, each Contributor hereby grants 44 | Recipient a non-exclusive, worldwide, royalty-free patent license under 45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 46 | transfer the Contribution of such Contributor, if any, in source code and 47 | object code form. This patent license shall apply to the combination of 48 | the Contribution and the Program if, at the time the Contribution is 49 | added by the Contributor, such addition of the Contribution causes such 50 | combination to be covered by the Licensed Patents. The patent license 51 | shall not apply to any other combinations which include the Contribution. 52 | No hardware per se is licensed hereunder. 53 | c) Recipient understands that although each Contributor grants the licenses 54 | to its Contributions set forth herein, no assurances are provided by any 55 | Contributor that the Program does not infringe the patent or other 56 | intellectual property rights of any other entity. Each Contributor 57 | disclaims any liability to Recipient for claims brought by any other 58 | entity based on infringement of intellectual property rights or 59 | otherwise. As a condition to exercising the rights and licenses granted 60 | hereunder, each Recipient hereby assumes sole responsibility to secure 61 | any other intellectual property rights needed, if any. For example, if a 62 | third party patent license is required to allow Recipient to distribute 63 | the Program, it is Recipient's responsibility to acquire that license 64 | before distributing the Program. 65 | d) Each Contributor represents that to its knowledge it has sufficient 66 | copyright rights in its Contribution, if any, to grant the copyright 67 | license set forth in this Agreement. 68 | 69 | 3. REQUIREMENTS 70 | 71 | A Contributor may choose to distribute the Program in object code form under 72 | its own license agreement, provided that: 73 | 74 | a) it complies with the terms and conditions of this Agreement; and 75 | b) its license agreement: 76 | i) effectively disclaims on behalf of all Contributors all warranties 77 | and conditions, express and implied, including warranties or 78 | conditions of title and non-infringement, and implied warranties or 79 | conditions of merchantability and fitness for a particular purpose; 80 | ii) effectively excludes on behalf of all Contributors all liability for 81 | damages, including direct, indirect, special, incidental and 82 | consequential damages, such as lost profits; 83 | iii) states that any provisions which differ from this Agreement are 84 | offered by that Contributor alone and not by any other party; and 85 | iv) states that source code for the Program is available from such 86 | Contributor, and informs licensees how to obtain it in a reasonable 87 | manner on or through a medium customarily used for software exchange. 88 | 89 | When the Program is made available in source code form: 90 | 91 | a) it must be made available under this Agreement; and 92 | b) a copy of this Agreement must be included with each copy of the Program. 93 | Contributors may not remove or alter any copyright notices contained 94 | within the Program. 95 | 96 | Each Contributor must identify itself as the originator of its Contribution, 97 | if 98 | any, in a manner that reasonably allows subsequent Recipients to identify the 99 | originator of the Contribution. 100 | 101 | 4. COMMERCIAL DISTRIBUTION 102 | 103 | Commercial distributors of software may accept certain responsibilities with 104 | respect to end users, business partners and the like. While this license is 105 | intended to facilitate the commercial use of the Program, the Contributor who 106 | includes the Program in a commercial product offering should do so in a manner 107 | which does not create potential liability for other Contributors. Therefore, 108 | if a Contributor includes the Program in a commercial product offering, such 109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify 110 | every other Contributor ("Indemnified Contributor") against any losses, 111 | damages and costs (collectively "Losses") arising from claims, lawsuits and 112 | other legal actions brought by a third party against the Indemnified 113 | Contributor to the extent caused by the acts or omissions of such Commercial 114 | Contributor in connection with its distribution of the Program in a commercial 115 | product offering. The obligations in this section do not apply to any claims 116 | or Losses relating to any actual or alleged intellectual property 117 | infringement. In order to qualify, an Indemnified Contributor must: 118 | a) promptly notify the Commercial Contributor in writing of such claim, and 119 | b) allow the Commercial Contributor to control, and cooperate with the 120 | Commercial Contributor in, the defense and any related settlement 121 | negotiations. The Indemnified Contributor may participate in any such claim at 122 | its own expense. 123 | 124 | For example, a Contributor might include the Program in a commercial product 125 | offering, Product X. That Contributor is then a Commercial Contributor. If 126 | that Commercial Contributor then makes performance claims, or offers 127 | warranties related to Product X, those performance claims and warranties are 128 | such Commercial Contributor's responsibility alone. Under this section, the 129 | Commercial Contributor would have to defend claims against the other 130 | Contributors related to those performance claims and warranties, and if a 131 | court requires any other Contributor to pay any damages as a result, the 132 | Commercial Contributor must pay those damages. 133 | 134 | 5. NO WARRANTY 135 | 136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN 137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each 140 | Recipient is solely responsible for determining the appropriateness of using 141 | and distributing the Program and assumes all risks associated with its 142 | exercise of rights under this Agreement , including but not limited to the 143 | risks and costs of program errors, compliance with applicable laws, damage to 144 | or loss of data, programs or equipment, and unavailability or interruption of 145 | operations. 146 | 147 | 6. DISCLAIMER OF LIABILITY 148 | 149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 156 | OF SUCH DAMAGES. 157 | 158 | 7. GENERAL 159 | 160 | If any provision of this Agreement is invalid or unenforceable under 161 | applicable law, it shall not affect the validity or enforceability of the 162 | remainder of the terms of this Agreement, and without further action by the 163 | parties hereto, such provision shall be reformed to the minimum extent 164 | necessary to make such provision valid and enforceable. 165 | 166 | If Recipient institutes patent litigation against any entity (including a 167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 168 | (excluding combinations of the Program with other software or hardware) 169 | infringes such Recipient's patent(s), then such Recipient's rights granted 170 | under Section 2(b) shall terminate as of the date such litigation is filed. 171 | 172 | All Recipient's rights under this Agreement shall terminate if it fails to 173 | comply with any of the material terms or conditions of this Agreement and does 174 | not cure such failure in a reasonable period of time after becoming aware of 175 | such noncompliance. If all Recipient's rights under this Agreement terminate, 176 | Recipient agrees to cease use and distribution of the Program as soon as 177 | reasonably practicable. However, Recipient's obligations under this Agreement 178 | and any licenses granted by Recipient relating to the Program shall continue 179 | and survive. 180 | 181 | Everyone is permitted to copy and distribute copies of this Agreement, but in 182 | order to avoid inconsistency the Agreement is copyrighted and may only be 183 | modified in the following manner. The Agreement Steward reserves the right to 184 | publish new versions (including revisions) of this Agreement from time to 185 | time. No one other than the Agreement Steward has the right to modify this 186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 187 | Eclipse Foundation may assign the responsibility to serve as the Agreement 188 | Steward to a suitable separate entity. Each new version of the Agreement will 189 | be given a distinguishing version number. The Program (including 190 | Contributions) may always be distributed subject to the version of the 191 | Agreement under which it was received. In addition, after a new version of the 192 | Agreement is published, Contributor may elect to distribute the Program 193 | (including its Contributions) under the new version. Except as expressly 194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 195 | licenses to the intellectual property of any Contributor under this Agreement, 196 | whether expressly, by implication, estoppel or otherwise. All rights in the 197 | Program not expressly granted under this Agreement are reserved. 198 | 199 | This Agreement is governed by the laws of the State of New York and the 200 | intellectual property laws of the United States of America. No party to this 201 | Agreement will bring a legal action under this Agreement more than one year 202 | after the cause of action arose. Each party waives its rights to a jury trial in 203 | any resulting litigation. 204 | 205 | 206 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | brew-install 2 | ===================================== 3 | 4 | The brew-install project is used to create a brew formula for installing 5 | clojure tools on the Mac. The outputs of this project are a tar file 6 | (versioned) and a brew formula (clojure.rb), suitable for updating in the 7 | brew central tap. 8 | 9 | The tar file contains: 10 | 11 | * clojure-tools jar - an uberjar for constructing classpaths via tools.deps 12 | * deps.edn - a copy of the root deps.edn file (no longer used at runtime) 13 | * example-deps.edn - the initial user deps.edn file 14 | * tools.edn - the tools.tools tool to auto install 15 | * clojure script - the main Clojure runner 16 | * clj script - a clojure wrapper for interactive repl use (adds rlwrap) 17 | 18 | ## Updating versions 19 | 20 | The clojure-tools version is defined by the pom.xml project version. It 21 | should be updated only by running script/update_version (the build does 22 | this automatically). The current version is stored in the VERSION file. 23 | 24 | The Clojure and tools.deps versions to include in the clojure-tools are 25 | taken from the deps.edn. 26 | 27 | ## Package script 28 | 29 | To create the packages and installers, run: 30 | 31 | ``` 32 | clojure -T:build release 33 | ``` 34 | 35 | ## Release Information 36 | 37 | These files are not released into Maven central like other libraries. Instead, the tar 38 | file is created and published as a Github release 39 | [here](https://github.com/clojure/brew-install/releases). 40 | 41 | The [Clojure homebrew tap](https://github.com/clojure/homebrew-tools) is updated when new releases 42 | are created or promoted to stable. 43 | 44 | The Homebrew Central Clojure recipe is updated manually so may lag the Clojure tap. 45 | 46 | ## References 47 | 48 | See the following resources for more information: 49 | 50 | * https://clojure.org/guides/install_clojure - installation 51 | * https://clojure.org/guides/deps_and_cli - deps and CLI guide 52 | * https://clojure.org/reference/deps_edn - deps.edn reference 53 | * https://clojure.org/reference/clojure_cli - Clojure CLI reference 54 | * https://github.com/clojure/tools.deps - dependency and classpath library 55 | 56 | ## Developer Information 57 | 58 | * [GitHub project](https://github.com/clojure/brew-install) 59 | * [How to contribute](https://clojure.org/community/contributing) 60 | * [Bug Tracker](https://clojure.atlassian.net/browse/TDEPS) 61 | 62 | ## License 63 | 64 | Copyright © Rich Hickey, Alex Miller and contributors 65 | 66 | Distributed under the Eclipse Public License 1.0, the same as Clojure. 67 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.12.1.1550 2 | -------------------------------------------------------------------------------- /VERSION_TEMPLATE: -------------------------------------------------------------------------------- 1 | 1.12.1.GENERATED_VERSION 2 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:paths [] 2 | 3 | :deps 4 | {org.clojure/clojure {:mvn/version "1.12.1"} 5 | org.clojure/tools.deps {:mvn/version "0.24.1523"} 6 | org.slf4j/slf4j-nop {:mvn/version "1.7.36"}} 7 | 8 | :aliases 9 | { 10 | ;; clj -T:build release 11 | :build 12 | {:deps {io.github.clojure/tools.build {:git/tag "v0.10.9" :git/sha "e405aac"}} 13 | :paths ["script"] 14 | :ns-default build} 15 | 16 | ;; clj -X:test 17 | :test {:extra-paths ["src/test/clojure" "src/main/clojure"] 18 | :extra-deps {io.github.cognitect-labs/test-runner 19 | {:git/tag "v0.5.1" :git/sha "dfb30dd"}} 20 | :exec-fn cognitect.test-runner.api/test 21 | :exec-args {:dirs ["src/test/clojure"] 22 | :patterns [".*"]}} 23 | }} 24 | -------------------------------------------------------------------------------- /devel.properties: -------------------------------------------------------------------------------- 1 | 1.12.1.1550 906c625679c72e7035875988a46392a1d83d16ee1df599a561a2fd33424b0d3f 2 | -------------------------------------------------------------------------------- /doc/clojure.1: -------------------------------------------------------------------------------- 1 | .\"to render: groff -Tascii -man doc/clojure.1 > clojure.man" 2 | .TH CLOJURE 1 "2019 June 6" 3 | .SH NAME 4 | clj, clojure \- runners to launch Clojure programs 5 | 6 | .SH SYNOPSIS 7 | 8 | .B clj 9 | [\fBclj-opts\fR] [\fB-Aaliases\fR] 10 | .br 11 | .B clojure 12 | [\fBclj-opts\fR] \fB-X\fR[\fBaliases\fR] \fBmy/fn?\fR [\fBkpath v\fR ...] \fBkv-map?\fR 13 | .br 14 | .B clojure 15 | [\fBclj-opts\fR] \fB-T\fR[\fBname|aliases\fR] \fBmy/fn\fR [\fBkpath v\fR ...] \fBkv-map?\fR 16 | .br 17 | .B clojure 18 | [\fBclj-opts\fR] \fB-M\fR[\fBaliases\fR] [\fBinit-opts\fR] [\fBmain-opts\fR] [\fBargs\fR] 19 | 20 | .SH DESCRIPTION 21 | 22 | The 23 | .B clojure 24 | tool is a runner for Clojure programs. 25 | .B clj 26 | is a wrapper for 27 | .B clojure 28 | that uses rlwrap to provide a better interactive experience. 29 | Users will typically run 30 | .BR clj . 31 | 32 | .SH EXAMPLES 33 | 34 | You can launch a Clojure REPL by running 35 | .BR clj . 36 | 37 | See the Deps and CLI Guide below for more complex usage. 38 | 39 | .SH OPTIONS 40 | 41 | The 42 | .B clj 43 | and 44 | .B clojure 45 | scripts can take three types of options, as shown in the 46 | synopsis. 47 | .B clj-opts 48 | are used to build the java-opts and 49 | classpath. 50 | .B init-opts 51 | refer to Clojure code to execute. 52 | .B main-opts 53 | are options to clojure.main. 54 | 55 | .SS clj-opts 56 | 57 | .TP 58 | .BI \-J opt 59 | Pass opt through in java_opts, ex: -J-Xmx512m 60 | 61 | .TP 62 | .BI \-A aliases 63 | Concatenated aliases for REPL execution, ex: -A:dev:mem 64 | 65 | .TP 66 | .BI \-X aliases\ \fIfn\fR " " \fIKPATH\fR " " \fIV\fR " " 67 | Exec alias to invoke one or more functions that take a map, 68 | with keypath/value overrides. Function must either be 69 | supplied or be in :exec-fn argmap for alias 70 | 71 | .TP 72 | .BI \-M aliases 73 | Exec clojure.main, either from opts in alias or command line 74 | 75 | .TP 76 | .BI \-P 77 | Prepare - download libs, cache classpath without executing 78 | 79 | .TP 80 | .BI \-Sdeps\ EDN 81 | Deps data or file to use as the last deps file to be merged 82 | 83 | .TP 84 | .BI \-Spath 85 | Compute classpath and echo to stdout only 86 | 87 | .TP 88 | .BI \-Stree 89 | Print dependency tree 90 | 91 | .TP 92 | .BI \-Scp\ CP 93 | Do NOT compute or cache classpath, use this one instead 94 | 95 | .TP 96 | .BI \-Srepro 97 | Ignore the ~/.clojure/deps.edn config file 98 | 99 | .TP 100 | .BI \-Sforce 101 | Force recomputation of the classpath (don't use the cache) 102 | 103 | .TP 104 | .BI \-Sverbose 105 | Print important path info to console 106 | 107 | .TP 108 | .BI \-Sthreads\ N 109 | Set specific number of download threads 110 | 111 | .TP 112 | .BI \-Strace 113 | Write a trace.edn file that traces deps expansion 114 | 115 | .TP 116 | .BI \-\- 117 | Stop parsing dep options and pass remaining arguments to clojure.main 118 | 119 | .TP 120 | .BI \-\-version 121 | Write version to stdout and exit 122 | 123 | .TP 124 | .BI \-version 125 | Write version to stderr and exit 126 | 127 | .SS init-opts 128 | 129 | .TP 130 | .BR \-i ", " \-\-init\ \fIpath\fR 131 | Load a file or resource located at \fIpath\fR 132 | 133 | .TP 134 | .BR \-e ", " \-\-eval\ \fIstring\fR 135 | Eval exprs in \fIstring\fR; print non-nil values 136 | 137 | .TP 138 | .BR \-\-report\ \fItarget\fR 139 | Report uncaught exception to \fItarget\fR: "file" (default), "stderr", or "none", overrides System property clojure.main.report 140 | 141 | .SS main-opts 142 | 143 | 144 | .TP 145 | .BR \-m ", " \-\-main\ \fIns-name \fR 146 | Call the -main function from namespace w/args 147 | 148 | .TP 149 | .BR \-r ", " \-\-repl 150 | Run a repl 151 | 152 | .TP 153 | .I path 154 | Run a script from a file or resource located at \fIpath\fR 155 | 156 | .TP 157 | .B \- 158 | Run a script from standard input 159 | 160 | .TP 161 | .BR \-h ", " \-? ", " \-\-help 162 | Print this help message and exit 163 | 164 | .SH CONFIGURATION 165 | 166 | This script reads configuration from 167 | .B deps.edn 168 | files. It will check against 169 | .B deps.edn 170 | files in the system root location, the user 171 | configuration directory (usually 172 | .BR ~/.clojure ), 173 | and the local directory. Files in each of these locations, if 174 | they exist, are merged to form one combined configuration 175 | file. The last specified configuration file's options 176 | overwrites any earlier files (e.g. local configs take 177 | priority). 178 | 179 | .SH SEE ALSO 180 | 181 | .IP https://clojure.org/guides/deps_and_cli 182 | Deps and CLI Guide 183 | .IP https://clojure.org/reference/deps_edn 184 | deps.edn Reference 185 | .IP https://clojure.org/reference/clojure_cli 186 | Clojure CLI Reference 187 | .IP https://clojure.org/reference/repl_and_main 188 | REPL and Main Entrypoints 189 | .IP https://clojure.org/releases/tools 190 | Release history and changelog 191 | 192 | .SH BUGS 193 | 194 | File issues at 195 | https://ask.clojure.org under category Libs / tools.deps. 196 | 197 | .SH AUTHORS 198 | 199 | clojure and clj are maintained by Alex Miller . 200 | This man page was written by Elana Hashman . 201 | 202 | .SH COPYRIGHT 203 | 204 | Copyright \(co Rich Hickey, Alex Miller and contributors. 205 | 206 | Distributed under the Eclipse Public License 1.0, the same as 207 | Clojure. 208 | -------------------------------------------------------------------------------- /epl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Eclipse Public License - Version 1.0 8 | 25 | 26 | 27 | 28 | 29 | 30 |

Eclipse Public License - v 1.0

31 | 32 |

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

36 | 37 |

1. DEFINITIONS

38 | 39 |

"Contribution" means:

40 | 41 |

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

43 |

b) in the case of each subsequent Contributor:

44 |

i) changes to the Program, and

45 |

ii) additions to the Program;

46 |

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

54 | 55 |

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

57 | 58 |

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

61 | 62 |

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

64 | 65 |

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

67 | 68 |

2. GRANT OF RIGHTS

69 | 70 |

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

76 | 77 |

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

88 | 89 |

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

101 | 102 |

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

105 | 106 |

3. REQUIREMENTS

107 | 108 |

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

110 | 111 |

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

113 | 114 |

b) its license agreement:

115 | 116 |

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

120 | 121 |

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

124 | 125 |

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

128 | 129 |

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

133 | 134 |

When the Program is made available in source code form:

135 | 136 |

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

137 | 138 |

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

140 | 141 |

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

143 | 144 |

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

147 | 148 |

4. COMMERCIAL DISTRIBUTION

149 | 150 |

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

172 | 173 |

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

183 | 184 |

5. NO WARRANTY

185 | 186 |

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

197 | 198 |

6. DISCLAIMER OF LIABILITY

199 | 200 |

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

208 | 209 |

7. GENERAL

210 | 211 |

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

216 | 217 |

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

223 | 224 |

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

232 | 233 |

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

252 | 253 |

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

258 | 259 | 260 | 261 | 262 | -------------------------------------------------------------------------------- /script/build.clj: -------------------------------------------------------------------------------- 1 | (ns build 2 | (:require 3 | [clojure.string :as str] 4 | [clojure.tools.build.api :as b])) 5 | 6 | ;; project config 7 | (def lib 'org.clojure/clojure-tools) 8 | (def version (str/trim (slurp "VERSION"))) 9 | (def basis (b/create-basis {})) 10 | (def clojure-ver (get-in basis [:libs 'org.clojure/clojure :mvn/version])) 11 | (def stable (str/split (str/trim (slurp "stable.properties")) #" ")) 12 | 13 | ;; dirs 14 | (def doc-dir "doc") 15 | (def target-dir "target") 16 | (def filtered-dir "target/filtered") 17 | (def class-dir "target/classes") 18 | (def exec-dir "target/exec") 19 | (def tar-dir "target/clojure-tools") 20 | (def zip-dir "target/win") 21 | (def uber-file (format "target/clojure-tools-%s.jar" version)) 22 | (def tar-file (format "target/clojure-tools-%s.tar.gz" version)) 23 | (def zip-file "target/clojure-tools.zip") 24 | (def exec-file "target/exec.jar") 25 | 26 | (defn clean 27 | [_] 28 | (b/delete {:path "target"})) 29 | 30 | (defn release 31 | [_] 32 | (clean nil) 33 | 34 | ;; Filter all resources, replacing properties as needed 35 | (b/copy-dir {:src-dirs ["src/main/resources"] 36 | :target-dir filtered-dir 37 | :replace {"${project.version}" version 38 | "${version.short}" (str/replace version "." "") 39 | "${clojure.version}" clojure-ver 40 | "${tools.deps.version}" (get-in basis [:libs 'org.clojure/tools.deps :mvn/version]) 41 | "${stable.version}" (first stable) 42 | "${stable.sha}" (second stable)}}) 43 | 44 | ;; Make the uber jar 45 | (b/compile-clj {:basis basis :class-dir class-dir :src-dirs [] 46 | :compile-opts {:elide-meta [:doc :file :line] :direct-linking true} 47 | :ns-compile '[clojure.tools.deps.script.make-classpath2 48 | clojure.tools.deps.script.generate-manifest2 49 | clojure.tools.deps.util.s3-aws-client]}) 50 | (b/uber {:basis basis :class-dir class-dir :uber-file uber-file}) 51 | 52 | ;; Make the exec jar 53 | (b/copy-dir {:src-dirs ["src/main/clojure"] :target-dir exec-dir}) 54 | (b/jar {:class-dir exec-dir :jar-file exec-file}) 55 | 56 | ;; Collect the tar file contents and make the tar and installer 57 | (doseq [f ["clojure" "clj" "install.sh" "linux-install.sh" "posix-install.sh"]] 58 | (b/process {:command-args ["chmod" "+x" (str filtered-dir "/clojure/install/" f)]})) 59 | (doseq [f ["clj" "clojure" "install.sh" "deps.edn" "example-deps.edn" "tools.edn"]] 60 | (b/copy-file {:src (str filtered-dir "/clojure/install/" f) :target (str tar-dir "/" f)})) 61 | (b/copy-file {:src (str doc-dir "/clojure.1") :target (str tar-dir "/clojure.1")}) 62 | (b/copy-file {:src (str doc-dir "/clojure.1") :target (str tar-dir "/clj.1")}) 63 | (b/copy-dir {:src-dirs [target-dir] :target-dir tar-dir :include "*.jar"}) 64 | (b/process {:command-args ["tar" "-cvzf" tar-file "-Ctarget" "clojure-tools"]}) 65 | (b/copy-file {:src (str filtered-dir "/clojure/install/linux-install.sh") :target (str target-dir "/linux-install.sh")}) 66 | (b/copy-file {:src (str filtered-dir "/clojure/install/posix-install.sh") :target (str target-dir "/posix-install.sh")}) 67 | 68 | ;; Collect the windows files and make the windows zip file and installer 69 | (doseq [f ["ClojureTools.psd1" "ClojureTools.psm1" "deps.edn" "example-deps.edn" "tools.edn"]] 70 | (b/copy-file {:src (str filtered-dir "/clojure/install/" f) :target (str zip-dir "/ClojureTools/" f)})) 71 | (b/copy-dir {:src-dirs [target-dir] :target-dir (str zip-dir "/ClojureTools") :include "*.jar"}) 72 | (b/zip {:src-dirs [zip-dir] :zip-file zip-file}) 73 | (b/copy-file {:src (str filtered-dir "/clojure/install/win-install.ps1") :target (str target-dir "/win-install.ps1")}) 74 | 75 | ;; Prep the brew files 76 | (let [sha (-> (:out (b/process {:command-args ["shasum" "-a" "256" tar-file] :out :capture})) (subs 0 64)) 77 | brew-recipe (slurp (str filtered-dir "/clojure/install/clojure.rb")) 78 | version-recipe (slurp (str filtered-dir "/clojure/install/clojure@version.rb"))] 79 | (b/write-file {:path "target/clojure.rb" :string (str/replace brew-recipe "SHA" sha)}) 80 | (b/write-file {:path (format "target/clojure@%s.rb" version) :string (str/replace version-recipe "SHA" sha)}))) 81 | -------------------------------------------------------------------------------- /script/print_version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | version_template=$(cat VERSION_TEMPLATE) 6 | rev=$(git rev-list HEAD --count) 7 | v=${version_template/GENERATED_VERSION/$rev} 8 | echo "$v" 9 | -------------------------------------------------------------------------------- /script/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # Commit and deploy to s3 6 | if [[ ! -z "$S3_BUCKET" ]]; then 7 | # Write devel properties 8 | version=$(cat VERSION) 9 | sha=$(shasum -a 256 "target/clojure-tools-$version.tar.gz" | cut -c 1-64) 10 | echo "$sha" > target/clojure-tools-$version.tar.gz.sha256 11 | echo "$version $sha" > devel.properties 12 | git add devel.properties 13 | git commit -m "update devel to $version" 14 | 15 | echo "Deploying https://download.clojure.org/install/clojure@$version.rb" 16 | aws s3 cp --only-show-errors "target/clojure.rb" "$S3_BUCKET/install/clojure.rb" 17 | aws s3 cp --only-show-errors "target/clojure@$version.rb" "$S3_BUCKET/install/clojure@$version.rb" 18 | echo "Deploying https://download.clojure.org/install/clojure-tools-$version.tar.gz" 19 | aws s3 cp --only-show-errors "target/clojure-tools-$version.tar.gz" "$S3_BUCKET/install/clojure-tools.tar.gz" 20 | aws s3 cp --only-show-errors "target/clojure-tools-$version.tar.gz" "$S3_BUCKET/install/clojure-tools-$version.tar.gz" 21 | echo "Deploying https://download.clojure.org/install/linux-install-$version.sh" 22 | aws s3 cp --only-show-errors "target/linux-install.sh" "$S3_BUCKET/install/linux-install.sh" 23 | aws s3 cp --only-show-errors "target/linux-install.sh" "$S3_BUCKET/install/linux-install-$version.sh" 24 | echo "Deploying https://download.clojure.org/install/posix-install-$version.sh" 25 | aws s3 cp --only-show-errors "target/posix-install.sh" "$S3_BUCKET/install/posix-install.sh" 26 | aws s3 cp --only-show-errors "target/posix-install.sh" "$S3_BUCKET/install/posix-install-$version.sh" 27 | echo "Deploying https://download.clojure.org/install/clojure-tools-$version.zip" 28 | echo "$(shasum -a 256 target/clojure-tools.zip | cut -c 1-64)" > target/clojure-tools.zip.sha256 29 | aws s3 cp --only-show-errors "target/clojure-tools.zip" "$S3_BUCKET/install/clojure-tools.zip" 30 | aws s3 cp --only-show-errors "target/clojure-tools.zip" "$S3_BUCKET/install/clojure-tools-$version.zip" 31 | echo "Deploying https://download.clojure.org/install/win-install-$version.ps1" 32 | aws s3 cp --only-show-errors "target/win-install.ps1" "$S3_BUCKET/install/win-install.ps1" 33 | aws s3 cp --only-show-errors "target/win-install.ps1" "$S3_BUCKET/install/win-install-$version.ps1" 34 | fi 35 | -------------------------------------------------------------------------------- /script/read_versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # Grab version info 6 | read stable_version stable_sha < stable.properties 7 | read devel_version devel_sha < devel.properties 8 | echo "Promoting stable from $stable_version to $devel_version" 9 | 10 | export STABLE_VERSION=$stable_version 11 | export STABLE_SHA=$stable_sha 12 | export DEVEL_VERSION=$devel_version 13 | export DEVEL_SHA=$devel_sha -------------------------------------------------------------------------------- /script/update_version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | v=$(script/print_version) 6 | echo "Setting version to $v" 7 | echo "$v" > VERSION 8 | git commit -m "update version to $v" VERSION 9 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/run/exec.clj: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.run.exec 10 | (:require 11 | ;; NOTE: ONLY depend on Clojure core, loaded in user's classpath so can't have any deps 12 | [clojure.edn :as edn] 13 | [clojure.java.io :as jio] 14 | [clojure.string :as str] 15 | [clojure.spec.alpha :as s]) 16 | (:import 17 | [clojure.lang ExceptionInfo] 18 | [java.io StringWriter Writer FileNotFoundException PushbackReader BufferedReader] 19 | [java.util.concurrent Executors ThreadFactory])) 20 | 21 | (set! *warn-on-reflection* true) 22 | (def ^:dynamic *ns-default* nil) 23 | (def ^:dynamic *ns-aliases* nil) 24 | 25 | (defn- err 26 | ^Throwable [& msg] 27 | (ex-info (str/join " " msg) {:exec-msg true})) 28 | 29 | (defn- requiring-resolve' 30 | ;; copied and modified from core to remove constraints on Clojure 1.10.x 31 | [sym] 32 | (if (nil? (namespace sym)) 33 | (throw (err "Not a qualified symbol:" sym)) 34 | (or (resolve sym) 35 | (do 36 | (-> sym namespace symbol require) 37 | (resolve sym))))) 38 | 39 | (defn remove-ns-keys 40 | "Remove keys in m with namespace string ns-str" 41 | [m ns-str] 42 | (reduce-kv #(if (= ns-str (namespace %2)) %1 (assoc %1 %2 %3)) {} m)) 43 | 44 | (defn- add-stream 45 | [envelope stream-tag ^Writer writer] 46 | (.flush writer) 47 | (let [s (str writer)] 48 | (if (str/blank? s) 49 | envelope 50 | (assoc envelope stream-tag s)))) 51 | 52 | (defn- envelope 53 | [args tag val out-wr err-wr start] 54 | (let [end (System/currentTimeMillis)] 55 | (cond-> {:tag tag 56 | :val (binding [*print-namespace-maps* false] (pr-str val)) 57 | :ms (- end start)} 58 | (= :capture (:clojure.exec/out args)) (add-stream :out out-wr) 59 | (= :capture (:clojure.exec/err args)) (add-stream :err err-wr)))) 60 | 61 | (defn apply-program 62 | [f args] 63 | (let [clean-args (remove-ns-keys args "clojure.exec") 64 | out-wr (StringWriter.) 65 | err-wr (StringWriter.) 66 | start (System/currentTimeMillis) 67 | envelope (binding [*out* out-wr, *err* err-wr] 68 | (try 69 | (envelope args :ret (f clean-args) out-wr err-wr start) 70 | (catch Throwable t 71 | (envelope args :err (Throwable->map t) out-wr err-wr start)) 72 | (finally 73 | (.close out-wr) 74 | (.close err-wr))))] 75 | (binding [*print-namespace-maps* false] 76 | (prn envelope)))) 77 | 78 | (defn exec 79 | "Resolve and execute the function f (a symbol) with args" 80 | [f args] 81 | (let [resolved-f (try 82 | (requiring-resolve' f) 83 | (catch FileNotFoundException _ 84 | (throw (err "Namespace could not be found on classpath:" (namespace f)))))] 85 | (if resolved-f 86 | (if (= :fn (:clojure.exec/invoke args)) 87 | (apply-program resolved-f args) 88 | (resolved-f args)) 89 | (throw (err "Namespace" (namespace f) "loaded but function not found:" (name f)))))) 90 | 91 | (defn- apply-overrides 92 | [args overrides] 93 | (reduce (fn [m [k v]] 94 | (if (sequential? k) 95 | (assoc-in m k v) 96 | (assoc m k v))) 97 | args (partition-all 2 overrides))) 98 | 99 | (defn- qualify-fn 100 | "Compute function symbol based on exec-fn, ns-aliases, and ns-default" 101 | [fsym ns-aliases ns-default] 102 | ;; validation - make specs? 103 | (when (and fsym (not (symbol? fsym))) 104 | (throw (err "Expected function symbol:" fsym))) 105 | 106 | (when fsym 107 | (if (qualified-ident? fsym) 108 | (let [nsym (get ns-aliases (symbol (namespace fsym)))] 109 | (if nsym 110 | (symbol (str nsym) (name fsym)) 111 | fsym)) 112 | (if ns-default 113 | (symbol (str ns-default) (str fsym)) 114 | (throw (err "Unqualified function can't be resolved:" fsym)))))) 115 | 116 | (defn- read-basis 117 | [] 118 | (when-let [f (jio/file (System/getProperty "clojure.basis"))] 119 | (if (and f (.exists f)) 120 | (->> f slurp (edn/read-string {:default tagged-literal})) 121 | (throw (err "No basis declared in clojure.basis system property"))))) 122 | 123 | (def arg-spec (s/cat :fns (s/? symbol?) :kvs (s/* (s/cat :k (s/nonconforming (s/or :keyword any? :path vector?)) :v any?)) :trailing (s/? map?))) 124 | 125 | (defn- build-fn-descriptor [{:keys [fns kvs trailing] :as extra}] 126 | (cond-> {} 127 | fns (assoc :function fns) 128 | trailing (assoc :trailing trailing) 129 | kvs (assoc :overrides (reduce #(-> %1 (conj (:k %2)) (conj (:v %2))) [] kvs)))) 130 | 131 | (defn- build-error [expl] 132 | (let [err-str (with-out-str 133 | (doseq [problem (:clojure.spec.alpha/problems expl)] 134 | (println (:reason problem) (:clojure.spec.alpha/value expl))))] 135 | (err "Problem parsing arguments: " err-str))) 136 | 137 | (defn- parse-fn 138 | [args] 139 | (when (seq args) 140 | (let [conf (s/conform arg-spec args)] 141 | (if (s/invalid? conf) 142 | (let [expl (s/explain-data arg-spec args)] 143 | (throw (build-error expl))) 144 | (build-fn-descriptor conf))))) 145 | 146 | (defn- read-args-stdin 147 | [prior-args] 148 | (let [eof (Object.) 149 | r (PushbackReader. (BufferedReader. *in*))] 150 | (loop [args prior-args] 151 | (let [arg (edn/read {:eof eof :default tagged-literal} r)] 152 | (if (= eof arg) 153 | args 154 | (recur (conj args arg))))))) 155 | 156 | (defn- read-args 157 | [args] 158 | (loop [[a & as] args 159 | read-args []] 160 | (if a 161 | (if (= a "-") 162 | (read-args-stdin read-args) 163 | (let [r (try 164 | (edn/read-string {:default tagged-literal} a) 165 | (catch Throwable _ 166 | (throw (err "Unreadable arg:" (pr-str a)))))] 167 | (recur as (conj read-args r)))) 168 | read-args))) 169 | 170 | (defn- set-daemon-agent-executor 171 | "Set Clojure's send-off agent executor (also affects futures). This is almost 172 | an exact rewrite of the Clojure's executor, but the Threads are created as 173 | daemons." 174 | [] 175 | (let [thread-counter (atom 0) 176 | thread-factory (reify ThreadFactory 177 | (newThread [_ runnable] 178 | (doto (Thread. runnable) 179 | (.setDaemon true) ;; DIFFERENT 180 | (.setName (format "CLI-agent-send-off-pool-%d" 181 | (first (swap-vals! thread-counter inc))))))) 182 | executor (Executors/newCachedThreadPool thread-factory)] 183 | (set-agent-send-off-executor! executor))) 184 | 185 | (defn ^:dynamic *exit* 186 | ;; normal exit 187 | ([]) 188 | ;; abnormal exit 189 | ([^Throwable t] (System/exit 1))) 190 | 191 | (defn -main 192 | "Execute a function with map kvs. 193 | 194 | The classpath is determined by the clojure script and make-classpath programs 195 | and has already been set. Any execute argmap keys indicated via aliases will 196 | be read from the basis file :argmap passed via -Dclojure.basis. The exec args 197 | have the following possible keys: 198 | :exec-fn - symbol to be resolved in terms of the namespace context, will 199 | be overridden if passed as arg 200 | :exec-args - map of kv args 201 | :ns-default - namespace default for resolving functions 202 | :ns-aliases - map of alias symbol to namespace symbol for resolving functions 203 | 204 | The actual args to exec are essentially same as to -X: 205 | [fn] (kpath v)+ map? 206 | 207 | fn is resolved from either :exec-fn or fn 208 | map to pass to fn is built from merge of: 209 | exec-args map 210 | map built from kpath/v's 211 | trailing map" 212 | [& args] 213 | (try 214 | (let [execute-args (:argmap (read-basis)) 215 | {:keys [function overrides trailing]} (-> args read-args parse-fn) 216 | {:keys [exec-fn exec-args ns-aliases ns-default]} execute-args 217 | f (or function exec-fn)] 218 | (when (nil? f) 219 | (if (symbol? (first overrides)) 220 | (throw (err "Key is missing value:" (last overrides))) 221 | (throw (err "No function found on command line or in :exec-fn")))) 222 | (set-daemon-agent-executor) 223 | (binding [*ns-default* ns-default 224 | *ns-aliases* ns-aliases] 225 | (let [qualified-fn (qualify-fn f ns-aliases ns-default) 226 | args (merge (apply-overrides exec-args overrides) trailing)] 227 | (exec qualified-fn args))) 228 | (*exit*)) 229 | (catch ExceptionInfo e 230 | (if (-> e ex-data :exec-msg) 231 | (binding [*out* *err*] 232 | (println (.getMessage e)) 233 | (*exit* e)) 234 | (throw e))))) 235 | 236 | (comment 237 | (parse-fn []) ;;=> nil 238 | (parse-fn [:a:b 'foo/bar]) ;;=> {:function [foo/bar]} 239 | (parse-fn [:a:b 'foo/bar :x 1 :y 2]) ;;=> {:function [foo/bar], :overrides [:x 1 :y 2]} 240 | (parse-fn [:a:b 'foo/bar :x 1 :y]) ;;=> Except, missing value for :y 241 | (parse-fn [:x 1 :k 1]) ;;=> {:overrides [:x 1 :k 1]} 242 | (parse-fn ['foo/bar]) ;;=> {:function [foo/bar]} 243 | (parse-fn ['foo/bar :x 1 :y]) ;;=> Except, missing value for :y 244 | (parse-fn [:x 1 :ZZZZZZZZZZZ]) ;;=> Except, missing value for :ZZZZZZZZZZZ 245 | 246 | (parse-fn [:a 1 :b 2]) ;;=> {:overrides [:a 1 :b 2]} 247 | (parse-fn [:a 1 :b 2 {:b 42}]) ;;=> {:overrides [:a 1 :b 2], :trailing {:b 42}} 248 | (parse-fn ['foo/bar {:a 1}]) ;;=> {:function [foo/bar], :trailing {:a 1}} 249 | (parse-fn [:x 1 :k 1 {:a 1}]) ;;=> {:overrides [:x 1 :k 1], :trailing {:a 1}} 250 | (parse-fn ['foo/bar :x 1 :y 2 {:y 42}]) ;;=> {:function [foo/bar], :overrides [:x 1 :y 2], :trailing {:y 42}} 251 | (parse-fn ['foo/bar :x 1 :y {:y 42}]) ;;=> {:function [foo/bar], :overrides [:x 1 :y {:y 42}]} 252 | 253 | (-> ["clojure.run.test-exec/save" ":a" "1" "[:b,:c]" "2"] 254 | read-args 255 | parse-fn) 256 | 257 | (s/conform arg-spec '[a b :a 1 :b 2 {}]) 258 | (s/conform arg-spec '[a b]) 259 | (s/conform arg-spec '[a]) 260 | (s/conform arg-spec '[a {:a 1 :b 2}]) 261 | (s/conform arg-spec '[:a 1 :b 2]) 262 | (s/conform arg-spec '[foo/bar :x 1 :y]) 263 | (s/conform arg-spec '[clojure.run.test-exec/save :a 1 [:b :c] 2])) 264 | 265 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/ClojureTools.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | 3 | # Script module or binary module file associated with this manifest. 4 | RootModule = 'ClojureTools.psm1' 5 | 6 | # Version number of this module. 7 | ModuleVersion = '${project.version}' 8 | 9 | # Supported PSEditions 10 | # CompatiblePSEditions = @() 11 | 12 | # ID used to uniquely identify this module 13 | GUID = 'd5a9d8ac-5951-4a8d-9dec-2d5f47518e5b' 14 | 15 | # Author of this module 16 | Author = 'Rich Hickey' 17 | 18 | # Company or vendor of this module 19 | CompanyName = 'Rich Hickey' 20 | 21 | # Copyright statement for this module 22 | Copyright = '(c) Rich Hickey. All rights reserved.' 23 | 24 | # Description of the functionality provided by this module 25 | Description = 'Provides an unofficial Clojure tools install' 26 | 27 | # Minimum version of the PowerShell engine required by this module 28 | # PowerShellVersion = '' 29 | 30 | # Name of the PowerShell host required by this module 31 | # PowerShellHostName = '' 32 | 33 | # Minimum version of the PowerShell host required by this module 34 | # PowerShellHostVersion = '' 35 | 36 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 37 | # DotNetFrameworkVersion = '' 38 | 39 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 40 | # CLRVersion = '' 41 | 42 | # Processor architecture (None, X86, Amd64) required by this module 43 | # ProcessorArchitecture = '' 44 | 45 | # Modules that must be imported into the global environment prior to importing this module 46 | # RequiredModules = @() 47 | 48 | # Assemblies that must be loaded prior to importing this module 49 | # RequiredAssemblies = @() 50 | 51 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 52 | # ScriptsToProcess = @() 53 | 54 | # Type files (.ps1xml) to be loaded when importing this module 55 | # TypesToProcess = @() 56 | 57 | # Format files (.ps1xml) to be loaded when importing this module 58 | # FormatsToProcess = @() 59 | 60 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 61 | # NestedModules = @() 62 | 63 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 64 | FunctionsToExport = 'Invoke-Clojure' 65 | 66 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 67 | CmdletsToExport = @() 68 | 69 | # Variables to export from this module 70 | VariablesToExport = '*' 71 | 72 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 73 | AliasesToExport = 'clj', 'clojure' 74 | 75 | # DSC resources to export from this module 76 | # DscResourcesToExport = @() 77 | 78 | # List of all modules packaged with this module 79 | # ModuleList = @() 80 | 81 | # List of all files packaged with this module 82 | FileList = 'deps.edn', 'example-deps.edn', 'exec.jar', 'clojure-tools-${project.version}.jar' 83 | 84 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 85 | PrivateData = @{ 86 | 87 | PSData = @{ 88 | 89 | # Tags applied to this module. These help with module discovery in online galleries. 90 | Tags = 'clojure' 91 | 92 | # A URL to the license for this module. 93 | LicenseUri = 'https://www.eclipse.org/legal/epl-v10.html' 94 | 95 | # A URL to the main website for this project. 96 | ProjectUri = 'https://github.com/clojure/brew-install' 97 | 98 | # A URL to an icon representing this module. 99 | # IconUri = '' 100 | 101 | # ReleaseNotes of this module 102 | # ReleaseNotes = '' 103 | 104 | } # End of PSData hashtable 105 | 106 | } # End of PrivateData hashtable 107 | 108 | # HelpInfo URI of this module 109 | # HelpInfoURI = '' 110 | 111 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 112 | # DefaultCommandPrefix = '' 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/ClojureTools.psm1: -------------------------------------------------------------------------------- 1 | function Get-StringHash($str) { 2 | $md5 = new-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider 3 | $utf8 = new-object -TypeName System.Text.UTF8Encoding 4 | return [System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($str))) 5 | } 6 | 7 | function Test-NewerFile($file1, $file2) { 8 | if (!(Test-Path $file1)) { 9 | return $FALSE 10 | } 11 | if (!(Test-Path $file2)) { 12 | return $TRUE 13 | } 14 | $mod1 = (Get-ChildItem $file1).LastWriteTimeUtc 15 | $mod2 = (Get-ChildItem $file2).LastWriteTimeUtc 16 | return $mod1 -gt $mod2 17 | } 18 | 19 | function Invoke-Clojure { 20 | $ErrorActionPreference = 'Stop' 21 | 22 | # Set dir containing the installed files 23 | $InstallDir = $PSScriptRoot 24 | $Version = '${project.version}' 25 | $ToolsCp = "$InstallDir\clojure-tools-$Version.jar" 26 | 27 | # Extract opts 28 | $PrintClassPath = $FALSE 29 | $Describe = $FALSE 30 | $Verbose = $FALSE 31 | $Trace = $FALSE 32 | $Force = $FALSE 33 | $Repro = $FALSE 34 | $Tree = $FALSE 35 | $Pom = $FALSE 36 | $Prep = $FALSE 37 | $Help = $FALSE 38 | $JvmOpts = @() 39 | $ReplAliases = @() 40 | $ClojureArgs = @() 41 | $Mode = "repl" 42 | 43 | $params = $args 44 | while ($params.Count -gt 0) { 45 | $arg, $params = $params 46 | if ($arg -ceq '-version') { 47 | Write-Error "Clojure CLI version $Version" 48 | return 49 | } elseif ($arg -ceq '--version') { 50 | Write-Output "Clojure CLI version $Version" 51 | return 52 | } elseif ($arg.StartsWith('-J')) { 53 | $JvmOpts += $arg.Substring(2) 54 | } elseif ($arg.StartsWith('-R')) { 55 | Write-Error "-R is no longer supported, use -A with repl, -M for main, -X for exec, -T for tool" 56 | return 57 | } elseif ($arg.StartsWith('-C')) { 58 | Write-Error "-C is no longer supported, use -A with repl, -M for main, -X for exec, -T for tool" 59 | return 60 | } elseif ($arg.StartsWith('-O')) { 61 | Write-Error "-O is no longer supported, use -A with repl, -M for main, -X for exec, -T for tool" 62 | return 63 | } elseif ($arg -ceq '-M') { 64 | $Mode = "main" 65 | $ClojureArgs += $params 66 | break 67 | } elseif ($arg -ceq '-M:') { 68 | $Mode = "main" 69 | $kw, $params = $params 70 | $MainAliases = ":$kw" 71 | $ClojureArgs += $params 72 | break 73 | } elseif ($arg -ceq '-T:') { 74 | $Mode = "tool" 75 | $kw, $params = $params 76 | $ToolAliases = ":$kw" 77 | $ClojureArgs += $params 78 | break 79 | } elseif ($arg -ceq '-T') { 80 | $Mode = "tool" 81 | $ClojureArgs += $params 82 | break 83 | } elseif ($arg.StartsWith('-T')) { 84 | $Mode = "tool" 85 | $ToolName = $arg.Substring(2) 86 | $ClojureArgs += $params 87 | break 88 | } elseif ($arg.StartsWith('-A')) { 89 | $aliases, $params = $params 90 | if ($aliases) { 91 | $ReplAliases += ":$aliases" 92 | } 93 | } elseif ($arg -ceq '-X') { 94 | $Mode = "exec" 95 | $ClojureArgs += $params 96 | break 97 | } elseif ($arg -ceq '-X:') { 98 | $Mode = "exec" 99 | $kw, $params = $params 100 | $ExecAliases = ":$kw" 101 | $ClojureArgs += $params 102 | break 103 | } elseif ($arg -ceq '-P') { 104 | $Prep = $TRUE 105 | } elseif ($arg -ceq '-Sdeps') { 106 | $DepsData, $params = $params 107 | } elseif ($arg -ceq '-Scp') { 108 | $ForceCP, $params = $params 109 | } elseif ($arg -ceq '-Spath') { 110 | $PrintClassPath = $TRUE 111 | } elseif ($arg -ceq '-Sverbose') { 112 | $Verbose = $TRUE 113 | } elseif ($arg -ceq '-Sthreads') { 114 | $Threads, $params = $params 115 | } elseif ($arg -ceq '-Strace') { 116 | $Trace = $TRUE 117 | } elseif ($arg -ceq '-Sdescribe') { 118 | $Describe = $TRUE 119 | } elseif ($arg -ceq '-Sforce') { 120 | $Force = $TRUE 121 | } elseif ($arg -ceq '-Srepro') { 122 | $Repro = $TRUE 123 | } elseif ($arg -ceq '-Stree') { 124 | $Tree = $TRUE 125 | } elseif ($arg -ceq '-Spom') { 126 | $Pom = $TRUE 127 | } elseif ($arg -ceq '-Sresolve-tags') { 128 | Write-Error "Option changed, use: clj -X:deps git-resolve-tags" 129 | return 130 | } elseif ($arg.StartsWith('-S')) { 131 | Write-Error "Invalid option: $arg" 132 | return 133 | } elseif ($arg -in '-h', '--help', '-?') { 134 | if ($MainAliases -or $AllAliases) { 135 | $ClojureArgs += $arg, $params 136 | break 137 | } else { 138 | $Help = $TRUE 139 | } 140 | } elseif ($arg -eq '--') { 141 | $ClojureArgs += $params 142 | break 143 | } else { 144 | $ClojureArgs += $arg, $params 145 | break 146 | } 147 | } 148 | 149 | # Find java executable 150 | $JavaCmd = (Get-Command java -ErrorAction SilentlyContinue).Path 151 | if (-not $JavaCmd) { 152 | $CandidateJavas = "$env:JAVA_HOME\bin\java.exe", "$env:JAVA_HOME\bin\java" 153 | $JavaCmd = $CandidateJavas | Where-Object { Test-Path $_ } | Select-Object -First 1 154 | if (-not ($env:JAVA_HOME -and $JavaCmd)) { 155 | Write-Error "Couldn't find 'java'. Please set JAVA_HOME." 156 | return 157 | } 158 | } 159 | if($env:JAVA_OPTS) { 160 | $JavaOpts = $env:JAVA_OPTS.Split(" ") 161 | } else { 162 | $JavaOpts = @() 163 | } 164 | if($env:CLJ_JVM_OPTS) { 165 | $CljJvmOpts = $env:CLJ_JVM_OPTS.Split(" ") 166 | } else { 167 | $CljJvmOpts = @() 168 | } 169 | 170 | if ($Help) { 171 | Write-Host @' 172 | Version: ${project.version} 173 | 174 | You use the Clojure tools ('clj' or 'clojure') to run Clojure programs 175 | on the JVM, e.g. to start a REPL or invoke a specific function with data. 176 | The Clojure tools will configure the JVM process by defining a classpath 177 | (of desired libraries), an execution environment (JVM options) and 178 | specifying a main class and args. 179 | 180 | Using a deps.edn file (or files), you tell Clojure where your source code 181 | resides and what libraries you need. Clojure will then calculate the full 182 | set of required libraries and a classpath, caching expensive parts of this 183 | process for better performance. 184 | 185 | The internal steps of the Clojure tools, as well as the Clojure functions 186 | you intend to run, are parameterized by data structures, often maps. Shell 187 | command lines are not optimized for passing nested data, so instead you 188 | will put the data structures in your deps.edn file and refer to them on the 189 | command line via 'aliases' - keywords that name data structures. 190 | 191 | 'clj' and 'clojure' differ in that 'clj' has extra support for use as a REPL 192 | in a terminal, and should be preferred unless you don't want that support, 193 | then use 'clojure'. 194 | 195 | Usage: 196 | Start a REPL clj [clj-opt*] [-Aaliases] 197 | Exec fn(s) clojure [clj-opt*] -X[aliases] a/fn? [kpath v]* kv-map? 198 | Run tool clojure [clj-opt*] -T[name|aliases] a/fn [kpath v] kv-map? 199 | Run main clojure [clj-opt*] -M[aliases] [init-opt*] [main-opt] [arg*] 200 | Prepare clojure [clj-opt*] -P [other exec opts] 201 | 202 | exec-opts: 203 | -Aaliases Use concatenated aliases to modify classpath 204 | -X[aliases] Use concatenated aliases to modify classpath or supply exec fn/args 205 | -T[name|aliases] Invoke tool by name or via aliases ala -X 206 | -M[aliases] Use concatenated aliases to modify classpath or supply main opts 207 | -P Prepare deps - download libs, cache classpath, but don't exec 208 | 209 | clj-opts: 210 | -Jopt Pass opt through in java_opts, ex: -J-Xmx512m 211 | -Sdeps EDN Deps data to use as the final deps file 212 | -Spath Compute classpath and echo to stdout only 213 | -Stree Print dependency tree 214 | -Scp CP Do NOT compute or cache classpath, use this one instead 215 | -Srepro Use only the local deps.edn (ignore other config files) 216 | -Sforce Force recomputation of the classpath (don't use the cache) 217 | -Sverbose Print important path info to console 218 | -Sthreads Set specific number of download threads 219 | -Strace Write a trace.edn file that traces deps expansion 220 | -- Stop parsing dep options and pass remaining arguments to clojure.main 221 | --version Print the version to stdout and exit 222 | -version Print the version to stderr and exit 223 | 224 | init-opt: 225 | -i, --init path Load a file or resource 226 | -e, --eval string Eval exprs in string; print non-nil values 227 | --report target Report uncaught exception to "file" (default), "stderr", or "none" 228 | 229 | main-opt: 230 | -m, --main ns-name Call the -main function from namespace w/args 231 | -r, --repl Run a repl 232 | path Run a script from a file or resource 233 | - Run a script from standard input 234 | -h, -?, --help Print this help message and exit 235 | 236 | Programs provided by :deps alias: 237 | -X:deps aliases List available aliases and their source 238 | -X:deps list List full transitive deps set and licenses 239 | -X:deps tree Print deps tree 240 | -X:deps find-versions Find available versions of a library 241 | -X:deps prep Prepare all unprepped libs in the dep tree 242 | -X:deps mvn-pom Generate (or update) pom.xml with deps and paths 243 | -X:deps mvn-install Install a maven jar to the local repository cache 244 | -X:deps git-resolve-tags Resolve git coord tags to shas and update deps.edn 245 | 246 | For more info, see: 247 | https://clojure.org/guides/deps_and_cli 248 | https://clojure.org/reference/repl_and_main 249 | '@ 250 | return 251 | } 252 | 253 | # Determine user config directory 254 | if ($env:CLJ_CONFIG) { 255 | $ConfigDir = $env:CLJ_CONFIG 256 | } elseif ($env:HOME) { 257 | $ConfigDir = "$env:HOME\.clojure" 258 | } else { 259 | $ConfigDir = "$env:USERPROFILE\.clojure" 260 | } 261 | 262 | # If user config directory does not exist, create it 263 | if (!(Test-Path "$ConfigDir")) { 264 | New-Item -Type Directory "$ConfigDir" | Out-Null 265 | } 266 | if (!(Test-Path "$ConfigDir\deps.edn")) { 267 | Copy-Item "$InstallDir\example-deps.edn" "$ConfigDir\deps.edn" 268 | } 269 | if (!(Test-Path "$ConfigDir\tools")) { 270 | New-Item -Type Directory "$ConfigDir\tools" | Out-Null 271 | } 272 | if (Test-NewerFile "$InstallDir\tools.edn" "$ConfigDir\tools\tools.edn") { 273 | Copy-Item "$InstallDir\tools.edn" "$ConfigDir\tools\tools.edn" 274 | } 275 | 276 | # Determine user cache directory 277 | if ($env:CLJ_CACHE) { 278 | $UserCacheDir = $env:CLJ_CACHE 279 | } else { 280 | $UserCacheDir = "$ConfigDir\.cpcache" 281 | } 282 | 283 | # Chain deps.edn in config paths. repro=skip config dir 284 | $ConfigProject='deps.edn' 285 | if ($Repro) { 286 | $ConfigPaths = "$InstallDir\deps.edn", 'deps.edn' 287 | } else { 288 | $ConfigUser = "$ConfigDir\deps.edn" 289 | $ConfigPaths = "$InstallDir\deps.edn", "$ConfigDir\deps.edn", 'deps.edn' 290 | } 291 | 292 | # Determine whether to use user or project cache 293 | if (Test-Path deps.edn) { 294 | $CacheDir = '.cpcache' 295 | if(!(Test-Path $CacheDir -PathType container)) { 296 | Try { 297 | New-Item -Name $CacheDir -ItemType "directory" 298 | } 299 | Catch { # fall back to user cache dir 300 | $CacheDirKey = Get-Location 301 | $CacheDir = $UserCacheDir 302 | } 303 | } 304 | } else { 305 | $CacheDir = $UserCacheDir 306 | } 307 | 308 | # Construct location of cached classpath file 309 | $CacheVersion = "5" 310 | $CacheKey = "$CacheVersion|$CacheDirKey|$($ReplAliases -join '')|$($JvmAliases -join '')|$ExecAliases|$MainAliases|$DepsData|$ToolName|$ToolAliases|$($ConfigPaths -join '|')" 311 | $CacheKeyHash = (Get-StringHash $CacheKey) -replace '-', '' 312 | 313 | $CpFile = "$CacheDir\$CacheKeyHash.cp" 314 | $JvmFile = "$CacheDir\$CacheKeyHash.jvm" 315 | $MainFile = "$CacheDir\$CacheKeyHash.main" 316 | $BasisFile = "$CacheDir\$CacheKeyHash.basis" 317 | $ManifestFile = "$CacheDir\$CacheKeyHash.manifest" 318 | 319 | # Print paths in verbose mode 320 | if ($Verbose) { 321 | Write-Output @" 322 | version = $Version 323 | install_dir = $InstallDir 324 | config_dir = $ConfigDir 325 | config_paths = $ConfigPaths 326 | cache_dir = $CacheDir 327 | cp_file = $CpFile 328 | "@ 329 | } 330 | 331 | # Check for stale classpath file 332 | $Stale = $FALSE 333 | if ($Force -or $Trace -or $Tree -or $Prep -or !(Test-Path $CpFile)) { 334 | $Stale = $TRUE 335 | } elseif ($ToolName -and (Test-NewerFile "$ConfigDir\tools\$ToolName.edn" "$CpFile" )) { 336 | $Stale = $TRUE 337 | } else { 338 | if ($ConfigPaths | Where-Object { Test-NewerFile $_ $CpFile }) { 339 | $Stale = $TRUE 340 | } 341 | if (Test-Path $ManifestFile) { 342 | $Manifests = @(Get-Content $ManifestFile) 343 | if ($Manifests | Where-Object { !(Test-Path $_) -or (Test-NewerFile $_ $CpFile) }) { 344 | $Stale = $TRUE 345 | } 346 | } 347 | } 348 | 349 | # Make tools args if needed 350 | if ($Stale -or $Pom) { 351 | $ToolsArgs = @() 352 | if ($DepsData) { 353 | $ToolsArgs += '--config-data' 354 | $ToolsArgs += $DepsData 355 | } 356 | if ($MainAliases) { 357 | $ToolsArgs += "-M$MainAliases" 358 | } 359 | if ($ReplAliases) { 360 | $ToolsArgs += "-A$($ReplAliases -join '')" 361 | } 362 | if ($ExecAliases) { 363 | $ToolsArgs += "-X$ExecAliases" 364 | } 365 | if ($Mode -ceq 'tool') { 366 | $ToolsArgs += "--tool-mode" 367 | } 368 | if ($ToolName) { 369 | $ToolsArgs += "--tool-name" 370 | $ToolsArgs += "$ToolName" 371 | } 372 | if ($ToolAliases) { 373 | $ToolsArgs += "-T$ToolAliases" 374 | } 375 | if ($ForceCp) { 376 | $ToolsArgs += '--skip-cp' 377 | } 378 | if ($Threads) { 379 | $ToolsArgs += '--threads' 380 | $ToolsArgs += $Threads 381 | } 382 | if ($Trace) { 383 | $ToolsArgs += '--trace' 384 | } 385 | if ($Tree) { 386 | $ToolsArgs += '--tree' 387 | } 388 | } 389 | 390 | # If stale, run make-classpath to refresh cached classpath 391 | if ($Stale -and (-not $Describe)) { 392 | if ($Verbose) { 393 | Write-Host "Refreshing classpath" 394 | } 395 | & $JavaCmd -XX:-OmitStackTraceInFastThrow @CljJvmOpts -classpath $ToolsCp clojure.main -m clojure.tools.deps.script.make-classpath2 --config-user $ConfigUser --config-project $ConfigProject --basis-file $BasisFile --cp-file $CpFile --jvm-file $JvmFile --main-file $MainFile --manifest-file $ManifestFile @ToolsArgs 396 | if ($LastExitCode -ne 0) { 397 | return 398 | } 399 | } 400 | 401 | if ($Describe) { 402 | $CP = '' 403 | } elseif ($ForceCp) { 404 | $CP = $ForceCp 405 | } else { 406 | $CP = Get-Content $CpFile 407 | } 408 | 409 | if ($Prep) { 410 | # Already done 411 | } elseif ($Pom) { 412 | & $JavaCmd -XX:-OmitStackTraceInFastThrow @CljJvmOpts -classpath $ToolsCp clojure.main -m clojure.tools.deps.script.generate-manifest2 --config-user $ConfigUser --config-project $ConfigProject --gen=pom @ToolsArgs 413 | } elseif ($PrintClassPath) { 414 | Write-Output $CP 415 | } elseif ($Describe) { 416 | $PathVector = ($ConfigPaths | ForEach-Object { "`"$($_.Replace("\","\\"))`"" }) -join ' ' 417 | Write-Output @" 418 | {:version "$Version" 419 | :config-files [$PathVector] 420 | :config-user "$($ConfigUser.Replace("\","\\"))" 421 | :config-project "$($ConfigProject.Replace("\","\\"))" 422 | :install-dir "$($InstallDir.Replace("\","\\"))" 423 | :config-dir "$($ConfigDir.Replace("\","\\"))" 424 | :cache-dir "$($CacheDir.Replace("\","\\"))" 425 | :force $(if ($Force) {"true"} else {"false"}) 426 | :repro $(if ($Repro) {"true"} else {"false"}) 427 | :main-aliases "$main_aliases" 428 | :repl-aliases "$repl_aliases" 429 | :exec-aliases "$exec_aliases"} 430 | "@ 431 | } elseif ($Tree) { 432 | # Already done 433 | } elseif ($Trace) { 434 | Write-Host "Wrote trace.edn" 435 | } else { 436 | if (Test-Path $JvmFile) { 437 | $JvmCacheOpts = @(Get-Content $JvmFile) 438 | } 439 | 440 | if (($Mode -eq 'exec') -or ($Mode -eq 'tool')) { 441 | & $JavaCmd -XX:-OmitStackTraceInFastThrow @JavaOpts @JvmCacheOpts @JvmOpts "-Dclojure.basis=$BasisFile" -classpath "$CP;$InstallDir/exec.jar" clojure.main -m clojure.run.exec @ClojureArgs 442 | } else { 443 | if (Test-Path $MainFile) { 444 | # TODO this seems dangerous 445 | $MainCacheOpts = @(Get-Content $MainFile) -replace '"', '\"' 446 | } 447 | if ($ClojureArgs.Count -gt 0 -and $Mode -eq 'repl') { 448 | Write-Warning "WARNING: Implicit use of clojure.main with options is deprecated, use -M" 449 | } 450 | & $JavaCmd -XX:-OmitStackTraceInFastThrow @JavaOpts @JvmCacheOpts @JvmOpts "-Dclojure.basis=$BasisFile" -classpath $CP clojure.main @MainCacheOpts @ClojureArgs 451 | } 452 | } 453 | } 454 | 455 | New-Alias -Name clj -Value Invoke-Clojure 456 | New-Alias -Name clojure -Value Invoke-Clojure 457 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/clj: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | bin_dir=BINDIR 4 | 5 | if type -p rlwrap >/dev/null 2>&1; then 6 | exec rlwrap -m -r -q '\"' -b "(){}[],^%#@\";:'" "$bin_dir/clojure" "$@" 7 | else 8 | echo "Please install rlwrap for command editing or use \"clojure\" instead." 9 | exit 1 10 | fi 11 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/clojure: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | install_dir=PREFIX 6 | version=${project.version} 7 | 8 | function join { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; } 9 | 10 | # Extract opts 11 | print_classpath=false 12 | describe=false 13 | verbose=false 14 | trace=false 15 | force=false 16 | repro=false 17 | tree=false 18 | pom=false 19 | help=false 20 | prep=false 21 | jvm_opts=() 22 | repl_aliases=() 23 | mode="repl" 24 | while [ $# -gt 0 ] 25 | do 26 | case "$1" in 27 | -version) 28 | >&2 echo "Clojure CLI version $version" 29 | exit 0 30 | ;; 31 | --version) 32 | echo "Clojure CLI version $version" 33 | exit 0 34 | ;; 35 | -J*) 36 | jvm_opts+=("${1:2}") 37 | shift 38 | ;; 39 | -R*) 40 | >&2 echo "-R is no longer supported, use -A with repl, -M for main, -X for exec, -T for tool" 41 | exit 1 42 | ;; 43 | -C*) 44 | >&2 echo "-C is no longer supported, use -A with repl, -M for main, -X for exec, -T for tool" 45 | exit 1 46 | ;; 47 | -O*) 48 | >&2 echo "-O is no longer supported, use -A with repl, -M for main, -X for exec, -T for tool" 49 | exit 1 50 | ;; 51 | -A) 52 | >&2 echo "-A requires an alias" 53 | exit 1 54 | ;; 55 | -A*) 56 | repl_aliases+=("${1:2}") 57 | shift 58 | ;; 59 | -M) 60 | mode="main" 61 | shift 62 | break 63 | ;; 64 | -M*) 65 | mode="main" 66 | main_aliases="${1:2}" 67 | shift 68 | break 69 | ;; 70 | -X) 71 | mode="exec" 72 | shift 73 | break 74 | ;; 75 | -X*) 76 | mode="exec" 77 | exec_aliases="${1:2}" 78 | shift 79 | break 80 | ;; 81 | -T:*) 82 | mode="tool" 83 | tool_aliases="${1:2}" 84 | shift 85 | break 86 | ;; 87 | -T*) 88 | mode="tool" 89 | tool_name="${1:2}" 90 | shift 91 | break 92 | ;; 93 | -T) 94 | mode="tool" 95 | shift 96 | break 97 | ;; 98 | -P) 99 | prep=true 100 | shift 101 | ;; 102 | -Sdeps) 103 | shift 104 | deps_data="${1}" 105 | shift 106 | ;; 107 | -Scp) 108 | shift 109 | force_cp="${1}" 110 | shift 111 | ;; 112 | -Spath) 113 | print_classpath=true 114 | shift 115 | ;; 116 | -Sverbose) 117 | verbose=true 118 | shift 119 | ;; 120 | -Sthreads) 121 | shift 122 | threads="${1}" 123 | shift 124 | ;; 125 | -Strace) 126 | trace=true 127 | shift 128 | ;; 129 | -Sdescribe) 130 | describe=true 131 | shift 132 | ;; 133 | -Sforce) 134 | force=true 135 | shift 136 | ;; 137 | -Srepro) 138 | repro=true 139 | shift 140 | ;; 141 | -Stree) 142 | tree=true 143 | shift 144 | ;; 145 | -Spom) 146 | pom=true 147 | shift 148 | ;; 149 | -Sresolve-tags) 150 | >&2 echo "Option changed, use: clj -X:deps git-resolve-tags" 151 | exit 1 152 | ;; 153 | -S*) 154 | >&2 echo "Invalid option: $1" 155 | exit 1 156 | ;; 157 | -h|--help|"-?") 158 | if [[ -n "$main_aliases" ]] || [[ ${#repl_aliases[@]} -gt 0 ]]; then 159 | break 160 | else 161 | help=true 162 | shift 163 | fi 164 | ;; 165 | --) 166 | shift 167 | break 168 | ;; 169 | *) 170 | break 171 | ;; 172 | esac 173 | done 174 | 175 | # Find java executable 176 | set +e 177 | JAVA_CMD=${JAVA_CMD:-$(type -p java)} 178 | set -e 179 | if [[ -z "$JAVA_CMD" ]]; then 180 | if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then 181 | JAVA_CMD="$JAVA_HOME/bin/java" 182 | else 183 | >&2 echo "Couldn't find 'java'. Please set JAVA_HOME." 184 | exit 1 185 | fi 186 | fi 187 | 188 | if "$help"; then 189 | cat <<-END 190 | Version: $version 191 | 192 | You use the Clojure tools ('clj' or 'clojure') to run Clojure programs 193 | on the JVM, e.g. to start a REPL or invoke a specific function with data. 194 | The Clojure tools will configure the JVM process by defining a classpath 195 | (of desired libraries), an execution environment (JVM options) and 196 | specifying a main class and args. 197 | 198 | Using a deps.edn file (or files), you tell Clojure where your source code 199 | resides and what libraries you need. Clojure will then calculate the full 200 | set of required libraries and a classpath, caching expensive parts of this 201 | process for better performance. 202 | 203 | The internal steps of the Clojure tools, as well as the Clojure functions 204 | you intend to run, are parameterized by data structures, often maps. Shell 205 | command lines are not optimized for passing nested data, so instead you 206 | will put the data structures in your deps.edn file and refer to them on the 207 | command line via 'aliases' - keywords that name data structures. 208 | 209 | 'clj' and 'clojure' differ in that 'clj' has extra support for use as a REPL 210 | in a terminal, and should be preferred unless you don't want that support, 211 | then use 'clojure'. 212 | 213 | Usage: 214 | Start a REPL clj [clj-opt*] [-Aaliases] 215 | Exec fn(s) clojure [clj-opt*] -X[aliases] a/fn? [kpath v]* kv-map? 216 | Run tool clojure [clj-opt*] -T[name|aliases] a/fn [kpath v] kv-map? 217 | Run main clojure [clj-opt*] -M[aliases] [init-opt*] [main-opt] [arg*] 218 | Prepare clojure [clj-opt*] -P [other exec opts] 219 | 220 | exec-opts: 221 | -Aaliases Use concatenated aliases to modify classpath 222 | -X[aliases] Use concatenated aliases to modify classpath or supply exec fn/args 223 | -T[toolname|aliases] Invoke tool by name or via aliases ala -X 224 | -M[aliases] Use concatenated aliases to modify classpath or supply main opts 225 | -P Prepare deps - download libs, cache classpath, but don't exec 226 | 227 | clj-opts: 228 | -Jopt Pass opt through in java_opts, ex: -J-Xmx512m 229 | -Sdeps EDN Deps data or file to use as the last deps file to be merged 230 | -Spath Compute classpath and echo to stdout only 231 | -Stree Print dependency tree 232 | -Scp CP Do NOT compute or cache classpath, use this one instead 233 | -Srepro Ignore the ~/.clojure/deps.edn config file 234 | -Sforce Force recomputation of the classpath (don't use the cache) 235 | -Sverbose Print important path info to console 236 | -Sthreads Set specific number of download threads 237 | -Strace Write a trace.edn file that traces deps expansion 238 | -- Stop parsing dep options and pass remaining arguments to clojure.main 239 | --version Print the version to stdout and exit 240 | -version Print the version to stderr and exit 241 | 242 | init-opt: 243 | -i, --init path Load a file or resource 244 | -e, --eval string Eval exprs in string; print non-nil values 245 | --report target Report uncaught exception to "file" (default), "stderr", or "none" 246 | 247 | main-opt: 248 | -m, --main ns-name Call the -main function from namespace w/args 249 | -r, --repl Run a repl 250 | path Run a script from a file or resource 251 | - Run a script from standard input 252 | -h, -?, --help Print this help message and exit 253 | 254 | Programs provided by :deps alias: 255 | -X:deps aliases List available aliases and their source 256 | -X:deps list List full transitive deps set and licenses 257 | -X:deps tree Print deps tree 258 | -X:deps find-versions Find available versions of a library 259 | -X:deps prep Prepare all unprepped libs in the dep tree 260 | -X:deps mvn-pom Generate (or update) pom.xml with deps and paths 261 | -X:deps mvn-install Install a maven jar to the local repository cache 262 | -X:deps git-resolve-tags Resolve git coord tags to shas and update deps.edn 263 | 264 | For more info, see: 265 | https://clojure.org/guides/deps_and_cli 266 | https://clojure.org/reference/repl_and_main 267 | END 268 | exit 0 269 | fi 270 | 271 | # Set tools classpath used for the various programs before the user's program 272 | tools_cp="$install_dir/libexec/clojure-tools-$version.jar" 273 | 274 | # Determine user config directory 275 | if [[ -n "$CLJ_CONFIG" ]]; then 276 | config_dir="$CLJ_CONFIG" 277 | elif [[ -n "$XDG_CONFIG_HOME" ]]; then 278 | config_dir="$XDG_CONFIG_HOME/clojure" 279 | else 280 | config_dir="$HOME/.clojure" 281 | fi 282 | 283 | # If user config directory does not exist, create it 284 | if [[ ! -d "$config_dir" ]]; then 285 | mkdir -p "$config_dir" 286 | fi 287 | if [[ ! -e "$config_dir/deps.edn" ]]; then 288 | cp "$install_dir/example-deps.edn" "$config_dir/deps.edn" 289 | fi 290 | if [ "$install_dir/tools.edn" -nt "$config_dir/tools/tools.edn" ]; then 291 | mkdir -p "$config_dir/tools" 292 | cp "$install_dir/tools.edn" "$config_dir/tools/tools.edn" 293 | fi 294 | 295 | # Determine user cache directory 296 | if [[ -n "$CLJ_CACHE" ]]; then 297 | user_cache_dir="$CLJ_CACHE" 298 | elif [[ -n "$XDG_CACHE_HOME" ]]; then 299 | user_cache_dir="$XDG_CACHE_HOME/clojure" 300 | else 301 | user_cache_dir="$config_dir/.cpcache" 302 | fi 303 | 304 | # Chain deps.edn in config paths. repro=skip config dir 305 | config_project="deps.edn" 306 | if "$repro"; then 307 | config_paths=("$install_dir/deps.edn" "deps.edn") 308 | else 309 | config_user="$config_dir/deps.edn" 310 | config_paths=("$install_dir/deps.edn" "$config_dir/deps.edn" "deps.edn") 311 | fi 312 | 313 | # Determine whether to use user or project cache 314 | if [[ -f deps.edn ]]; then 315 | if [ -w "." ]; then 316 | cache_dir=.cpcache 317 | else # can't write to .cpcache 318 | cache_dir_key="$PWD" 319 | cache_dir="$user_cache_dir" 320 | fi 321 | else 322 | cache_dir="$user_cache_dir" 323 | fi 324 | 325 | # Construct location of cached classpath file 326 | cache_version=6 327 | val="$cache_version|$cache_dir_key|$(join '' ${repl_aliases[@]})|$exec_aliases|$main_aliases|$deps_data|$tool_name|$tool_aliases" 328 | for config_path in "${config_paths[@]}"; do 329 | if [[ -f "$config_path" ]]; then 330 | val="$val|$config_path" 331 | else 332 | val="$val|NIL" 333 | fi 334 | done 335 | ck=$(echo "$val" | cksum | cut -d" " -f 1) 336 | 337 | cp_file="$cache_dir/$ck.cp" 338 | jvm_file="$cache_dir/$ck.jvm" 339 | main_file="$cache_dir/$ck.main" 340 | basis_file="$cache_dir/$ck.basis" 341 | manifest_file="$cache_dir/$ck.manifest" 342 | 343 | # Print paths in verbose mode 344 | if "$verbose"; then 345 | echo "version = $version" 346 | echo "install_dir = $install_dir" 347 | echo "config_dir = $config_dir" 348 | echo "config_paths =" "${config_paths[@]}" 349 | echo "root_deps = $tools_cp" 350 | echo "user_deps = $config_user" 351 | echo "project_deps = $config_project" 352 | echo "cache_dir = $cache_dir" 353 | echo "cp_file = $cp_file" 354 | echo 355 | fi 356 | 357 | # Check for stale classpath file 358 | stale=false 359 | if "$force" || "$trace" || "$tree" || "$prep" || [ ! -f "$cp_file" ]; then 360 | stale=true 361 | elif [[ -n "$tool_name" ]] && [ "$config_dir/tools/$tool_name.edn" -nt "$cp_file" ]; then 362 | stale=true 363 | else 364 | # Are deps.edn files stale? 365 | for config_path in "${config_paths[@]}"; do 366 | if [ "$config_path" -nt "$cp_file" ]; then 367 | stale=true 368 | break 369 | fi 370 | done 371 | 372 | # If -Sdeps is a file, and it exists, is it stale? 373 | if [[ "$deps_data" != \{* ]] && [[ -e "$deps_data" ]] && [ "$deps_data" -nt "$cp_file" ]; then 374 | stale=true 375 | fi 376 | 377 | # Are .jar files in classpath missing? 378 | IFS=':' read -ra cp_entries <<<"$(cat $cp_file)" 379 | for cp_entry in "${cp_entries[@]}"; do 380 | if [[ "$cp_entry" == *.jar && ! -f "$cp_entry" ]]; then 381 | stale=true 382 | break 383 | fi 384 | done 385 | 386 | # Are manifest files in local/git deps stale? 387 | if [[ "$stale" = false && -f "$manifest_file" ]]; then 388 | set +e 389 | IFS=$'\n' read -ra manifest_files -d '' <"$manifest_file" 390 | set -e 391 | for manifest in "${manifest_files[@]}"; do 392 | if [[ ! -f "$manifest" || "$manifest" -nt "$cp_file" ]]; then 393 | stale=true 394 | break 395 | fi 396 | done 397 | fi 398 | fi 399 | 400 | # Make tools args if needed 401 | if "$stale" || "$pom"; then 402 | tools_args=() 403 | if [[ -n "$deps_data" ]]; then 404 | tools_args+=("--config-data" "$deps_data") 405 | fi 406 | if [[ -n "$main_aliases" ]]; then 407 | tools_args+=("-M$main_aliases") 408 | fi 409 | if [[ ${#repl_aliases[@]} -gt 0 ]]; then 410 | tools_args+=("-A$(join '' ${repl_aliases[@]})") 411 | fi 412 | if [[ -n "$exec_aliases" ]]; then 413 | tools_args+=("-X$exec_aliases") 414 | fi 415 | if [ "$mode" == "tool" ]; then 416 | tools_args+=("--tool-mode") 417 | fi 418 | if [[ -n "$tool_name" ]]; then 419 | tools_args+=("--tool-name" "$tool_name") 420 | fi 421 | if [[ -n "$tool_aliases" ]]; then 422 | tools_args+=("-T$tool_aliases") 423 | fi 424 | if [[ -n "$force_cp" ]]; then 425 | tools_args+=("--skip-cp") 426 | fi 427 | if [[ -n "$threads" ]]; then 428 | tools_args+=("--threads" "$threads") 429 | fi 430 | if "$trace"; then 431 | tools_args+=("--trace") 432 | fi 433 | if "$tree"; then 434 | tools_args+=("--tree") 435 | fi 436 | fi 437 | 438 | # If stale, run make-classpath to refresh cached classpath 439 | if [[ "$stale" = true && "$describe" = false ]]; then 440 | if "$verbose"; then 441 | >&2 echo "Refreshing classpath" 442 | fi 443 | "$JAVA_CMD" -XX:-OmitStackTraceInFastThrow $CLJ_JVM_OPTS -classpath "$tools_cp" clojure.main -m clojure.tools.deps.script.make-classpath2 --config-user "$config_user" --config-project "$config_project" --basis-file "$basis_file" --cp-file "$cp_file" --jvm-file "$jvm_file" --main-file "$main_file" --manifest-file "$manifest_file" "${tools_args[@]}" 444 | fi 445 | 446 | if "$describe"; then 447 | cp= 448 | elif [[ -n "$force_cp" ]]; then 449 | cp="$force_cp" 450 | else 451 | cp=$(cat "$cp_file") 452 | fi 453 | 454 | if "$prep"; then 455 | exit 0 456 | elif "$pom"; then 457 | exec "$JAVA_CMD" -XX:-OmitStackTraceInFastThrow $CLJ_JVM_OPTS -classpath "$tools_cp" clojure.main -m clojure.tools.deps.script.generate-manifest2 --config-user "$config_user" --config-project "$config_project" --gen=pom "${tools_args[@]}" 458 | elif "$print_classpath"; then 459 | echo "$cp" 460 | elif "$describe"; then 461 | for config_path in "${config_paths[@]}"; do 462 | if [[ -f "$config_path" ]]; then 463 | path_vector="$path_vector\"$config_path\" " 464 | fi 465 | done 466 | cat <<-END 467 | {:version "$version" 468 | :config-files [$path_vector] 469 | :config-user "$config_user" 470 | :config-project "$config_project" 471 | :install-dir "$install_dir" 472 | :config-dir "$config_dir" 473 | :cache-dir "$cache_dir" 474 | :force $force 475 | :repro $repro 476 | :main-aliases "$main_aliases" 477 | :repl-aliases "${repl_aliases[@]}"} 478 | END 479 | elif "$tree"; then 480 | exit 0 481 | elif "$trace"; then 482 | >&2 echo "Wrote trace.edn" 483 | else 484 | set -f 485 | if [[ -f "$jvm_file" ]]; then 486 | set +e 487 | IFS=$'\n' read -ra jvm_cache_opts -d '' <"$jvm_file" 488 | set -e 489 | fi 490 | 491 | if [ "$mode" == "tool" ] || [ "$mode" == "exec" ]; then 492 | exec "$JAVA_CMD" -XX:-OmitStackTraceInFastThrow $JAVA_OPTS "${jvm_cache_opts[@]}" "${jvm_opts[@]}" "-Dclojure.basis=$basis_file" -classpath "$cp:$install_dir/libexec/exec.jar" clojure.main -m clojure.run.exec "$@" 493 | else 494 | if [[ -f "$main_file" ]]; then 495 | set +e 496 | IFS=$'\n' read -ra main_cache_opts -d '' <"$main_file" 497 | set -e 498 | fi 499 | if [ "$#" -gt 0 ] && [ "$mode" == "repl" ]; then 500 | >&2 echo "WARNING: Implicit use of clojure.main with options is deprecated, use -M $@" 501 | fi 502 | exec "$JAVA_CMD" -XX:-OmitStackTraceInFastThrow $JAVA_OPTS "${jvm_cache_opts[@]}" "${jvm_opts[@]}" "-Dclojure.basis=$basis_file" -classpath "$cp" clojure.main "${main_cache_opts[@]}" "$@" 503 | fi 504 | fi 505 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/clojure.rb: -------------------------------------------------------------------------------- 1 | class Clojure < Formula 2 | desc "The Clojure Programming Language" 3 | homepage "https://clojure.org" 4 | url "https://github.com/clojure/brew-install/releases/download/${stable.version}/clojure-tools-${stable.version}.tar.gz" 5 | mirror "https://download.clojure.org/install/clojure-tools-${stable.version}.tar.gz" 6 | sha256 "${stable.sha}" 7 | license "EPL-1.0" 8 | 9 | depends_on "rlwrap" 10 | 11 | uses_from_macos "ruby" => :build 12 | 13 | def install 14 | system "./install.sh", prefix 15 | end 16 | 17 | test do 18 | ENV["TERM"] = "xterm" 19 | system("#{bin}/clj -M -e nil") 20 | %w[clojure clj].each do |clj| 21 | assert_equal "2", shell_output("#{bin}/#{clj} -M -e \"(+ 1 1)\"").strip 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/clojure@version.rb: -------------------------------------------------------------------------------- 1 | class ClojureAT${version.short} < Formula 2 | desc "The Clojure Programming Language" 3 | homepage "https://clojure.org" 4 | url "https://github.com/clojure/brew-install/releases/download/${project.version}/clojure-tools-${project.version}.tar.gz" 5 | mirror "https://download.clojure.org/install/clojure-tools-${project.version}.tar.gz" 6 | sha256 "SHA" 7 | license "EPL-1.0" 8 | 9 | depends_on "rlwrap" 10 | 11 | uses_from_macos "ruby" => :build 12 | 13 | def install 14 | system "./install.sh", prefix 15 | end 16 | 17 | test do 18 | ENV["TERM"] = "xterm" 19 | system("#{bin}/clj -M -e nil") 20 | %w[clojure clj].each do |clj| 21 | assert_equal "2", shell_output("#{bin}/#{clj} -M -e \"(+ 1 1)\"").strip 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/deps.edn: -------------------------------------------------------------------------------- 1 | { 2 | :paths ["src"] 3 | 4 | :deps { 5 | org.clojure/clojure {:mvn/version "${clojure.version}"} 6 | } 7 | 8 | :aliases { 9 | :deps {:replace-paths [] 10 | :replace-deps {org.clojure/tools.deps.cli {:mvn/version "0.11.91"}} 11 | :ns-default clojure.tools.deps.cli.api 12 | :ns-aliases {help clojure.tools.deps.cli.help}} 13 | :test {:extra-paths ["test"]} 14 | } 15 | 16 | :mvn/repos { 17 | "central" {:url "https://repo1.maven.org/maven2/"} 18 | "clojars" {:url "https://repo.clojars.org/"} 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/example-deps.edn: -------------------------------------------------------------------------------- 1 | { 2 | :aliases { 3 | ;; Add cross-project aliases here 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | prefix="$1" 4 | 5 | # default config file 6 | cp deps.edn "$prefix" 7 | cp example-deps.edn "$prefix" 8 | cp tools.edn "$prefix" 9 | 10 | # jar needed by scripts 11 | mkdir -p "$prefix/libexec" 12 | cp ./*.jar "$prefix/libexec" 13 | 14 | # scripts 15 | ${HOMEBREW_RUBY_PATH} -pi.bak -e "gsub(/PREFIX/, '$prefix')" clojure 16 | ${HOMEBREW_RUBY_PATH} -pi.bak -e "gsub(/BINDIR/, '$prefix/bin')" clj 17 | mkdir -p "$prefix/bin" 18 | cp clojure "$prefix/bin" 19 | cp clj "$prefix/bin" 20 | 21 | # man pages 22 | mkdir -p "$prefix/share/man/man1" 23 | cp clojure.1 "$prefix/share/man/man1" 24 | cp clj.1 "$prefix/share/man/man1" 25 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/linux-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | # Start 6 | do_usage() { 7 | echo "Installs the Clojure command line tools." 8 | echo -e 9 | echo "Usage:" 10 | echo "linux-install.sh [-p|--prefix ]" 11 | exit 1 12 | } 13 | 14 | default_prefix_dir="/usr/local" 15 | 16 | # use getopt if the number of params grows 17 | prefix_dir=$default_prefix_dir 18 | prefix_param=${1:-} 19 | prefix_value=${2:-} 20 | if [[ "$prefix_param" = "-p" || "$prefix_param" = "--prefix" ]]; then 21 | if [[ -z "$prefix_value" ]]; then 22 | do_usage 23 | else 24 | prefix_dir="$prefix_value" 25 | fi 26 | fi 27 | 28 | echo "Downloading and expanding tar" 29 | curl -L -O https://github.com/clojure/brew-install/releases/download/${project.version}/clojure-tools-${project.version}.tar.gz 30 | tar xzf clojure-tools-${project.version}.tar.gz 31 | 32 | lib_dir="$prefix_dir/lib" 33 | bin_dir="$prefix_dir/bin" 34 | man_dir="$prefix_dir/share/man/man1" 35 | clojure_lib_dir="$lib_dir/clojure" 36 | 37 | echo "Installing libs into $clojure_lib_dir" 38 | mkdir -p $bin_dir $man_dir $clojure_lib_dir/libexec 39 | install -m644 clojure-tools/deps.edn "$clojure_lib_dir/deps.edn" 40 | install -m644 clojure-tools/example-deps.edn "$clojure_lib_dir/example-deps.edn" 41 | install -m644 clojure-tools/tools.edn "$clojure_lib_dir/tools.edn" 42 | install -m644 clojure-tools/exec.jar "$clojure_lib_dir/libexec/exec.jar" 43 | install -m644 clojure-tools/clojure-tools-${project.version}.jar "$clojure_lib_dir/libexec/clojure-tools-${project.version}.jar" 44 | 45 | echo "Installing clojure and clj into $bin_dir" 46 | sed -i -e 's@PREFIX@'"$clojure_lib_dir"'@g' clojure-tools/clojure 47 | sed -i -e 's@BINDIR@'"$bin_dir"'@g' clojure-tools/clj 48 | install -m755 clojure-tools/clojure "$bin_dir/clojure" 49 | install -m755 clojure-tools/clj "$bin_dir/clj" 50 | 51 | echo "Installing man pages into $man_dir" 52 | install -m644 clojure-tools/clojure.1 "$man_dir/clojure.1" 53 | install -m644 clojure-tools/clj.1 "$man_dir/clj.1" 54 | 55 | echo "Removing download" 56 | rm -rf clojure-tools 57 | rm -rf clojure-tools-${project.version}.tar.gz 58 | 59 | echo "Use clj -h for help." 60 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/posix-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | # Start 6 | do_usage() { 7 | echo "Installs the Clojure command line tools." 8 | echo -e 9 | echo "Usage:" 10 | echo "posix-install.sh [-p|--prefix ]" 11 | exit 1 12 | } 13 | 14 | default_prefix_dir="/usr/local" 15 | 16 | # use getopt if the number of params grows 17 | prefix_dir=$default_prefix_dir 18 | prefix_param=${1:-} 19 | prefix_value=${2:-} 20 | if [ "$prefix_param" = "-p" -o "$prefix_param" = "--prefix" ]; then 21 | if [ -z "$prefix_value" ]; then 22 | do_usage 23 | else 24 | prefix_dir="$prefix_value" 25 | fi 26 | fi 27 | 28 | echo "Downloading and expanding tar" 29 | curl -L -O https://github.com/clojure/brew-install/releases/download/${project.version}/clojure-tools-${project.version}.tar.gz 30 | tar xzf clojure-tools-${project.version}.tar.gz 31 | 32 | lib_dir="$prefix_dir/lib" 33 | bin_dir="$prefix_dir/bin" 34 | man_dir="$prefix_dir/share/man/man1" 35 | clojure_lib_dir="$lib_dir/clojure" 36 | 37 | echo "Installing libs into $clojure_lib_dir" 38 | mkdir -p $bin_dir $man_dir $clojure_lib_dir/libexec 39 | 40 | do_install() { 41 | local mode="$1" 42 | local src="$2" 43 | local dest="$3" 44 | 45 | cp "$src" "$dest" 46 | chmod "$mode" "$dest" 47 | } 48 | 49 | do_install 644 clojure-tools/deps.edn "$clojure_lib_dir/deps.edn" 50 | do_install 644 clojure-tools/example-deps.edn "$clojure_lib_dir/example-deps.edn" 51 | do_install 644 clojure-tools/tools.edn "$clojure_lib_dir/tools.edn" 52 | do_install 644 clojure-tools/exec.jar "$clojure_lib_dir/libexec/exec.jar" 53 | do_install 644 clojure-tools/clojure-tools-${project.version}.jar "$clojure_lib_dir/libexec/clojure-tools-${project.version}.jar" 54 | 55 | echo "Installing clojure and clj into $bin_dir" 56 | sed -i -e 's@PREFIX@'"$clojure_lib_dir"'@g' clojure-tools/clojure 57 | sed -i -e 's@BINDIR@'"$bin_dir"'@g' clojure-tools/clj 58 | do_install 755 clojure-tools/clojure "$bin_dir/clojure" 59 | do_install 755 clojure-tools/clj "$bin_dir/clj" 60 | 61 | echo "Installing man pages into $man_dir" 62 | do_install 644 clojure-tools/clojure.1 "$man_dir/clojure.1" 63 | do_install 644 clojure-tools/clj.1 "$man_dir/clj.1" 64 | 65 | echo "Removing download" 66 | rm -rf clojure-tools 67 | rm -rf clojure-tools-${project.version}.tar.gz 68 | 69 | echo "Use clj -h for help." 70 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/tools.edn: -------------------------------------------------------------------------------- 1 | {:lib io.github.clojure/tools.tools 2 | :coord {:git/tag "v0.3.4" 3 | :git/sha "0e9e6c8b409ac916ad6f2ec5bc075bbcb09545c0"}} 4 | -------------------------------------------------------------------------------- /src/main/resources/clojure/install/win-install.ps1: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pwsh 2 | 3 | $ErrorActionPreference = 'Stop' 4 | $ProgressPreference = 'SilentlyContinue' 5 | 6 | $Version = '${project.version}' 7 | $ClojureToolsUrl = "https://github.com/clojure/brew-install/releases/download/$Version/clojure-tools.zip" 8 | 9 | Write-Host 'Downloading Clojure tools' -ForegroundColor Gray 10 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls12' 11 | Invoke-WebRequest -Uri $ClojureToolsUrl -OutFile clojure-tools.zip 12 | 13 | Write-Warning 'Clojure will install as a module in your PowerShell module path.' 14 | Write-Host '' 15 | Write-Host 'Possible install locations:' 16 | 17 | $InstallLocations = $env:PSModulePath -split [IO.Path]::PathSeparator 18 | for ($Index = 0; $Index -lt $InstallLocations.Length; $Index++) { 19 | Write-Host (' {0}) {1}' -f ($Index + 1), $InstallLocations[$Index]) 20 | } 21 | $Choice = Read-Host 'Enter number of preferred install location' 22 | $DestinationPath = $InstallLocations[$Choice - 1] 23 | 24 | Write-Host '' 25 | 26 | $ExistingLocation = "$DestinationPath\ClojureTools" 27 | if (Test-Path $ExistingLocation) { 28 | Write-Host 'Cleaning up existing install' -ForegroundColor Gray 29 | Remove-Item -Path $ExistingLocation -Recurse 30 | } 31 | 32 | Write-Host 'Installing PowerShell module' 33 | Expand-Archive clojure-tools.zip -DestinationPath $DestinationPath 34 | 35 | Write-Host 'Removing download' 36 | Remove-Item clojure-tools.zip 37 | 38 | Write-Host 'Clojure now installed. Use "clj -h" for help.' -ForegroundColor Green 39 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/run/test_exec.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.run.test-exec 2 | (:require 3 | [clojure.edn :as edn] 4 | [clojure.test :refer :all] 5 | [clojure.string :as str] 6 | [clojure.run.exec :as exec] 7 | clojure.set) 8 | (:import 9 | [java.io File] 10 | [clojure.lang ExceptionInfo])) 11 | 12 | (defn submap? 13 | "Is m1 a subset of m2?" 14 | [m1 m2] 15 | (if (and (map? m1) (map? m2)) 16 | (every? (fn [[k v]] (and (contains? m2 k) 17 | (submap? v (get m2 k)))) 18 | m1) 19 | (= m1 m2))) 20 | 21 | (deftest test-read-args 22 | (is (= [] (#'exec/read-args []))) 23 | (is (= ['a [1 2] :k] (#'exec/read-args ["a" "[1 2]" ":k"]))) 24 | 25 | ;; unreadable arg message contains the bad value 26 | (is (thrown-with-msg? ExceptionInfo #":::a" (#'exec/read-args [":::a"])))) 27 | 28 | (deftest test-parse-fn 29 | (are [expected args] (= expected (#'exec/parse-fn args)) 30 | nil [] 31 | {:function 'foo/bar} ['foo/bar] 32 | {:overrides [:x 1 :y 1]} [:x 1 :y 1] 33 | {:function 'foo} ['foo] 34 | {:function 'foo :overrides [:x 1 :y 1]} ['foo :x 1 :y 1] 35 | {:overrides [:x 1 :y 1]} [:x 1 :y 1] 36 | {:overrides [:a 1 :b 2], :trailing {:b 42}} [:a 1 :b 2 {:b 42}] 37 | {:function 'foo/bar, :trailing {:a 1}} ['foo/bar {:a 1}] 38 | {:overrides [:x 1 :k 1], :trailing {:a 1}} [:x 1 :k 1 {:a 1}] 39 | {:function 'foo/bar, :overrides [:x 1 :y 2], :trailing {:y 42}} ['foo/bar :x 1 :y 2 {:y 42}]) 40 | 41 | ;; missing last override value prints value missing for key (like hash-map) 42 | (is (thrown-with-msg? ExceptionInfo #":y" (#'exec/parse-fn [:x 1 :y]))) 43 | ) 44 | 45 | (deftest test-qualify-fn 46 | (are [expected sym aliases default] 47 | (= expected (#'exec/qualify-fn sym aliases default)) 48 | 'a/b 'a/b nil nil 49 | 'a/b 'b nil 'a 50 | 'a/b 'my-alias/b {'my-alias 'a} nil) 51 | 52 | ;; function is not a symbol 53 | (is (thrown-with-msg? ExceptionInfo #"100" (#'exec/qualify-fn 100 nil nil))) 54 | 55 | ;; unqualified, no default-ns 56 | (is (thrown-with-msg? ExceptionInfo #"my-sym" (#'exec/qualify-fn 'my-sym nil nil)))) 57 | 58 | (def stash (atom nil)) 59 | (defn save [val] (reset! stash val)) 60 | 61 | (defn- encapsulate-main-with-effect 62 | [exec-args args] 63 | (let [fake-basis (File/createTempFile "basis" nil)] 64 | (save nil) 65 | (.deleteOnExit fake-basis) 66 | (binding [*print-namespace-maps* false] 67 | (spit fake-basis (pr-str {:argmap exec-args})) 68 | (System/setProperty "clojure.basis" (.getAbsolutePath fake-basis))) 69 | (binding [exec/*exit* (constantly nil)] 70 | (apply exec/-main args)) 71 | @stash)) 72 | 73 | (defn puppet [{:keys [ret err print-val print-val-err]}] 74 | (when print-val 75 | (print print-val) 76 | (flush)) 77 | (when print-val-err 78 | (binding [*out* *err*] 79 | (print print-val-err) 80 | (flush))) 81 | (if err 82 | (throw (RuntimeException. err)) 83 | ret)) 84 | 85 | (defn- encapsulate-invoke 86 | [exec-args args] 87 | (let [fake-basis (File/createTempFile "basis" nil)] 88 | (.deleteOnExit fake-basis) 89 | (binding [*print-namespace-maps* false] 90 | (spit fake-basis (pr-str {:argmap exec-args})) 91 | (System/setProperty "clojure.basis" (.getAbsolutePath fake-basis))) 92 | (binding [exec/*exit* (constantly nil)] 93 | (edn/read-string 94 | (with-out-str 95 | (apply exec/-main args)))))) 96 | 97 | (defmacro with-err-str 98 | "Evaluates exprs in a context in which *err* is bound to a fresh 99 | StringWriter. Returns the string created by any nested printing 100 | calls." 101 | {:added "1.0"} 102 | [& body] 103 | `(let [s# (new java.io.StringWriter)] 104 | (binding [*err* s#] 105 | ~@body 106 | (str s#)))) 107 | 108 | (deftest test-main 109 | (are [stashed args exec-args] (= stashed (encapsulate-main-with-effect exec-args args)) 110 | ;; ad hoc, fully resolved, with both key and path vector 111 | {:a 1, :b {:c 2}} ["clojure.run.test-exec/save" ":a" "1" "[:b,:c]" "2"] {} 112 | 113 | ;; ad hoc, resolved by default-ns 114 | {:a 1} ["save" ":a" "1"] {:ns-default 'clojure.run.test-exec} 115 | 116 | ;; ad hoc, resolved alias 117 | {:a 1} ["a/save" ":a" "1"] {:ns-aliases {'a 'clojure.run.test-exec}} 118 | 119 | ;; exec-fn with overrides 120 | {:a 1, :b 2} [":b" "2"] {:exec-fn 'clojure.run.test-exec/save :exec-args {:a 1 :b 1}} 121 | 122 | ;; exec-fn resolved by :ns-default, aliased exec-args 123 | {:a 1, :b 1} [] {:exec-fn 'save, :exec-args {:a 1, :b 1} :ns-default 'clojure.run.test-exec}) 124 | 125 | (are [return args exec-args] (submap? return (encapsulate-invoke exec-args (map pr-str args))) 126 | ;; non-map return, note that val is stringified! 127 | {:tag :ret, :val "42"} 128 | ['clojure.run.test-exec/puppet {:clojure.exec/invoke :fn, :ret 42}] {} 129 | 130 | ;; map return 131 | {:tag :ret, :val "{:a \"1\"}"} 132 | ['clojure.run.test-exec/puppet {:clojure.exec/invoke :fn, :ret {:a "1"}}] {} 133 | 134 | ;; capture out 135 | {:tag :ret :val "42" :out "hi there"} 136 | ['clojure.run.test-exec/puppet {:clojure.exec/invoke :fn, :ret 42, :print-val "hi there", :clojure.exec/out :capture}] {} 137 | 138 | ;; capture err 139 | {:tag :ret :val "42" :err "hi there"} 140 | ['clojure.run.test-exec/puppet {:clojure.exec/invoke :fn, :ret 42, :print-val-err "hi there", :clojure.exec/err :capture}] {}) 141 | 142 | (let [res (encapsulate-invoke {} (map pr-str ['clojure.run.test-exec/puppet {:clojure.exec/invoke :fn, :err "msg"}]))] 143 | (is (= :err (:tag res))) 144 | (is (str/starts-with? (:val res) "{:via [{:type java.lang.RuntimeException, :message \"msg\""))) 145 | 146 | ;; missing override val: "Key is missing value: :foo\n" 147 | (is (str/includes? (with-err-str (encapsulate-main-with-effect {} [":foo"])) ":foo")) 148 | 149 | ;; no function: "No function found on command line or in :exec-fn\n" 150 | (is (str/includes? (with-err-str (encapsulate-main-with-effect {} [])) "No function")) 151 | 152 | ;; unqualified function: "Unqualified function can't be resolved: foo\n" 153 | (is (str/includes? (with-err-str (encapsulate-main-with-effect {} ["foo"])) "foo")) 154 | ) 155 | 156 | (comment 157 | (test-main) 158 | 159 | ) -------------------------------------------------------------------------------- /stable.properties: -------------------------------------------------------------------------------- 1 | 1.12.1.1550 906c625679c72e7035875988a46392a1d83d16ee1df599a561a2fd33424b0d3f 2 | --------------------------------------------------------------------------------