mirror of
https://github.com/pesde-pkg/pesde.git
synced 2024-12-12 11:00:36 +00:00
feat: self managed versioning
This commit is contained in:
parent
0fcddedad6
commit
7f8b2761ab
29 changed files with 1011 additions and 571 deletions
34
.github/workflows/release.yaml
vendored
34
.github/workflows/release.yaml
vendored
|
@ -3,6 +3,8 @@ on:
|
|||
push:
|
||||
tags:
|
||||
- v*
|
||||
env:
|
||||
BIN_NAME: pesde
|
||||
jobs:
|
||||
# Better to check first, runners other than ubuntu-latest take up more free minutes
|
||||
check:
|
||||
|
@ -14,7 +16,7 @@ jobs:
|
|||
run: cargo check --all-features --locked
|
||||
|
||||
build:
|
||||
needs: [check]
|
||||
needs: [ check ]
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
|
@ -44,10 +46,8 @@ jobs:
|
|||
- name: Set env
|
||||
shell: bash
|
||||
run: |
|
||||
BIN_NAME=pesde
|
||||
ARCHIVE_NAME=$BIN_NAME-$(echo ${{ github.ref_name }} | cut -c 2-)-${{ matrix.host }}-${{ matrix.arch }}.zip
|
||||
ARCHIVE_NAME=${{ env.BIN_NAME }}-$(echo ${{ github.ref_name }} | cut -c 2-)-${{ matrix.host }}-${{ matrix.arch }}
|
||||
|
||||
echo "BIN_NAME=$BIN_NAME" >> $GITHUB_ENV
|
||||
echo "ARCHIVE_NAME=$ARCHIVE_NAME" >> $GITHUB_ENV
|
||||
|
||||
- name: Build
|
||||
|
@ -57,23 +57,31 @@ jobs:
|
|||
shell: bash
|
||||
run: |
|
||||
if [ ${{ matrix.host }} = "windows" ]; then
|
||||
cp target/${{ matrix.target }}/release/${{ env.BIN_NAME }}.exe ${{ env.BIN_NAME }}.exe
|
||||
7z a ${{ env.ARCHIVE_NAME }} ${{ env.BIN_NAME }}.exe
|
||||
mv target/${{ matrix.target }}/release/${{ env.BIN_NAME }}.exe ${{ env.BIN_NAME }}.exe
|
||||
7z a ${{ env.ARCHIVE_NAME }}.zip ${{ env.BIN_NAME }}.exe
|
||||
tar -czf ${{ env.ARCHIVE_NAME }}.tar.gz ${{ env.BIN_NAME }}.exe
|
||||
else
|
||||
cp target/${{ matrix.target }}/release/${{ env.BIN_NAME }} ${{ env.BIN_NAME }}
|
||||
zip -r ${{ env.ARCHIVE_NAME }} ${{ env.BIN_NAME }}
|
||||
mv target/${{ matrix.target }}/release/${{ env.BIN_NAME }} ${{ env.BIN_NAME }}
|
||||
zip -r ${{ env.ARCHIVE_NAME }}.zip ${{ env.BIN_NAME }}
|
||||
tar -czf ${{ env.ARCHIVE_NAME }}.tar.gz ${{ env.BIN_NAME }}
|
||||
fi
|
||||
|
||||
- name: Upload assets
|
||||
- name: Upload zip artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.ARCHIVE_NAME }}
|
||||
path: ${{ env.ARCHIVE_NAME }}
|
||||
name: ${{ env.ARCHIVE_NAME }}.zip
|
||||
path: ${{ env.ARCHIVE_NAME }}.zip
|
||||
|
||||
- name: Upload tar.gz artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.ARCHIVE_NAME }}.tar.gz
|
||||
path: ${{ env.ARCHIVE_NAME }}.tar.gz
|
||||
|
||||
publish:
|
||||
name: Publish to crates.io
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
needs: [ build ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Publish
|
||||
|
@ -85,7 +93,7 @@ jobs:
|
|||
permissions:
|
||||
contents: write
|
||||
pull-requests: read
|
||||
needs: [build, publish]
|
||||
needs: [ build, publish ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
|
234
Cargo.lock
generated
234
Cargo.lock
generated
|
@ -72,9 +72,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.14"
|
||||
version = "0.6.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
|
||||
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
|
@ -87,33 +87,33 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
|
||||
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
|
||||
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
|
||||
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.3"
|
||||
version = "3.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
|
||||
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.52.0",
|
||||
|
@ -222,7 +222,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -257,7 +257,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -338,9 +338,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.9.1"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
|
||||
checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
|
@ -450,9 +450,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.9"
|
||||
version = "4.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462"
|
||||
checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
@ -460,9 +460,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.9"
|
||||
version = "4.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942"
|
||||
checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
@ -472,21 +472,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.8"
|
||||
version = "4.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
|
||||
checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
|
||||
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
|
||||
|
||||
[[package]]
|
||||
name = "clru"
|
||||
|
@ -496,9 +496,9 @@ checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59"
|
|||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
|
@ -608,7 +608,7 @@ dependencies = [
|
|||
"bitflags 1.3.2",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"mio 0.8.11",
|
||||
"parking_lot",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
|
@ -655,7 +655,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -666,7 +666,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
|||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -682,9 +682,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "dbus-secret-service"
|
||||
version = "4.0.1"
|
||||
version = "4.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3ae92ba157c1fd7e3453bf8fad9cd2e62783fe5f65047fd3b52fcbf6594aef"
|
||||
checksum = "1caa0c241c01ad8d99a78d553567d38f873dd3ac16eca33a5370d650ab25584e"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"block-padding",
|
||||
|
@ -722,7 +722,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -735,7 +735,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -750,10 +750,10 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
name = "dirs"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
|
||||
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
@ -778,7 +778,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -832,7 +832,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1004,7 +1004,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1161,7 +1161,7 @@ dependencies = [
|
|||
"gix-utils",
|
||||
"itoa",
|
||||
"thiserror",
|
||||
"winnow 0.6.14",
|
||||
"winnow 0.6.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1243,7 +1243,7 @@ dependencies = [
|
|||
"smallvec",
|
||||
"thiserror",
|
||||
"unicode-bom",
|
||||
"winnow 0.6.14",
|
||||
"winnow 0.6.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1261,9 +1261,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gix-credentials"
|
||||
version = "0.24.3"
|
||||
version = "0.24.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91b446df0841c9d74b3f98f21657b892581a4af78904a22e0cbc6144da972eea"
|
||||
checksum = "198588f532e4d1202e04e6c3f50e4d7c060dffc66801c6f53cc246f1d234739e"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"gix-command",
|
||||
|
@ -1461,7 +1461,7 @@ checksum = "999ce923619f88194171a67fb3e6d613653b8d4d6078b529b15a765da0edcc17"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1496,7 +1496,7 @@ dependencies = [
|
|||
"itoa",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"winnow 0.6.14",
|
||||
"winnow 0.6.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1619,7 +1619,7 @@ dependencies = [
|
|||
"gix-utils",
|
||||
"maybe-async",
|
||||
"thiserror",
|
||||
"winnow 0.6.14",
|
||||
"winnow 0.6.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1651,7 +1651,7 @@ dependencies = [
|
|||
"gix-validate",
|
||||
"memmap2",
|
||||
"thiserror",
|
||||
"winnow 0.6.14",
|
||||
"winnow 0.6.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1728,9 +1728,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gix-tempfile"
|
||||
version = "14.0.0"
|
||||
version = "14.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3b0e276cd08eb2a22e9f286a4f13a222a01be2defafa8621367515375644b99"
|
||||
checksum = "006acf5a613e0b5cf095d8e4b3f48c12a60d9062aa2b2dd105afaf8344a5600c"
|
||||
dependencies = [
|
||||
"gix-fs",
|
||||
"libc",
|
||||
|
@ -2212,9 +2212,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.0"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
|
@ -2224,9 +2224,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
|||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.31"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
|
||||
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@ -2242,9 +2242,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "keyring"
|
||||
version = "3.0.3"
|
||||
version = "3.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9961b98f55dc0b2737000132505bdafa249abab147ee9de43c50ae04a054aa6c"
|
||||
checksum = "c118b1bc529b034aad851808f41f49a69a337d10e112039e7f342e5fd514635b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"dbus-secret-service",
|
||||
|
@ -2256,9 +2256,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "kstring"
|
||||
version = "2.0.0"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747"
|
||||
checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1"
|
||||
dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
@ -2390,7 +2390,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2454,6 +2454,18 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.9",
|
||||
"libc",
|
||||
"wasi",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "newline-converter"
|
||||
version = "0.3.0"
|
||||
|
@ -2582,9 +2594,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
|||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.1"
|
||||
version = "0.36.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce"
|
||||
checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -2705,7 +2717,7 @@ dependencies = [
|
|||
"chrono",
|
||||
"clap",
|
||||
"colored",
|
||||
"directories",
|
||||
"dirs",
|
||||
"flate2",
|
||||
"full_moon",
|
||||
"git2",
|
||||
|
@ -2728,8 +2740,9 @@ dependencies = [
|
|||
"thiserror",
|
||||
"threadpool",
|
||||
"toml",
|
||||
"toml_edit 0.22.16",
|
||||
"toml_edit 0.22.17",
|
||||
"url",
|
||||
"winreg",
|
||||
"zip",
|
||||
]
|
||||
|
||||
|
@ -2750,7 +2763,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2885,14 +2898,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quinn-udp"
|
||||
version = "0.5.2"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46"
|
||||
checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
|
@ -3100,9 +3112,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.11"
|
||||
version = "0.23.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0"
|
||||
checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"ring",
|
||||
|
@ -3130,9 +3142,9 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
|
|||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.102.5"
|
||||
version = "0.102.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78"
|
||||
checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
|
@ -3228,7 +3240,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3250,14 +3262,14 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.6"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
|
||||
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -3301,7 +3313,7 @@ dependencies = [
|
|||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3355,7 +3367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"mio 0.8.11",
|
||||
"signal-hook",
|
||||
]
|
||||
|
||||
|
@ -3445,9 +3457,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.71"
|
||||
version = "2.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
|
||||
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -3530,7 +3542,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3602,17 +3614,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.38.1"
|
||||
version = "1.39.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df"
|
||||
checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"mio 1.0.1",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3641,21 +3653,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.15"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28"
|
||||
checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit 0.22.16",
|
||||
"toml_edit 0.22.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.6"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
|
||||
checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -3673,15 +3685,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.16"
|
||||
version = "0.22.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788"
|
||||
checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16"
|
||||
dependencies = [
|
||||
"indexmap 2.2.6",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow 0.6.14",
|
||||
"winnow 0.6.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3730,7 +3742,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3845,9 +3857,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
|||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
|
@ -3895,7 +3907,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -3929,7 +3941,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -4149,9 +4161,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.14"
|
||||
version = "0.6.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f"
|
||||
checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -4189,9 +4201,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zbus"
|
||||
version = "4.3.1"
|
||||
version = "4.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "851238c133804e0aa888edf4a0229481c753544ca12a60fd1c3230c8a500fe40"
|
||||
checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725"
|
||||
dependencies = [
|
||||
"async-broadcast",
|
||||
"async-process",
|
||||
|
@ -4221,14 +4233,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zbus_macros"
|
||||
version = "4.3.1"
|
||||
version = "4.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d5a3f12c20bd473be3194af6b49d50d7bb804ef3192dc70eddedb26b85d9da7"
|
||||
checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
|
@ -4260,7 +4272,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4280,7 +4292,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4356,9 +4368,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "4.1.2"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1724a2b330760dc7d2a8402d841119dc869ef120b139d29862d6980e9c75bfc9"
|
||||
checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe"
|
||||
dependencies = [
|
||||
"endi",
|
||||
"enumflags2",
|
||||
|
@ -4369,24 +4381,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zvariant_derive"
|
||||
version = "4.1.2"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55025a7a518ad14518fb243559c058a2e5b848b015e31f1d90414f36e3317859"
|
||||
checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant_utils"
|
||||
version = "2.0.0"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc242db087efc22bd9ade7aa7809e4ba828132edc312871584a6b4391bdf8786"
|
||||
checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.71",
|
||||
"syn 2.0.72",
|
||||
]
|
||||
|
|
32
Cargo.toml
32
Cargo.toml
|
@ -10,7 +10,24 @@ repository = "https://github.com/daimond113/pesde"
|
|||
include = ["src/**/*", "Cargo.toml", "Cargo.lock", "README.md", "LICENSE", "CHANGELOG.md"]
|
||||
|
||||
[features]
|
||||
bin = ["clap", "directories", "pretty_env_logger", "reqwest/json", "reqwest/multipart", "indicatif", "indicatif-log-bridge", "inquire", "toml_edit", "colored", "anyhow", "keyring", "open", "gix/worktree-mutation", "serde_json"]
|
||||
bin = [
|
||||
"clap",
|
||||
"dirs",
|
||||
"pretty_env_logger",
|
||||
"reqwest/json",
|
||||
"reqwest/multipart",
|
||||
"indicatif",
|
||||
"indicatif-log-bridge",
|
||||
"inquire",
|
||||
"toml_edit",
|
||||
"colored",
|
||||
"anyhow",
|
||||
"keyring",
|
||||
"open",
|
||||
"gix/worktree-mutation",
|
||||
"serde_json",
|
||||
"winreg"
|
||||
]
|
||||
wally-compat = ["zip", "serde_json", "roblox"]
|
||||
roblox = []
|
||||
lune = []
|
||||
|
@ -27,7 +44,7 @@ uninlined_format_args = "warn"
|
|||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
toml = "0.8.15"
|
||||
toml = "0.8.16"
|
||||
serde_with = "3.9.0"
|
||||
gix = { version = "0.64.0", default-features = false, features = ["blocking-http-transport-reqwest-rust-tls", "revparse-regex", "credentials"] }
|
||||
semver = { version = "1.0.23", features = ["serde"] }
|
||||
|
@ -53,16 +70,19 @@ serde_json = { version = "1.0.120", optional = true }
|
|||
|
||||
anyhow = { version = "1.0.86", optional = true }
|
||||
open = { version = "5.3.0", optional = true }
|
||||
keyring = { version = "3.0.3", features = ["crypto-rust", "windows-native", "apple-native", "linux-native"], optional = true }
|
||||
keyring = { version = "3.0.4", features = ["crypto-rust", "windows-native", "apple-native", "linux-native"], optional = true }
|
||||
colored = { version = "2.1.0", optional = true }
|
||||
toml_edit = { version = "0.22.16", optional = true }
|
||||
clap = { version = "4.5.9", features = ["derive"], optional = true }
|
||||
directories = { version = "5.0.1", optional = true }
|
||||
toml_edit = { version = "0.22.17", optional = true }
|
||||
clap = { version = "4.5.11", features = ["derive"], optional = true }
|
||||
dirs = { version = "5.0.1", optional = true }
|
||||
pretty_env_logger = { version = "0.5.0", optional = true }
|
||||
indicatif = { version = "0.17.8", optional = true }
|
||||
indicatif-log-bridge = { version = "0.2.2", optional = true }
|
||||
inquire = { version = "0.7.5", optional = true }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winreg = { version = "0.52.0", optional = true }
|
||||
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = []
|
||||
|
|
75
src/cli/auth.rs
Normal file
75
src/cli/auth.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
use crate::cli::config::{read_config, write_config};
|
||||
use anyhow::Context;
|
||||
use keyring::Entry;
|
||||
use serde::Deserialize;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn get_token<P: AsRef<Path>>(data_dir: P) -> anyhow::Result<Option<String>> {
|
||||
match std::env::var("PESDE_TOKEN") {
|
||||
Ok(token) => return Ok(Some(token)),
|
||||
Err(std::env::VarError::NotPresent) => {}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
|
||||
let config = read_config(data_dir)?;
|
||||
if let Some(token) = config.token {
|
||||
return Ok(Some(token));
|
||||
}
|
||||
|
||||
match Entry::new("token", env!("CARGO_PKG_NAME")) {
|
||||
Ok(entry) => match entry.get_password() {
|
||||
Ok(token) => return Ok(Some(token)),
|
||||
Err(keyring::Error::PlatformFailure(_) | keyring::Error::NoEntry) => {}
|
||||
Err(e) => return Err(e.into()),
|
||||
},
|
||||
Err(keyring::Error::PlatformFailure(_)) => {}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn set_token<P: AsRef<Path>>(data_dir: P, token: Option<&str>) -> anyhow::Result<()> {
|
||||
let entry = match Entry::new("token", env!("CARGO_PKG_NAME")) {
|
||||
Ok(entry) => entry,
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
|
||||
let result = if let Some(token) = token {
|
||||
entry.set_password(token)
|
||||
} else {
|
||||
entry.delete_credential()
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(keyring::Error::PlatformFailure(_) | keyring::Error::NoEntry) => {}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
|
||||
let mut config = read_config(&data_dir)?;
|
||||
config.token = token.map(|s| s.to_string());
|
||||
write_config(data_dir, &config)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct UserResponse {
|
||||
login: String,
|
||||
}
|
||||
|
||||
pub fn get_token_login(
|
||||
reqwest: &reqwest::blocking::Client,
|
||||
access_token: &str,
|
||||
) -> anyhow::Result<String> {
|
||||
let response = reqwest
|
||||
.get("https://api.github.com/user")
|
||||
.header("Authorization", format!("Bearer {access_token}"))
|
||||
.send()
|
||||
.context("failed to send user request")?
|
||||
.json::<UserResponse>()
|
||||
.context("failed to parse user response")?;
|
||||
|
||||
Ok(response.login)
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
use anyhow::Context;
|
||||
use clap::Subcommand;
|
||||
use pesde::Project;
|
||||
use serde::Deserialize;
|
||||
|
||||
mod login;
|
||||
mod logout;
|
||||
mod whoami;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct UserResponse {
|
||||
login: String,
|
||||
}
|
||||
|
||||
pub fn get_token_login(
|
||||
reqwest: &reqwest::blocking::Client,
|
||||
access_token: &str,
|
||||
) -> anyhow::Result<String> {
|
||||
let response = reqwest
|
||||
.get("https://api.github.com/user")
|
||||
.header("Authorization", format!("Bearer {access_token}"))
|
||||
.send()
|
||||
.context("failed to send user request")?
|
||||
.json::<UserResponse>()
|
||||
.context("failed to parse user response")?;
|
||||
|
||||
Ok(response.login)
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum AuthCommands {
|
||||
/// Logs in into GitHub, and stores the token
|
||||
Login(login::LoginCommand),
|
||||
/// Removes the stored token
|
||||
Logout(logout::LogoutCommand),
|
||||
/// Prints the username of the currently logged-in user
|
||||
#[clap(name = "whoami")]
|
||||
WhoAmI(whoami::WhoAmICommand),
|
||||
}
|
||||
|
||||
impl AuthCommands {
|
||||
pub fn run(self, project: Project) -> anyhow::Result<()> {
|
||||
match self {
|
||||
AuthCommands::Login(login) => login.run(project),
|
||||
AuthCommands::Logout(logout) => logout.run(project),
|
||||
AuthCommands::WhoAmI(whoami) => whoami.run(project),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
use crate::cli::{auth::get_token_login, read_config, reqwest_client, set_token};
|
||||
use crate::cli::{
|
||||
auth::{get_token_login, set_token},
|
||||
config::read_config,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use clap::Args;
|
||||
use colored::Colorize;
|
||||
|
@ -171,9 +174,7 @@ impl LoginCommand {
|
|||
anyhow::bail!("code expired, please re-run the login command");
|
||||
}
|
||||
|
||||
pub fn run(self, project: Project) -> anyhow::Result<()> {
|
||||
let reqwest = reqwest_client(project.data_dir())?;
|
||||
|
||||
pub fn run(self, project: Project, reqwest: reqwest::blocking::Client) -> anyhow::Result<()> {
|
||||
let token = match self.token {
|
||||
Some(token) => token,
|
||||
None => self.authenticate_device_flow(&project, &reqwest)?,
|
|
@ -1,4 +1,4 @@
|
|||
use crate::cli::set_token;
|
||||
use crate::cli::auth::set_token;
|
||||
use clap::Args;
|
||||
use pesde::Project;
|
||||
|
27
src/cli/commands/auth/mod.rs
Normal file
27
src/cli/commands/auth/mod.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use clap::Subcommand;
|
||||
use pesde::Project;
|
||||
|
||||
mod login;
|
||||
mod logout;
|
||||
mod whoami;
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum AuthCommands {
|
||||
/// Logs in into GitHub, and stores the token
|
||||
Login(login::LoginCommand),
|
||||
/// Removes the stored token
|
||||
Logout(logout::LogoutCommand),
|
||||
/// Prints the username of the currently logged-in user
|
||||
#[clap(name = "whoami")]
|
||||
WhoAmI(whoami::WhoAmICommand),
|
||||
}
|
||||
|
||||
impl AuthCommands {
|
||||
pub fn run(self, project: Project, reqwest: reqwest::blocking::Client) -> anyhow::Result<()> {
|
||||
match self {
|
||||
AuthCommands::Login(login) => login.run(project, reqwest),
|
||||
AuthCommands::Logout(logout) => logout.run(project),
|
||||
AuthCommands::WhoAmI(whoami) => whoami.run(project, reqwest),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::cli::{auth::get_token_login, get_token, reqwest_client};
|
||||
use crate::cli::{auth::get_token_login, get_token};
|
||||
use clap::Args;
|
||||
use colored::Colorize;
|
||||
use pesde::Project;
|
||||
|
@ -7,7 +7,7 @@ use pesde::Project;
|
|||
pub struct WhoAmICommand {}
|
||||
|
||||
impl WhoAmICommand {
|
||||
pub fn run(self, project: Project) -> anyhow::Result<()> {
|
||||
pub fn run(self, project: Project, reqwest: reqwest::blocking::Client) -> anyhow::Result<()> {
|
||||
let token = match get_token(project.data_dir())? {
|
||||
Some(token) => token,
|
||||
None => {
|
||||
|
@ -16,10 +16,7 @@ impl WhoAmICommand {
|
|||
}
|
||||
};
|
||||
|
||||
println!(
|
||||
"logged in as {}",
|
||||
get_token_login(&reqwest_client(project.data_dir())?, &token)?.bold()
|
||||
);
|
||||
println!("logged in as {}", get_token_login(&reqwest, &token)?.bold());
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::cli::{read_config, write_config, CliConfig};
|
||||
use crate::cli::config::{read_config, write_config, CliConfig};
|
||||
use clap::Args;
|
||||
use pesde::Project;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::cli::{read_config, write_config, CliConfig};
|
||||
use crate::cli::config::{read_config, write_config, CliConfig};
|
||||
use clap::Args;
|
||||
use pesde::Project;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::cli::read_config;
|
||||
use crate::cli::config::read_config;
|
||||
use anyhow::Context;
|
||||
use clap::Args;
|
||||
use colored::Colorize;
|
|
@ -1,4 +1,4 @@
|
|||
use crate::cli::{home_dir, reqwest_client, IsUpToDate};
|
||||
use crate::cli::{files::make_executable, home_dir, IsUpToDate};
|
||||
use anyhow::Context;
|
||||
use clap::Args;
|
||||
use indicatif::MultiProgress;
|
||||
|
@ -55,7 +55,12 @@ end
|
|||
}
|
||||
|
||||
impl InstallCommand {
|
||||
pub fn run(self, project: Project, multi: MultiProgress) -> anyhow::Result<()> {
|
||||
pub fn run(
|
||||
self,
|
||||
project: Project,
|
||||
multi: MultiProgress,
|
||||
reqwest: reqwest::blocking::Client,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut refreshed_sources = HashSet::new();
|
||||
|
||||
let manifest = project
|
||||
|
@ -133,7 +138,7 @@ impl InstallCommand {
|
|||
.download_graph(
|
||||
&graph,
|
||||
&mut refreshed_sources,
|
||||
&reqwest_client(project.data_dir())?,
|
||||
&reqwest,
|
||||
self.threads as usize,
|
||||
)
|
||||
.context("failed to download dependencies")?;
|
||||
|
@ -174,22 +179,16 @@ impl InstallCommand {
|
|||
continue;
|
||||
};
|
||||
|
||||
if alias == env!("CARGO_BIN_NAME") {
|
||||
log::warn!("package {alias} has the same name as the CLI, skipping bin link");
|
||||
continue;
|
||||
}
|
||||
|
||||
let bin_file = bin_folder.join(format!("{alias}.luau"));
|
||||
std::fs::write(&bin_file, bin_link_file(alias))
|
||||
.context("failed to write bin link file")?;
|
||||
|
||||
// TODO: test if this actually works
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
let mut perms = std::fs::metadata(&bin_file)
|
||||
.context("failed to get bin link file metadata")?
|
||||
.permissions();
|
||||
perms.set_mode(perms.mode() | 0o111);
|
||||
std::fs::set_permissions(&bin_file, perms)
|
||||
.context("failed to set bin link file permissions")?;
|
||||
}
|
||||
make_executable(&bin_file).context("failed to make bin link executable")?;
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
76
src/cli/commands/mod.rs
Normal file
76
src/cli/commands/mod.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use indicatif::MultiProgress;
|
||||
use pesde::Project;
|
||||
|
||||
mod auth;
|
||||
mod config;
|
||||
mod init;
|
||||
mod install;
|
||||
#[cfg(feature = "patches")]
|
||||
mod patch;
|
||||
#[cfg(feature = "patches")]
|
||||
mod patch_commit;
|
||||
mod publish;
|
||||
mod run;
|
||||
mod self_install;
|
||||
mod self_upgrade;
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
pub enum Subcommand {
|
||||
/// Authentication-related commands
|
||||
#[command(subcommand)]
|
||||
Auth(auth::AuthCommands),
|
||||
|
||||
/// Configuration-related commands
|
||||
#[command(subcommand)]
|
||||
Config(config::ConfigCommands),
|
||||
|
||||
/// Initializes a manifest file in the current directory
|
||||
Init(init::InitCommand),
|
||||
|
||||
/// Runs a script, an executable package, or a file with Lune
|
||||
Run(run::RunCommand),
|
||||
|
||||
/// Installs all dependencies for the project
|
||||
Install(install::InstallCommand),
|
||||
|
||||
/// Publishes the project to the registry
|
||||
Publish(publish::PublishCommand),
|
||||
|
||||
/// Installs the pesde binary and scripts
|
||||
SelfInstall(self_install::SelfInstallCommand),
|
||||
|
||||
/// Sets up a patching environment for a package
|
||||
#[cfg(feature = "patches")]
|
||||
Patch(patch::PatchCommand),
|
||||
|
||||
/// Finalizes a patching environment for a package
|
||||
#[cfg(feature = "patches")]
|
||||
PatchCommit(patch_commit::PatchCommitCommand),
|
||||
|
||||
/// Installs the latest version of pesde
|
||||
SelfUpgrade(self_upgrade::SelfUpgradeCommand),
|
||||
}
|
||||
|
||||
impl Subcommand {
|
||||
pub fn run(
|
||||
self,
|
||||
project: Project,
|
||||
multi: MultiProgress,
|
||||
reqwest: reqwest::blocking::Client,
|
||||
) -> anyhow::Result<()> {
|
||||
match self {
|
||||
Subcommand::Auth(auth) => auth.run(project, reqwest),
|
||||
Subcommand::Config(config) => config.run(project),
|
||||
Subcommand::Init(init) => init.run(project),
|
||||
Subcommand::Run(run) => run.run(project),
|
||||
Subcommand::Install(install) => install.run(project, multi, reqwest),
|
||||
Subcommand::Publish(publish) => publish.run(project),
|
||||
Subcommand::SelfInstall(self_install) => self_install.run(project),
|
||||
#[cfg(feature = "patches")]
|
||||
Subcommand::Patch(patch) => patch.run(project, reqwest),
|
||||
#[cfg(feature = "patches")]
|
||||
Subcommand::PatchCommit(patch_commit) => patch_commit.run(project),
|
||||
Subcommand::SelfUpgrade(self_upgrade) => self_upgrade.run(project, reqwest),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::cli::{reqwest_client, IsUpToDate, VersionedPackageName};
|
||||
use crate::cli::{IsUpToDate, VersionedPackageName};
|
||||
use anyhow::Context;
|
||||
use clap::Args;
|
||||
use colored::Colorize;
|
||||
|
@ -16,7 +16,7 @@ pub struct PatchCommand {
|
|||
}
|
||||
|
||||
impl PatchCommand {
|
||||
pub fn run(self, project: Project) -> anyhow::Result<()> {
|
||||
pub fn run(self, project: Project, reqwest: reqwest::blocking::Client) -> anyhow::Result<()> {
|
||||
let graph = if project.is_up_to_date(true)? {
|
||||
project.deser_lockfile()?.graph
|
||||
} else {
|
||||
|
@ -39,12 +39,7 @@ impl PatchCommand {
|
|||
.join(chrono::Utc::now().timestamp().to_string());
|
||||
std::fs::create_dir_all(&directory)?;
|
||||
|
||||
source.download(
|
||||
&node.node.pkg_ref,
|
||||
&directory,
|
||||
&project,
|
||||
&reqwest_client(project.data_dir())?,
|
||||
)?;
|
||||
source.download(&node.node.pkg_ref, &directory, &project, &reqwest)?;
|
||||
|
||||
// TODO: if MANIFEST_FILE_NAME does not exist, try to convert it
|
||||
|
88
src/cli/commands/self_install.rs
Normal file
88
src/cli/commands/self_install.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use crate::cli::{files::make_executable, home_dir, scripts::update_scripts_folder, HOME_DIR};
|
||||
use anyhow::Context;
|
||||
use clap::Args;
|
||||
use colored::Colorize;
|
||||
use pesde::Project;
|
||||
use std::fs::create_dir_all;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
pub struct SelfInstallCommand {
|
||||
#[cfg(windows)]
|
||||
#[arg(short, long)]
|
||||
skip_add_to_path: bool,
|
||||
}
|
||||
|
||||
impl SelfInstallCommand {
|
||||
pub fn run(self, project: Project) -> anyhow::Result<()> {
|
||||
update_scripts_folder(&project)?;
|
||||
|
||||
let bin_dir = home_dir()?.join("bin");
|
||||
create_dir_all(&bin_dir).context("failed to create bin folder")?;
|
||||
|
||||
#[cfg(windows)]
|
||||
if !self.skip_add_to_path {
|
||||
use winreg::{enums::HKEY_CURRENT_USER, RegKey};
|
||||
|
||||
let current_user = RegKey::predef(HKEY_CURRENT_USER);
|
||||
let env = current_user
|
||||
.create_subkey("Environment")
|
||||
.context("failed to open Environment key")?
|
||||
.0;
|
||||
let path: String = env.get_value("Path").context("failed to get Path value")?;
|
||||
|
||||
let exists = path
|
||||
.split(';')
|
||||
.any(|part| part == bin_dir.to_string_lossy().as_ref());
|
||||
|
||||
if !exists {
|
||||
let new_path = format!("{path};{}", bin_dir.to_string_lossy());
|
||||
env.set_value("Path", &new_path)
|
||||
.context("failed to set Path value")?;
|
||||
}
|
||||
|
||||
println!(
|
||||
"installed {} {}!",
|
||||
env!("CARGO_PKG_NAME").cyan(),
|
||||
env!("CARGO_PKG_VERSION").yellow(),
|
||||
);
|
||||
|
||||
if !exists {
|
||||
println!(
|
||||
"\nin order to allow binary exports as executables {}.\n\n{}",
|
||||
format!("`~/{HOME_DIR}/bin` was added to PATH").green(),
|
||||
"please restart your shell for this to take effect"
|
||||
.yellow()
|
||||
.bold()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
println!(
|
||||
r#"installed {} {}! in order to be able to run binary exports as programs, add the following line to your shell profile:
|
||||
|
||||
{}
|
||||
|
||||
and then restart your shell.
|
||||
"#,
|
||||
env!("CARGO_PKG_NAME").cyan(),
|
||||
env!("CARGO_PKG_VERSION").yellow(),
|
||||
format!(r#"export PATH="$PATH:~/{}/bin""#, HOME_DIR)
|
||||
.bold()
|
||||
.green()
|
||||
);
|
||||
}
|
||||
|
||||
let copy_to = bin_dir
|
||||
.join(env!("CARGO_BIN_NAME"))
|
||||
.with_extension(std::env::consts::EXE_EXTENSION);
|
||||
|
||||
std::fs::copy(std::env::current_exe()?, ©_to)
|
||||
.context("failed to copy executable to bin folder")?;
|
||||
|
||||
make_executable(©_to)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
20
src/cli/commands/self_upgrade.rs
Normal file
20
src/cli/commands/self_upgrade.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
use crate::cli::{config::read_config, version::get_or_download_version};
|
||||
use clap::Args;
|
||||
use pesde::Project;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
pub struct SelfUpgradeCommand {
|
||||
#[cfg(windows)]
|
||||
#[arg(short, long)]
|
||||
skip_add_to_path: bool,
|
||||
}
|
||||
|
||||
impl SelfUpgradeCommand {
|
||||
pub fn run(self, project: Project, reqwest: reqwest::blocking::Client) -> anyhow::Result<()> {
|
||||
let config = read_config(project.data_dir())?;
|
||||
|
||||
get_or_download_version(&reqwest, &config.last_checked_updates.unwrap().1)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
60
src/cli/config.rs
Normal file
60
src/cli/config.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
use anyhow::Context;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CliConfig {
|
||||
#[serde(
|
||||
serialize_with = "crate::util::serialize_gix_url",
|
||||
deserialize_with = "crate::util::deserialize_gix_url"
|
||||
)]
|
||||
pub default_index: gix::Url,
|
||||
#[serde(
|
||||
serialize_with = "crate::util::serialize_gix_url",
|
||||
deserialize_with = "crate::util::deserialize_gix_url"
|
||||
)]
|
||||
pub scripts_repo: gix::Url,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub token: Option<String>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub last_checked_updates: Option<(chrono::DateTime<chrono::Utc>, semver::Version)>,
|
||||
}
|
||||
|
||||
impl Default for CliConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
default_index: "https://github.com/daimond113/pesde-index"
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
scripts_repo: "https://github.com/daimond113/pesde-scripts"
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
token: None,
|
||||
|
||||
last_checked_updates: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_config<P: AsRef<Path>>(data_dir: P) -> anyhow::Result<CliConfig> {
|
||||
let config_string = match std::fs::read_to_string(data_dir.as_ref().join("config.toml")) {
|
||||
Ok(config_string) => config_string,
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
|
||||
return Ok(CliConfig::default());
|
||||
}
|
||||
Err(e) => return Err(e).context("failed to read config file"),
|
||||
};
|
||||
|
||||
let config = toml::from_str(&config_string).context("failed to parse config file")?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn write_config<P: AsRef<Path>>(data_dir: P, config: &CliConfig) -> anyhow::Result<()> {
|
||||
let config_string = toml::to_string(config).context("failed to serialize config")?;
|
||||
std::fs::write(data_dir.as_ref().join("config.toml"), config_string)
|
||||
.context("failed to write config file")?;
|
||||
|
||||
Ok(())
|
||||
}
|
19
src/cli/files.rs
Normal file
19
src/cli/files.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use std::path::Path;
|
||||
|
||||
pub fn make_executable<P: AsRef<Path>>(_path: P) -> anyhow::Result<()> {
|
||||
// TODO: test if this actually works
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use anyhow::Context;
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
let mut perms = std::fs::metadata(&_path)
|
||||
.context("failed to get bin link file metadata")?
|
||||
.permissions();
|
||||
perms.set_mode(perms.mode() | 0o111);
|
||||
std::fs::set_permissions(&_path, perms)
|
||||
.context("failed to set bin link file permissions")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
301
src/cli/mod.rs
301
src/cli/mod.rs
|
@ -1,246 +1,21 @@
|
|||
use crate::util::authenticate_conn;
|
||||
pub mod auth;
|
||||
pub mod commands;
|
||||
pub mod config;
|
||||
pub mod files;
|
||||
pub mod scripts;
|
||||
pub mod version;
|
||||
|
||||
use crate::cli::auth::get_token;
|
||||
use anyhow::Context;
|
||||
use gix::remote::Direction;
|
||||
use indicatif::MultiProgress;
|
||||
use keyring::Entry;
|
||||
use pesde::{lockfile::DownloadedGraph, names::PackageNames, source::VersionId, Project};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashSet, path::Path, str::FromStr};
|
||||
use std::{collections::HashSet, str::FromStr};
|
||||
|
||||
mod auth;
|
||||
mod config;
|
||||
mod init;
|
||||
mod install;
|
||||
#[cfg(feature = "patches")]
|
||||
mod patch;
|
||||
#[cfg(feature = "patches")]
|
||||
mod patch_commit;
|
||||
mod publish;
|
||||
mod run;
|
||||
mod self_install;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CliConfig {
|
||||
#[serde(
|
||||
serialize_with = "crate::util::serialize_gix_url",
|
||||
deserialize_with = "crate::util::deserialize_gix_url"
|
||||
)]
|
||||
pub default_index: gix::Url,
|
||||
#[serde(
|
||||
serialize_with = "crate::util::serialize_gix_url",
|
||||
deserialize_with = "crate::util::deserialize_gix_url"
|
||||
)]
|
||||
pub scripts_repo: gix::Url,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub token: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for CliConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
default_index: "https://github.com/daimond113/pesde-index"
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
scripts_repo: "https://github.com/daimond113/pesde-scripts"
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
token: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_config(data_dir: &Path) -> anyhow::Result<CliConfig> {
|
||||
let config_string = match std::fs::read_to_string(data_dir.join("config.toml")) {
|
||||
Ok(config_string) => config_string,
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
|
||||
return Ok(CliConfig::default());
|
||||
}
|
||||
Err(e) => return Err(e).context("failed to read config file"),
|
||||
};
|
||||
|
||||
let config = toml::from_str(&config_string).context("failed to parse config file")?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn write_config(data_dir: &Path, config: &CliConfig) -> anyhow::Result<()> {
|
||||
let config_string = toml::to_string(config).context("failed to serialize config")?;
|
||||
std::fs::write(data_dir.join("config.toml"), config_string)
|
||||
.context("failed to write config file")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_token(data_dir: &Path) -> anyhow::Result<Option<String>> {
|
||||
match std::env::var("PESDE_TOKEN") {
|
||||
Ok(token) => return Ok(Some(token)),
|
||||
Err(std::env::VarError::NotPresent) => {}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
|
||||
let config = read_config(data_dir)?;
|
||||
if let Some(token) = config.token {
|
||||
return Ok(Some(token));
|
||||
}
|
||||
|
||||
match Entry::new("token", env!("CARGO_PKG_NAME")) {
|
||||
Ok(entry) => match entry.get_password() {
|
||||
Ok(token) => return Ok(Some(token)),
|
||||
Err(keyring::Error::PlatformFailure(_) | keyring::Error::NoEntry) => {}
|
||||
Err(e) => return Err(e.into()),
|
||||
},
|
||||
Err(keyring::Error::PlatformFailure(_)) => {}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn set_token(data_dir: &Path, token: Option<&str>) -> anyhow::Result<()> {
|
||||
let entry = match Entry::new("token", env!("CARGO_PKG_NAME")) {
|
||||
Ok(entry) => entry,
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
|
||||
let result = if let Some(token) = token {
|
||||
entry.set_password(token)
|
||||
} else {
|
||||
entry.delete_credential()
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(keyring::Error::PlatformFailure(_) | keyring::Error::NoEntry) => {}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
|
||||
let mut config = read_config(data_dir)?;
|
||||
config.token = token.map(|s| s.to_string());
|
||||
write_config(data_dir, &config)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn reqwest_client(data_dir: &Path) -> anyhow::Result<reqwest::blocking::Client> {
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
if let Some(token) = get_token(data_dir)? {
|
||||
headers.insert(
|
||||
reqwest::header::AUTHORIZATION,
|
||||
format!("Bearer {token}")
|
||||
.parse()
|
||||
.context("failed to create auth header")?,
|
||||
);
|
||||
}
|
||||
|
||||
headers.insert(
|
||||
reqwest::header::ACCEPT,
|
||||
"application/json"
|
||||
.parse()
|
||||
.context("failed to create accept header")?,
|
||||
);
|
||||
|
||||
Ok(reqwest::blocking::Client::builder()
|
||||
.user_agent(concat!(
|
||||
env!("CARGO_PKG_NAME"),
|
||||
"/",
|
||||
env!("CARGO_PKG_VERSION")
|
||||
))
|
||||
.default_headers(headers)
|
||||
.build()?)
|
||||
}
|
||||
pub const HOME_DIR: &str = concat!(".", env!("CARGO_PKG_NAME"));
|
||||
|
||||
pub fn home_dir() -> anyhow::Result<std::path::PathBuf> {
|
||||
Ok(directories::UserDirs::new()
|
||||
Ok(dirs::home_dir()
|
||||
.context("failed to get home directory")?
|
||||
.home_dir()
|
||||
.join(concat!(".", env!("CARGO_PKG_NAME"))))
|
||||
}
|
||||
|
||||
pub fn update_scripts_folder(project: &Project) -> anyhow::Result<()> {
|
||||
let scripts_dir = home_dir()?.join("scripts");
|
||||
|
||||
if scripts_dir.exists() {
|
||||
let repo = gix::open(&scripts_dir).context("failed to open scripts repository")?;
|
||||
|
||||
let remote = repo
|
||||
.find_default_remote(Direction::Fetch)
|
||||
.context("missing default remote of scripts repository")?
|
||||
.context("failed to find default remote of scripts repository")?;
|
||||
|
||||
let mut connection = remote
|
||||
.connect(Direction::Fetch)
|
||||
.context("failed to connect to default remote of scripts repository")?;
|
||||
|
||||
authenticate_conn(&mut connection, project.auth_config());
|
||||
|
||||
let results = connection
|
||||
.prepare_fetch(gix::progress::Discard, Default::default())
|
||||
.context("failed to prepare scripts repository fetch")?
|
||||
.receive(gix::progress::Discard, &false.into())
|
||||
.context("failed to receive new scripts repository contents")?;
|
||||
|
||||
let remote_ref = results
|
||||
.ref_map
|
||||
.remote_refs
|
||||
.first()
|
||||
.context("failed to get remote refs of scripts repository")?;
|
||||
|
||||
let unpacked = remote_ref.unpack();
|
||||
let oid = unpacked
|
||||
.1
|
||||
.or(unpacked.2)
|
||||
.context("couldn't find oid in remote ref")?;
|
||||
|
||||
let tree = repo
|
||||
.find_object(oid)
|
||||
.context("failed to find scripts repository tree")?
|
||||
.peel_to_tree()
|
||||
.context("failed to peel scripts repository object to tree")?;
|
||||
|
||||
let mut index = gix::index::File::from_state(
|
||||
gix::index::State::from_tree(&tree.id, &repo.objects, Default::default())
|
||||
.context("failed to create index state from scripts repository tree")?,
|
||||
repo.index_path(),
|
||||
);
|
||||
|
||||
let opts = gix::worktree::state::checkout::Options {
|
||||
overwrite_existing: true,
|
||||
destination_is_initially_empty: false,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
gix::worktree::state::checkout(
|
||||
&mut index,
|
||||
repo.work_dir().context("scripts repo is bare")?,
|
||||
repo.objects
|
||||
.clone()
|
||||
.into_arc()
|
||||
.context("failed to clone objects")?,
|
||||
&gix::progress::Discard,
|
||||
&gix::progress::Discard,
|
||||
&false.into(),
|
||||
opts,
|
||||
)
|
||||
.context("failed to checkout scripts repository")?;
|
||||
|
||||
index
|
||||
.write(gix::index::write::Options::default())
|
||||
.context("failed to write index")?;
|
||||
} else {
|
||||
std::fs::create_dir_all(&scripts_dir).context("failed to create scripts directory")?;
|
||||
|
||||
let cli_config = read_config(project.data_dir())?;
|
||||
|
||||
gix::prepare_clone(cli_config.scripts_repo, &scripts_dir)
|
||||
.context("failed to prepare scripts repository clone")?
|
||||
.fetch_then_checkout(gix::progress::Discard, &false.into())
|
||||
.context("failed to fetch and checkout scripts repository")?
|
||||
.0
|
||||
.main_worktree(gix::progress::Discard, &false.into())
|
||||
.context("failed to set scripts repository as main worktree")?;
|
||||
};
|
||||
|
||||
Ok(())
|
||||
.join(HOME_DIR))
|
||||
}
|
||||
|
||||
pub trait IsUpToDate {
|
||||
|
@ -346,55 +121,3 @@ impl VersionedPackageName {
|
|||
pub fn parse_gix_url(s: &str) -> Result<gix::Url, gix::url::parse::Error> {
|
||||
s.try_into()
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
pub enum Subcommand {
|
||||
/// Authentication-related commands
|
||||
#[command(subcommand)]
|
||||
Auth(auth::AuthCommands),
|
||||
|
||||
/// Configuration-related commands
|
||||
#[command(subcommand)]
|
||||
Config(config::ConfigCommands),
|
||||
|
||||
/// Initializes a manifest file in the current directory
|
||||
Init(init::InitCommand),
|
||||
|
||||
/// Runs a script, an executable package, or a file with Lune
|
||||
Run(run::RunCommand),
|
||||
|
||||
/// Installs all dependencies for the project
|
||||
Install(install::InstallCommand),
|
||||
|
||||
/// Publishes the project to the registry
|
||||
Publish(publish::PublishCommand),
|
||||
|
||||
/// Installs the pesde binary and scripts
|
||||
SelfInstall(self_install::SelfInstallCommand),
|
||||
|
||||
/// Sets up a patching environment for a package
|
||||
#[cfg(feature = "patches")]
|
||||
Patch(patch::PatchCommand),
|
||||
|
||||
/// Finalizes a patching environment for a package
|
||||
#[cfg(feature = "patches")]
|
||||
PatchCommit(patch_commit::PatchCommitCommand),
|
||||
}
|
||||
|
||||
impl Subcommand {
|
||||
pub fn run(self, project: Project, multi: MultiProgress) -> anyhow::Result<()> {
|
||||
match self {
|
||||
Subcommand::Auth(auth) => auth.run(project),
|
||||
Subcommand::Config(config) => config.run(project),
|
||||
Subcommand::Init(init) => init.run(project),
|
||||
Subcommand::Run(run) => run.run(project),
|
||||
Subcommand::Install(install) => install.run(project, multi),
|
||||
Subcommand::Publish(publish) => publish.run(project),
|
||||
Subcommand::SelfInstall(self_install) => self_install.run(project),
|
||||
#[cfg(feature = "patches")]
|
||||
Subcommand::Patch(patch) => patch.run(project),
|
||||
#[cfg(feature = "patches")]
|
||||
Subcommand::PatchCommit(patch_commit) => patch_commit.run(project),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
94
src/cli/scripts.rs
Normal file
94
src/cli/scripts.rs
Normal file
|
@ -0,0 +1,94 @@
|
|||
use crate::{
|
||||
cli::{config::read_config, home_dir},
|
||||
util::authenticate_conn,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use gix::remote::Direction;
|
||||
use pesde::Project;
|
||||
|
||||
pub fn update_scripts_folder(project: &Project) -> anyhow::Result<()> {
|
||||
let scripts_dir = home_dir()?.join("scripts");
|
||||
|
||||
if scripts_dir.exists() {
|
||||
let repo = gix::open(&scripts_dir).context("failed to open scripts repository")?;
|
||||
|
||||
let remote = repo
|
||||
.find_default_remote(Direction::Fetch)
|
||||
.context("missing default remote of scripts repository")?
|
||||
.context("failed to find default remote of scripts repository")?;
|
||||
|
||||
let mut connection = remote
|
||||
.connect(Direction::Fetch)
|
||||
.context("failed to connect to default remote of scripts repository")?;
|
||||
|
||||
authenticate_conn(&mut connection, project.auth_config());
|
||||
|
||||
let results = connection
|
||||
.prepare_fetch(gix::progress::Discard, Default::default())
|
||||
.context("failed to prepare scripts repository fetch")?
|
||||
.receive(gix::progress::Discard, &false.into())
|
||||
.context("failed to receive new scripts repository contents")?;
|
||||
|
||||
let remote_ref = results
|
||||
.ref_map
|
||||
.remote_refs
|
||||
.first()
|
||||
.context("failed to get remote refs of scripts repository")?;
|
||||
|
||||
let unpacked = remote_ref.unpack();
|
||||
let oid = unpacked
|
||||
.1
|
||||
.or(unpacked.2)
|
||||
.context("couldn't find oid in remote ref")?;
|
||||
|
||||
let tree = repo
|
||||
.find_object(oid)
|
||||
.context("failed to find scripts repository tree")?
|
||||
.peel_to_tree()
|
||||
.context("failed to peel scripts repository object to tree")?;
|
||||
|
||||
let mut index = gix::index::File::from_state(
|
||||
gix::index::State::from_tree(&tree.id, &repo.objects, Default::default())
|
||||
.context("failed to create index state from scripts repository tree")?,
|
||||
repo.index_path(),
|
||||
);
|
||||
|
||||
let opts = gix::worktree::state::checkout::Options {
|
||||
overwrite_existing: true,
|
||||
destination_is_initially_empty: false,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
gix::worktree::state::checkout(
|
||||
&mut index,
|
||||
repo.work_dir().context("scripts repo is bare")?,
|
||||
repo.objects
|
||||
.clone()
|
||||
.into_arc()
|
||||
.context("failed to clone objects")?,
|
||||
&gix::progress::Discard,
|
||||
&gix::progress::Discard,
|
||||
&false.into(),
|
||||
opts,
|
||||
)
|
||||
.context("failed to checkout scripts repository")?;
|
||||
|
||||
index
|
||||
.write(gix::index::write::Options::default())
|
||||
.context("failed to write index")?;
|
||||
} else {
|
||||
std::fs::create_dir_all(&scripts_dir).context("failed to create scripts directory")?;
|
||||
|
||||
let cli_config = read_config(project.data_dir())?;
|
||||
|
||||
gix::prepare_clone(cli_config.scripts_repo, &scripts_dir)
|
||||
.context("failed to prepare scripts repository clone")?
|
||||
.fetch_then_checkout(gix::progress::Discard, &false.into())
|
||||
.context("failed to fetch and checkout scripts repository")?
|
||||
.0
|
||||
.main_worktree(gix::progress::Discard, &false.into())
|
||||
.context("failed to set scripts repository as main worktree")?;
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
use crate::cli::{home_dir, update_scripts_folder};
|
||||
use anyhow::Context;
|
||||
use clap::Args;
|
||||
use pesde::Project;
|
||||
use std::fs::create_dir_all;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
pub struct SelfInstallCommand {}
|
||||
|
||||
impl SelfInstallCommand {
|
||||
pub fn run(self, project: Project) -> anyhow::Result<()> {
|
||||
update_scripts_folder(&project)?;
|
||||
|
||||
create_dir_all(home_dir()?.join("bin")).context("failed to create bin folder")?;
|
||||
|
||||
// TODO: add the bin folder to the PATH
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
218
src/cli/version.rs
Normal file
218
src/cli/version.rs
Normal file
|
@ -0,0 +1,218 @@
|
|||
use std::{
|
||||
fs::create_dir_all,
|
||||
io::Read,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use colored::Colorize;
|
||||
use reqwest::header::ACCEPT;
|
||||
use semver::Version;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::cli::{
|
||||
config::{read_config, write_config, CliConfig},
|
||||
files::make_executable,
|
||||
home_dir,
|
||||
};
|
||||
|
||||
pub fn current_version() -> Version {
|
||||
Version::parse(env!("CARGO_PKG_VERSION")).unwrap()
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Release {
|
||||
tag_name: String,
|
||||
assets: Vec<Asset>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Asset {
|
||||
name: String,
|
||||
url: url::Url,
|
||||
}
|
||||
|
||||
fn get_repo() -> (String, String) {
|
||||
let mut parts = env!("CARGO_PKG_REPOSITORY").split('/').skip(3);
|
||||
(
|
||||
parts.next().unwrap().to_string(),
|
||||
parts.next().unwrap().to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
const CHECK_INTERVAL: chrono::Duration = chrono::Duration::seconds(30);
|
||||
|
||||
pub fn check_for_updates<P: AsRef<Path>>(
|
||||
reqwest: &reqwest::blocking::Client,
|
||||
data_dir: P,
|
||||
) -> anyhow::Result<()> {
|
||||
let (owner, repo) = get_repo();
|
||||
|
||||
let config = read_config(&data_dir)?;
|
||||
|
||||
let version = if let Some((_, version)) = config
|
||||
.last_checked_updates
|
||||
.filter(|(time, _)| chrono::Utc::now() - *time < CHECK_INTERVAL)
|
||||
{
|
||||
version
|
||||
} else {
|
||||
let releases = reqwest
|
||||
.get(format!(
|
||||
"https://api.github.com/repos/{owner}/{repo}/releases",
|
||||
))
|
||||
.send()
|
||||
.context("failed to send request to GitHub API")?
|
||||
.json::<Vec<Release>>()
|
||||
.context("failed to parse GitHub API response")?;
|
||||
|
||||
let version = releases
|
||||
.into_iter()
|
||||
.map(|release| Version::parse(release.tag_name.trim_start_matches('v')).unwrap())
|
||||
.max()
|
||||
.context("failed to find latest version")?;
|
||||
|
||||
write_config(
|
||||
&data_dir,
|
||||
&CliConfig {
|
||||
last_checked_updates: Some((chrono::Utc::now(), version.clone())),
|
||||
..config
|
||||
},
|
||||
)?;
|
||||
|
||||
version
|
||||
};
|
||||
|
||||
if version > current_version() {
|
||||
let name = env!("CARGO_PKG_NAME");
|
||||
|
||||
let unformatted_message = format!("a new version of {name} is available: {version}");
|
||||
|
||||
let message = format!(
|
||||
"a new version of {} is available: {}",
|
||||
name.cyan(),
|
||||
version.to_string().yellow().bold()
|
||||
);
|
||||
|
||||
let stars = "-"
|
||||
.repeat(unformatted_message.len() + 4)
|
||||
.bright_magenta()
|
||||
.bold();
|
||||
let column = "|".bright_magenta().bold();
|
||||
|
||||
println!("\n{stars}\n{column} {message} {column}\n{stars}\n",);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn download_github_release(
|
||||
reqwest: &reqwest::blocking::Client,
|
||||
version: &Version,
|
||||
) -> anyhow::Result<Vec<u8>> {
|
||||
let (owner, repo) = get_repo();
|
||||
|
||||
let release = reqwest
|
||||
.get(format!(
|
||||
"https://api.github.com/repos/{owner}/{repo}/releases/tags/v{version}",
|
||||
))
|
||||
.send()
|
||||
.context("failed to send request to GitHub API")?
|
||||
.json::<Release>()
|
||||
.context("failed to parse GitHub API response")?;
|
||||
|
||||
let asset = release
|
||||
.assets
|
||||
.into_iter()
|
||||
.find(|asset| {
|
||||
asset.name.ends_with(&format!(
|
||||
"-{}-{}.tar.gz",
|
||||
std::env::consts::OS,
|
||||
std::env::consts::ARCH
|
||||
))
|
||||
})
|
||||
.context("failed to find asset for current platform")?;
|
||||
|
||||
let bytes = reqwest
|
||||
.get(asset.url)
|
||||
.header(ACCEPT, "application/octet-stream")
|
||||
.send()
|
||||
.context("failed to send request to download asset")?
|
||||
.bytes()
|
||||
.context("failed to download asset")?;
|
||||
|
||||
let mut decoder = flate2::read::GzDecoder::new(bytes.as_ref());
|
||||
let mut archive = tar::Archive::new(&mut decoder);
|
||||
|
||||
let entry = archive
|
||||
.entries()
|
||||
.context("failed to read archive entries")?
|
||||
.next()
|
||||
.context("archive has no entry")?
|
||||
.context("failed to get first archive entry")?;
|
||||
|
||||
entry
|
||||
.bytes()
|
||||
.collect::<Result<Vec<u8>, std::io::Error>>()
|
||||
.context("failed to read archive entry bytes")
|
||||
}
|
||||
|
||||
pub fn get_or_download_version(
|
||||
reqwest: &reqwest::blocking::Client,
|
||||
version: &Version,
|
||||
) -> anyhow::Result<Option<PathBuf>> {
|
||||
#[cfg(debug_assertions)]
|
||||
// possible hard to debug issues with the versioning system overtaking the debug build
|
||||
return Ok(None);
|
||||
|
||||
let path = home_dir()?.join("versions");
|
||||
create_dir_all(&path).context("failed to create versions directory")?;
|
||||
|
||||
let path = path
|
||||
.join(version.to_string())
|
||||
.with_extension(std::env::consts::EXE_EXTENSION);
|
||||
|
||||
let is_requested_version = *version == current_version();
|
||||
|
||||
if path.exists() {
|
||||
return Ok(if is_requested_version {
|
||||
None
|
||||
} else {
|
||||
Some(path)
|
||||
});
|
||||
}
|
||||
|
||||
if is_requested_version {
|
||||
std::fs::copy(std::env::current_exe()?, &path)
|
||||
.context("failed to copy current executable to version directory")?;
|
||||
} else {
|
||||
let bytes = download_github_release(reqwest, version)?;
|
||||
std::fs::write(&path, bytes).context("failed to write downloaded version file")?;
|
||||
}
|
||||
|
||||
make_executable(&path).context("failed to make downloaded version executable")?;
|
||||
|
||||
Ok(if is_requested_version {
|
||||
None
|
||||
} else {
|
||||
Some(path)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn max_installed_version() -> anyhow::Result<Version> {
|
||||
#[cfg(debug_assertions)]
|
||||
return Ok(current_version());
|
||||
|
||||
let versions_dir = home_dir()?.join("versions");
|
||||
create_dir_all(&versions_dir).context("failed to create versions directory")?;
|
||||
|
||||
let max_version = std::fs::read_dir(versions_dir)
|
||||
.context("failed to read versions directory")?
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.map(|entry| Version::parse(entry.path().file_stem().unwrap().to_str().unwrap()).unwrap())
|
||||
.max()
|
||||
.filter(|v| v >= ¤t_version())
|
||||
.unwrap_or_else(current_version);
|
||||
|
||||
Ok(max_version)
|
||||
}
|
115
src/main.rs
115
src/main.rs
|
@ -1,4 +1,9 @@
|
|||
use crate::cli::get_token;
|
||||
use crate::cli::{
|
||||
auth::get_token,
|
||||
home_dir,
|
||||
version::{check_for_updates, current_version, get_or_download_version, max_installed_version},
|
||||
};
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
use colored::Colorize;
|
||||
use indicatif::MultiProgress;
|
||||
|
@ -18,30 +23,39 @@ struct Cli {
|
|||
version: (),
|
||||
|
||||
#[command(subcommand)]
|
||||
subcommand: cli::Subcommand,
|
||||
subcommand: cli::commands::Subcommand,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn run() -> anyhow::Result<()> {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
'scripts: {
|
||||
let exe = std::env::current_exe().expect("failed to get current executable path");
|
||||
if exe.parent().is_some_and(|parent| {
|
||||
parent.as_os_str() != "bin"
|
||||
|| parent
|
||||
.parent()
|
||||
.is_some_and(|parent| parent.as_os_str() != cli::HOME_DIR)
|
||||
}) {
|
||||
break 'scripts;
|
||||
}
|
||||
|
||||
let exe_name = exe.with_extension("");
|
||||
let exe_name = exe_name.file_name().unwrap();
|
||||
|
||||
if exe_name != env!("CARGO_BIN_NAME") {
|
||||
let args = std::env::args_os();
|
||||
if exe_name == env!("CARGO_BIN_NAME") {
|
||||
break 'scripts;
|
||||
}
|
||||
|
||||
let status = std::process::Command::new("lune")
|
||||
.arg("run")
|
||||
.arg(exe.with_extension("luau"))
|
||||
.args(args.skip(1))
|
||||
.args(std::env::args_os().skip(1))
|
||||
.current_dir(std::env::current_dir().unwrap())
|
||||
.status()
|
||||
.expect("failed to run lune");
|
||||
|
||||
std::process::exit(status.code().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
let multi = {
|
||||
let logger = pretty_env_logger::formatted_builder()
|
||||
|
@ -54,21 +68,82 @@ fn main() {
|
|||
multi
|
||||
};
|
||||
|
||||
let project_dirs =
|
||||
directories::ProjectDirs::from("com", env!("CARGO_PKG_NAME"), env!("CARGO_BIN_NAME"))
|
||||
.expect("couldn't get home directory");
|
||||
let cwd = std::env::current_dir().expect("failed to get current working directory");
|
||||
let cli = Cli::parse();
|
||||
|
||||
let data_dir = project_dirs.data_dir();
|
||||
create_dir_all(data_dir).expect("failed to create data directory");
|
||||
let data_dir = home_dir()?.join("data");
|
||||
create_dir_all(&data_dir).expect("failed to create data directory");
|
||||
|
||||
if let Err(err) = get_token(data_dir).and_then(|token| {
|
||||
cli.subcommand.run(
|
||||
Project::new(cwd, data_dir, AuthConfig::new().with_pesde_token(token)),
|
||||
multi,
|
||||
)
|
||||
}) {
|
||||
let token = get_token(&data_dir)?;
|
||||
|
||||
let project = Project::new(
|
||||
cwd,
|
||||
&data_dir,
|
||||
AuthConfig::new().with_pesde_token(token.as_ref()),
|
||||
);
|
||||
|
||||
let reqwest = {
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
if let Some(token) = token {
|
||||
headers.insert(
|
||||
reqwest::header::AUTHORIZATION,
|
||||
format!("Bearer {token}")
|
||||
.parse()
|
||||
.context("failed to create auth header")?,
|
||||
);
|
||||
}
|
||||
|
||||
headers.insert(
|
||||
reqwest::header::ACCEPT,
|
||||
"application/json"
|
||||
.parse()
|
||||
.context("failed to create accept header")?,
|
||||
);
|
||||
|
||||
reqwest::blocking::Client::builder()
|
||||
.user_agent(concat!(
|
||||
env!("CARGO_PKG_NAME"),
|
||||
"/",
|
||||
env!("CARGO_PKG_VERSION")
|
||||
))
|
||||
.default_headers(headers)
|
||||
.build()?
|
||||
};
|
||||
|
||||
check_for_updates(&reqwest, &data_dir)?;
|
||||
|
||||
let target_version = project
|
||||
.deser_manifest()
|
||||
.ok()
|
||||
.and_then(|manifest| manifest.pesde_version);
|
||||
|
||||
// store the current version in case it needs to be used later
|
||||
get_or_download_version(&reqwest, ¤t_version())?;
|
||||
|
||||
let exe_path = if let Some(version) = target_version {
|
||||
Some(get_or_download_version(&reqwest, &version)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let exe_path = if let Some(exe_path) = exe_path {
|
||||
exe_path
|
||||
} else {
|
||||
get_or_download_version(&reqwest, &max_installed_version()?)?
|
||||
};
|
||||
|
||||
if let Some(exe_path) = exe_path {
|
||||
let status = std::process::Command::new(exe_path)
|
||||
.args(std::env::args_os().skip(1))
|
||||
.status()
|
||||
.expect("failed to run new version");
|
||||
|
||||
std::process::exit(status.code().unwrap());
|
||||
}
|
||||
|
||||
Cli::parse().subcommand.run(project, multi, reqwest)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(err) = run() {
|
||||
eprintln!("{}: {err}\n", "error".red().bold());
|
||||
|
||||
let cause = err.chain().skip(1).collect::<Vec<_>>();
|
||||
|
|
|
@ -51,6 +51,8 @@ pub struct Manifest {
|
|||
#[cfg(feature = "patches")]
|
||||
#[serde(default, skip_serializing)]
|
||||
pub patches: BTreeMap<PackageNames, BTreeMap<VersionId, RelativePathBuf>>,
|
||||
#[serde(default, skip_serializing)]
|
||||
pub pesde_version: Option<Version>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||
pub dependencies: BTreeMap<String, DependencySpecifiers>,
|
||||
|
|
Loading…
Reference in a new issue