├── .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 | 
23 | _The showcase demonstrates an upgrade of agones_
24 |
25 |
26 | Kubediff | Kubectl diff
27 | :-------------------------:|:-------------------------:
28 |  | 
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 |
--------------------------------------------------------------------------------