Repository: Olical/depot Branch: main Commit: a306d4dc338b Files: 20 Total size: 48.2 KB Directory structure: gitextract__8nqrtm7/ ├── .dir-locals.el ├── .github/ │ └── workflows/ │ └── test.yaml ├── .gitignore ├── CHANGES.md ├── CODE_OF_CONDUCT.md ├── README-v1.md ├── README.md ├── UNLICENSE ├── build.clj ├── deps.edn ├── mise.toml ├── src/ │ └── depot/ │ ├── outdated/ │ │ ├── main.clj │ │ ├── resolve_virtual.clj │ │ └── update.clj │ ├── outdated.clj │ └── zip.clj ├── test/ │ └── depot/ │ ├── outdated/ │ │ ├── resolve_virtual_test.clj │ │ └── update_test.clj │ └── zip_test.clj └── tests.edn ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dir-locals.el ================================================ ((nil . ((cider-clojure-cli-global-options . "-A:test")))) ================================================ FILE: .github/workflows/test.yaml ================================================ name: Test on: [push] jobs: test: strategy: matrix: os: [ubuntu-latest] # os: [ubuntu-latest, macOS-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v4 - name: Mise uses: jdx/mise-action@v2 - name: Cache uses: actions/cache@v4 with: path: | ~/.m2/repository ~/.gitlibs ~/.deps.clj key: cljdeps-${{ hashFiles('deps.edn') }} restore-keys: cljdeps- - name: Execute Kaocha run: mise test ================================================ FILE: .gitignore ================================================ .cpcache/ target/ .nrepl-port .calva/ .clj-kondo/ .lsp/ ================================================ FILE: CHANGES.md ================================================ # Depot changes ## v2.4.1 Fix tests and some compatibility issues around [rewrite-clj](https://github.com/clj-commons/rewrite-clj) v1 and whitespace. ## v2.4.0 - Merge [#56](https://github.com/Olical/depot/pull/56) - Update deps version && add `:git/url` for git repo. Thank you, [@JackSho](https://github.com/JackSho)! ## v2.3.0 - Merge [#55](https://github.com/Olical/depot/pull/55) - Adds default-deps to keys checked for aliases. Thank you, [@timothypratley](https://github.com/timothypratley)! ## v2.2.0 - Add a `--fail` flag that will cause the program to exit with code `1` (non-zero) if something was out of date. Useful for CI. [#39](https://github.com/Olical/depot/issues/39) - Updated all dependencies. ## v2.1.0 - Merge [#47](https://github.com/Olical/depot/pull/47) - Update dependencies, including `tools.deps.alpha` itself. ## v2.0.1 - Fix `pom.xml`, there was no source code in `v2.0.0`. ## v2.0.0 - **Breaking** Replaced the `--update` flag with the `--write` flag. - **Breaking** Changed scoping rules to be the same with or without the `--write` flag - **Breaking** Remove support for the `--overrides` flag. `:override-deps` will be checked by default. To ignore them, use the `:depot/ignore` metadata. - **Breaking** Changed scoping rules to be the same with or without the `--resolve-virtual` flag - **Breaking** Changed `--resolve-virtual` to be read-only unless combined with `--write` - Fixed inconsistent output styles - Added the `--every` flag which allows checking all aliases at once - Bump various dependencies. ## v1.8.4 - Republish v1.8.3 without the `target` directory which contained some old AOTed classes. Thanks for the heads up, Sean Corfield! ## v1.8.3 - Merge [#24](https://github.com/Olical/depot/pull/24) - Replace calls to `clojure-env` with new API. ## v1.8.2 - Merge [#21](https://github.com/Olical/depot/pull/21) - Handle uneval nodes, fixing [#20](https://github.com/Olical/depot/issues/20). `--resolve-virtual` should now be stable, all thanks to [@plexus](https://github.com/plexus). ## v1.8.1 - Merge [#19](https://github.com/Olical/depot/pull/19) - Fix depot.zip/left, clean up whitespace. ## v1.8.0 - Merge [#17](https://github.com/Olical/depot/pull/17) - Resolve snapshots. ## v1.7.0 - Merge [#16](https://github.com/Olical/depot/pull/16) - Reduce the runtime by making multiple requests in parallel. ## v1.6.0 - Merge [#15](https://github.com/Olical/depot/pull/15) - Consider overrides in the outdated check mode too. ## v1.5.1 - Merge [#13](https://github.com/Olical/depot/pull/13) - Fix a couple of issues with `--update`. ## v1.5.0 - Merge [#9](https://github.com/Olical/depot/pull/9) - Ignore "RELEASE" and "LATEST", bring back Clojure 1.8 compatibility (as mentioned in [#7](https://github.com/Olical/depot/issues/7)). - Merge [#10](https://github.com/Olical/depot/pull/10) - Let --update also check :override-deps. Even more improvements from [@plexus](https://github.com/plexus)! I also sorted out some formatting and deleted some unused forms, but that's all. ## v1.4.0 - Merge [#6](https://github.com/Olical/depot/pull/6) - Updating `deps.edn` automatically with `--update`. Thank you very much, [@plexus](https://github.com/plexus)! ## v1.3.0 - Merge [#5](https://github.com/Olical/depot/pull/5) - Support `:override-deps`. - Bump `org.clojure/tools.cli` to `0.4.1`. - Bump `org.clojure/tools.deps.alpha` to `0.5.460`. ## v1.2.0 - Merge [#4](https://github.com/Olical/depot/pull/4) - Add support for git dependencies. Thank you, [@kennyjwilli](https://github.com/kennyjwilli), great contribution. ## v1.1.0 - Merge [#3](https://github.com/Olical/depot/pull/3) - Only consider changes when selected and latest are non-blank strings. - Gather changes and print a nice table rather than printing as differences are found. - Print a message if no changes can be found. Thank you very much, [@robert-stuttaford](https://github.com/robert-stuttaford)! ## v1.0.1 - Only try to check dependencies that use the `:mvn/version` key, attempting to parse git shas was causing an error. [#1](https://github.com/Olical/depot/issues/1) ## v1.0.0 - Initial release with `depot.outdated.main` that checks for outdated dependencies in your `deps.edn` file. ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at olliec87+depot@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ ================================================ FILE: README-v1.md ================================================ # Depot [![Clojars Project](https://img.shields.io/clojars/v/olical/depot.svg)](https://clojars.org/olical/depot) Find newer versions of your dependencies in your `deps.edn` file using the [Clojure CLI][cli]. This works for maven _and_ git dependencies. ## Usage You can try it out easily with this one liner: ```bash $ clojure -Sdeps '{:deps {olical/depot {:mvn/version "1.8.4"}}}' -m depot.outdated.main | Dependency | Current | Latest | |---------------------|---------|--------| | org.clojure/clojure | 1.9.0 | 1.10.0 | ``` I'd recommend adding depot as an alias in your own `deps.edn` file, this will allow it to check itself for updates: > Note: Replace the ellipsis with the current version shown above. ```clojure {:deps {} :aliases {:outdated {:extra-deps {olical/depot {:mvn/version "..."}} :main-opts ["-m" "depot.outdated.main"]}}} ``` ```bash $ clojure -Aoutdated -a outdated | Dependency | Current | Latest | |--------------|---------|--------| | olical/depot | ..... | ..... | ``` ### Updating `deps.edn` To automatically update the versions in `deps.edn`, use `--update`. ```bash $ clojure -m depot.outdated.main --update Updating: deps.edn rewrite-clj {:mvn/version "0.6.0"} -> {:mvn/version "0.6.1"} cider/cider-nrepl {:mvn/version "0.17.0"} -> {:mvn/version "0.18.0"} clj-time {:mvn/version "0.14.4"} -> {:mvn/version "0.15.1"} olical/cljs-test-runner {:git/sha "5a18d41648d5c3a64632b5fec07734d32cca7671"} -> {:git/sha "da9710b389782d4637ef114176f6e741225e16f0"} ``` This will leave any formatting, whitespace, and comments intact. It will update both the top level deps and any `:aliases` / `:extra-deps`. To prevent Depot from touching certain parts of your `deps.edn`, mark them with the `^:depot/ignore` metadata. ``` clojure {:deps {...} :aliases {;; used for testing against older versions of Clojure :clojure-1.8 ^:depot/ignore {:extra-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} :clojure-1.9 ^:depot/ignore {:extra-deps {org.clojure/clojure {:mvn/version "1.9.0"}}}}} ``` `--update` by default looks for `deps.edn` in the current working directory. You can instead pass one or more filenames in explicitly. ``` bash $ clojure -m depot.outdated.main --update ../my-project/deps.edn ``` ## Freezing snapshots Maven has a concept called "virtual" versions, these are similar to Git branches, they are pointers to another version, and the version they point to can change over time. The best known example are snapshot releases. When your `deps.edn` refers to a version `0.4.1-SNAPSHOT`, the version that actually gets installed will look like `0.4.1-20190222.154954-1`. A maintainer can publish as many snapshots as they like, all with the same version string. This means that re-running the same code twice might yield different results, if in the meanwhile a new snapshot was released. So installing `0.4.1-SNAPSHOT` again later on may install a completely different version. For the sake of stability and reproducibility it may be desirable to "lock" this version. This is what the `--resolve-virtual` flag is for. The `--resolve-virtual` flag will replace the snapshot version with the current timestamped version that the SNAPSHOT is an alias of, so that your code is once again deterministic. Besides `SNAPSHOT` versions `--resolve-virtual` will also handle the special version strings `"RELEASE"` and `"LATEST"` ``` % clojure -Sdeps '{:deps {olical/depot {:local/root "/home/arne/github/depot"}}}' -m depot.outdated.main --resolve-virtual Resolving: deps.edn cider/piggieback 0.4.1-SNAPSHOT --> 0.4.1-20190222.154954-1 ``` ## Existing work This project is inspired by [lein-ancient][], it relies on [version-clj][] (by the same author, [xsc][]) for parsing and comparison of version numbers. ## Contributors * [@Olical](https://github.com/Olical) - Initial work and general maintenance. * [@daaku](https://github.com/daaku) - Ensuring `:override-deps` is adhered to in the non-mutating mode. * [@kennyjwilli](https://github.com/kennyjwilli) - Git dependency support and table improvements. * [@lverns](https://github.com/lverns) - Reducing the runtime significantly by making multiple requests in parallel. * [@plexus](https://github.com/plexus) - Both the `--update` and `--resolve-virtual` systems, so many improvements! * [@robert-stuttaford](https://github.com/robert-stuttaford) - Presenting results in a neat table. * [@seancorfield](https://github.com/seancorfield) - Support for `:override-deps`. * [@dharrigan](https://github.com/dharrigan) - Bump dependencies, fixing warnings. ## Unlicenced Find the full [unlicense][] in the `UNLICENSE` file, but here's a snippet. >This is free and unencumbered software released into the public domain. > >Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. Do what you want. Learn as much as you can. Unlicense more software. [unlicense]: http://unlicense.org/ [lein-ancient]: https://github.com/xsc/lein-ancient [version-clj]: https://github.com/xsc/version-clj [xsc]: https://github.com/xsc [cli]: https://clojure.org/guides/deps_and_cli ================================================ FILE: README.md ================================================ # Depot [![Clojars Project](https://img.shields.io/clojars/v/olical/depot.svg)](https://clojars.org/olical/depot) > Warning: I'm not actively maintaining this project, I'm finally releasing `v2+` since it's been sitting around for far too long. It contains a bunch of breaking changes that are mentioned in `CHANGES.md`. > > You may have better luck with [liquidz/antq](https://github.com/liquidz/antq) or [slipset/deps-ancient](https://github.com/slipset/deps-ancient). If you'd like to see this project developed and maintained further I'm open to inviting other maintainers or promoting forks. I'm reluctant to transfer ownership and publishing rights to the artifact since that's been used for malicious purposes in recent times. > > If this version isn't to your liking you can still rely on `v1.8.4` (or earlier) and the legacy documentation in `README-v1.md`. Find newer versions of your dependencies in your `deps.edn` file using the [Clojure CLI][cli]. This works for maven _and_ git dependencies. ## Usage You can try it out easily with this one liner: ```bash $ clojure -Sdeps '{:deps {olical/depot {:mvn/version "RELEASE"}}}' -M -m depot.outdated.main Checking for old versions in: deps.edn org.clojure/clojure {:mvn/version "1.9.0"} -> {:mvn/version "1.12.1"} ``` I'd recommend adding depot as an alias in your own `deps.edn` file, this will allow it to check itself for updates: ```clojure {:deps {} :aliases {:outdated {:replace-deps {olical/depot {:mvn/version "2.4.1"}} :main-opts ["-m" "depot.outdated.main"]}}} ``` ```bash $ clojure -Aoutdated --aliases outdated Checking for old versions in: deps.edn olical/depot {:mvn/version "..."} -> {:mvn/version "..."} ``` ### Controlling which files are checked By default Depot looks for `deps.edn` in the current working directory. You can instead pass one or more filenames in explicitly. ```bash $ clojure -Aoutdated ../my-project/deps.edn ``` ### Controlling which part of the file are checked By default, only dependencies under the top-level `:deps` are considered. To also consider `:default-deps`, `:extra-deps` and `:override-deps` under aliases, use the `--aliases alias1,alias2` to specify alias, or the `--every` flag to consider all aliases. To prevent Depot from touching certain parts of your `deps.edn`, mark them with the `^:depot/ignore` metadata. ```clojure {:deps {...} :aliases {;; used for testing against older versions of Clojure :clojure-1.8 ^:depot/ignore {:extra-deps {org.clojure/clojure {:mvn/version "1.8.0"}}} :clojure-1.9 ^:depot/ignore {:extra-deps {org.clojure/clojure {:mvn/version "1.9.0"}}}}} ``` The metadata can be placed on the artifact name, the coord map or on any map containing the dependency in question. ### Updating `deps.edn` By default, depot only prints the new versions. To update the file in place, include the `--write` flag. This will leave any formatting, whitespace, and comments intact. ```bash $ clojure -Aoutdated --write Updating old versions in: deps.edn rewrite-clj {:mvn/version "0.6.0"} -> {:mvn/version "0.6.1"} cider/cider-nrepl {:mvn/version "0.17.0"} -> {:mvn/version "0.18.0"} clj-time {:mvn/version "0.14.4"} -> {:mvn/version "0.15.1"} olical/cljs-test-runner {:git/sha "5a18d41648d5c3a64632b5fec07734d32cca7671"} -> {:git/sha "da9710b389782d4637ef114176f6e741225e16f0"} ``` ### Freezing snapshots Maven has a concept called "virtual" versions, these are similar to Git branches, they are pointers to another version, and the version they point to can change over time. The best known example are snapshot releases. When your `deps.edn` refers to a version `0.4.1-SNAPSHOT`, the version that actually gets installed will look like `0.4.1-20190222.154954-1`. A maintainer can publish as many snapshots as they like, all with the same version string. This means that re-running the same code twice might yield different results, if in the meanwhile a new snapshot was released. So installing `0.4.1-SNAPSHOT` again later on may install a completely different version. For the sake of stability and reproducibility it may be desirable to "lock" this version. This is what the `--resolve-virtual` flag is for. The `--resolve-virtual` flag will resolve the virtual version to the current timestamped version that the SNAPSHOT is an alias of, so that your code is once again deterministic. Besides `SNAPSHOT` versions `--resolve-virtual` will also handle the special version strings `"RELEASE"` and `"LATEST"` ``` % clojure -Aoutdated --resolve-virtual Checking virtual versions in: deps.edn cider/piggieback {:mvn/version "0.4.1-SNAPSHOT"} -> {:mvn/version "0.4.1-20190222.154954-1"} ``` ## Existing work This project is inspired by [lein-ancient][], it relies on [version-clj][] (by the same author, [xsc][]) for parsing and comparison of version numbers. ## Contributors - [@Olical](https://github.com/Olical) - Initial work and general maintenance. - [@daaku](https://github.com/daaku) - Ensuring `:override-deps` is adhered to in the non-mutating mode. - [@kennyjwilli](https://github.com/kennyjwilli) - Git dependency support and table improvements. - [@lverns](https://github.com/lverns) - Reducing the runtime significantly by making multiple requests in parallel. - [@plexus](https://github.com/plexus) - Both the `--update` and `--resolve-virtual` systems, so many improvements! - [@robert-stuttaford](https://github.com/robert-stuttaford) - Presenting results in a neat table. - [@seancorfield](https://github.com/seancorfield) - Support for `:override-deps`. - [@dharrigan](https://github.com/dharrigan) - Bump dependencies, fixing warnings. - [@dotemacs](https://github.com/dotemacs) - Updating dependencies, supporting newer `tools.deps.alpha` versions. - [@timothypratley](https://github.com/timothypratley) - Adding `:default-deps` support. ## Unlicenced Find the full [unlicense][] in the `UNLICENSE` file, but here's a snippet. > This is free and unencumbered software released into the public domain. > > Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. Do what you want. Learn as much as you can. Unlicense more software. [unlicense]: http://unlicense.org/ [lein-ancient]: https://github.com/xsc/lein-ancient [version-clj]: https://github.com/xsc/version-clj [xsc]: https://github.com/xsc [cli]: https://clojure.org/guides/deps_and_cli ================================================ FILE: UNLICENSE ================================================ This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to ================================================ FILE: build.clj ================================================ (ns build (:require [clojure.tools.build.api :as b] [deps-deploy.deps-deploy :as dd])) (def lib 'olical/depot) ;; TODO Use the GitHub rev / tag ;; https://github.com/jlesquembre/clojars-publish-action/blob/89a4eb7bdbe1270621e6643250afce152701699e/src/entrypoint.clj#L41-L47 (def version "2.4.1") ; (b/git-count-revs nil) (def class-dir "target/classes") (def jar-file (format "target/%s-%s.jar" (name lib) version)) (def pom-template [[:description "Find newer versions of your dependencies in your deps.edn file."] [:url "https://github.com/Olical/depot"] [:licenses [:license [:name "Unlicense"] [:url "https://unlicense.org/"]]] [:developers [:developer [:name "Oliver Caldwell"]]] [:scm [:url "https://github.com/Olical/depot"] [:connection "scm:git:https://github.com/Olical/depot.git"] [:developerConnection "scm:git:ssh://git@github.com:Olical/depot.git"] [:tag (str "v" version)]]]) (def basis (delay (b/create-basis {:project "deps.edn"}))) (defn clean [_] (b/delete {:path "target"})) (defn jar [_] (b/write-pom {:class-dir class-dir :lib lib :version version :basis @basis :pom-data pom-template :src-dirs ["src"]}) (b/copy-dir {:src-dirs ["src" "resources"] :target-dir class-dir}) (b/jar {:class-dir class-dir :jar-file jar-file})) (defn deploy "Deploy the JAR to Clojars." [opts] (dd/deploy {:installer :remote :artifact (b/resolve-path jar-file) :pom-file (b/pom-path {:lib lib :class-dir class-dir})}) opts) ================================================ FILE: deps.edn ================================================ {:paths ["src"] :deps {org.clojure/clojure {:mvn/version "1.12.1"} org.clojure/tools.deps {:mvn/version "0.24.1523"} org.clojure/tools.cli {:mvn/version "1.1.230"} rewrite-clj/rewrite-clj {:mvn/version "1.2.50"} version-clj/version-clj {:mvn/version "2.0.3"}} :aliases {:test {:extra-paths ["test"] :extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"} nubank/matcher-combinators {:mvn/version "3.9.1"}} :main-opts ["-m" "kaocha.runner"]} :flowstorm {:classpath-overrides {org.clojure/clojure nil} :extra-deps {com.github.flow-storm/clojure {:mvn/version "1.12.1"} com.github.flow-storm/flow-storm-dbg {:mvn/version "4.4.6"}} :jvm-opts ["-Dflowstorm.startRecording=false" "-Dclojure.storm.instrumentEnable=true" "-Dflowstorm.title=Storm" "-Dflowstorm.theme=dark"]} :dev {:extra-deps {cider/cider-nrepl {:mvn/version "0.56.0"}} :main-opts ["-m" "nrepl.cmdline" "--middleware" "[cider.nrepl/cider-middleware]"]} :format {:deps {cljfmt/cljfmt {:mvn/version "0.9.2"}} :main-opts ["-m" "cljfmt.main" "fix"]} :build {:extra-deps {io.github.clojure/tools.build {:mvn/version "0.10.9"} slipset/deps-deploy {:mvn/version "0.2.2"}} :ns-default build} :example-outdated-deps-for-self-test {:extra-deps {;; Only here to check depot functionality. org.slf4j/slf4j-simple {:mvn/version "2.0.17"} clj-time/clj-time {:mvn/version "0.15.2"} cider/cider-nrepl {:mvn/version "0.57.0"} olical/cljs-test-runner {:git/url "https://github.com/Olical/cljs-test-runner.git" :git/sha "5a18d41648d5c3a64632b5fec07734d32cca7671"}}} :outdated {:replace-deps {olical/depot {:mvn/version "RELEASE"}} :main-opts ["-m" "depot.outdated.main"]}}} ================================================ FILE: mise.toml ================================================ [tools] clojure = "1.12.1" java = "temurin-21.0.6+7.0.LTS" [tasks.format] run = "clojure -M:format" [tasks.test] description = "Run the test suite with Kaocha." raw = true run = "clojure -M:dev:test" [tasks.dogfood] description = "Run depot on itself (well, the example-outdated-deps-for-self-test alias)" run = "clojure -Aexample-outdated-deps-for-self-test -m depot.outdated.main -a example-outdated-deps-for-self-test -t release,qualified" [tasks.repl] description = "Start an nREPL with Flowstorm configured." raw = true run = "clojure -M:test:dev:flowstorm" [tasks.build] run = "clojure -T:build jar" [tasks.clean] run = "clojure -T:build clean" [tasks.deploy] run = "clojure -T:build deploy" ================================================ FILE: src/depot/outdated/main.clj ================================================ (ns depot.outdated.main (:require [clojure.set :as set] [clojure.string :as str] [clojure.tools.cli :as cli] [depot.outdated :as depot] [depot.outdated.update :as update] [depot.outdated.resolve-virtual :as resolve-virtual])) (defn comma-str->keywords-set [comma-str] (into #{} (map keyword) (str/split comma-str #","))) (defn keywords-set->comma-str [kws] (str/join "," (map name kws))) (def version-types-str (keywords-set->comma-str depot/version-types)) (def cli-options [["-a" "--aliases ALIASES" "Comma list of aliases to use when reading deps.edn" :parse-fn comma-str->keywords-set] ["-t" "--consider-types TYPES" (str "Comma list of version types to consider out of " version-types-str) :default #{:release} :default-desc "release" :parse-fn comma-str->keywords-set ;; TODO: check the :errors after parsing for this error :validate [#(set/subset? % depot/version-types) (str "Must be subset of " depot/version-types)]] ["-e" "--every" "Expand search to all aliases."] ["-w" "--write" "Instead of just printing changes, write them back to the file."] ["-r" "--resolve-virtual" "Convert -SNAPSHOT/RELEASE/LATEST versions into immutable references."] ["-f" "--fail" "Return a non-zero exit status if anything was out of date."] ["-h" "--help"]]) (def ^:private messages {:resolve-virtual {:start-read-only "Checking virtual versions in: %s" :start-write "Resolving virtual versions in: %s" :no-changes " No virtual versions found"} :update-old {:start-read-only "Checking for old versions in: %s" :start-write "Updating old versions in: %s" :no-changes " All up to date!"}}) (defn- exit [code] (shutdown-agents) (System/exit code)) (defn -main [& args] (let [{{:keys [aliases consider-types every help write resolve-virtual fail]} :options files :arguments summary :summary} (cli/parse-opts args cli-options)] (cond help (do (println "USAGE: clojure -m depot.outdated.main [OPTIONS] [FILES]\n") (println " If no files are given, defaults to using \"deps.edn\".\n") (println summary)) :else (let [files (if (seq files) files ["deps.edn"]) check-alias? (if every (constantly true) (set aliases)) messages (if resolve-virtual (:resolve-virtual messages) (:update-old messages)) new-versions (if resolve-virtual resolve-virtual/pinned-versions depot/newer-versions)] (when (and every aliases) (println "--every and --aliases are mutually exclusive.") (exit 1)) (let [application-results (mapv #(update/apply-new-versions % consider-types check-alias? write messages new-versions) files)] (when (and fail (some :newer-deps? application-results)) (exit 1))))) (exit 0))) ================================================ FILE: src/depot/outdated/resolve_virtual.clj ================================================ (ns depot.outdated.resolve-virtual (:require [depot.zip :as dzip] [depot.outdated :as outdated] [clojure.tools.deps.util.maven :as maven] [clojure.string :as str])) (defn resolve-version [lib coord {:keys [mvn/repos mvn/local-repo]}] (let [artifact (maven/coord->artifact lib coord) system (maven/make-system) session (outdated/make-session system (or local-repo maven/default-local-repo)) remote-repos (mapv maven/remote-repo repos) request (org.eclipse.aether.resolution.VersionRequest. artifact remote-repos nil)] (.getVersion (.resolveVersion system session request)))) (defn pinned-versions "Find all deps in a `:deps` or `:default-deps` or `:extra-deps` or `:override-deps` map to be pinned, at the top level and in aliases. `loc` points at the top level map." [loc config] (dzip/mapped-libs loc (fn [artifact coords] (when-let [mvn-version (:mvn/version coords)] (when (some (partial str/ends-with? mvn-version) ["-SNAPSHOT" "LATEST" "RELEASE"]) {:version-key :mvn/version :old-version mvn-version :new-version (resolve-version artifact coords config)}))))) ================================================ FILE: src/depot/outdated/update.clj ================================================ (ns depot.outdated.update (:require [clojure.tools.deps :as deps.alpha] [depot.zip :as dzip] [rewrite-clj.zip :as rzip])) (defmacro with-print-namespace-maps [bool & body] (if (find-var 'clojure.core/*print-namespace-maps*) `(binding [*print-namespace-maps* ~bool] ~@body) ;; pre Clojure 1.9 `(do ~@body))) (defn- apply-new-version [new-versions loc] (let [artifact (rzip/sexpr loc) coords-loc (-> loc dzip/right dzip/enter-meta) {version-key :version-key new-version :new-version old-version :old-version :as v} (get new-versions artifact)] (-> (if (and v (seq (rzip/sexpr coords-loc))) (with-print-namespace-maps false (println " " artifact (pr-str {version-key old-version}) "->" (pr-str {version-key new-version})) (dzip/zassoc coords-loc version-key new-version)) coords-loc) dzip/exit-meta dzip/left))) (defn- apply-to-deps-map "Given an `loc` pointing at a map, navigate to the sub-map at k, and apply f to every key in it. Returns an `loc` at the 'same' point in the tree." [loc k f] (-> loc (dzip/zget k) dzip/enter-meta (as-> % (dzip/map-keys f %)) dzip/exit-meta rzip/up (or loc))) (defn- apply-top-level-deps "Given a root `loc`, and a new-versions map, apply f to the top-level dependencies." [loc f] (apply-to-deps-map loc :deps f)) (defn- apply-alias-deps [loc f] (-> loc (apply-to-deps-map :default-deps f) (apply-to-deps-map :extra-deps f) (apply-to-deps-map :override-deps f))) (defn- apply-aliases-deps "`loc` points to the root of the deps.edn file." [loc include-alias? f] (if-let [alias-map (dzip/zget loc :aliases)] (dzip/map-keys (fn [loc] (let [alias-name (rzip/sexpr loc)] (if (include-alias? alias-name) (-> loc rzip/right dzip/enter-meta (apply-alias-deps f) dzip/exit-meta rzip/left) loc))) alias-map) loc)) (defn apply-new-versions [file consider-types include-alias? write? messages new-versions] (let [start-message ((if write? :start-write :start-read-only) messages)] (printf (str start-message "\n") file)) (let [{:keys [root-edn user-edn project-edn]} (deps.alpha/find-edn-maps) deps (deps.alpha/merge-edns [root-edn user-edn project-edn]) config (-> deps (select-keys [:mvn/repos :mvn/local-repo]) (assoc :consider-types consider-types)) loc (rzip/of-file file) old-deps (slurp file) new-versions (new-versions loc config) loc' (-> loc (apply-top-level-deps (partial apply-new-version new-versions)) (apply-aliases-deps include-alias? (partial apply-new-version new-versions))) new-deps (rzip/root-string loc') newer-deps? (not= old-deps new-deps)] (when (and loc' new-deps) ;; defensive check to prevent writing an empty deps.edn (if newer-deps? (try (when write? (spit file new-deps)) (catch java.io.FileNotFoundException e (println " [ERROR] Permission denied: " file))) (println (:no-changes messages)))) {:newer-deps? newer-deps?})) ================================================ FILE: src/depot/outdated.clj ================================================ (ns depot.outdated (:require [clojure.java.shell :as sh] [clojure.string :as str] [clojure.tools.deps.extensions :as ext] [clojure.tools.deps.util.maven :as maven] [clojure.tools.deps.extensions.git :as git] [depot.zip :as dzip] [version-clj.core :as version]) (:import org.apache.maven.repository.internal.MavenRepositorySystemUtils [org.eclipse.aether RepositorySystem RepositorySystemSession] org.eclipse.aether.resolution.VersionRangeRequest)) (def version-types #{:snapshot :qualified :release}) (defn version-type [v] (let [type (-> (version/version->seq v) (last) (first))] (cond (= type "snapshot") :snapshot (string? type) :qualified (integer? type) :release :else :unrecognised))) (defn make-session ^RepositorySystemSession [^RepositorySystem system local-repo] (let [session (MavenRepositorySystemUtils/newSession) local-repo-mgr (.newLocalRepositoryManager system session (maven/make-local-repo local-repo))] (.setLocalRepositoryManager session local-repo-mgr) session)) (defn coord->version-status [lib coord {:keys [mvn/repos mvn/local-repo]}] (let [local-repo (or local-repo maven/default-local-repo) remote-repos (mapv maven/remote-repo repos) system (maven/make-system) session (make-session system local-repo) selected (:mvn/version coord) artifact (maven/coord->artifact lib (assoc coord :mvn/version "[0,)")) versions-req (doto (new VersionRangeRequest) (.setArtifact artifact) (.setRepositories remote-repos)) versions (->> (.resolveVersionRange system session versions-req) (.getVersions) (map str))] {:selected selected :types (group-by version-type versions)})) (defn find-latest [types consider-types] (let [versions (->> (select-keys types consider-types) (vals) (apply concat))] (-> (sort version/version-compare versions) (last)))) (defmulti -current-latest-map (fn [_ coord _] (ext/coord-type coord))) (defmethod -current-latest-map :default [_ _ _] nil) (defmethod -current-latest-map :mvn [lib coord {:keys [consider-types] :as config}] (let [{:keys [types selected]} (coord->version-status lib coord config) latest (find-latest types consider-types)] (when (and (not (str/blank? selected)) (not (str/blank? latest)) (= (version/version-compare latest selected) 1)) {:current selected :latest latest}))) (defn- parse-git-ls-remote "Returns a map of ref name to the latest sha for that ref name." [s] (let [lines (-> s (str/trim-newline) (str/split #"\n"))] (into {} (comp (map (fn [x] (-> x (str/triml) (str/split #"\t") (reverse) (vec)))) (filter #(= 2 (count %)))) lines))) (defn with-git-url "Add a :git/url key to coords if artifact is a Git dependency. Details: https://clojure.org/reference/deps_edn#deps_git" [artifact coords] (if (and (contains? coords :git/sha) (not (contains? coords :git/url))) (if-let [git-url (git/auto-git-url artifact)] (assoc coords :git/url git-url) coords) coords)) (comment (with-git-url 'io.github.olical/depot {:git/tag "v2.2.0" :git/sha "f4806e4"}) ;; => #:git{:tag "v2.2.0", :sha "f4806e4", :url "https://github.com/olical/depot"}) (defmethod -current-latest-map :git [lib coord _] (let [coord (with-git-url lib coord) {:keys [exit out]} (sh/sh "git" "ls-remote" (:git/url coord)) latest-remote-sha (get (parse-git-ls-remote out) "HEAD")] (when (and (= exit 0) (neg? (ext/compare-versions lib coord (assoc coord :git/sha latest-remote-sha) {}))) {:current (:git/sha coord) :latest latest-remote-sha}))) (defn current-latest-map "Returns a map containing `:current` and `:latest` if the dependency has a newer version otherwise returns `nil`." [lib coord config] (-current-latest-map lib coord config)) (defn newer-versions "Find all deps in a `:deps` or `:default-deps` or `:extra-deps` or `:override-deps` map to be updated, at the top level and in aliases. `loc` points at the top level map." [loc config] (dzip/mapped-libs loc (fn [artifact coords] (let [[old-version version-key] (or (some-> coords :mvn/version (vector :mvn/version)) (some-> coords :git/sha (vector :git/sha))) new-version (-> (current-latest-map artifact coords config) (get :latest))] (when (and old-version ;; ignore these Maven 2 legacy identifiers (not (#{"RELEASE" "LATEST"} old-version)) new-version) {:version-key version-key :old-version old-version :new-version new-version}))))) ================================================ FILE: src/depot/zip.clj ================================================ (ns depot.zip "Extra zipper helpers." (:require [rewrite-clj.zip :as rzip])) (defn- zip-skip-ws "Skip whitespace, comments, and uneval nodes." [loc next-fn skip-fn end?-fn] (loop [loc loc] (cond (nil? loc) loc (end?-fn loc) loc (#{:comment :whitespace :newline :comma} (rzip/tag loc)) (recur (next-fn loc)) (= :uneval (rzip/tag loc)) (recur (skip-fn loc)) :else loc))) (defn left "Like [[rewrite-clj.zip/left], but also skip over uneval nodes" [loc] (some-> loc rzip/left (zip-skip-ws rzip/left rzip/left (constantly false)))) (defn right "Like [[rewrite-clj.zip/right]], but also skip over uneval nodes" [loc] (some-> loc rzip/right (zip-skip-ws rzip/right rzip/right (constantly false)))) (defn znext "Like [[rewrite-clj.zip/next]], but also skip over uneval nodes" [loc] (some-> loc rzip/next (zip-skip-ws rzip/next rzip/right rzip/end?))) (defn enter-meta "If the given `loc` is a meta node, navigate down to the value to which it is attached, else return the `loc`." [loc] (if (not= :meta (rzip/tag loc)) loc (-> loc rzip/down right (recur)))) (defn exit-meta "If the given `loc`'s parent is a meta node, return the first ancestor whose parent is not, else return the `loc`." [loc] (let [loc' (rzip/up loc)] (if (= :meta (rzip/tag loc')) (recur loc') loc))) (defn zget "Like [[clojure.core/get]], but for a zipper over a map. Takes and returns a zipper (loc)." [loc key] {:pre [(rzip/map? loc)]} (right (rzip/find-value (rzip/down loc) (comp right right) key))) (defn zassoc "Like [[clojure.core/assoc]], but for a zipper over a map. New keys will be added at the end, preserving indentation." [loc k v] {:pre [(rzip/map? loc)]} (if-let [vloc (zget loc k)] ;; key found, just replace the value (rzip/up (rzip/replace vloc v)) ;; key not found, add it to the end of the map (let [;; loc to the last value in the map loc (rzip/rightmost (rzip/down loc))] ;; insert key and value (-> loc (rzip/insert-right k) (rzip/right) (rzip/insert-right v) (rzip/up))))) (defn map-keys "Like [[rewrite-clj.zip/map-keys]], but account for uneval nodes." [f zloc] (loop [loc (rzip/down zloc) parent zloc] (if-not (and loc (rzip/node loc)) parent (if-let [v (f loc)] (recur (right (right v)) (rzip/up v)) (recur (right (right loc)) parent))))) (defn ignore-loc? "Should the version at the current position be ignored? Returns true if any ancestor has the `^:depot/ignore` metadata." [loc] (boolean (rzip/find loc rzip/up (fn [loc] (:depot/ignore (meta (rzip/sexpr loc))))))) ;; TODO make sure this only matches map keys (defn lib? "Is the loc at a library name." [loc] (and loc (= :token (rzip/tag loc)) (rzip/map? (rzip/up loc)) (#{:deps :default-deps :extra-deps :override-deps} (some-> loc rzip/up left rzip/sexpr)))) (defn next-lib "Find the next loc, depth first, that is a library name." [loc] (rzip/find-next loc znext lib?)) (defn lib-loc-seq "A sequence of zippers each pointing at a library name." [loc] (->> loc next-lib (iterate next-lib) (take-while identity))) (defn loc->lib "Given a zipper pointing at a library name, return a pair of [name coordinate-map]" [loc] [(rzip/sexpr loc) (rzip/sexpr (right loc))]) (defn mapped-libs "Find every unignored dep in a `:deps` or `:extra-deps` or `:override-deps` map, at the top level and in aliases, and return a map of artifact to output of (f artifact coords). f must be free of side-effects. `loc` points at the top level map." [loc f] (->> (lib-loc-seq loc) (filter (fn [loc] (and (not (ignore-loc? loc)) (not (ignore-loc? (right loc)))))) (map loc->lib) (pmap (fn [[artifact coords]] [artifact (f artifact coords)])) (into {}))) ================================================ FILE: test/depot/outdated/resolve_virtual_test.clj ================================================ (ns depot.outdated.resolve-virtual-test (:require [depot.outdated.resolve-virtual :as r] [clojure.test :refer :all] [rewrite-clj.zip :as rzip] [clojure.tools.deps.util.maven :as maven] [clojure.string :as str] [depot.zip :as dzip])) (deftest resolve-version-test (is (str/starts-with? (r/resolve-version 'cider/piggieback {:mvn/version "0.4.1-SNAPSHOT"} {:mvn/repos maven/standard-repos}) "0.4.1-20"))) ================================================ FILE: test/depot/outdated/update_test.clj ================================================ (ns depot.outdated.update-test (:require [clojure.test :refer :all] [depot.outdated.update :as u] [rewrite-clj.node :as node] [rewrite-clj.zip :as rzip] [clojure.tools.deps.util.maven :as maven])) (def CONSIDER_TYPES_RELEASES #{:release}) (def REPOS {:mvn/repos maven/standard-repos}) (deftest missing-top-level-deps (let [input (rzip/edn (node/coerce {:aliases {:test {:extra-deps {'midje {:mvn/version "1.9.8"}}}}}))] (is (= input (#'u/apply-top-level-deps input identity))))) (deftest empty-coordinate-map (let [loc (-> (node/coerce {'org.clojure/clojure {}}) rzip/edn rzip/down) result (#'u/apply-new-version {'org.clojure/clojure {:old-version "1.10.0" :new-version "1.10.1" :version-key :mvn/version}} loc)] (is (= loc result)))) ================================================ FILE: test/depot/zip_test.clj ================================================ (ns depot.zip-test (:require [depot.zip :as u] [rewrite-clj.zip :as rzip] [rewrite-clj.node :as node] [clojure.test :refer :all])) (deftest enter-meta-test (are [input] (= :map (-> (rzip/of-string input) (rzip/get :d) (u/enter-meta) (rzip/tag))) "{:d {:a 0 :b 1}}" "{:d ^:depot/ignore {:a 0 :b 1}}" "{:d ^:depot/ignore ^:foo/bar {:a 0 :b 1}}")) (deftest exit-meta-test (are [input] (= {:d {:a 0 :b 1}} (-> (rzip/of-string input) (rzip/get :d) (u/enter-meta) (u/exit-meta) (rzip/up) (rzip/sexpr))) "{:d {:a 0 :b 1}}" "{:d ^:depot/ignore {:a 0 :b 1}}" "{:d ^:depot/ignore ^:foo/bar {:a 0 :b 1}}")) (deftest right-test (is (= :y (-> (rzip/of-string "[:x ,,#_123\n :y]") rzip/down u/right rzip/sexpr)))) (deftest left-test (is (= :x (-> (rzip/of-string "[:x ,,#_123\n :y]") rzip/down rzip/rightmost u/left rzip/sexpr)))) (deftest zget-test (is (= :bar (-> (rzip/edn (node/coerce {:foo :bar :bar :baz})) (u/zget :foo) (rzip/sexpr)))) (is (nil? (-> (rzip/edn (node/coerce {:foo :bar :bar :baz})) (u/zget :unkown)))) (is (= :baz (-> (rzip/of-string "{:foo :bar #_uneval :bar :baz}") (u/zget :bar) (rzip/sexpr))))) (deftest zassoc-test (let [loc (rzip/of-string "{:foo :bar,\n :baz :baq}")] (is (= "{:foo 123,\n :baz :baq}" (-> loc (u/zassoc :foo 123) rzip/root-string))) (is (= "{:foo :bar,\n :baz 123}" (-> loc (u/zassoc :baz 123) rzip/root-string))) (is (= "{:foo :bar,\n :baz :baq :baq 123}" (-> loc (u/zassoc :baq 123) rzip/root-string))))) (deftest lib-loc-seq-test (let [loc (rzip/of-string (pr-str '{:deps {foo {:mvn/version "1.0"}} :aliases {:test {:extra-deps {bar {:mvn/version "1.9.8"}}}}})) loc-seq (u/lib-loc-seq loc)] (is (= 2 (count loc-seq))) (is (= (-> loc rzip/down rzip/right rzip/down) (first loc-seq))) (is (= (-> loc rzip/down rzip/right rzip/right rzip/right rzip/down rzip/right rzip/down rzip/right rzip/down) (second loc-seq))))) (deftest ignore-loc?-test (testing "don't update when tagged with :depot/ignore" (is (true? (u/ignore-loc? (rzip/find-value (rzip/of-string "{:aliases {:dev ^:depot/ignore {:deps {foo/bar {}}}}} :test {:deps {baz/baq {}}}") rzip/next 'foo/bar))))) (testing "do update by default" (is (false? (u/ignore-loc? (rzip/find-value (rzip/of-string "{:aliases {:dev ^:depot/ignore {:deps {foo/bar {}}}}} :test {:deps {baz/baq {}}}") rzip/next 'baz/baq)))))) (deftest mapped-libs-test (let [loc (rzip/edn (node/coerce '{:deps {org.clojure/clojure {:mvn/version "1.10.1"}} :aliases {:dev {:extra-deps {foo.bar {:git/sha "abiglonghash"}}} :test {:extra-deps {foo.baz {:mvn/version "1.2.3"}} :override-deps {foo.baz.sublib {:mvn/version "1.2.2"}}}}}))] (is (= '{org.clojure/clojure [org.clojure/clojure {:mvn/version "1.10.1"}] foo.bar [foo.bar {:git/sha "abiglonghash"}] foo.baz [foo.baz {:mvn/version "1.2.3"}] foo.baz.sublib [foo.baz.sublib {:mvn/version "1.2.2"}]} (u/mapped-libs loc (fn [& args] args)))) (is (every? nil? (vals (u/mapped-libs loc (constantly nil))))))) ================================================ FILE: tests.edn ================================================ #kaocha/v1 {:plugins [:kaocha.plugin/notifier]}