├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── README.md ├── pull_request_template.md └── workflows │ └── main.yaml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── Makefile ├── docs └── images │ ├── diff_kubediff.png │ ├── diff_original.png │ ├── kubediff-showcase.gif │ └── kubediff.png └── src ├── assets ├── config.yaml └── diff.sh ├── commands.rs ├── enums.rs ├── logger.rs ├── main.rs ├── print.rs ├── processor.rs └── settings.rs /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | rami.daghlawi@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ 93 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | 12 | 13 | **To Reproduce** 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | 22 | 23 | **Screenshots** 24 | 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Additional context** 32 | 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | 12 | 13 | **Describe the solution you'd like** 14 | 15 | 16 | **Describe alternatives you've considered** 17 | 18 | 19 | **Additional context** 20 | 21 | -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 | # kubediff 2 | 3 |
4 | Table of Contents 5 | 6 | - [kubediff](#kubediff) 7 | * [Showcase](#showcase) 8 | * [About The Project](#about-the-project) 9 | + [What](#what) 10 | + [Why](#why) 11 | + [How](#how) 12 | * [Getting Started](#getting-started) 13 | + [Prerequisite](#prerequisite) 14 | + [Installation](#installation) 15 | * [Usage](#usage) 16 | * [Roadmap](#roadmap) 17 | * [Troubleshooting](#troubleshooting)) 18 | 19 |
20 | 21 | ## Showcase 22 | ![showcase](https://raw.github.com/Ramilito/kubediff/main/docs/images/kubediff-showcase.gif) 23 | _The showcase demonstrates an upgrade of agones_ 24 | 25 | 26 | Kubediff | Kubectl diff 27 | :-------------------------:|:-------------------------: 28 | ![comparison_kubediff](https://raw.github.com/Ramilito/kubediff/main/docs/images/diff_kubediff.png) | ![comparison_original](https://raw.github.com/Ramilito/kubediff/main/docs/images/diff_original.png) 29 | _Notice that kubediff has removed the hated managedFields_ 30 | 31 | ## About The Project 32 | 33 | ### What 34 | Used to sanity check and understand what has changed between environments. 35 | 36 | This cli tool written in Rust is a wrapper around kubectl diff and is supposed to diff one or multiple projects instead of 37 | single files against any environment you want, be it docker-desktop, dev, prod. 38 | 39 | It takes a glob pattern to one or more projects and beautifies the output so you can get an understanding on what differences there are. 40 | 41 | ### Why 42 | Ever asked yourself, what is deployed on my cluster? Or, 43 | * are all changes applied to the cluster? 44 | * What differences are there between the environments? 45 | * What have I forgotten to deploy? 46 | * Has something changed without us knowing it? 47 | * Forgot to add a change in git after hotfixing it in prod? Well, look no further...well a couple of lines further, I guess... 48 | 49 | 50 | ### How 51 | We will loop over the projects files and run kubectl build, then pipe the output into kubectl diff and then process the output of that to make it pretty. 52 | 53 | ## Getting Started 54 | 55 | ### Prerequisite 56 | 57 | * yq is needed for less clutter (can be made optional fairly easy) 58 | 59 | ### Installation 60 | Download and extract the binary. 61 | ``` 62 | KUBEDIFF_VERSION=0.1.7 && \ 63 | KUBEDIFF_OS=x86_64-unknown-linux-gnu && \ 64 | wget "https://github.com/Ramilito/kubediff/releases/download/${KUBEDIFF_VERSION}/kubediff_${KUBEDIFF_VERSION}_${KUBEDIFF_OS}.tar.gz" && \ 65 | mkdir -p $HOME/.kube/kubediff && tar zxpf kubediff_${KUBEDIFF_VERSION}_${KUBEDIFF_OS}.tar.gz -C $HOME/.kube/kubediff 66 | ``` 67 | 68 | Add it to your PATH in .zshrc/.bashrc. 69 | ``` 70 | export PATH="$PATH:/home/$USER/.kube/kubediff" 71 | ``` 72 | 73 | ## Usage 74 | 75 | ### Configuration 76 | Se the available commands by running kubediff -h 77 | 78 | Regular usage would be to list your projects in the config.yaml file located at the install directory 79 | 80 | 81 | **_Few projects, will use the kustomization file located at that path:_** 82 | ``` 83 | configs: 84 | include: 85 | - "~/projectone/serviceone/k8s" 86 | - "~/projecttwo/servicetwo/k8s" 87 | ``` 88 | 89 | **_Many projects (monorepo), will use glob pattern to find all services:_** 90 | ``` 91 | configs: 92 | include: 93 | - "~/monorepo/Services/**/k8s" 94 | ``` 95 | 96 | **_Many environments, will suffix the variable to end of the paths in ```config.yaml```, example below will look in "~/monorepo/Services/\**/k8s/dev"_** 97 | ``` 98 | kubediff -e dev 99 | ``` 100 | 101 | **_You can also bypass the config by passing either -path or -inplace argument:_** 102 | ``` 103 | kubediff -p ~/path-to-dir-or-file 104 | kubediff -i 105 | ``` 106 | ## Roadmap 107 | 108 | - [ ] Remove, make optional or include dependency on yq 109 | - [ ] Change theme with input 110 | 111 | ## Troubleshooting 112 | 113 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | 4 | 5 | Fixes # (issue) 6 | 7 | ## Type of change 8 | 9 | 10 | 11 | - [ ] Bug fix (non-breaking change which fixes an issue) 12 | - [ ] New feature (non-breaking change which adds functionality) 13 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 14 | - [ ] This change requires a documentation update 15 | 16 | # How Has This Been Tested? 17 | 18 | 19 | 20 | - [ ] Test A 21 | - [ ] Test B 22 | 23 | **Test Configuration**: 24 | * Firmware version: 25 | * Hardware: 26 | * Toolchain: 27 | * SDK: 28 | 29 | # Checklist: 30 | 31 | - [ ] My code follows the style guidelines of this project 32 | - [ ] I have performed a self-review of my own code 33 | - [ ] I have commented my code, particularly in hard-to-understand areas 34 | - [ ] I have made corresponding changes to the documentation 35 | - [ ] My changes generate no new warnings 36 | - [ ] I have added tests that prove my fix is effective or that my feature works 37 | - [ ] New and existing unit tests pass locally with my changes 38 | - [ ] Any dependent changes have been merged and published in downstream modules 39 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | push: 4 | branches: 5 | - main 6 | release: 7 | types: [created, edited] 8 | 9 | name: Main 10 | 11 | jobs: 12 | build_and_test: 13 | name: Rust project 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | target: 18 | - armv7-unknown-linux-musleabi 19 | - x86_64-pc-windows-gnu 20 | - x86_64-unknown-linux-gnu 21 | steps: 22 | - uses: actions/cache@v3 23 | with: 24 | path: | 25 | ~/.cargo/bin/ 26 | ~/.cargo/registry/index/ 27 | ~/.cargo/registry/cache/ 28 | ~/.cargo/git/db/ 29 | target/ 30 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 31 | - uses: actions/checkout@v3 32 | with: 33 | fetch-depth: 0 34 | 35 | - name: Get latest tag 36 | id: get-latest-tag 37 | run: | 38 | echo LATEST_TAG=$(git describe --abbrev=0 --tags $(git rev-list --tags --max-count=1)) >> $GITHUB_ENV 39 | 40 | - uses: actions-rs/toolchain@v1 41 | with: 42 | toolchain: stable 43 | target: ${{ matrix.target }} 44 | override: true 45 | 46 | - uses: actions-rs/cargo@v1 47 | name: Build and test 48 | with: 49 | use-cross: true 50 | command: build 51 | args: --release --target=${{ matrix.target }} 52 | 53 | - name: Package 54 | if: github.event_name == 'release' && github.event.action == 'created' 55 | run: | 56 | make bundle_release TARGET=${{ matrix.target }} 57 | 58 | - uses: svenstaro/upload-release-action@v2 59 | if: github.event_name == 'release' && (github.event.action == 'created' || github.event.action == 'edited') 60 | name: Upload release 61 | with: 62 | repo_token: ${{ secrets.GITHUB_TOKEN }} 63 | file: target/${{ matrix.target}}/release/kubediff_${{ matrix.target }}.tar.gz 64 | asset_name: kubediff_${{ env.LATEST_TAG }}_${{ matrix.target }}.tar.gz 65 | tag: ${{ env.LATEST_TAG }} 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adler" 7 | version = "1.0.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 10 | 11 | [[package]] 12 | name = "ahash" 13 | version = "0.7.6" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" 16 | dependencies = [ 17 | "getrandom", 18 | "once_cell", 19 | "version_check", 20 | ] 21 | 22 | [[package]] 23 | name = "aho-corasick" 24 | version = "1.1.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" 27 | dependencies = [ 28 | "memchr", 29 | ] 30 | 31 | [[package]] 32 | name = "ansi_colours" 33 | version = "1.2.2" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "6a1558bd2075d341b9ca698ec8eb6fcc55a746b1fc4255585aad5b141d918a80" 36 | dependencies = [ 37 | "rgb", 38 | ] 39 | 40 | [[package]] 41 | name = "anstream" 42 | version = "0.6.14" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" 45 | dependencies = [ 46 | "anstyle", 47 | "anstyle-parse", 48 | "anstyle-query", 49 | "anstyle-wincon", 50 | "colorchoice", 51 | "is_terminal_polyfill", 52 | "utf8parse", 53 | ] 54 | 55 | [[package]] 56 | name = "anstyle" 57 | version = "1.0.7" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" 60 | 61 | [[package]] 62 | name = "anstyle-parse" 63 | version = "0.2.4" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" 66 | dependencies = [ 67 | "utf8parse", 68 | ] 69 | 70 | [[package]] 71 | name = "anstyle-query" 72 | version = "1.1.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" 75 | dependencies = [ 76 | "windows-sys 0.52.0", 77 | ] 78 | 79 | [[package]] 80 | name = "anstyle-wincon" 81 | version = "3.0.3" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" 84 | dependencies = [ 85 | "anstyle", 86 | "windows-sys 0.52.0", 87 | ] 88 | 89 | [[package]] 90 | name = "anyhow" 91 | version = "1.0.75" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" 94 | 95 | [[package]] 96 | name = "async-trait" 97 | version = "0.1.57" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" 100 | dependencies = [ 101 | "proc-macro2", 102 | "quote", 103 | "syn 1.0.99", 104 | ] 105 | 106 | [[package]] 107 | name = "autocfg" 108 | version = "1.1.0" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 111 | 112 | [[package]] 113 | name = "base64" 114 | version = "0.13.0" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 117 | 118 | [[package]] 119 | name = "base64" 120 | version = "0.22.1" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 123 | 124 | [[package]] 125 | name = "bat" 126 | version = "0.24.0" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "9dcc9e5637c2330d8eb7b920f2aa5d9e184446c258466f825ea1412c7614cc86" 129 | dependencies = [ 130 | "ansi_colours", 131 | "bincode", 132 | "bugreport", 133 | "bytesize", 134 | "clap", 135 | "clircle", 136 | "console", 137 | "content_inspector", 138 | "encoding_rs", 139 | "etcetera", 140 | "flate2", 141 | "git2", 142 | "globset", 143 | "grep-cli", 144 | "home", 145 | "nu-ansi-term", 146 | "once_cell", 147 | "path_abs", 148 | "plist", 149 | "regex", 150 | "semver", 151 | "serde", 152 | "serde_yaml 0.9.29", 153 | "shell-words", 154 | "syntect", 155 | "thiserror", 156 | "unicode-width", 157 | "walkdir", 158 | "wild", 159 | ] 160 | 161 | [[package]] 162 | name = "bincode" 163 | version = "1.3.3" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 166 | dependencies = [ 167 | "serde", 168 | ] 169 | 170 | [[package]] 171 | name = "bitflags" 172 | version = "1.3.2" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 175 | 176 | [[package]] 177 | name = "bitflags" 178 | version = "2.4.1" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" 181 | 182 | [[package]] 183 | name = "block-buffer" 184 | version = "0.10.2" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" 187 | dependencies = [ 188 | "generic-array", 189 | ] 190 | 191 | [[package]] 192 | name = "bstr" 193 | version = "1.9.1" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" 196 | dependencies = [ 197 | "memchr", 198 | "regex-automata", 199 | "serde", 200 | ] 201 | 202 | [[package]] 203 | name = "bugreport" 204 | version = "0.5.0" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "535120b8182547808081a66f1f77a64533c780b23da26763e0ee34dfb94f98c9" 207 | dependencies = [ 208 | "git-version", 209 | "shell-escape", 210 | "sys-info", 211 | ] 212 | 213 | [[package]] 214 | name = "bytemuck" 215 | version = "1.11.0" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" 218 | 219 | [[package]] 220 | name = "bytesize" 221 | version = "1.3.0" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" 224 | 225 | [[package]] 226 | name = "cc" 227 | version = "1.0.73" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" 230 | dependencies = [ 231 | "jobserver", 232 | ] 233 | 234 | [[package]] 235 | name = "cfg-if" 236 | version = "1.0.0" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 239 | 240 | [[package]] 241 | name = "clap" 242 | version = "4.5.9" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" 245 | dependencies = [ 246 | "clap_builder", 247 | "clap_derive", 248 | ] 249 | 250 | [[package]] 251 | name = "clap_builder" 252 | version = "4.5.9" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" 255 | dependencies = [ 256 | "anstream", 257 | "anstyle", 258 | "clap_lex", 259 | "strsim", 260 | "terminal_size", 261 | ] 262 | 263 | [[package]] 264 | name = "clap_derive" 265 | version = "4.5.8" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" 268 | dependencies = [ 269 | "heck", 270 | "proc-macro2", 271 | "quote", 272 | "syn 2.0.39", 273 | ] 274 | 275 | [[package]] 276 | name = "clap_lex" 277 | version = "0.7.1" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" 280 | 281 | [[package]] 282 | name = "clircle" 283 | version = "0.4.0" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "c8e87cbed5354f17bd8ca8821a097fb62599787fe8f611743fad7ee156a0a600" 286 | dependencies = [ 287 | "cfg-if", 288 | "libc", 289 | "serde", 290 | "winapi", 291 | ] 292 | 293 | [[package]] 294 | name = "colorchoice" 295 | version = "1.0.1" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" 298 | 299 | [[package]] 300 | name = "colored" 301 | version = "2.0.4" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" 304 | dependencies = [ 305 | "is-terminal", 306 | "lazy_static", 307 | "windows-sys 0.48.0", 308 | ] 309 | 310 | [[package]] 311 | name = "config" 312 | version = "0.13.2" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "11f1667b8320afa80d69d8bbe40830df2c8a06003d86f73d8e003b2c48df416d" 315 | dependencies = [ 316 | "async-trait", 317 | "json5", 318 | "lazy_static", 319 | "nom", 320 | "pathdiff", 321 | "ron", 322 | "rust-ini", 323 | "serde", 324 | "serde_json", 325 | "toml", 326 | "yaml-rust", 327 | ] 328 | 329 | [[package]] 330 | name = "console" 331 | version = "0.15.8" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" 334 | dependencies = [ 335 | "encode_unicode", 336 | "lazy_static", 337 | "libc", 338 | "unicode-width", 339 | "windows-sys 0.52.0", 340 | ] 341 | 342 | [[package]] 343 | name = "content_inspector" 344 | version = "0.2.4" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38" 347 | dependencies = [ 348 | "memchr", 349 | ] 350 | 351 | [[package]] 352 | name = "cpufeatures" 353 | version = "0.2.3" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "1079fb8528d9f9c888b1e8aa651e6e079ade467323d58f75faf1d30b1808f540" 356 | dependencies = [ 357 | "libc", 358 | ] 359 | 360 | [[package]] 361 | name = "crc32fast" 362 | version = "1.3.2" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 365 | dependencies = [ 366 | "cfg-if", 367 | ] 368 | 369 | [[package]] 370 | name = "crossbeam-deque" 371 | version = "0.8.3" 372 | source = "registry+https://github.com/rust-lang/crates.io-index" 373 | checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" 374 | dependencies = [ 375 | "cfg-if", 376 | "crossbeam-epoch", 377 | "crossbeam-utils", 378 | ] 379 | 380 | [[package]] 381 | name = "crossbeam-epoch" 382 | version = "0.9.15" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" 385 | dependencies = [ 386 | "autocfg", 387 | "cfg-if", 388 | "crossbeam-utils", 389 | "memoffset", 390 | "scopeguard", 391 | ] 392 | 393 | [[package]] 394 | name = "crossbeam-utils" 395 | version = "0.8.16" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" 398 | dependencies = [ 399 | "cfg-if", 400 | ] 401 | 402 | [[package]] 403 | name = "crypto-common" 404 | version = "0.1.6" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 407 | dependencies = [ 408 | "generic-array", 409 | "typenum", 410 | ] 411 | 412 | [[package]] 413 | name = "deranged" 414 | version = "0.3.11" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 417 | dependencies = [ 418 | "powerfmt", 419 | ] 420 | 421 | [[package]] 422 | name = "digest" 423 | version = "0.10.3" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" 426 | dependencies = [ 427 | "block-buffer", 428 | "crypto-common", 429 | ] 430 | 431 | [[package]] 432 | name = "dirs" 433 | version = "4.0.0" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" 436 | dependencies = [ 437 | "dirs-sys", 438 | ] 439 | 440 | [[package]] 441 | name = "dirs-sys" 442 | version = "0.3.7" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" 445 | dependencies = [ 446 | "libc", 447 | "redox_users", 448 | "winapi", 449 | ] 450 | 451 | [[package]] 452 | name = "dlv-list" 453 | version = "0.3.0" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" 456 | 457 | [[package]] 458 | name = "either" 459 | version = "1.9.0" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" 462 | 463 | [[package]] 464 | name = "encode_unicode" 465 | version = "0.3.6" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 468 | 469 | [[package]] 470 | name = "encoding_rs" 471 | version = "0.8.34" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" 474 | dependencies = [ 475 | "cfg-if", 476 | ] 477 | 478 | [[package]] 479 | name = "equivalent" 480 | version = "1.0.1" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 483 | 484 | [[package]] 485 | name = "errno" 486 | version = "0.3.8" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" 489 | dependencies = [ 490 | "libc", 491 | "windows-sys 0.52.0", 492 | ] 493 | 494 | [[package]] 495 | name = "etcetera" 496 | version = "0.8.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" 499 | dependencies = [ 500 | "cfg-if", 501 | "home", 502 | "windows-sys 0.48.0", 503 | ] 504 | 505 | [[package]] 506 | name = "flate2" 507 | version = "1.0.24" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" 510 | dependencies = [ 511 | "crc32fast", 512 | "miniz_oxide", 513 | ] 514 | 515 | [[package]] 516 | name = "fnv" 517 | version = "1.0.7" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 520 | 521 | [[package]] 522 | name = "form_urlencoded" 523 | version = "1.0.1" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 526 | dependencies = [ 527 | "matches", 528 | "percent-encoding", 529 | ] 530 | 531 | [[package]] 532 | name = "generic-array" 533 | version = "0.14.6" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 536 | dependencies = [ 537 | "typenum", 538 | "version_check", 539 | ] 540 | 541 | [[package]] 542 | name = "getrandom" 543 | version = "0.2.7" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" 546 | dependencies = [ 547 | "cfg-if", 548 | "libc", 549 | "wasi", 550 | ] 551 | 552 | [[package]] 553 | name = "git-version" 554 | version = "0.3.5" 555 | source = "registry+https://github.com/rust-lang/crates.io-index" 556 | checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899" 557 | dependencies = [ 558 | "git-version-macro", 559 | "proc-macro-hack", 560 | ] 561 | 562 | [[package]] 563 | name = "git-version-macro" 564 | version = "0.3.5" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" 567 | dependencies = [ 568 | "proc-macro-hack", 569 | "proc-macro2", 570 | "quote", 571 | "syn 1.0.99", 572 | ] 573 | 574 | [[package]] 575 | name = "git2" 576 | version = "0.18.3" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" 579 | dependencies = [ 580 | "bitflags 2.4.1", 581 | "libc", 582 | "libgit2-sys", 583 | "log", 584 | "url", 585 | ] 586 | 587 | [[package]] 588 | name = "glob" 589 | version = "0.3.0" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" 592 | 593 | [[package]] 594 | name = "globset" 595 | version = "0.4.14" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" 598 | dependencies = [ 599 | "aho-corasick", 600 | "bstr", 601 | "log", 602 | "regex-automata", 603 | "regex-syntax 0.8.2", 604 | ] 605 | 606 | [[package]] 607 | name = "grep-cli" 608 | version = "0.1.10" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "ea40788c059ab8b622c4d074732750bfb3bd2912e2dd58eabc11798a4d5ad725" 611 | dependencies = [ 612 | "bstr", 613 | "globset", 614 | "libc", 615 | "log", 616 | "termcolor", 617 | "winapi-util", 618 | ] 619 | 620 | [[package]] 621 | name = "hashbrown" 622 | version = "0.12.3" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 625 | dependencies = [ 626 | "ahash", 627 | ] 628 | 629 | [[package]] 630 | name = "hashbrown" 631 | version = "0.14.5" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 634 | 635 | [[package]] 636 | name = "heck" 637 | version = "0.5.0" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 640 | 641 | [[package]] 642 | name = "hermit-abi" 643 | version = "0.3.3" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" 646 | 647 | [[package]] 648 | name = "home" 649 | version = "0.5.9" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 652 | dependencies = [ 653 | "windows-sys 0.52.0", 654 | ] 655 | 656 | [[package]] 657 | name = "idna" 658 | version = "0.2.3" 659 | source = "registry+https://github.com/rust-lang/crates.io-index" 660 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 661 | dependencies = [ 662 | "matches", 663 | "unicode-bidi", 664 | "unicode-normalization", 665 | ] 666 | 667 | [[package]] 668 | name = "indexmap" 669 | version = "1.9.1" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" 672 | dependencies = [ 673 | "autocfg", 674 | "hashbrown 0.12.3", 675 | ] 676 | 677 | [[package]] 678 | name = "indexmap" 679 | version = "2.2.6" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 682 | dependencies = [ 683 | "equivalent", 684 | "hashbrown 0.14.5", 685 | ] 686 | 687 | [[package]] 688 | name = "is-terminal" 689 | version = "0.4.9" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" 692 | dependencies = [ 693 | "hermit-abi", 694 | "rustix", 695 | "windows-sys 0.48.0", 696 | ] 697 | 698 | [[package]] 699 | name = "is_terminal_polyfill" 700 | version = "1.70.0" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" 703 | 704 | [[package]] 705 | name = "itoa" 706 | version = "1.0.3" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" 709 | 710 | [[package]] 711 | name = "jobserver" 712 | version = "0.1.24" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" 715 | dependencies = [ 716 | "libc", 717 | ] 718 | 719 | [[package]] 720 | name = "json5" 721 | version = "0.4.1" 722 | source = "registry+https://github.com/rust-lang/crates.io-index" 723 | checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" 724 | dependencies = [ 725 | "pest", 726 | "pest_derive", 727 | "serde", 728 | ] 729 | 730 | [[package]] 731 | name = "kubediff" 732 | version = "0.1.7" 733 | dependencies = [ 734 | "anyhow", 735 | "bat", 736 | "clap", 737 | "colored", 738 | "config", 739 | "dirs", 740 | "glob", 741 | "rayon", 742 | "regex", 743 | "serde", 744 | "serde_json", 745 | "serde_yaml 0.8.26", 746 | ] 747 | 748 | [[package]] 749 | name = "lazy_static" 750 | version = "1.4.0" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 753 | 754 | [[package]] 755 | name = "libc" 756 | version = "0.2.150" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" 759 | 760 | [[package]] 761 | name = "libgit2-sys" 762 | version = "0.16.2+1.7.2" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" 765 | dependencies = [ 766 | "cc", 767 | "libc", 768 | "libz-sys", 769 | "pkg-config", 770 | ] 771 | 772 | [[package]] 773 | name = "libz-sys" 774 | version = "1.1.8" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" 777 | dependencies = [ 778 | "cc", 779 | "libc", 780 | "pkg-config", 781 | "vcpkg", 782 | ] 783 | 784 | [[package]] 785 | name = "linked-hash-map" 786 | version = "0.5.6" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" 789 | 790 | [[package]] 791 | name = "linux-raw-sys" 792 | version = "0.4.12" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" 795 | 796 | [[package]] 797 | name = "log" 798 | version = "0.4.22" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 801 | 802 | [[package]] 803 | name = "matches" 804 | version = "0.1.9" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" 807 | 808 | [[package]] 809 | name = "memchr" 810 | version = "2.7.4" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 813 | 814 | [[package]] 815 | name = "memoffset" 816 | version = "0.9.0" 817 | source = "registry+https://github.com/rust-lang/crates.io-index" 818 | checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" 819 | dependencies = [ 820 | "autocfg", 821 | ] 822 | 823 | [[package]] 824 | name = "minimal-lexical" 825 | version = "0.2.1" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 828 | 829 | [[package]] 830 | name = "miniz_oxide" 831 | version = "0.5.3" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" 834 | dependencies = [ 835 | "adler", 836 | ] 837 | 838 | [[package]] 839 | name = "nom" 840 | version = "7.1.1" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" 843 | dependencies = [ 844 | "memchr", 845 | "minimal-lexical", 846 | ] 847 | 848 | [[package]] 849 | name = "nu-ansi-term" 850 | version = "0.49.0" 851 | source = "registry+https://github.com/rust-lang/crates.io-index" 852 | checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" 853 | dependencies = [ 854 | "windows-sys 0.48.0", 855 | ] 856 | 857 | [[package]] 858 | name = "num-conv" 859 | version = "0.1.0" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 862 | 863 | [[package]] 864 | name = "once_cell" 865 | version = "1.19.0" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 868 | 869 | [[package]] 870 | name = "onig" 871 | version = "6.3.2" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | checksum = "1eb3502504c9c8b06634b38bfdda86a9a8cef6277f3dec4d8b17c115110dd2a3" 874 | dependencies = [ 875 | "bitflags 1.3.2", 876 | "lazy_static", 877 | "libc", 878 | "onig_sys", 879 | ] 880 | 881 | [[package]] 882 | name = "onig_sys" 883 | version = "69.8.0" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "8bf3fbc9b931b6c9af85d219c7943c274a6ad26cff7488a2210215edd5f49bf8" 886 | dependencies = [ 887 | "cc", 888 | "pkg-config", 889 | ] 890 | 891 | [[package]] 892 | name = "ordered-multimap" 893 | version = "0.4.3" 894 | source = "registry+https://github.com/rust-lang/crates.io-index" 895 | checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" 896 | dependencies = [ 897 | "dlv-list", 898 | "hashbrown 0.12.3", 899 | ] 900 | 901 | [[package]] 902 | name = "path_abs" 903 | version = "0.5.1" 904 | source = "registry+https://github.com/rust-lang/crates.io-index" 905 | checksum = "05ef02f6342ac01d8a93b65f96db53fe68a92a15f41144f97fb00a9e669633c3" 906 | dependencies = [ 907 | "std_prelude", 908 | ] 909 | 910 | [[package]] 911 | name = "pathdiff" 912 | version = "0.2.1" 913 | source = "registry+https://github.com/rust-lang/crates.io-index" 914 | checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" 915 | 916 | [[package]] 917 | name = "percent-encoding" 918 | version = "2.1.0" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 921 | 922 | [[package]] 923 | name = "pest" 924 | version = "2.2.1" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "69486e2b8c2d2aeb9762db7b4e00b0331156393555cff467f4163ff06821eef8" 927 | dependencies = [ 928 | "thiserror", 929 | "ucd-trie", 930 | ] 931 | 932 | [[package]] 933 | name = "pest_derive" 934 | version = "2.2.1" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | checksum = "b13570633aff33c6d22ce47dd566b10a3b9122c2fe9d8e7501895905be532b91" 937 | dependencies = [ 938 | "pest", 939 | "pest_generator", 940 | ] 941 | 942 | [[package]] 943 | name = "pest_generator" 944 | version = "2.2.1" 945 | source = "registry+https://github.com/rust-lang/crates.io-index" 946 | checksum = "b3c567e5702efdc79fb18859ea74c3eb36e14c43da7b8c1f098a4ed6514ec7a0" 947 | dependencies = [ 948 | "pest", 949 | "pest_meta", 950 | "proc-macro2", 951 | "quote", 952 | "syn 1.0.99", 953 | ] 954 | 955 | [[package]] 956 | name = "pest_meta" 957 | version = "2.2.1" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "5eb32be5ee3bbdafa8c7a18b0a8a8d962b66cfa2ceee4037f49267a50ee821fe" 960 | dependencies = [ 961 | "once_cell", 962 | "pest", 963 | "sha-1", 964 | ] 965 | 966 | [[package]] 967 | name = "pkg-config" 968 | version = "0.3.25" 969 | source = "registry+https://github.com/rust-lang/crates.io-index" 970 | checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" 971 | 972 | [[package]] 973 | name = "plist" 974 | version = "1.7.0" 975 | source = "registry+https://github.com/rust-lang/crates.io-index" 976 | checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" 977 | dependencies = [ 978 | "base64 0.22.1", 979 | "indexmap 2.2.6", 980 | "quick-xml", 981 | "serde", 982 | "time", 983 | ] 984 | 985 | [[package]] 986 | name = "powerfmt" 987 | version = "0.2.0" 988 | source = "registry+https://github.com/rust-lang/crates.io-index" 989 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 990 | 991 | [[package]] 992 | name = "proc-macro-hack" 993 | version = "0.5.19" 994 | source = "registry+https://github.com/rust-lang/crates.io-index" 995 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 996 | 997 | [[package]] 998 | name = "proc-macro2" 999 | version = "1.0.70" 1000 | source = "registry+https://github.com/rust-lang/crates.io-index" 1001 | checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" 1002 | dependencies = [ 1003 | "unicode-ident", 1004 | ] 1005 | 1006 | [[package]] 1007 | name = "quick-xml" 1008 | version = "0.32.0" 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" 1010 | checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" 1011 | dependencies = [ 1012 | "memchr", 1013 | ] 1014 | 1015 | [[package]] 1016 | name = "quote" 1017 | version = "1.0.33" 1018 | source = "registry+https://github.com/rust-lang/crates.io-index" 1019 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 1020 | dependencies = [ 1021 | "proc-macro2", 1022 | ] 1023 | 1024 | [[package]] 1025 | name = "rayon" 1026 | version = "1.8.0" 1027 | source = "registry+https://github.com/rust-lang/crates.io-index" 1028 | checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" 1029 | dependencies = [ 1030 | "either", 1031 | "rayon-core", 1032 | ] 1033 | 1034 | [[package]] 1035 | name = "rayon-core" 1036 | version = "1.12.0" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" 1039 | dependencies = [ 1040 | "crossbeam-deque", 1041 | "crossbeam-utils", 1042 | ] 1043 | 1044 | [[package]] 1045 | name = "redox_syscall" 1046 | version = "0.2.16" 1047 | source = "registry+https://github.com/rust-lang/crates.io-index" 1048 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1049 | dependencies = [ 1050 | "bitflags 1.3.2", 1051 | ] 1052 | 1053 | [[package]] 1054 | name = "redox_users" 1055 | version = "0.4.3" 1056 | source = "registry+https://github.com/rust-lang/crates.io-index" 1057 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 1058 | dependencies = [ 1059 | "getrandom", 1060 | "redox_syscall", 1061 | "thiserror", 1062 | ] 1063 | 1064 | [[package]] 1065 | name = "regex" 1066 | version = "1.10.2" 1067 | source = "registry+https://github.com/rust-lang/crates.io-index" 1068 | checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" 1069 | dependencies = [ 1070 | "aho-corasick", 1071 | "memchr", 1072 | "regex-automata", 1073 | "regex-syntax 0.8.2", 1074 | ] 1075 | 1076 | [[package]] 1077 | name = "regex-automata" 1078 | version = "0.4.3" 1079 | source = "registry+https://github.com/rust-lang/crates.io-index" 1080 | checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" 1081 | dependencies = [ 1082 | "aho-corasick", 1083 | "memchr", 1084 | "regex-syntax 0.8.2", 1085 | ] 1086 | 1087 | [[package]] 1088 | name = "regex-syntax" 1089 | version = "0.6.27" 1090 | source = "registry+https://github.com/rust-lang/crates.io-index" 1091 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 1092 | 1093 | [[package]] 1094 | name = "regex-syntax" 1095 | version = "0.8.2" 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" 1097 | checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" 1098 | 1099 | [[package]] 1100 | name = "rgb" 1101 | version = "0.8.33" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "c3b221de559e4a29df3b957eec92bc0de6bc8eaf6ca9cfed43e5e1d67ff65a34" 1104 | dependencies = [ 1105 | "bytemuck", 1106 | ] 1107 | 1108 | [[package]] 1109 | name = "ron" 1110 | version = "0.7.1" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" 1113 | dependencies = [ 1114 | "base64 0.13.0", 1115 | "bitflags 1.3.2", 1116 | "serde", 1117 | ] 1118 | 1119 | [[package]] 1120 | name = "rust-ini" 1121 | version = "0.18.0" 1122 | source = "registry+https://github.com/rust-lang/crates.io-index" 1123 | checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" 1124 | dependencies = [ 1125 | "cfg-if", 1126 | "ordered-multimap", 1127 | ] 1128 | 1129 | [[package]] 1130 | name = "rustix" 1131 | version = "0.38.26" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" 1134 | dependencies = [ 1135 | "bitflags 2.4.1", 1136 | "errno", 1137 | "libc", 1138 | "linux-raw-sys", 1139 | "windows-sys 0.52.0", 1140 | ] 1141 | 1142 | [[package]] 1143 | name = "ryu" 1144 | version = "1.0.11" 1145 | source = "registry+https://github.com/rust-lang/crates.io-index" 1146 | checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" 1147 | 1148 | [[package]] 1149 | name = "same-file" 1150 | version = "1.0.6" 1151 | source = "registry+https://github.com/rust-lang/crates.io-index" 1152 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1153 | dependencies = [ 1154 | "winapi-util", 1155 | ] 1156 | 1157 | [[package]] 1158 | name = "scopeguard" 1159 | version = "1.2.0" 1160 | source = "registry+https://github.com/rust-lang/crates.io-index" 1161 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1162 | 1163 | [[package]] 1164 | name = "semver" 1165 | version = "1.0.13" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" 1168 | 1169 | [[package]] 1170 | name = "serde" 1171 | version = "1.0.193" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" 1174 | dependencies = [ 1175 | "serde_derive", 1176 | ] 1177 | 1178 | [[package]] 1179 | name = "serde_derive" 1180 | version = "1.0.193" 1181 | source = "registry+https://github.com/rust-lang/crates.io-index" 1182 | checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" 1183 | dependencies = [ 1184 | "proc-macro2", 1185 | "quote", 1186 | "syn 2.0.39", 1187 | ] 1188 | 1189 | [[package]] 1190 | name = "serde_json" 1191 | version = "1.0.83" 1192 | source = "registry+https://github.com/rust-lang/crates.io-index" 1193 | checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" 1194 | dependencies = [ 1195 | "itoa", 1196 | "ryu", 1197 | "serde", 1198 | ] 1199 | 1200 | [[package]] 1201 | name = "serde_yaml" 1202 | version = "0.8.26" 1203 | source = "registry+https://github.com/rust-lang/crates.io-index" 1204 | checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" 1205 | dependencies = [ 1206 | "indexmap 1.9.1", 1207 | "ryu", 1208 | "serde", 1209 | "yaml-rust", 1210 | ] 1211 | 1212 | [[package]] 1213 | name = "serde_yaml" 1214 | version = "0.9.29" 1215 | source = "registry+https://github.com/rust-lang/crates.io-index" 1216 | checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" 1217 | dependencies = [ 1218 | "indexmap 2.2.6", 1219 | "itoa", 1220 | "ryu", 1221 | "serde", 1222 | "unsafe-libyaml", 1223 | ] 1224 | 1225 | [[package]] 1226 | name = "sha-1" 1227 | version = "0.10.0" 1228 | source = "registry+https://github.com/rust-lang/crates.io-index" 1229 | checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" 1230 | dependencies = [ 1231 | "cfg-if", 1232 | "cpufeatures", 1233 | "digest", 1234 | ] 1235 | 1236 | [[package]] 1237 | name = "shell-escape" 1238 | version = "0.1.5" 1239 | source = "registry+https://github.com/rust-lang/crates.io-index" 1240 | checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" 1241 | 1242 | [[package]] 1243 | name = "shell-words" 1244 | version = "1.1.0" 1245 | source = "registry+https://github.com/rust-lang/crates.io-index" 1246 | checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" 1247 | 1248 | [[package]] 1249 | name = "std_prelude" 1250 | version = "0.2.12" 1251 | source = "registry+https://github.com/rust-lang/crates.io-index" 1252 | checksum = "8207e78455ffdf55661170876f88daf85356e4edd54e0a3dbc79586ca1e50cbe" 1253 | 1254 | [[package]] 1255 | name = "strsim" 1256 | version = "0.11.1" 1257 | source = "registry+https://github.com/rust-lang/crates.io-index" 1258 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 1259 | 1260 | [[package]] 1261 | name = "syn" 1262 | version = "1.0.99" 1263 | source = "registry+https://github.com/rust-lang/crates.io-index" 1264 | checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" 1265 | dependencies = [ 1266 | "proc-macro2", 1267 | "quote", 1268 | "unicode-ident", 1269 | ] 1270 | 1271 | [[package]] 1272 | name = "syn" 1273 | version = "2.0.39" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" 1276 | dependencies = [ 1277 | "proc-macro2", 1278 | "quote", 1279 | "unicode-ident", 1280 | ] 1281 | 1282 | [[package]] 1283 | name = "syntect" 1284 | version = "5.0.0" 1285 | source = "registry+https://github.com/rust-lang/crates.io-index" 1286 | checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8" 1287 | dependencies = [ 1288 | "bincode", 1289 | "bitflags 1.3.2", 1290 | "flate2", 1291 | "fnv", 1292 | "lazy_static", 1293 | "once_cell", 1294 | "onig", 1295 | "plist", 1296 | "regex-syntax 0.6.27", 1297 | "serde", 1298 | "serde_derive", 1299 | "serde_json", 1300 | "thiserror", 1301 | "walkdir", 1302 | "yaml-rust", 1303 | ] 1304 | 1305 | [[package]] 1306 | name = "sys-info" 1307 | version = "0.9.1" 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" 1309 | checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c" 1310 | dependencies = [ 1311 | "cc", 1312 | "libc", 1313 | ] 1314 | 1315 | [[package]] 1316 | name = "termcolor" 1317 | version = "1.4.1" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" 1320 | dependencies = [ 1321 | "winapi-util", 1322 | ] 1323 | 1324 | [[package]] 1325 | name = "terminal_size" 1326 | version = "0.3.0" 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" 1328 | checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" 1329 | dependencies = [ 1330 | "rustix", 1331 | "windows-sys 0.48.0", 1332 | ] 1333 | 1334 | [[package]] 1335 | name = "thiserror" 1336 | version = "1.0.32" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" 1339 | dependencies = [ 1340 | "thiserror-impl", 1341 | ] 1342 | 1343 | [[package]] 1344 | name = "thiserror-impl" 1345 | version = "1.0.32" 1346 | source = "registry+https://github.com/rust-lang/crates.io-index" 1347 | checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" 1348 | dependencies = [ 1349 | "proc-macro2", 1350 | "quote", 1351 | "syn 1.0.99", 1352 | ] 1353 | 1354 | [[package]] 1355 | name = "time" 1356 | version = "0.3.36" 1357 | source = "registry+https://github.com/rust-lang/crates.io-index" 1358 | checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" 1359 | dependencies = [ 1360 | "deranged", 1361 | "itoa", 1362 | "num-conv", 1363 | "powerfmt", 1364 | "serde", 1365 | "time-core", 1366 | "time-macros", 1367 | ] 1368 | 1369 | [[package]] 1370 | name = "time-core" 1371 | version = "0.1.2" 1372 | source = "registry+https://github.com/rust-lang/crates.io-index" 1373 | checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 1374 | 1375 | [[package]] 1376 | name = "time-macros" 1377 | version = "0.2.18" 1378 | source = "registry+https://github.com/rust-lang/crates.io-index" 1379 | checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" 1380 | dependencies = [ 1381 | "num-conv", 1382 | "time-core", 1383 | ] 1384 | 1385 | [[package]] 1386 | name = "tinyvec" 1387 | version = "1.6.0" 1388 | source = "registry+https://github.com/rust-lang/crates.io-index" 1389 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1390 | dependencies = [ 1391 | "tinyvec_macros", 1392 | ] 1393 | 1394 | [[package]] 1395 | name = "tinyvec_macros" 1396 | version = "0.1.0" 1397 | source = "registry+https://github.com/rust-lang/crates.io-index" 1398 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1399 | 1400 | [[package]] 1401 | name = "toml" 1402 | version = "0.5.9" 1403 | source = "registry+https://github.com/rust-lang/crates.io-index" 1404 | checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" 1405 | dependencies = [ 1406 | "serde", 1407 | ] 1408 | 1409 | [[package]] 1410 | name = "typenum" 1411 | version = "1.15.0" 1412 | source = "registry+https://github.com/rust-lang/crates.io-index" 1413 | checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" 1414 | 1415 | [[package]] 1416 | name = "ucd-trie" 1417 | version = "0.1.4" 1418 | source = "registry+https://github.com/rust-lang/crates.io-index" 1419 | checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" 1420 | 1421 | [[package]] 1422 | name = "unicode-bidi" 1423 | version = "0.3.8" 1424 | source = "registry+https://github.com/rust-lang/crates.io-index" 1425 | checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" 1426 | 1427 | [[package]] 1428 | name = "unicode-ident" 1429 | version = "1.0.3" 1430 | source = "registry+https://github.com/rust-lang/crates.io-index" 1431 | checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" 1432 | 1433 | [[package]] 1434 | name = "unicode-normalization" 1435 | version = "0.1.21" 1436 | source = "registry+https://github.com/rust-lang/crates.io-index" 1437 | checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" 1438 | dependencies = [ 1439 | "tinyvec", 1440 | ] 1441 | 1442 | [[package]] 1443 | name = "unicode-width" 1444 | version = "0.1.13" 1445 | source = "registry+https://github.com/rust-lang/crates.io-index" 1446 | checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" 1447 | 1448 | [[package]] 1449 | name = "unsafe-libyaml" 1450 | version = "0.2.11" 1451 | source = "registry+https://github.com/rust-lang/crates.io-index" 1452 | checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" 1453 | 1454 | [[package]] 1455 | name = "url" 1456 | version = "2.2.2" 1457 | source = "registry+https://github.com/rust-lang/crates.io-index" 1458 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 1459 | dependencies = [ 1460 | "form_urlencoded", 1461 | "idna", 1462 | "matches", 1463 | "percent-encoding", 1464 | ] 1465 | 1466 | [[package]] 1467 | name = "utf8parse" 1468 | version = "0.2.2" 1469 | source = "registry+https://github.com/rust-lang/crates.io-index" 1470 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 1471 | 1472 | [[package]] 1473 | name = "vcpkg" 1474 | version = "0.2.15" 1475 | source = "registry+https://github.com/rust-lang/crates.io-index" 1476 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1477 | 1478 | [[package]] 1479 | name = "version_check" 1480 | version = "0.9.4" 1481 | source = "registry+https://github.com/rust-lang/crates.io-index" 1482 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1483 | 1484 | [[package]] 1485 | name = "walkdir" 1486 | version = "2.3.2" 1487 | source = "registry+https://github.com/rust-lang/crates.io-index" 1488 | checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" 1489 | dependencies = [ 1490 | "same-file", 1491 | "winapi", 1492 | "winapi-util", 1493 | ] 1494 | 1495 | [[package]] 1496 | name = "wasi" 1497 | version = "0.11.0+wasi-snapshot-preview1" 1498 | source = "registry+https://github.com/rust-lang/crates.io-index" 1499 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1500 | 1501 | [[package]] 1502 | name = "wild" 1503 | version = "2.1.0" 1504 | source = "registry+https://github.com/rust-lang/crates.io-index" 1505 | checksum = "05b116685a6be0c52f5a103334cbff26db643826c7b3735fc0a3ba9871310a74" 1506 | dependencies = [ 1507 | "glob", 1508 | ] 1509 | 1510 | [[package]] 1511 | name = "winapi" 1512 | version = "0.3.9" 1513 | source = "registry+https://github.com/rust-lang/crates.io-index" 1514 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1515 | dependencies = [ 1516 | "winapi-i686-pc-windows-gnu", 1517 | "winapi-x86_64-pc-windows-gnu", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "winapi-i686-pc-windows-gnu" 1522 | version = "0.4.0" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1525 | 1526 | [[package]] 1527 | name = "winapi-util" 1528 | version = "0.1.8" 1529 | source = "registry+https://github.com/rust-lang/crates.io-index" 1530 | checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" 1531 | dependencies = [ 1532 | "windows-sys 0.52.0", 1533 | ] 1534 | 1535 | [[package]] 1536 | name = "winapi-x86_64-pc-windows-gnu" 1537 | version = "0.4.0" 1538 | source = "registry+https://github.com/rust-lang/crates.io-index" 1539 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1540 | 1541 | [[package]] 1542 | name = "windows-sys" 1543 | version = "0.48.0" 1544 | source = "registry+https://github.com/rust-lang/crates.io-index" 1545 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1546 | dependencies = [ 1547 | "windows-targets 0.48.5", 1548 | ] 1549 | 1550 | [[package]] 1551 | name = "windows-sys" 1552 | version = "0.52.0" 1553 | source = "registry+https://github.com/rust-lang/crates.io-index" 1554 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1555 | dependencies = [ 1556 | "windows-targets 0.52.0", 1557 | ] 1558 | 1559 | [[package]] 1560 | name = "windows-targets" 1561 | version = "0.48.5" 1562 | source = "registry+https://github.com/rust-lang/crates.io-index" 1563 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 1564 | dependencies = [ 1565 | "windows_aarch64_gnullvm 0.48.5", 1566 | "windows_aarch64_msvc 0.48.5", 1567 | "windows_i686_gnu 0.48.5", 1568 | "windows_i686_msvc 0.48.5", 1569 | "windows_x86_64_gnu 0.48.5", 1570 | "windows_x86_64_gnullvm 0.48.5", 1571 | "windows_x86_64_msvc 0.48.5", 1572 | ] 1573 | 1574 | [[package]] 1575 | name = "windows-targets" 1576 | version = "0.52.0" 1577 | source = "registry+https://github.com/rust-lang/crates.io-index" 1578 | checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" 1579 | dependencies = [ 1580 | "windows_aarch64_gnullvm 0.52.0", 1581 | "windows_aarch64_msvc 0.52.0", 1582 | "windows_i686_gnu 0.52.0", 1583 | "windows_i686_msvc 0.52.0", 1584 | "windows_x86_64_gnu 0.52.0", 1585 | "windows_x86_64_gnullvm 0.52.0", 1586 | "windows_x86_64_msvc 0.52.0", 1587 | ] 1588 | 1589 | [[package]] 1590 | name = "windows_aarch64_gnullvm" 1591 | version = "0.48.5" 1592 | source = "registry+https://github.com/rust-lang/crates.io-index" 1593 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 1594 | 1595 | [[package]] 1596 | name = "windows_aarch64_gnullvm" 1597 | version = "0.52.0" 1598 | source = "registry+https://github.com/rust-lang/crates.io-index" 1599 | checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" 1600 | 1601 | [[package]] 1602 | name = "windows_aarch64_msvc" 1603 | version = "0.48.5" 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" 1605 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 1606 | 1607 | [[package]] 1608 | name = "windows_aarch64_msvc" 1609 | version = "0.52.0" 1610 | source = "registry+https://github.com/rust-lang/crates.io-index" 1611 | checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" 1612 | 1613 | [[package]] 1614 | name = "windows_i686_gnu" 1615 | version = "0.48.5" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 1618 | 1619 | [[package]] 1620 | name = "windows_i686_gnu" 1621 | version = "0.52.0" 1622 | source = "registry+https://github.com/rust-lang/crates.io-index" 1623 | checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" 1624 | 1625 | [[package]] 1626 | name = "windows_i686_msvc" 1627 | version = "0.48.5" 1628 | source = "registry+https://github.com/rust-lang/crates.io-index" 1629 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 1630 | 1631 | [[package]] 1632 | name = "windows_i686_msvc" 1633 | version = "0.52.0" 1634 | source = "registry+https://github.com/rust-lang/crates.io-index" 1635 | checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" 1636 | 1637 | [[package]] 1638 | name = "windows_x86_64_gnu" 1639 | version = "0.48.5" 1640 | source = "registry+https://github.com/rust-lang/crates.io-index" 1641 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 1642 | 1643 | [[package]] 1644 | name = "windows_x86_64_gnu" 1645 | version = "0.52.0" 1646 | source = "registry+https://github.com/rust-lang/crates.io-index" 1647 | checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" 1648 | 1649 | [[package]] 1650 | name = "windows_x86_64_gnullvm" 1651 | version = "0.48.5" 1652 | source = "registry+https://github.com/rust-lang/crates.io-index" 1653 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 1654 | 1655 | [[package]] 1656 | name = "windows_x86_64_gnullvm" 1657 | version = "0.52.0" 1658 | source = "registry+https://github.com/rust-lang/crates.io-index" 1659 | checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" 1660 | 1661 | [[package]] 1662 | name = "windows_x86_64_msvc" 1663 | version = "0.48.5" 1664 | source = "registry+https://github.com/rust-lang/crates.io-index" 1665 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 1666 | 1667 | [[package]] 1668 | name = "windows_x86_64_msvc" 1669 | version = "0.52.0" 1670 | source = "registry+https://github.com/rust-lang/crates.io-index" 1671 | checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" 1672 | 1673 | [[package]] 1674 | name = "yaml-rust" 1675 | version = "0.4.5" 1676 | source = "registry+https://github.com/rust-lang/crates.io-index" 1677 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" 1678 | dependencies = [ 1679 | "linked-hash-map", 1680 | ] 1681 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kubediff" 3 | version = "0.1.7" 4 | edition = "2021" 5 | authors = ["https://github.com/ramilito"] 6 | 7 | [dependencies] 8 | anyhow = "1.0.75" 9 | bat = "0.24.0" 10 | clap = { version = "4.5.9", features = ["derive"] } 11 | colored = "2.0.4" 12 | config = "0.13.2" 13 | dirs = "4.0.0" 14 | glob = "0.3.0" 15 | rayon = "1.8.0" 16 | regex = "1.10.2" 17 | serde = {version = "1.0.142", features = ["derive"]} 18 | serde_json = "1.0.83" 19 | serde_yaml = "0.8.26" 20 | 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Rami Daghlawi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | LATEST_TAG := $(shell git describe --abbrev=0 --tags $(git rev-list --tags --max-count=1)) 4 | 5 | define bundle_release 6 | @echo "" 7 | if [[ "$(1)" == *"windows"* ]]; then \ 8 | tar -czvf ./target/$(1)/release/kubediff_$(1).tar.gz src/assets/ ./target/$(1)/release/kubediff.exe; \ 9 | else \ 10 | tar -czvf ./target/$(1)/release/kubediff_$(1).tar.gz src/assets/ ./target/$(1)/release/kubediff; \ 11 | fi 12 | endef 13 | 14 | .PHONY: bundle_release 15 | bundle_release: 16 | $(call bundle_release,${TARGET}) 17 | 18 | .PHONY: build 19 | build: 20 | cargo build 21 | cp ./src/assets/diff.sh ./target/debug/ 22 | cp ./src/assets/config.yaml ./target/debug/ 23 | 24 | .PHONY: build_local 25 | build_local: build 26 | cargo build --release 27 | mkdir -p ~/.kube/kubediff 28 | cp ./target/release/kubediff ~/.kube/kubediff/ 29 | cp ./src/assets/diff.sh ~/.kube/kubediff/ 30 | cp ./src/assets/config.yaml ~/.kube/kubediff/ 31 | 32 | .PHONY: run 33 | run: 34 | cargo run -- -e local 35 | 36 | .PHONY: deploy_local 37 | deploy_local: build_local run 38 | 39 | -------------------------------------------------------------------------------- /docs/images/diff_kubediff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramilito/kubediff/650d8eec71e41c6e97213219b9c65b44b52d31d8/docs/images/diff_kubediff.png -------------------------------------------------------------------------------- /docs/images/diff_original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramilito/kubediff/650d8eec71e41c6e97213219b9c65b44b52d31d8/docs/images/diff_original.png -------------------------------------------------------------------------------- /docs/images/kubediff-showcase.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramilito/kubediff/650d8eec71e41c6e97213219b9c65b44b52d31d8/docs/images/kubediff-showcase.gif -------------------------------------------------------------------------------- /docs/images/kubediff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramilito/kubediff/650d8eec71e41c6e97213219b9c65b44b52d31d8/docs/images/kubediff.png -------------------------------------------------------------------------------- /src/assets/config.yaml: -------------------------------------------------------------------------------- 1 | configs: 2 | log: "Info" 3 | include: 4 | - "include_me" 5 | 6 | exclude: 7 | - "exclude_me" 8 | -------------------------------------------------------------------------------- /src/assets/diff.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DIFF_ARGS=( 4 | "--minimal" 5 | "--width=120" 6 | "-u" 7 | "-N" 8 | ) 9 | if [[ ! $ANSIBLE_MODE = YES ]]; then 10 | DIFF_ARGS+=("--color=always") 11 | fi 12 | 13 | 14 | find "$@" -type f -exec yq e -i 'del( 15 | .metadata.managedFields, 16 | .metadata.ownerReferences, 17 | .metadata.generation, 18 | .metadata.creationTimestamp, 19 | .webhooks, 20 | .spec.caBundle, 21 | .metadata.annotations["kubectl.kubernetes.io/last-applied-configuration"], 22 | .metadata.annotations["argocd.argoproj.io/tracking-id"] 23 | )' {} \; 24 | 25 | diff "${DIFF_ARGS[@]}" "$@" | awk '!/^diff/ {if ($1 ~ /(---|\+\+\+)/) {print $1, $2} else {print $0}}' 26 | -------------------------------------------------------------------------------- /src/commands.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fs, 3 | io::{Error, ErrorKind, Write}, 4 | path::Path, 5 | process::{Command, Stdio}, 6 | sync::{Arc, Mutex}, 7 | }; 8 | 9 | use crate::logger::Logger; 10 | 11 | pub struct Commands; 12 | 13 | impl Commands { 14 | pub fn get_diff(input: &str) -> anyhow::Result { 15 | let script_path = get_script(); 16 | let mut diff = Command::new("kubectl") 17 | .env("KUBECTL_EXTERNAL_DIFF", script_path) 18 | .arg("diff") 19 | .arg("-f") 20 | .arg("-") 21 | .stdin(Stdio::piped()) 22 | .stdout(Stdio::piped()) 23 | .spawn()?; 24 | 25 | if let Some(stdin) = diff.stdin.as_mut() { 26 | stdin.write_all(input.as_bytes())?; 27 | } 28 | 29 | let output = diff.wait_with_output()?; 30 | let result = String::from_utf8(output.stdout)?; 31 | Ok(result) 32 | } 33 | 34 | pub fn get_build(logger: Arc>, target: &str) -> anyhow::Result { 35 | if Path::new(target).is_file() { 36 | return run_command(&["cat", target], logger.clone()); 37 | } 38 | 39 | if is_kustomize_directory(target)? { 40 | return run_command(&["kubectl", "kustomize", target], logger.clone()); 41 | } 42 | 43 | let mut combined_output = String::new(); 44 | for entry in fs::read_dir(target)? { 45 | let entry = entry?; 46 | if entry.path().is_file() { 47 | let e = entry.path(); 48 | let file_path = e.to_str().unwrap(); 49 | let output = run_command(&["cat", file_path], logger.clone())?; 50 | combined_output.push_str(&output); 51 | } 52 | } 53 | 54 | Ok(combined_output) 55 | } 56 | } 57 | 58 | fn get_script() -> String { 59 | let mut path = std::env::current_exe().unwrap(); 60 | path.pop(); 61 | path.push("diff.sh"); 62 | path.to_str().unwrap().to_string() 63 | } 64 | 65 | fn run_command(args: &[&str], logger: Arc>) -> anyhow::Result { 66 | let output = Command::new(args[0]) 67 | .args(&args[1..]) 68 | .stdin(Stdio::piped()) 69 | .stdout(Stdio::piped()) 70 | .stderr(Stdio::piped()) 71 | .spawn()? 72 | .wait_with_output()?; 73 | 74 | if output.status.success() { 75 | Ok(String::from_utf8(output.stdout)?) 76 | } else { 77 | let stderr = String::from_utf8(output.stderr)?; 78 | logger.lock().unwrap().log_error(stderr.clone()); 79 | Err(Error::new( 80 | ErrorKind::Other, 81 | format!("Build failed with error: {}", stderr), 82 | ) 83 | .into()) 84 | } 85 | } 86 | 87 | fn is_kustomize_directory(target: &str) -> anyhow::Result { 88 | for entry in fs::read_dir(target)? { 89 | let entry = entry?; 90 | let file_name = entry.file_name(); 91 | if file_name == "kustomization.yaml" 92 | || file_name == "kustomization.yml" 93 | || file_name == "Kustomization" 94 | { 95 | return Ok(true); 96 | } 97 | } 98 | Ok(false) 99 | } 100 | -------------------------------------------------------------------------------- /src/enums.rs: -------------------------------------------------------------------------------- 1 | use clap::ValueEnum; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Default, Debug, Copy, Clone, PartialEq, ValueEnum, Serialize, Deserialize)] 5 | pub enum LogLevel { 6 | Info, 7 | Warning, 8 | #[default] 9 | Error, 10 | } 11 | -------------------------------------------------------------------------------- /src/logger.rs: -------------------------------------------------------------------------------- 1 | use colored::Colorize; 2 | use regex::Regex; 3 | 4 | use crate::{enums::LogLevel, print::Pretty, Cli}; 5 | 6 | pub struct Logger { 7 | arg_log: Option, 8 | term_width: Option, 9 | config_log: LogLevel, 10 | } 11 | 12 | impl Logger { 13 | pub fn new(args: Cli, config_log: LogLevel) -> Self { 14 | Logger { 15 | arg_log: args.log, 16 | term_width: args.term_width, 17 | config_log, 18 | } 19 | } 20 | 21 | pub fn log_info(&self, message: String) { 22 | let level = self.arg_log.unwrap_or(self.config_log); 23 | if level == LogLevel::Info { 24 | Pretty::print_info(message, self.term_width) 25 | }; 26 | } 27 | 28 | pub fn log_warning(&self, message: String) { 29 | let level = self.arg_log.unwrap_or(self.config_log); 30 | 31 | if level == LogLevel::Warning || level == LogLevel::Info { 32 | Pretty::print_warning(message, self.term_width) 33 | }; 34 | } 35 | 36 | pub fn log_error(&self, message: String) { 37 | let formatted = format_error_message(&message); 38 | Pretty::print_error(formatted,self.term_width); 39 | } 40 | } 41 | 42 | fn format_error_message(error_message: &str) -> String { 43 | // Find and colorize the word "Error" 44 | let re_error_word = Regex::new(r"\bError\b").unwrap(); 45 | let colored_message = re_error_word.replace_all(&error_message, |_: ®ex::Captures| { 46 | "Error".red().to_string() 47 | }); 48 | 49 | format!("{}\n", colored_message) 50 | } 51 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod commands; 2 | mod enums; 3 | mod logger; 4 | mod print; 5 | mod processor; 6 | mod settings; 7 | 8 | use std::{ 9 | path::Path, 10 | sync::{Arc, Mutex}, 11 | }; 12 | 13 | use crate::{enums::LogLevel, logger::Logger, processor::Process, settings::Settings}; 14 | use clap::Parser; 15 | use colored::Colorize; 16 | 17 | #[derive(Debug, Parser, Clone)] 18 | #[clap(author, version, about, long_about = None)] 19 | pub struct Cli { 20 | #[clap(short, long, value_parser)] 21 | env: Option, 22 | #[clap(short, long, value_parser)] 23 | inplace: bool, 24 | #[clap(short, long, value_parser)] 25 | path: Option, 26 | #[clap(short, long, value_enum)] 27 | log: Option, 28 | #[clap(short, long, value_parser)] 29 | term_width: Option, 30 | } 31 | 32 | fn main() -> anyhow::Result<()> { 33 | let args = Cli::parse(); 34 | let settings = Settings::load().expect("Failed to load config file!"); 35 | let logger = Arc::new(Mutex::new(Logger::new(args.clone(), settings.configs.log))); 36 | 37 | let targets = Process::get_entries(args.clone(), settings); 38 | 39 | for target in targets { 40 | if Path::new(&target).exists() { 41 | Process::process_target(args.clone(), &logger, &target)?; 42 | } else { 43 | let message = "Must build at directory: not a valid directory ⚠️" 44 | .yellow() 45 | .to_string(); 46 | logger 47 | .lock() 48 | .unwrap() 49 | .log_warning(format!("\n{}:{}\n", message, &target)) 50 | } 51 | } 52 | 53 | Ok(()) 54 | } 55 | -------------------------------------------------------------------------------- /src/print.rs: -------------------------------------------------------------------------------- 1 | use bat::{Input, PagingMode, PrettyPrinter}; 2 | 3 | pub struct Pretty {} 4 | impl Pretty { 5 | #[allow(dead_code)] 6 | pub fn print_themes() { 7 | let printer = PrettyPrinter::new(); 8 | 9 | println!("Syntaxes:"); 10 | for syntax in printer.syntaxes() { 11 | println!("- {} ({})", syntax.name, syntax.file_extensions.join(", ")); 12 | } 13 | 14 | println!(); 15 | 16 | println!("Themes:"); 17 | for theme in printer.themes() { 18 | println!("- {}", theme); 19 | } 20 | } 21 | pub fn print_path(string: String, term_width: Option) { 22 | let mut printer = PrettyPrinter::new(); 23 | printer 24 | .input(Input::from_bytes(&string.as_bytes())) 25 | .header(false) 26 | .grid(true) 27 | .language("syslog") 28 | .theme("OneHalfDark"); 29 | if term_width.is_some() { 30 | printer.term_width(term_width.unwrap()); 31 | } 32 | printer.print().unwrap(); 33 | } 34 | 35 | pub fn print_info(string: String, term_width: Option) { 36 | let mut printer = PrettyPrinter::new(); 37 | printer 38 | .input(Input::from_bytes(&string.as_bytes())) 39 | .header(false) 40 | .grid(false) 41 | .language("yaml") 42 | .theme("OneHalfDark"); 43 | 44 | if term_width.is_some() { 45 | printer.term_width(term_width.unwrap()); 46 | } 47 | printer.print().unwrap(); 48 | } 49 | 50 | pub fn print_warning(string: String, term_width: Option) { 51 | let mut printer = PrettyPrinter::new(); 52 | printer 53 | .input(Input::from_bytes(&string.as_bytes())) 54 | .header(false) 55 | .grid(true) 56 | .language("log") 57 | .theme("OneHalfDark"); 58 | 59 | if term_width.is_some() { 60 | printer.term_width(term_width.unwrap()); 61 | } 62 | printer.print().unwrap(); 63 | } 64 | 65 | pub fn print_error(string: String, term_width: Option) { 66 | let mut printer = PrettyPrinter::new(); 67 | printer 68 | .header(false) 69 | .grid(true) 70 | .line_numbers(false) 71 | .use_italics(true) 72 | .language("log") 73 | .theme("Monokai Extended Bright") 74 | .paging_mode(PagingMode::Never) 75 | .input(Input::from_bytes(&string.as_bytes())); 76 | 77 | if term_width.is_some() { 78 | printer.term_width(term_width.unwrap()); 79 | } 80 | printer.print().unwrap(); 81 | } 82 | pub fn print(string: String, filename: Option<&str>, term_width: Option) { 83 | let mut printer = PrettyPrinter::new(); 84 | printer 85 | .input( 86 | Input::from_bytes(&string.as_bytes()) 87 | .name(filename.unwrap_or("Diff.yaml")) 88 | .kind("Name"), 89 | ) 90 | .header(true) 91 | .grid(true) 92 | .line_numbers(true) 93 | .use_italics(true) 94 | .language("diff") 95 | .theme("gruvbox-dark") 96 | .paging_mode(PagingMode::Never); 97 | 98 | if term_width.is_some() { 99 | printer.term_width(term_width.unwrap()); 100 | } 101 | printer.print().unwrap(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/processor.rs: -------------------------------------------------------------------------------- 1 | use rayon::prelude::*; 2 | use serde::Deserialize; 3 | use serde_yaml::Value; 4 | 5 | use std::{ 6 | collections::HashSet, 7 | env, 8 | sync::{Arc, Mutex}, 9 | }; 10 | 11 | use crate::{commands::Commands, logger::Logger, print::Pretty, settings::Settings, Cli}; 12 | pub struct Process {} 13 | 14 | impl Process { 15 | pub fn get_entries(args: Cli, mut settings: Settings) -> HashSet { 16 | let mut targets = HashSet::new(); 17 | 18 | if args.inplace { 19 | let cwd = env::current_dir().unwrap().to_str().unwrap().to_string(); 20 | targets.insert(cwd); 21 | } else if args.path.is_some() { 22 | let path = args.path.unwrap(); 23 | targets.insert(path); 24 | } else { 25 | settings.configs.env = args.env.unwrap_or_default(); 26 | targets = Settings::get_service_paths(&settings).expect(""); 27 | } 28 | return targets; 29 | } 30 | 31 | pub fn process_target( 32 | args: Cli, 33 | logger: &Arc>, 34 | target: &str, 35 | ) -> anyhow::Result<()> { 36 | Pretty::print_path(format!("Path: {}", target.to_string()), args.term_width); 37 | let build = Commands::get_build(logger.clone(), target)?; 38 | 39 | let handles: Vec<_> = serde_yaml::Deserializer::from_str(build.as_str()) 40 | .filter_map(|document| { 41 | let v_result = Value::deserialize(document); 42 | 43 | match handle_deserialization_result(v_result) { 44 | Ok(v) => Some(v), 45 | Err(error) => { 46 | Pretty::print_info(error.to_string(), args.term_width); 47 | None 48 | } 49 | } 50 | }) 51 | .collect(); 52 | 53 | handles.par_iter().for_each(|v| { 54 | let logger_clone = Arc::clone(&logger); 55 | let string = serde_yaml::to_string(&v).unwrap(); 56 | let diff = Commands::get_diff(&string).unwrap(); 57 | if diff.len() > 0 { 58 | let filename = &v["metadata"]["name"]; 59 | Pretty::print(diff, filename.as_str(), args.term_width); 60 | } else { 61 | let logger = logger_clone.lock().unwrap(); 62 | handle_no_changes(&logger, &v); 63 | } 64 | }); 65 | Ok(()) 66 | } 67 | } 68 | 69 | fn handle_no_changes(logger: &Logger, v: &Value) { 70 | logger.log_info(format!( 71 | "No changes in: {:?} {:?} {:?}\n", 72 | v["apiVersion"].as_str().unwrap(), 73 | v["kind"].as_str().unwrap(), 74 | v["metadata"]["name"].as_str().unwrap() 75 | )); 76 | } 77 | 78 | fn handle_deserialization_result( 79 | v_result: Result, 80 | ) -> Result { 81 | match v_result { 82 | Ok(result) => Ok(result), 83 | Err(error) => Err(error.to_string()), 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/settings.rs: -------------------------------------------------------------------------------- 1 | use glob::glob; 2 | use serde::{Deserialize, Serialize}; 3 | use std::collections::HashSet; 4 | use std::io::{BufReader, Error}; 5 | use std::path::Path; 6 | use std::{fs::File, io}; 7 | 8 | use crate::enums::LogLevel; 9 | 10 | #[derive(Debug, Serialize, Deserialize)] 11 | pub struct Configs { 12 | #[serde(default)] 13 | pub include: Vec, 14 | #[serde(default)] 15 | pub exclude: Vec, 16 | #[serde(skip_serializing_if = "String::is_empty", default)] 17 | pub env: String, 18 | #[serde(default)] 19 | pub log: LogLevel, 20 | } 21 | 22 | pub fn expanduser(path: &str) -> String { 23 | if path.starts_with("~/") { 24 | format!("{}/{}", dirs::home_dir().unwrap().display(), &path[2..]) 25 | } else { 26 | path.to_string() 27 | } 28 | } 29 | 30 | #[derive(Debug, Deserialize)] 31 | pub struct Settings { 32 | pub configs: Configs, 33 | } 34 | 35 | impl Settings { 36 | pub fn path() -> String { 37 | format!( 38 | "{}/.kube/kubediff/config.yaml", 39 | dirs::home_dir().unwrap().display() 40 | ) 41 | } 42 | 43 | pub fn load() -> Result { 44 | let settings_path_str = Self::path(); 45 | let settings_path = Path::new(&settings_path_str); 46 | let file = File::open(settings_path)?; 47 | let reader = BufReader::new(file); 48 | let settings: Settings = serde_yaml::from_reader(reader).unwrap(); 49 | 50 | Ok(settings) 51 | } 52 | 53 | pub fn get_service_paths(&self) -> Result, Error> { 54 | let mut paths = HashSet::new(); 55 | let env: String = self.configs.env.to_string(); 56 | for inc in &self.configs.include { 57 | let expanded = expanduser(&inc); 58 | for entry in glob(&expanded).expect("Failed to read glob pattern") { 59 | match entry { 60 | Ok(path) => { 61 | paths.insert(format!("{}/{}", path.display().to_string(), env)); 62 | } 63 | Err(e) => { 64 | println!("{:?}", e); 65 | } 66 | } 67 | } 68 | } 69 | for exc in &self.configs.exclude { 70 | let expanded = expanduser(&exc); 71 | for entry in glob(&expanded).expect("Failed to read glob pattern") { 72 | match entry { 73 | Ok(path) => { 74 | paths.remove(&format!("{}/{}", path.display().to_string(), env)); 75 | } 76 | Err(e) => { 77 | println!("{:?}", e); 78 | } 79 | } 80 | } 81 | } 82 | 83 | Ok(paths) 84 | } 85 | } 86 | --------------------------------------------------------------------------------