mirror of
https://github.com/veeso/termscp.git
synced 2026-08-31 01:15:56 -07:00
ci: migrate project automation to Just (#442)
Deploy docs to GitHub Pages / deploy (push) Has been cancelled
Site / build-site (push) Has been cancelled
Install.sh / build (macos-latest) (push) Has been cancelled
Install.sh / build (ubuntu-latest) (push) Has been cancelled
CI / toolchain (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / install-scripts (push) Has been cancelled
CI / crates-ubuntu-latest (push) Has been cancelled
CI / crates-windows-latest (push) Has been cancelled
CI / doc (push) Has been cancelled
CI / deny (push) Has been cancelled
CI / crates-macos-latest (push) Has been cancelled
Deploy docs to GitHub Pages / deploy (push) Has been cancelled
Site / build-site (push) Has been cancelled
Install.sh / build (macos-latest) (push) Has been cancelled
Install.sh / build (ubuntu-latest) (push) Has been cancelled
CI / toolchain (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / install-scripts (push) Has been cancelled
CI / crates-ubuntu-latest (push) Has been cancelled
CI / crates-windows-latest (push) Has been cancelled
CI / doc (push) Has been cancelled
CI / deny (push) Has been cancelled
CI / crates-macos-latest (push) Has been cancelled
* ci: migrate project automation to Just Centralize build, test, release, dependency, hook, and website commands in Just recipes. Pin workflow tooling, use the repository toolchain, and run the complete validation set in CI. * ci: codex being codex * docs: update CLAUDE.md for just task runner migration Reflect the switch to just recipes for build/test/clippy/fmt, note dprint replacing raw rustfmt, and add a cross-platform code requirement. * fix: resolve clippy warnings breaking CI on ubuntu and windows Use clone() instead of implicit to_string() on already-owned String values, gate the windows-only unused make_file_at import behind cfg(posix), and fix unused mut / manual assign-op in the windows-only localhost test. * fix: fmt
This commit is contained in:
committed by
GitHub
parent
08c51a32cc
commit
afbc74113f
Executable
+53
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# termscp pre-commit hook.
|
||||||
|
#
|
||||||
|
# Runs three gates before a commit is recorded:
|
||||||
|
# 1. trufflehog -- scan the staged tree for verified/unknown secrets
|
||||||
|
# 2. dprint -- check formatting (Markdown, TOML, YAML, Rust)
|
||||||
|
# 3. cargo-deny -- advisories, licenses, bans, and sources
|
||||||
|
#
|
||||||
|
# Install with `just setup_githooks` (sets core.hooksPath to .githooks).
|
||||||
|
# Bypass in an emergency with `git commit --no-verify`.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "pre-commit: $1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
command -v just >/dev/null 2>&1 || fail "just not found; install it to run the pre-commit checks"
|
||||||
|
|
||||||
|
if ! git diff --cached --quiet --diff-filter=ACMR --; then
|
||||||
|
command -v trufflehog >/dev/null 2>&1 || fail "trufflehog not found; install it or commit with --no-verify"
|
||||||
|
|
||||||
|
# Check the exact tree that will be committed, not possibly different
|
||||||
|
# working-tree contents. The trailing slash is required by checkout-index.
|
||||||
|
index_tree="$(mktemp -d)"
|
||||||
|
cleanup() {
|
||||||
|
rm -rf -- "$index_tree"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
git checkout-index --all --prefix="$index_tree/"
|
||||||
|
|
||||||
|
echo "pre-commit: scanning staged tree for secrets"
|
||||||
|
(
|
||||||
|
cd "$index_tree"
|
||||||
|
just scan_secrets . --fail-on-scan-errors
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "pre-commit: checking staged-tree formatting"
|
||||||
|
(
|
||||||
|
cd "$index_tree"
|
||||||
|
just fmt_check
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "pre-commit: checking staged-tree dependencies"
|
||||||
|
(
|
||||||
|
cd "$index_tree"
|
||||||
|
just deny
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "pre-commit: all checks passed"
|
||||||
@@ -4,7 +4,6 @@ about: Create a report of the bug you've encountered
|
|||||||
title: "[BUG] - ISSUE_TITLE"
|
title: "[BUG] - ISSUE_TITLE"
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: veeso
|
assignees: veeso
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ about: Report a typo/error in a repository document
|
|||||||
title: "[COPY] - ISSUE_TITLE"
|
title: "[COPY] - ISSUE_TITLE"
|
||||||
labels: documentation
|
labels: documentation
|
||||||
assignees: veeso
|
assignees: veeso
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Report
|
## Report
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ about: Suggest an idea to improve termscp
|
|||||||
title: "[Feature Request] - FEATURE_TITLE"
|
title: "[Feature Request] - FEATURE_TITLE"
|
||||||
labels: "new feature"
|
labels: "new feature"
|
||||||
assignees: veeso
|
assignees: veeso
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|||||||
@@ -4,5 +4,4 @@ about: Ask what you want about the project
|
|||||||
title: "[QUESTION] - TITLE"
|
title: "[QUESTION] - TITLE"
|
||||||
labels: question
|
labels: question
|
||||||
assignees: veeso
|
assignees: veeso
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ about: Create a report of a security vulnerability
|
|||||||
title: "[SECURITY] - ISSUE_TITLE"
|
title: "[SECURITY] - ISSUE_TITLE"
|
||||||
labels: security
|
labels: security
|
||||||
assignees: veeso
|
assignees: veeso
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ Please select relevant options.
|
|||||||
- [ ] I formatted the code with `cargo fmt`
|
- [ ] I formatted the code with `cargo fmt`
|
||||||
- [ ] I checked my code using `cargo clippy` and reports no warnings
|
- [ ] I checked my code using `cargo clippy` and reports no warnings
|
||||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||||
- [ ] I have introduced no new *C-bindings*
|
- [ ] I have introduced no new _C-bindings_
|
||||||
- [ ] The changes I've made are Windows, MacOS, UNIX, Linux compatible (or I've handled them using `cfg target_os`)
|
- [ ] The changes I've made are Windows, MacOS, UNIX, Linux compatible (or I've handled them using `cfg target_os`)
|
||||||
- [ ] I increased or maintained the code coverage for the project, compared to the previous commit
|
- [ ] I increased or maintained the code coverage for the project, compared to the previous commit
|
||||||
|
|
||||||
## Acceptance tests
|
## Acceptance tests
|
||||||
|
|
||||||
wait for a *project maintainer* to fulfill this section...
|
wait for a _project maintainer_ to fulfill this section...
|
||||||
|
|
||||||
- [ ] regression test: ...
|
- [ ] regression test: ...
|
||||||
|
|||||||
+95
-25
@@ -5,12 +5,12 @@ on:
|
|||||||
branches: [main]
|
branches: [main]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- "*.md"
|
- "*.md"
|
||||||
- "./site/**/*"
|
- "site/**"
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- "*.md"
|
- "*.md"
|
||||||
- "./site/**/*"
|
- "site/**"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
@@ -19,20 +19,60 @@ permissions:
|
|||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
toolchain:
|
||||||
name: build-(${{ matrix.os }})
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
channel: ${{ steps.extract.outputs.result }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Extract toolchain channel from rust-toolchain.toml
|
||||||
|
id: extract
|
||||||
|
uses: mikefarah/yq@c14f446382944492701b16c1ddb48bb9dbe683e3 # v4.53.6
|
||||||
|
with:
|
||||||
|
cmd: yq '.toolchain.channel' rust-toolchain.toml
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Install Rust (nightly)
|
||||||
|
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
|
||||||
|
with:
|
||||||
|
toolchain: nightly
|
||||||
|
components: rustfmt
|
||||||
|
- name: Check formatting
|
||||||
|
uses: dprint/check@9cb3a2b17a8e606d37aae341e49df3654933fc23 # v2.3
|
||||||
|
|
||||||
|
install-scripts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Install just
|
||||||
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
|
- name: Check install scripts
|
||||||
|
run: just check_install_scripts
|
||||||
|
|
||||||
|
crates:
|
||||||
|
needs: toolchain
|
||||||
|
name: crates-${{ matrix.os }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Install Linux dependencies
|
- name: Install Linux dependencies
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: sudo apt update && sudo apt install -y libdbus-1-dev libsmbclient-dev
|
run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev libsmbclient-dev
|
||||||
- name: Install macOS dependencies
|
- name: Install macOS dependencies
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
@@ -41,28 +81,58 @@ jobs:
|
|||||||
pkg-config \
|
pkg-config \
|
||||||
samba
|
samba
|
||||||
brew link --force samba
|
brew link --force samba
|
||||||
- name: Install nightly toolchain
|
- name: Install Rust
|
||||||
if: runner.os == 'Linux'
|
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
|
||||||
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
|
||||||
with:
|
with:
|
||||||
toolchain: nightly
|
toolchain: ${{ needs.toolchain.outputs.channel }}
|
||||||
components: rustfmt
|
|
||||||
- name: Format
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
run: cargo +nightly fmt --all -- --check
|
|
||||||
- name: Install stable toolchain
|
|
||||||
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
|
||||||
with:
|
|
||||||
toolchain: stable
|
|
||||||
components: clippy
|
components: clippy
|
||||||
|
- name: Install just
|
||||||
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
- name: Build
|
- name: Build
|
||||||
if: runner.os != 'Linux'
|
run: just build_crates
|
||||||
run: cargo build
|
- name: Test (Linux)
|
||||||
- name: Run tests (Linux)
|
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: cargo test --no-default-features --features github-actions --no-fail-fast
|
run: just test "--no-default-features --features github-actions --no-fail-fast"
|
||||||
- name: Run tests
|
- name: Test
|
||||||
if: runner.os != 'Linux'
|
if: runner.os != 'Linux'
|
||||||
run: cargo test --verbose --features github-actions
|
run: just test "--verbose --features github-actions"
|
||||||
- name: Clippy
|
- name: Clippy
|
||||||
run: cargo clippy -- -Dwarnings
|
run: just clippy "-- -D warnings"
|
||||||
|
|
||||||
|
doc:
|
||||||
|
needs: toolchain
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Install Linux dependencies
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev libsmbclient-dev
|
||||||
|
- name: Install Rust
|
||||||
|
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
|
||||||
|
with:
|
||||||
|
toolchain: ${{ needs.toolchain.outputs.channel }}
|
||||||
|
- name: Install just
|
||||||
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
|
- name: Build documentation
|
||||||
|
run: just doc
|
||||||
|
|
||||||
|
deny:
|
||||||
|
needs: toolchain
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Install Rust
|
||||||
|
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
|
||||||
|
with:
|
||||||
|
toolchain: ${{ needs.toolchain.outputs.channel }}
|
||||||
|
- name: Install cargo-deny
|
||||||
|
uses: taiki-e/install-action@37f7c5781271959fb65b6b35224e28652ff2b63d # v2.87.0
|
||||||
|
with:
|
||||||
|
tool: cargo-deny
|
||||||
|
- name: Install just
|
||||||
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
|
- name: Check dependencies
|
||||||
|
run: just deny
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Install termscp from script
|
- name: Install termscp from script
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
name: github-pages
|
name: github-pages
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Install mdBook
|
- name: Install mdBook
|
||||||
@@ -58,9 +58,9 @@ jobs:
|
|||||||
<a href="./en-US/">termscp documentation</a>
|
<a href="./en-US/">termscp documentation</a>
|
||||||
HTML
|
HTML
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
|
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
||||||
with:
|
with:
|
||||||
path: site_out
|
path: site_out
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
id: deployment
|
id: deployment
|
||||||
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
|
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
||||||
|
|||||||
@@ -22,23 +22,35 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
version: ${{ inputs.version }}
|
version: ${{ inputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.RELEASE_PAT }}
|
token: ${{ secrets.RELEASE_PAT }}
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
|
|
||||||
|
- name: Validate version
|
||||||
|
env:
|
||||||
|
VERSION: ${{ inputs.version }}
|
||||||
|
run: |
|
||||||
|
if [[ ! "$VERSION" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
|
||||||
|
echo "invalid release version: $VERSION (expected MAJOR.MINOR.PATCH)" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Configure git identity
|
- name: Configure git identity
|
||||||
run: |
|
run: |
|
||||||
git config user.name "veeso"
|
git config user.name "veeso"
|
||||||
git config user.email "christian.visintin@veeso.dev"
|
git config user.email "christian.visintin@veeso.dev"
|
||||||
|
|
||||||
- name: Install git-cliff
|
- name: Install git-cliff
|
||||||
uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e # v2
|
uses: taiki-e/install-action@37f7c5781271959fb65b6b35224e28652ff2b63d # v2.87.0
|
||||||
with:
|
with:
|
||||||
tool: git-cliff
|
tool: git-cliff
|
||||||
|
|
||||||
|
- name: Install just
|
||||||
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
|
|
||||||
- name: Bump version
|
- name: Bump version
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ inputs.version }}
|
VERSION: ${{ inputs.version }}
|
||||||
@@ -47,7 +59,7 @@ jobs:
|
|||||||
- name: Generate CHANGELOG
|
- name: Generate CHANGELOG
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ inputs.version }}
|
VERSION: ${{ inputs.version }}
|
||||||
run: git-cliff --tag "v$VERSION" -o CHANGELOG.md
|
run: just changelog "$VERSION"
|
||||||
|
|
||||||
- name: Generate release notes
|
- name: Generate release notes
|
||||||
env:
|
env:
|
||||||
@@ -55,7 +67,7 @@ jobs:
|
|||||||
run: git-cliff --unreleased --tag "v$VERSION" --strip header -o RELEASE_NOTES.md
|
run: git-cliff --unreleased --tag "v$VERSION" --strip header -o RELEASE_NOTES.md
|
||||||
|
|
||||||
- name: Upload release notes
|
- name: Upload release notes
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
with:
|
with:
|
||||||
name: release-notes
|
name: release-notes
|
||||||
path: RELEASE_NOTES.md
|
path: RELEASE_NOTES.md
|
||||||
@@ -111,15 +123,20 @@ jobs:
|
|||||||
TARGET: ${{ matrix.target }}
|
TARGET: ${{ matrix.target }}
|
||||||
FEATURES: ${{ matrix.features }}
|
FEATURES: ${{ matrix.features }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
ref: ${{ inputs.dry_run && github.sha || 'main' }}
|
ref: ${{ inputs.dry_run && github.sha || 'main' }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
- name: Install just
|
||||||
with:
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
targets: ${{ matrix.target }}
|
- name: Install Rust target
|
||||||
|
if: matrix.kind != 'windows'
|
||||||
|
run: rustup target add "$TARGET"
|
||||||
|
- name: Install Rust target
|
||||||
|
if: matrix.kind == 'windows'
|
||||||
|
run: rustup target add "$env:TARGET"
|
||||||
|
|
||||||
# ---- Linux: native per-arch build (x86_64 on ubuntu-latest, aarch64 on ubuntu-24.04-arm) ----
|
# ---- Linux: native per-arch build (x86_64 on ubuntu-latest, aarch64 on ubuntu-24.04-arm) ----
|
||||||
- name: Install dependencies (Linux)
|
- name: Install dependencies (Linux)
|
||||||
@@ -156,10 +173,10 @@ jobs:
|
|||||||
cargo install cargo-deb
|
cargo install cargo-deb
|
||||||
- name: Build (Linux)
|
- name: Build (Linux)
|
||||||
if: matrix.kind == 'linux'
|
if: matrix.kind == 'linux'
|
||||||
run: cargo build --release --features smb-vendored --target "$TARGET"
|
run: just build_release "$TARGET" "--features smb-vendored"
|
||||||
- name: Build deb (Linux)
|
- name: Build deb (Linux)
|
||||||
if: matrix.kind == 'linux'
|
if: matrix.kind == 'linux'
|
||||||
run: cargo deb --no-build --target "$TARGET" --features smb-vendored
|
run: just package_deb "$TARGET"
|
||||||
|
|
||||||
# ---- macOS ----
|
# ---- macOS ----
|
||||||
- name: Install deps (macOS)
|
- name: Install deps (macOS)
|
||||||
@@ -173,12 +190,12 @@ jobs:
|
|||||||
cpanm Parse::Yapp::Driver
|
cpanm Parse::Yapp::Driver
|
||||||
- name: Build (macOS)
|
- name: Build (macOS)
|
||||||
if: matrix.kind == 'macos'
|
if: matrix.kind == 'macos'
|
||||||
run: cargo build --release $FEATURES --target "$TARGET"
|
run: just build_release "$TARGET" "$FEATURES"
|
||||||
|
|
||||||
# ---- Windows ----
|
# ---- Windows ----
|
||||||
- name: Build (Windows)
|
- name: Build (Windows)
|
||||||
if: matrix.kind == 'windows'
|
if: matrix.kind == 'windows'
|
||||||
run: cargo build --release --features smb-vendored --target "$env:TARGET"
|
run: just build_release "$env:TARGET" "--features smb-vendored"
|
||||||
|
|
||||||
# ---- Package posix (tar.gz) ----
|
# ---- Package posix (tar.gz) ----
|
||||||
- name: Package (posix)
|
- name: Package (posix)
|
||||||
@@ -204,7 +221,7 @@ jobs:
|
|||||||
run: cp target/"$TARGET"/debian/*.deb artifact/
|
run: cp target/"$TARGET"/debian/*.deb artifact/
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
with:
|
with:
|
||||||
name: build-${{ matrix.target }}
|
name: build-${{ matrix.target }}
|
||||||
path: artifact/*
|
path: artifact/*
|
||||||
@@ -218,14 +235,14 @@ jobs:
|
|||||||
VERSION: ${{ needs.prepare.outputs.version }}
|
VERSION: ${{ needs.prepare.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Download build artifacts
|
- name: Download build artifacts
|
||||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||||
with:
|
with:
|
||||||
pattern: build-*
|
pattern: build-*
|
||||||
path: dl
|
path: dl
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Checkout homebrew tap
|
- name: Checkout homebrew tap
|
||||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
repository: veeso/homebrew-termscp
|
repository: veeso/homebrew-termscp
|
||||||
token: ${{ secrets.RELEASE_PAT }}
|
token: ${{ secrets.RELEASE_PAT }}
|
||||||
@@ -316,21 +333,21 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
VERSION: ${{ needs.prepare.outputs.version }}
|
VERSION: ${{ needs.prepare.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.RELEASE_PAT }}
|
token: ${{ secrets.RELEASE_PAT }}
|
||||||
ref: ${{ inputs.dry_run && github.sha || 'main' }}
|
ref: ${{ inputs.dry_run && github.sha || 'main' }}
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
|
|
||||||
- name: Download build artifacts
|
- name: Download build artifacts
|
||||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||||
with:
|
with:
|
||||||
pattern: build-*
|
pattern: build-*
|
||||||
path: dl
|
path: dl
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Download release notes
|
- name: Download release notes
|
||||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||||
with:
|
with:
|
||||||
name: release-notes
|
name: release-notes
|
||||||
path: notes
|
path: notes
|
||||||
@@ -355,7 +372,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload assets artifact (dry run)
|
- name: Upload assets artifact (dry run)
|
||||||
if: ${{ inputs.dry_run }}
|
if: ${{ inputs.dry_run }}
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
with:
|
with:
|
||||||
name: release-assets-dryrun
|
name: release-assets-dryrun
|
||||||
path: out/*
|
path: out/*
|
||||||
@@ -380,13 +397,14 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
VERSION: ${{ needs.prepare.outputs.version }}
|
VERSION: ${{ needs.prepare.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
ref: main
|
ref: main
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
- name: Install just
|
||||||
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
|
|
||||||
- name: Install dependencies (Linux)
|
- name: Install dependencies (Linux)
|
||||||
run: |
|
run: |
|
||||||
@@ -421,12 +439,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Authenticate to crates.io
|
- name: Authenticate to crates.io
|
||||||
id: auth
|
id: auth
|
||||||
uses: rust-lang/crates-io-auth-action@bbd81622f20ce9e2dd9622e3218b975523e45bbe # v1.0.4
|
uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5
|
||||||
|
|
||||||
- name: Publish to crates.io
|
- name: Publish to crates.io
|
||||||
env:
|
env:
|
||||||
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
|
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
|
||||||
run: cargo publish --features smb-vendored
|
run: just publish_crate
|
||||||
|
|
||||||
publish-choco:
|
publish-choco:
|
||||||
needs: [prepare, release]
|
needs: [prepare, release]
|
||||||
|
|||||||
@@ -9,30 +9,28 @@ on:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: site
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-site:
|
build-site:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: site/package-lock.json
|
cache-dependency-path: site/package-lock.json
|
||||||
|
- name: Install just
|
||||||
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: just site_install
|
||||||
- name: Format
|
- name: Format
|
||||||
run: npm run format:check
|
run: just site_fmt_check
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: npm run check
|
run: just site_check
|
||||||
- name: Test
|
- name: Test
|
||||||
run: npm test --if-present
|
run: just site_test
|
||||||
- name: Build
|
- name: Build
|
||||||
run: npm run build
|
run: just site_build
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ jobs:
|
|||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@a20b814fb01b71def3bd6f56e7494d667ddf28da # v4.1.1
|
- uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0
|
||||||
with:
|
with:
|
||||||
days-before-issue-stale: 30
|
days-before-issue-stale: 30
|
||||||
days-before-issue-close: 7
|
days-before-issue-close: 7
|
||||||
|
|||||||
+40
-8
@@ -1,3 +1,5 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
## 1.1.1
|
## 1.1.1
|
||||||
|
|
||||||
Released on 2026-06-08
|
Released on 2026-06-08
|
||||||
@@ -10,6 +12,7 @@ Released on 2026-06-08
|
|||||||
> crates.io versions are immutable (no overwrite) and Chocolatey's
|
> crates.io versions are immutable (no overwrite) and Chocolatey's
|
||||||
> moderation queue blocks a fast re-push, so a clean 1.1.1 without vergen
|
> moderation queue blocks a fast re-push, so a clean 1.1.1 without vergen
|
||||||
> is the only fix.
|
> is the only fix.
|
||||||
|
|
||||||
## 1.1.0
|
## 1.1.0
|
||||||
|
|
||||||
Released on 2026-06-08
|
Released on 2026-06-08
|
||||||
@@ -191,6 +194,7 @@ Released on 2026-06-08
|
|||||||
> The old manual dist/build/* scripts and dist/{deb,rpm}.sh are superseded by the
|
> The old manual dist/build/* scripts and dist/{deb,rpm}.sh are superseded by the
|
||||||
> automated release workflow. Add the chocolatey package consumed by release.yml.
|
> automated release workflow. Add the chocolatey package consumed by release.yml.
|
||||||
- **site:** copy install.sh from repo root at build time (single source)
|
- **site:** copy install.sh from repo root at build time (single source)
|
||||||
|
|
||||||
## 1.0.0
|
## 1.0.0
|
||||||
|
|
||||||
Released on 2026-04-18
|
Released on 2026-04-18
|
||||||
@@ -243,6 +247,7 @@ Released on 2026-04-18
|
|||||||
> `fs_pane_mut()`. This eliminates most `is_local_tab()` branching across
|
> `fs_pane_mut()`. This eliminates most `is_local_tab()` branching across
|
||||||
> 15+ action files.
|
> 15+ action files.
|
||||||
> Key changes:
|
> Key changes:
|
||||||
|
>
|
||||||
> - Add `fs: Box<dyn HostBridge>` to Pane, remove from FileTransferActivity
|
> - Add `fs: Box<dyn HostBridge>` to Pane, remove from FileTransferActivity
|
||||||
> - Replace per-side method pairs with unified pane-dispatched methods
|
> - Replace per-side method pairs with unified pane-dispatched methods
|
||||||
> - Unify navigation (changedir, reload, scan, file_exists, has_file_changed)
|
> - Unify navigation (changedir, reload, scan, file_exists, has_file_changed)
|
||||||
@@ -278,7 +283,7 @@ Released on 2026-04-18
|
|||||||
> encryption (authenticated, with random nonces) while keeping a legacy
|
> encryption (authenticated, with random nonces) while keeping a legacy
|
||||||
> AES-128-CBC decryption path to transparently handle existing bookmarks.
|
> AES-128-CBC decryption path to transparently handle existing bookmarks.
|
||||||
- replace recursive byte-counting with entry-based transfer progress (#395)
|
- replace recursive byte-counting with entry-based transfer progress (#395)
|
||||||
> * fix: replace recursive byte-counting with entry-based transfer progress
|
> - fix: replace recursive byte-counting with entry-based transfer progress
|
||||||
>
|
>
|
||||||
> Replace the expensive recursive `get_total_transfer_size` pre-calculation
|
> Replace the expensive recursive `get_total_transfer_size` pre-calculation
|
||||||
> with a lightweight entry-based counter (`TransferProgress`) for the
|
> with a lightweight entry-based counter (`TransferProgress`) for the
|
||||||
@@ -394,6 +399,7 @@ Released on 2026-04-18
|
|||||||
### Style
|
### Style
|
||||||
|
|
||||||
- linter
|
- linter
|
||||||
|
|
||||||
## 0.19.1
|
## 0.19.1
|
||||||
|
|
||||||
Released on 2025-12-20
|
Released on 2025-12-20
|
||||||
@@ -407,6 +413,7 @@ Released on 2025-12-20
|
|||||||
- install.sh deb name
|
- install.sh deb name
|
||||||
- install.sh deb name
|
- install.sh deb name
|
||||||
- Updated dependencies to allow build on NetBSD
|
- Updated dependencies to allow build on NetBSD
|
||||||
|
|
||||||
## 0.19.0
|
## 0.19.0
|
||||||
|
|
||||||
Released on 2025-11-11
|
Released on 2025-11-11
|
||||||
@@ -414,13 +421,13 @@ Released on 2025-11-11
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Import bookmarks from ssh config with a CLI command (#364)
|
- Import bookmarks from ssh config with a CLI command (#364)
|
||||||
> * feat: Import bookmarks from ssh config with a CLI command
|
> - feat: Import bookmarks from ssh config with a CLI command
|
||||||
>
|
>
|
||||||
> Use import-ssh-hosts to import all the possible hosts by the configured ssh config or the default one on your machine
|
> Use import-ssh-hosts to import all the possible hosts by the configured ssh config or the default one on your machine
|
||||||
- Changed file overwrite behaviour (#366)
|
- Changed file overwrite behaviour (#366)
|
||||||
> Now the user can choose for each file whether to overwrite, skip or overwrite all/skip all.
|
> Now the user can choose for each file whether to overwrite, skip or overwrite all/skip all.
|
||||||
- Added `<CTRL+S>` keybinding to get the total size of selected paths. (#367)
|
- Added `<CTRL+S>` keybinding to get the total size of selected paths. (#367)
|
||||||
> * feat: Added `<CTRL+S>` keybinding to get the total size of selected paths.
|
> - feat: Added `<CTRL+S>` keybinding to get the total size of selected paths.
|
||||||
- Merge branch '0.19.0'
|
- Merge branch '0.19.0'
|
||||||
|
|
||||||
### CI
|
### CI
|
||||||
@@ -440,7 +447,7 @@ Released on 2025-11-11
|
|||||||
- typo in file open error message (#349)
|
- typo in file open error message (#349)
|
||||||
- SMB support for MacOS with vendored build of libsmbclient.
|
- SMB support for MacOS with vendored build of libsmbclient.
|
||||||
- Report a message while calculating total size of files to transfer. (#362)
|
- Report a message while calculating total size of files to transfer. (#362)
|
||||||
> * fix: Report a message while calculating total size of files to transfer.
|
> - fix: Report a message while calculating total size of files to transfer.
|
||||||
>
|
>
|
||||||
> Currently, in case of huge transfers the app may look frozen while calculating the transfer size. We should at least report to the user we are actually doing something.
|
> Currently, in case of huge transfers the app may look frozen while calculating the transfer size. We should at least report to the user we are actually doing something.
|
||||||
- Issues with update checks (#363)
|
- Issues with update checks (#363)
|
||||||
@@ -456,6 +463,7 @@ Released on 2025-11-11
|
|||||||
- 0.19 deps
|
- 0.19 deps
|
||||||
- remotefs-ssh 0.7.1
|
- remotefs-ssh 0.7.1
|
||||||
> This version fixes compatibility with hosts which don't use bash/sh as the default shell.
|
> This version fixes compatibility with hosts which don't use bash/sh as the default shell.
|
||||||
|
|
||||||
## 0.18.0
|
## 0.18.0
|
||||||
|
|
||||||
Released on 2025-06-10
|
Released on 2025-06-10
|
||||||
@@ -464,7 +472,7 @@ Released on 2025-06-10
|
|||||||
|
|
||||||
- **Updated dependencies** and updated the Rust edition to `2024`
|
- **Updated dependencies** and updated the Rust edition to `2024`
|
||||||
- Replaced the `Exec` popup with a fully functional terminal emulator (#348)
|
- Replaced the `Exec` popup with a fully functional terminal emulator (#348)
|
||||||
> * feat: Replaced the `Exec` popup with a fully functional terminal emulator
|
> - feat: Replaced the `Exec` popup with a fully functional terminal emulator
|
||||||
- 0.18
|
- 0.18
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
@@ -475,6 +483,7 @@ Released on 2025-06-10
|
|||||||
### Style
|
### Style
|
||||||
|
|
||||||
- catppuccin themes
|
- catppuccin themes
|
||||||
|
|
||||||
## 0.17.0
|
## 0.17.0
|
||||||
|
|
||||||
Released on 2025-03-23
|
Released on 2025-03-23
|
||||||
@@ -523,6 +532,7 @@ Released on 2025-03-23
|
|||||||
- aws-s3 0.4.2
|
- aws-s3 0.4.2
|
||||||
- build docker for x86
|
- build docker for x86
|
||||||
- so apparently native-tls vendored tries to build openssl on windows, wtf guys?
|
- so apparently native-tls vendored tries to build openssl on windows, wtf guys?
|
||||||
|
|
||||||
## 0.16.1
|
## 0.16.1
|
||||||
|
|
||||||
Released on 2024-11-12
|
Released on 2024-11-12
|
||||||
@@ -532,6 +542,7 @@ Released on 2024-11-12
|
|||||||
- cfg unix forbidden in rust .82
|
- cfg unix forbidden in rust .82
|
||||||
- gg rust 1.82 for introducing a nice breaking change in config which was not mentioned in changelog
|
- gg rust 1.82 for introducing a nice breaking change in config which was not mentioned in changelog
|
||||||
- 0.16.1
|
- 0.16.1
|
||||||
|
|
||||||
## 0.16.0
|
## 0.16.0
|
||||||
|
|
||||||
Released on 2024-10-14
|
Released on 2024-10-14
|
||||||
@@ -550,6 +561,7 @@ Released on 2024-10-14
|
|||||||
- issue 292 New version alert was not displayed due to a semver regex issue. (#300)
|
- issue 292 New version alert was not displayed due to a semver regex issue. (#300)
|
||||||
- 0.16
|
- 0.16
|
||||||
- tiny ui issue
|
- tiny ui issue
|
||||||
|
|
||||||
## 0.15.0
|
## 0.15.0
|
||||||
|
|
||||||
Released on 2024-10-03
|
Released on 2024-10-03
|
||||||
@@ -572,14 +584,14 @@ Released on 2024-10-03
|
|||||||
- issue 277 Fix a bug in the configuration page, which caused being stuck if the added SSH key was empty
|
- issue 277 Fix a bug in the configuration page, which caused being stuck if the added SSH key was empty
|
||||||
- popup texts
|
- popup texts
|
||||||
- `isolated-tests` feature to run tests for releasing on distributions which run in isolated environments (#286)
|
- `isolated-tests` feature to run tests for releasing on distributions which run in isolated environments (#286)
|
||||||
> * fix: `isolated-tests` feature to run tests for releasing on distributions which run in isolated environments
|
> - fix: `isolated-tests` feature to run tests for releasing on distributions which run in isolated environments
|
||||||
>
|
> - fix: cond
|
||||||
> * fix: cond
|
|
||||||
- set date
|
- set date
|
||||||
- github ci is stable and reliable (one worker broken each 2 weeks)
|
- github ci is stable and reliable (one worker broken each 2 weeks)
|
||||||
- ci
|
- ci
|
||||||
- readme
|
- readme
|
||||||
- include build.rs
|
- include build.rs
|
||||||
|
|
||||||
## 0.14.0
|
## 0.14.0
|
||||||
|
|
||||||
Released on 2024-07-17
|
Released on 2024-07-17
|
||||||
@@ -608,6 +620,7 @@ Released on 2024-07-17
|
|||||||
- german manual
|
- german manual
|
||||||
- removed support for RPM
|
- removed support for RPM
|
||||||
- changelog
|
- changelog
|
||||||
|
|
||||||
## 0.13.0
|
## 0.13.0
|
||||||
|
|
||||||
Released on 2024-03-02
|
Released on 2024-03-02
|
||||||
@@ -624,6 +637,7 @@ Released on 2024-03-02
|
|||||||
- debian script
|
- debian script
|
||||||
- debian script
|
- debian script
|
||||||
- lint???
|
- lint???
|
||||||
|
|
||||||
## 0.12.2
|
## 0.12.2
|
||||||
|
|
||||||
Released on 2023-10-01
|
Released on 2023-10-01
|
||||||
@@ -636,6 +650,7 @@ Released on 2023-10-01
|
|||||||
|
|
||||||
- fmt
|
- fmt
|
||||||
- panic if the terminal screen is too small
|
- panic if the terminal screen is too small
|
||||||
|
|
||||||
## 0.12.1
|
## 0.12.1
|
||||||
|
|
||||||
Released on 2023-07-06
|
Released on 2023-07-06
|
||||||
@@ -659,6 +674,7 @@ Released on 2023-07-06
|
|||||||
- don't run CI on site/.md change
|
- don't run CI on site/.md change
|
||||||
- rustup target
|
- rustup target
|
||||||
- don't update path breadcrumb if enter/scan dir failed (#203)
|
- don't update path breadcrumb if enter/scan dir failed (#203)
|
||||||
|
|
||||||
## 0.12.0
|
## 0.12.0
|
||||||
|
|
||||||
Released on 2023-05-16
|
Released on 2023-05-16
|
||||||
@@ -677,6 +693,7 @@ Released on 2023-05-16
|
|||||||
- pavao 0.2.3
|
- pavao 0.2.3
|
||||||
- macos script
|
- macos script
|
||||||
- release date
|
- release date
|
||||||
|
|
||||||
## 0.11.3
|
## 0.11.3
|
||||||
|
|
||||||
Released on 2023-04-19
|
Released on 2023-04-19
|
||||||
@@ -688,6 +705,7 @@ Released on 2023-04-19
|
|||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- relative paths windows (#167)
|
- relative paths windows (#167)
|
||||||
|
|
||||||
## 0.11.2
|
## 0.11.2
|
||||||
|
|
||||||
Released on 2023-04-18
|
Released on 2023-04-18
|
||||||
@@ -696,6 +714,7 @@ Released on 2023-04-18
|
|||||||
|
|
||||||
- dependencies up-to-date
|
- dependencies up-to-date
|
||||||
- site 0.11.2
|
- site 0.11.2
|
||||||
|
|
||||||
## 0.8.1
|
## 0.8.1
|
||||||
|
|
||||||
Released on 2022-03-22
|
Released on 2022-03-22
|
||||||
@@ -703,6 +722,7 @@ Released on 2022-03-22
|
|||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- footer listed "Delete" shortcut as "Make Dir"
|
- footer listed "Delete" shortcut as "Make Dir"
|
||||||
|
|
||||||
## 0.8.0
|
## 0.8.0
|
||||||
|
|
||||||
Released on 2022-01-06
|
Released on 2022-01-06
|
||||||
@@ -710,6 +730,7 @@ Released on 2022-01-06
|
|||||||
### Arch
|
### Arch
|
||||||
|
|
||||||
- install rust only if not found on local system
|
- install rust only if not found on local system
|
||||||
|
|
||||||
## 0.7.0
|
## 0.7.0
|
||||||
|
|
||||||
Released on 2021-10-12
|
Released on 2021-10-12
|
||||||
@@ -717,6 +738,7 @@ Released on 2021-10-12
|
|||||||
### Option
|
### Option
|
||||||
|
|
||||||
- prompt user when about to replace an existing file caused by a file transfer
|
- prompt user when about to replace an existing file caused by a file transfer
|
||||||
|
|
||||||
## 0.6.1
|
## 0.6.1
|
||||||
|
|
||||||
Released on 2021-08-30
|
Released on 2021-08-30
|
||||||
@@ -724,6 +746,7 @@ Released on 2021-08-30
|
|||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- When copying files with tricky copy, the upper progress bar shows no text
|
- When copying files with tricky copy, the upper progress bar shows no text
|
||||||
|
|
||||||
## 0.5.1
|
## 0.5.1
|
||||||
|
|
||||||
Released on 2021-06-21
|
Released on 2021-06-21
|
||||||
@@ -731,6 +754,7 @@ Released on 2021-06-21
|
|||||||
### Fix
|
### Fix
|
||||||
|
|
||||||
- target_family unix means also macos and linux; use BSD target_os
|
- target_family unix means also macos and linux; use BSD target_os
|
||||||
|
|
||||||
## 0.5.0
|
## 0.5.0
|
||||||
|
|
||||||
Released on 2021-05-23
|
Released on 2021-05-23
|
||||||
@@ -743,6 +767,7 @@ Released on 2021-05-23
|
|||||||
### Grcov
|
### Grcov
|
||||||
|
|
||||||
- exclude activities
|
- exclude activities
|
||||||
|
|
||||||
## 0.4.1
|
## 0.4.1
|
||||||
|
|
||||||
Released on 2021-04-06
|
Released on 2021-04-06
|
||||||
@@ -767,6 +792,7 @@ Released on 2021-04-06
|
|||||||
### SCP
|
### SCP
|
||||||
|
|
||||||
- fixed symlink not properly detected
|
- fixed symlink not properly detected
|
||||||
|
|
||||||
## 0.4.0
|
## 0.4.0
|
||||||
|
|
||||||
Released on 2021-03-27
|
Released on 2021-03-27
|
||||||
@@ -786,6 +812,7 @@ Released on 2021-03-27
|
|||||||
### View
|
### View
|
||||||
|
|
||||||
- return String instead of id
|
- return String instead of id
|
||||||
|
|
||||||
## 0.3.3
|
## 0.3.3
|
||||||
|
|
||||||
Released on 2021-02-28
|
Released on 2021-02-28
|
||||||
@@ -793,6 +820,7 @@ Released on 2021-02-28
|
|||||||
### Git
|
### Git
|
||||||
|
|
||||||
- check for new updates (utils)
|
- check for new updates (utils)
|
||||||
|
|
||||||
## 0.3.2
|
## 0.3.2
|
||||||
|
|
||||||
Released on 2021-01-24
|
Released on 2021-01-24
|
||||||
@@ -800,6 +828,7 @@ Released on 2021-01-24
|
|||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
- don't run on windows
|
- don't run on windows
|
||||||
|
|
||||||
## 0.3.0
|
## 0.3.0
|
||||||
|
|
||||||
Released on 2021-01-10
|
Released on 2021-01-10
|
||||||
@@ -834,6 +863,7 @@ Released on 2021-01-10
|
|||||||
### SetupActivity
|
### SetupActivity
|
||||||
|
|
||||||
- <CTRL+E> as <DEL>
|
- <CTRL+E> as <DEL>
|
||||||
|
|
||||||
## 0.2.0
|
## 0.2.0
|
||||||
|
|
||||||
Released on 2020-12-21
|
Released on 2020-12-21
|
||||||
@@ -845,6 +875,7 @@ Released on 2020-12-21
|
|||||||
### Scp
|
### Scp
|
||||||
|
|
||||||
- when username was not provided, it didn't fallback to current username
|
- when username was not provided, it didn't fallback to current username
|
||||||
|
|
||||||
## 0.1.2
|
## 0.1.2
|
||||||
|
|
||||||
Released on 2020-12-13
|
Released on 2020-12-13
|
||||||
@@ -852,6 +883,7 @@ Released on 2020-12-13
|
|||||||
### FsEntry
|
### FsEntry
|
||||||
|
|
||||||
- :*::symlink is now a Option<Box<FsEntry>>; this improved symlinks, which gave errors some times
|
- :*::symlink is now a Option<Box<FsEntry>>; this improved symlinks, which gave errors some times
|
||||||
|
|
||||||
## 0.1.0
|
## 0.1.0
|
||||||
|
|
||||||
Released on 2020-12-06
|
Released on 2020-12-06
|
||||||
|
|||||||
@@ -12,28 +12,31 @@ termscp is a terminal file transfer client with a TUI (Terminal User Interface),
|
|||||||
|
|
||||||
## Build & Development Commands
|
## Build & Development Commands
|
||||||
|
|
||||||
|
Task runner is `just` (modular recipes under `just/*.just`, imported by root `justfile`). Run `just --list` for the full set.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Build
|
# Build
|
||||||
cargo build
|
just build_crates # cargo build --workspace
|
||||||
cargo build --release
|
just build_crates "--release"
|
||||||
cargo build --no-default-features # minimal build without SMB/keyring
|
cargo build --no-default-features # minimal build without SMB/keyring (no just recipe)
|
||||||
|
|
||||||
# Test (CI-equivalent)
|
# Test (CI-equivalent)
|
||||||
cargo test --no-default-features --features github-actions --no-fail-fast
|
just test "--no-default-features --features github-actions --no-fail-fast"
|
||||||
|
|
||||||
# Run a single test
|
# Run a single test / a module (use cargo directly, just recipes don't take test names)
|
||||||
cargo test <test_name> -- --nocapture
|
cargo test <test_name> -- --nocapture
|
||||||
|
|
||||||
# Run tests for a module
|
|
||||||
cargo test --lib filetransfer::
|
cargo test --lib filetransfer::
|
||||||
cargo test --lib config::params::tests
|
cargo test --lib config::params::tests
|
||||||
|
|
||||||
# Lint
|
# Lint
|
||||||
cargo clippy -- -Dwarnings
|
just clippy "-- -D warnings"
|
||||||
|
|
||||||
# Format
|
# Format (dprint: Markdown, TOML, YAML, and Rust via nightly rustfmt)
|
||||||
cargo fmt --all -- --check # check only
|
just fmt_check # check only
|
||||||
cargo fmt --all # fix
|
just fmt # fix
|
||||||
|
|
||||||
|
# All code checks at once (fmt_check, clippy -D warnings, doc, deny, install script lint)
|
||||||
|
just check_code
|
||||||
```
|
```
|
||||||
|
|
||||||
### System Dependencies (for building)
|
### System Dependencies (for building)
|
||||||
@@ -67,7 +70,7 @@ main.rs → parse CLI args → ActivityManager::new() → ActivityManager::run()
|
|||||||
### Key Modules
|
### Key Modules
|
||||||
|
|
||||||
| Module | Path | Purpose |
|
| Module | Path | Purpose |
|
||||||
|--------|------|---------|
|
| -------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||||
| **activity_manager** | `src/activity_manager.rs` | Orchestrates activity lifecycle and transitions |
|
| **activity_manager** | `src/activity_manager.rs` | Orchestrates activity lifecycle and transitions |
|
||||||
| **ui/activities** | `src/ui/activities/{auth,filetransfer,setup}/` | Three main screens, each implementing the `Activity` trait |
|
| **ui/activities** | `src/ui/activities/{auth,filetransfer,setup}/` | Three main screens, each implementing the `Activity` trait |
|
||||||
| **ui/context** | `src/ui/context.rs` | Shared `Context` struct (terminal, config, bookmarks, theme) |
|
| **ui/context** | `src/ui/context.rs` | Shared `Context` struct (terminal, config, bookmarks, theme) |
|
||||||
@@ -86,6 +89,7 @@ main.rs → parse CLI args → ActivityManager::new() → ActivityManager::run()
|
|||||||
### Conditional Compilation
|
### Conditional Compilation
|
||||||
|
|
||||||
The `build.rs` defines cfg aliases via `cfg_aliases`:
|
The `build.rs` defines cfg aliases via `cfg_aliases`:
|
||||||
|
|
||||||
- `posix`, `macos`, `linux`, `win` — platform shortcuts
|
- `posix`, `macos`, `linux`, `win` — platform shortcuts
|
||||||
- `smb`, `smb_unix`, `smb_windows` — feature + platform combinations
|
- `smb`, `smb_unix`, `smb_windows` — feature + platform combinations
|
||||||
|
|
||||||
@@ -106,6 +110,7 @@ Platform-specific dependencies: SSH and FTP crates use different TLS backends on
|
|||||||
|
|
||||||
## Other conventions
|
## Other conventions
|
||||||
|
|
||||||
- Always run `cargo +nightly fmt --all` and `cargo clippy --no-default-features -- -Dwarnings` after modifying Rust code
|
- Always run `just fmt` and `just clippy "-- -D warnings"` after modifying Rust code
|
||||||
- Always put plans to `./.claude/plans/`
|
- Always put plans to `./.claude/plans/`
|
||||||
- When changing behavior that is documented under `docs/` (paths, config keys, commands, flags, etc.), update BOTH `docs/en-US/` and `docs/zh-CN/` to keep the translations in sync
|
- When changing behavior that is documented under `docs/` (paths, config keys, commands, flags, etc.), update BOTH `docs/en-US/` and `docs/zh-CN/` to keep the translations in sync
|
||||||
|
- All code must be cross-platform compatible (Windows, macOS, Linux) — avoid POSIX-only APIs, hardcoded path separators, or shell-specific behavior unless gated behind the `posix`/`win` cfg aliases
|
||||||
|
|||||||
+10
-10
@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
|
|||||||
Examples of behavior that contributes to a positive environment for our
|
Examples of behavior that contributes to a positive environment for our
|
||||||
community include:
|
community include:
|
||||||
|
|
||||||
* Demonstrating empathy and kindness toward other people
|
- Demonstrating empathy and kindness toward other people
|
||||||
* Being respectful of differing opinions, viewpoints, and experiences
|
- Being respectful of differing opinions, viewpoints, and experiences
|
||||||
* Giving and gracefully accepting constructive feedback
|
- Giving and gracefully accepting constructive feedback
|
||||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
and learning from the experience
|
and learning from the experience
|
||||||
* Focusing on what is best not just for us as individuals, but for the overall
|
- Focusing on what is best not just for us as individuals, but for the overall
|
||||||
community
|
community
|
||||||
|
|
||||||
Examples of unacceptable behavior include:
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery, and sexual attention or advances of
|
- The use of sexualized language or imagery, and sexual attention or advances of
|
||||||
any kind
|
any kind
|
||||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
- Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or email address,
|
- Publishing others' private information, such as a physical or email address,
|
||||||
without their explicit permission
|
without their explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
- Other conduct which could reasonably be considered inappropriate in a
|
||||||
professional setting
|
professional setting
|
||||||
|
|
||||||
## Enforcement Responsibilities
|
## Enforcement Responsibilities
|
||||||
|
|||||||
+1
-1
@@ -150,5 +150,5 @@ You can view the developer guide [here](https://docs.termscp.rs/en-US/developer/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Thank you for any contribution!
|
Thank you for any contribution!\
|
||||||
Christian Visintin
|
Christian Visintin
|
||||||
|
|||||||
Generated
+35
-35
@@ -514,7 +514,7 @@ dependencies = [
|
|||||||
"aws-smithy-runtime-api",
|
"aws-smithy-runtime-api",
|
||||||
"aws-smithy-types",
|
"aws-smithy-types",
|
||||||
"h2 0.3.27",
|
"h2 0.3.27",
|
||||||
"h2 0.4.14",
|
"h2 0.4.19",
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"http 1.4.2",
|
"http 1.4.2",
|
||||||
"http-body 0.4.6",
|
"http-body 0.4.6",
|
||||||
@@ -924,9 +924,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chacha20"
|
name = "chacha20"
|
||||||
version = "0.10.0"
|
version = "0.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
|
checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cipher 0.5.2",
|
"cipher 0.5.2",
|
||||||
@@ -1117,7 +1117,7 @@ dependencies = [
|
|||||||
"crc",
|
"crc",
|
||||||
"digest 0.10.7",
|
"digest 0.10.7",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"spin 0.10.0",
|
"spin 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1147,9 +1147,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-epoch"
|
name = "crossbeam-epoch"
|
||||||
version = "0.9.18"
|
version = "0.9.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
@@ -1213,9 +1213,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-bigint"
|
name = "crypto-bigint"
|
||||||
version = "0.7.3"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42a0d26b245348befa0c121944541476763dcc46ede886c88f9d12e1697d27c3"
|
checksum = "1a52aa3fcda4e6302a9f48734f234d35d4721b96f8fe07d073f07ce9df4f0271"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cpubits",
|
"cpubits",
|
||||||
"ctutils",
|
"ctutils",
|
||||||
@@ -1256,7 +1256,7 @@ version = "0.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21f41f23de7d24cdbda7f0c4d9c0351f99a4ceb258ef30e5c1927af8987ffe5a"
|
checksum = "21f41f23de7d24cdbda7f0c4d9c0351f99a4ceb258ef30e5c1927af8987ffe5a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crypto-bigint 0.7.3",
|
"crypto-bigint 0.7.5",
|
||||||
"libm",
|
"libm",
|
||||||
"rand_core 0.10.1",
|
"rand_core 0.10.1",
|
||||||
]
|
]
|
||||||
@@ -1568,7 +1568,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users",
|
"redox_users",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1770,7 +1770,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "102d3643d30dd8b559613c5cced68317199597fffb278cdc88daa2ef7fafc935"
|
checksum = "102d3643d30dd8b559613c5cced68317199597fffb278cdc88daa2ef7fafc935"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base16ct 1.0.0",
|
"base16ct 1.0.0",
|
||||||
"crypto-bigint 0.7.3",
|
"crypto-bigint 0.7.5",
|
||||||
"crypto-common 0.2.2",
|
"crypto-common 0.2.2",
|
||||||
"digest 0.11.3",
|
"digest 0.11.3",
|
||||||
"ff 0.14.0",
|
"ff 0.14.0",
|
||||||
@@ -1826,7 +1826,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2238,9 +2238,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.14"
|
version = "0.4.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733"
|
checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -2492,7 +2492,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"h2 0.4.14",
|
"h2 0.4.19",
|
||||||
"http 1.4.2",
|
"http 1.4.2",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"httparse",
|
"httparse",
|
||||||
@@ -2599,7 +2599,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2 0.6.4",
|
"socket2 0.5.10",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -3088,7 +3088,7 @@ version = "1.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"spin 0.9.8",
|
"spin 0.9.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4269,7 +4269,7 @@ version = "0.14.0-rc.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f845ec3240cd5ed5e1e31cf3ff633a5bf47c698dc4092ba9e767415b3d393406"
|
checksum = "f845ec3240cd5ed5e1e31cf3ff633a5bf47c698dc4092ba9e767415b3d393406"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crypto-bigint 0.7.3",
|
"crypto-bigint 0.7.5",
|
||||||
"crypto-common 0.2.2",
|
"crypto-common 0.2.2",
|
||||||
"ff 0.14.0",
|
"ff 0.14.0",
|
||||||
"rand_core 0.10.1",
|
"rand_core 0.10.1",
|
||||||
@@ -4335,7 +4335,7 @@ dependencies = [
|
|||||||
"quinn-udp",
|
"quinn-udp",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustls 0.23.40",
|
"rustls 0.23.40",
|
||||||
"socket2 0.6.4",
|
"socket2 0.5.10",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -4372,7 +4372,7 @@ dependencies = [
|
|||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"socket2 0.6.4",
|
"socket2 0.5.10",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
@@ -4425,7 +4425,7 @@ version = "0.10.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
|
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chacha20 0.10.0",
|
"chacha20 0.10.2",
|
||||||
"getrandom 0.4.2",
|
"getrandom 0.4.2",
|
||||||
"rand_core 0.10.1",
|
"rand_core 0.10.1",
|
||||||
]
|
]
|
||||||
@@ -4781,7 +4781,7 @@ dependencies = [
|
|||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2 0.4.14",
|
"h2 0.4.19",
|
||||||
"http 1.4.2",
|
"http 1.4.2",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
@@ -4895,7 +4895,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "30b2aa4ba0d89f73d1e332df05be0eeab8840351c36ca5654341dfdb57bb3caf"
|
checksum = "30b2aa4ba0d89f73d1e332df05be0eeab8840351c36ca5654341dfdb57bb3caf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-oid 0.10.2",
|
"const-oid 0.10.2",
|
||||||
"crypto-bigint 0.7.3",
|
"crypto-bigint 0.7.5",
|
||||||
"crypto-primes",
|
"crypto-primes",
|
||||||
"digest 0.11.3",
|
"digest 0.11.3",
|
||||||
"pkcs1 0.8.0-rc.4",
|
"pkcs1 0.8.0-rc.4",
|
||||||
@@ -4931,7 +4931,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"cbc 0.2.1",
|
"cbc 0.2.1",
|
||||||
"cipher 0.5.2",
|
"cipher 0.5.2",
|
||||||
"crypto-bigint 0.7.3",
|
"crypto-bigint 0.7.5",
|
||||||
"ctr 0.10.1",
|
"ctr 0.10.1",
|
||||||
"curve25519-dalek 5.0.0-rc.0",
|
"curve25519-dalek 5.0.0-rc.0",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
@@ -5150,7 +5150,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.12.1",
|
"linux-raw-sys 0.12.1",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5796,20 +5796,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.9.8"
|
version = "0.9.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.10.0"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
|
checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spki"
|
name = "spki"
|
||||||
@@ -5868,7 +5868,7 @@ dependencies = [
|
|||||||
"aes 0.9.1",
|
"aes 0.9.1",
|
||||||
"aes-gcm 0.11.0-rc.4",
|
"aes-gcm 0.11.0-rc.4",
|
||||||
"cbc 0.2.1",
|
"cbc 0.2.1",
|
||||||
"chacha20 0.10.0",
|
"chacha20 0.10.2",
|
||||||
"cipher 0.5.2",
|
"cipher 0.5.2",
|
||||||
"ctr 0.10.1",
|
"ctr 0.10.1",
|
||||||
"ctutils",
|
"ctutils",
|
||||||
@@ -5898,7 +5898,7 @@ checksum = "7abf34aa716da5d5b4c496936d042ea282ab392092cd68a72ef6a8863ff8c96a"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base64ct",
|
"base64ct",
|
||||||
"bytes",
|
"bytes",
|
||||||
"crypto-bigint 0.7.3",
|
"crypto-bigint 0.7.5",
|
||||||
"ctutils",
|
"ctutils",
|
||||||
"digest 0.11.3",
|
"digest 0.11.3",
|
||||||
"pem-rfc7468 1.0.0",
|
"pem-rfc7468 1.0.0",
|
||||||
@@ -6117,10 +6117,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.4.2",
|
"getrandom 0.3.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.1.4",
|
"rustix 1.1.4",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7031,7 +7031,7 @@ version = "0.1.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
+9
-23
@@ -1,17 +1,17 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "termscp"
|
name = "termscp"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
edition = "2024"
|
|
||||||
authors = ["Christian Visintin <christian.visintin@veeso.dev>"]
|
authors = ["Christian Visintin <christian.visintin@veeso.dev>"]
|
||||||
description = "termscp is a feature rich terminal file transfer and explorer with support for SCP/SFTP/FTP/Kube/S3/WebDAV"
|
|
||||||
license = "MIT"
|
|
||||||
repository = "https://github.com/veeso/termscp"
|
|
||||||
categories = ["command-line-utilities"]
|
categories = ["command-line-utilities"]
|
||||||
|
edition = "2024"
|
||||||
homepage = "https://termscp.rs"
|
homepage = "https://termscp.rs"
|
||||||
include = ["/src/**/*", "/build.rs", "/LICENSE", "/README.md", "/CHANGELOG.md"]
|
include = ["/src/**/*", "/build.rs", "/LICENSE", "/README.md", "/CHANGELOG.md"]
|
||||||
keywords = ["terminal", "ftp", "scp", "sftp", "tui"]
|
keywords = ["terminal", "ftp", "scp", "sftp", "tui"]
|
||||||
|
license = "MIT"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
rust-version = "1.89.0"
|
repository = "https://github.com/veeso/termscp"
|
||||||
|
rust-version = "1.98.0"
|
||||||
|
description = "termscp is a feature rich terminal file transfer and explorer with support for SCP/SFTP/FTP/Kube/S3/WebDAV"
|
||||||
|
|
||||||
[package.metadata.rpm]
|
[package.metadata.rpm]
|
||||||
package = "termscp"
|
package = "termscp"
|
||||||
@@ -62,18 +62,10 @@ remotefs = "0.3"
|
|||||||
remotefs-aws-s3 = "0.4"
|
remotefs-aws-s3 = "0.4"
|
||||||
remotefs-kube = "0.4"
|
remotefs-kube = "0.4"
|
||||||
remotefs-smb = { version = "0.3", optional = true }
|
remotefs-smb = { version = "0.3", optional = true }
|
||||||
remotefs-ssh = { version = "0.8", default-features = false, features = [
|
remotefs-ssh = { version = "0.8", default-features = false, features = ["russh"] }
|
||||||
"russh",
|
|
||||||
] }
|
|
||||||
remotefs-webdav = "0.2"
|
remotefs-webdav = "0.2"
|
||||||
rpassword = "7"
|
rpassword = "7"
|
||||||
self_update = { version = "0.42", default-features = false, features = [
|
self_update = { version = "0.42", default-features = false, features = ["archive-tar", "archive-zip", "compression-flate2", "compression-zip-deflate", "rustls"] }
|
||||||
"archive-tar",
|
|
||||||
"archive-zip",
|
|
||||||
"compression-flate2",
|
|
||||||
"compression-zip-deflate",
|
|
||||||
"rustls",
|
|
||||||
] }
|
|
||||||
semver = "1"
|
semver = "1"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
shellexpand = "3"
|
shellexpand = "3"
|
||||||
@@ -91,16 +83,10 @@ whoami = "2"
|
|||||||
wildmatch = "2"
|
wildmatch = "2"
|
||||||
|
|
||||||
[target."cfg(any(target_os = \"linux\", target_os = \"freebsd\"))".dependencies]
|
[target."cfg(any(target_os = \"linux\", target_os = \"freebsd\"))".dependencies]
|
||||||
dbus-secret-service-keyring-store = { version = "1", features = [
|
dbus-secret-service-keyring-store = { version = "1", features = ["crypto-rust", "vendored"] }
|
||||||
"crypto-rust",
|
|
||||||
"vendored",
|
|
||||||
] }
|
|
||||||
|
|
||||||
[target."cfg(target_family = \"unix\")".dependencies]
|
[target."cfg(target_family = \"unix\")".dependencies]
|
||||||
remotefs-ftp = { version = "0.4", features = [
|
remotefs-ftp = { version = "0.4", features = ["native-tls", "native-tls-vendored"] }
|
||||||
"native-tls",
|
|
||||||
"native-tls-vendored",
|
|
||||||
] }
|
|
||||||
uzers = "0.12"
|
uzers = "0.12"
|
||||||
|
|
||||||
[target."cfg(target_family = \"windows\")".dependencies]
|
[target."cfg(target_family = \"windows\")".dependencies]
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import "./just/build.just"
|
||||||
|
import "./just/changelog.just"
|
||||||
|
import "./just/code_check.just"
|
||||||
|
import "./just/publish.just"
|
||||||
|
import "./just/site.just"
|
||||||
|
import "./just/test.just"
|
||||||
|
|
||||||
|
# Lists all the available commands
|
||||||
|
default:
|
||||||
|
@just --list
|
||||||
@@ -75,7 +75,7 @@ Termscp is a feature rich terminal file transfer and explorer, with support for
|
|||||||
|
|
||||||
## Get started 🚀
|
## Get started 🚀
|
||||||
|
|
||||||
If you're considering to install termscp I want to thank you 💜 ! I hope you will enjoy termscp!
|
If you're considering to install termscp I want to thank you 💜 ! I hope you will enjoy termscp!\
|
||||||
If you want to contribute to this project, don't forget to check out our [contribute guide](CONTRIBUTING.md).
|
If you want to contribute to this project, don't forget to check out our [contribute guide](CONTRIBUTING.md).
|
||||||
|
|
||||||
If you are a Linux, a FreeBSD or a MacOS user this simple shell script will install termscp on your system with a single command:
|
If you are a Linux, a FreeBSD or a MacOS user this simple shell script will install termscp on your system with a single command:
|
||||||
@@ -131,10 +131,10 @@ These requirements are not forced required to run termscp, but to enjoy all of i
|
|||||||
|
|
||||||
- **Linux/FreeBSD** users:
|
- **Linux/FreeBSD** users:
|
||||||
- To **open** files via `V` (at least one of these)
|
- To **open** files via `V` (at least one of these)
|
||||||
- *xdg-open*
|
- _xdg-open_
|
||||||
- *gio*
|
- _gio_
|
||||||
- *gnome-open*
|
- _gnome-open_
|
||||||
- *kde-open*
|
- _kde-open_
|
||||||
- **Linux** users:
|
- **Linux** users:
|
||||||
- A keyring manager: read more in the [User manual](https://docs.termscp.rs/en-US/configuration/password-security.html#linux-keyring)
|
- A keyring manager: read more in the [User manual](https://docs.termscp.rs/en-US/configuration/password-security.html#linux-keyring)
|
||||||
- **WSL** users
|
- **WSL** users
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
# cargo-deny configuration for termscp.
|
||||||
|
#
|
||||||
|
# Run locally with `just deny`. The same command runs in CI and enforces
|
||||||
|
# advisories, licenses, bans, and dependency sources.
|
||||||
|
#
|
||||||
|
# Docs: https://embarkstudios.github.io/cargo-deny/
|
||||||
|
|
||||||
|
[graph]
|
||||||
|
all-features = true
|
||||||
|
|
||||||
|
[output]
|
||||||
|
feature-depth = 1
|
||||||
|
|
||||||
|
[advisories]
|
||||||
|
db-urls = ["https://github.com/rustsec/advisory-db"]
|
||||||
|
yanked = "deny"
|
||||||
|
unmaintained = "all"
|
||||||
|
# These are temporary, reachable transitive-risk acceptances owned by the
|
||||||
|
# termscp maintainers. Review or remove every exception by 2026-12-31. The
|
||||||
|
# upgrade target is a remotefs/self_update release line that accepts each fixed
|
||||||
|
# dependency version; until then, connections to untrusted endpoints remain an
|
||||||
|
# acknowledged denial-of-service and certificate-validation risk.
|
||||||
|
ignore = [
|
||||||
|
# h2 0.3 is retained transitively by the reqwest 0.11/AWS HTTP stack; its
|
||||||
|
# dependency constraints cannot select the fixed h2 0.4 release.
|
||||||
|
{ id = "RUSTSEC-2026-0258", reason = "owner: termscp maintainers; review by 2026-12-31; upgrade reqwest/AWS stack to fixed h2" },
|
||||||
|
# number_prefix is retained by self_update through indicatif. It is
|
||||||
|
# unmaintained, but has no reported vulnerability or compatible replacement.
|
||||||
|
{ id = "RUSTSEC-2025-0119", reason = "owner: termscp maintainers; review by 2026-12-31; upgrade self_update/indicatif" },
|
||||||
|
# Both affected quick-xml lines are constrained by remotefs-webdav and
|
||||||
|
# self_update to versions older than the fixed 0.41 release.
|
||||||
|
{ id = "RUSTSEC-2026-0194", reason = "owner: termscp maintainers; review by 2026-12-31; upgrade remotefs-webdav/self_update to quick-xml >=0.41" },
|
||||||
|
{ id = "RUSTSEC-2026-0195", reason = "owner: termscp maintainers; review by 2026-12-31; upgrade remotefs-webdav/self_update to quick-xml >=0.41" },
|
||||||
|
# The SSH stack requires RSA, for which RustSec reports no safe upgrade.
|
||||||
|
{ id = "RUSTSEC-2023-0071", reason = "owner: termscp maintainers; review by 2026-12-31; replace RSA dependency when upstream fix exists" },
|
||||||
|
# russh-keys retains an older russh-cryptovec line and cannot select the
|
||||||
|
# fixed 0.60.3 release without an upstream dependency update.
|
||||||
|
{ id = "RUSTSEC-2026-0153", reason = "owner: termscp maintainers; review by 2026-12-31; upgrade remotefs-ssh/russh-keys to russh-cryptovec >=0.60.3" },
|
||||||
|
# rustls-pemfile is retained by the WebDAV and Kubernetes clients. Both
|
||||||
|
# versions are unmaintained but have no reported vulnerability.
|
||||||
|
{ id = "RUSTSEC-2025-0134", reason = "owner: termscp maintainers; review by 2026-12-31; upgrade WebDAV/Kubernetes clients away from rustls-pemfile" },
|
||||||
|
# The AWS HTTP stack retains rustls 0.21 and rustls-webpki 0.101, which cannot
|
||||||
|
# select the fixed rustls-webpki release.
|
||||||
|
{ id = "RUSTSEC-2026-0098", reason = "owner: termscp maintainers; review by 2026-12-31; upgrade AWS HTTP stack to fixed rustls-webpki" },
|
||||||
|
{ id = "RUSTSEC-2026-0099", reason = "owner: termscp maintainers; review by 2026-12-31; upgrade AWS HTTP stack to fixed rustls-webpki" },
|
||||||
|
{ id = "RUSTSEC-2026-0104", reason = "owner: termscp maintainers; review by 2026-12-31; upgrade AWS HTTP stack to fixed rustls-webpki" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[licenses]
|
||||||
|
allow = [
|
||||||
|
"Apache-2.0",
|
||||||
|
"BSD-1-Clause",
|
||||||
|
"BSD-2-Clause",
|
||||||
|
"BSD-3-Clause",
|
||||||
|
"BSL-1.0",
|
||||||
|
"CC0-1.0",
|
||||||
|
"CDLA-Permissive-2.0",
|
||||||
|
"ISC",
|
||||||
|
"MIT",
|
||||||
|
"MIT-0",
|
||||||
|
"MPL-2.0",
|
||||||
|
"Unicode-3.0",
|
||||||
|
"Unlicense",
|
||||||
|
"Zlib",
|
||||||
|
]
|
||||||
|
confidence-threshold = 0.8
|
||||||
|
exceptions = [
|
||||||
|
# The WebDAV backend currently depends on rustydav, which declares GPL-3.0.
|
||||||
|
# Keep this exception crate-scoped so no other GPL dependency is admitted.
|
||||||
|
{ allow = ["GPL-3.0"], crate = "rustydav" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[licenses.private]
|
||||||
|
ignore = false
|
||||||
|
|
||||||
|
[bans]
|
||||||
|
multiple-versions = "warn"
|
||||||
|
wildcards = "deny"
|
||||||
|
allow-wildcard-paths = true
|
||||||
|
highlight = "all"
|
||||||
|
workspace-default-features = "allow"
|
||||||
|
external-default-features = "allow"
|
||||||
|
allow = []
|
||||||
|
deny = []
|
||||||
|
skip = []
|
||||||
|
skip-tree = []
|
||||||
|
|
||||||
|
[sources]
|
||||||
|
unknown-registry = "deny"
|
||||||
|
unknown-git = "deny"
|
||||||
|
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
||||||
|
allow-git = []
|
||||||
Vendored
+4
@@ -4,6 +4,10 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
VERSION="${1:?usage: bump_version.sh <version> [date] [root]}"
|
VERSION="${1:?usage: bump_version.sh <version> [date] [root]}"
|
||||||
|
if [[ ! "$VERSION" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
|
||||||
|
echo "invalid release version: $VERSION (expected MAJOR.MINOR.PATCH)" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
DATE="${2:-$(date +%F)}"
|
DATE="${2:-$(date +%F)}"
|
||||||
ROOT="${3:-$(git rev-parse --show-toplevel)}"
|
ROOT="${3:-$(git rev-parse --show-toplevel)}"
|
||||||
|
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ works best from different frameworks:
|
|||||||
more, read <https://github.com/veeso/tui-realm>.
|
more, read <https://github.com/veeso/tui-realm>.
|
||||||
- **Components**: components are built around tui in order to reuse widgets. This
|
- **Components**: components are built around tui in order to reuse widgets. This
|
||||||
is achieved through the `Component` trait, inspired by
|
is achieved through the `Component` trait, inspired by
|
||||||
[React](https://reactjs.org/). Each component has its *Properties* and can have
|
[React](https://reactjs.org/). Each component has its _Properties_ and can have
|
||||||
its *States*. Each component must handle input events, accept new properties,
|
its _States_. Each component must handle input events, accept new properties,
|
||||||
and provide a method to **render** itself. This logic now lives in
|
and provide a method to **render** itself. This logic now lives in
|
||||||
[tui-realm](https://github.com/veeso/tui-realm).
|
[tui-realm](https://github.com/veeso/tui-realm).
|
||||||
- **Messages: an Elm-based approach**: input events are handled with an approach
|
- **Messages: an Elm-based approach**: input events are handled with an approach
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ termscp 是一个功能丰富的终端文件浏览和传输工具,支持 SCP/S
|
|||||||
|
|
||||||
## 开始 🚀
|
## 开始 🚀
|
||||||
|
|
||||||
如果您正在考虑安装 termscp,我想对您表示感谢 💜 ! 希望您会喜欢 termscp!
|
如果您正在考虑安装 termscp,我想对您表示感谢 💜 ! 希望您会喜欢 termscp!\
|
||||||
如果您想为此项目做出贡献,请不要忘记查看我们的[贡献指南](CONTRIBUTING.md)。
|
如果您想为此项目做出贡献,请不要忘记查看我们的[贡献指南](CONTRIBUTING.md)。
|
||||||
|
|
||||||
如果您是 Linux、FreeBSD 或 MacOS 用户,使用以下简单的 shell 脚本即可通过单行指令在您的系统上安装 termscp:
|
如果您是 Linux、FreeBSD 或 MacOS 用户,使用以下简单的 shell 脚本即可通过单行指令在您的系统上安装 termscp:
|
||||||
@@ -131,10 +131,10 @@ pacman -S termscp
|
|||||||
|
|
||||||
- **Linux/FreeBSD** 用户:
|
- **Linux/FreeBSD** 用户:
|
||||||
- 用 `V` **打开**文件(至少其中之一)
|
- 用 `V` **打开**文件(至少其中之一)
|
||||||
- *xdg-open*
|
- _xdg-open_
|
||||||
- *gio*
|
- _gio_
|
||||||
- *gnome-open*
|
- _gnome-open_
|
||||||
- *kde-open*
|
- _kde-open_
|
||||||
- **Linux** 用户:
|
- **Linux** 用户:
|
||||||
- 密钥环管理器:在[用户手册](https://docs.termscp.rs/zh-CN/configuration/password-security.html#linux-密钥环)中阅读更多内容
|
- 密钥环管理器:在[用户手册](https://docs.termscp.rs/zh-CN/configuration/password-security.html#linux-密钥环)中阅读更多内容
|
||||||
- **WSL** 用户
|
- **WSL** 用户
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ termscp [options]... -b [bookmark-name] -b [bookmark-name] [local-wrkdir]
|
|||||||
## 选项
|
## 选项
|
||||||
|
|
||||||
| Key | 说明 |
|
| Key | 说明 |
|
||||||
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
| -------------------- | ------------------------------------------------ |
|
||||||
| `-b <bookmark-name>` | 将位置地址参数解析为书签名称。重复使用该标志可以打开多个书签。 |
|
| `-b <bookmark-name>` | 将位置地址参数解析为书签名称。重复使用该标志可以打开多个书签。 |
|
||||||
| `-D` | 启用 `TRACE` 日志级别(调试/详细日志)。 |
|
| `-D` | 启用 `TRACE` 日志级别(调试/详细日志)。 |
|
||||||
| `-P <password>` | 从命令行提供密码。重复使用该标志可为多个远程主机提供密码;其顺序必须与地址参数一致。不推荐使用。 |
|
| `-P <password>` | 从命令行提供密码。重复使用该标志可为多个远程主机提供密码;其顺序必须与地址参数一致。不推荐使用。 |
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
以下是格式化器支持的键:
|
以下是格式化器支持的键:
|
||||||
|
|
||||||
| 键 | 说明 |
|
| 键 | 说明 |
|
||||||
| --------- | ------------------------------------------------------------------------------------------------ |
|
| --------- | --------------------------------------------------------------- |
|
||||||
| `ATIME` | 最后访问时间(默认 `%b %d %Y %H:%M`);`EXTRA` 为时间格式(例如 `{ATIME:8:%H:%M}`) |
|
| `ATIME` | 最后访问时间(默认 `%b %d %Y %H:%M`);`EXTRA` 为时间格式(例如 `{ATIME:8:%H:%M}`) |
|
||||||
| `CTIME` | 创建时间(默认 `%b %d %Y %H:%M`);`EXTRA` 为时间格式(例如 `{CTIME:8:%H:%M}`) |
|
| `CTIME` | 创建时间(默认 `%b %d %Y %H:%M`);`EXTRA` 为时间格式(例如 `{CTIME:8:%H:%M}`) |
|
||||||
| `GROUP` | 所属组 |
|
| `GROUP` | 所属组 |
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ termscp 接受以下颜色格式:
|
|||||||
### 认证页面
|
### 认证页面
|
||||||
|
|
||||||
| 键 | 说明 |
|
| 键 | 说明 |
|
||||||
| ---------------- | -------------------------- |
|
| ---------------- | ----------- |
|
||||||
| `auth_address` | IP 地址输入框的颜色 |
|
| `auth_address` | IP 地址输入框的颜色 |
|
||||||
| `auth_bookmarks` | 书签面板的颜色 |
|
| `auth_bookmarks` | 书签面板的颜色 |
|
||||||
| `auth_password` | 密码输入框的颜色 |
|
| `auth_password` | 密码输入框的颜色 |
|
||||||
@@ -67,7 +67,7 @@ termscp 接受以下颜色格式:
|
|||||||
### 传输页面
|
### 传输页面
|
||||||
|
|
||||||
| 键 | 说明 |
|
| 键 | 说明 |
|
||||||
| -------------------------------------- | -------------------------------------------------- |
|
| -------------------------------------- | ------------------------------- |
|
||||||
| `transfer_local_explorer_background` | 本地主机浏览器的背景色 |
|
| `transfer_local_explorer_background` | 本地主机浏览器的背景色 |
|
||||||
| `transfer_local_explorer_foreground` | 本地主机浏览器的前景色 |
|
| `transfer_local_explorer_foreground` | 本地主机浏览器的前景色 |
|
||||||
| `transfer_local_explorer_highlighted` | 本地主机浏览器的边框及高亮颜色 |
|
| `transfer_local_explorer_highlighted` | 本地主机浏览器的边框及高亮颜色 |
|
||||||
@@ -87,7 +87,7 @@ termscp 接受以下颜色格式:
|
|||||||
这些样式适用于应用程序的不同部分。
|
这些样式适用于应用程序的不同部分。
|
||||||
|
|
||||||
| 键 | 说明 |
|
| 键 | 说明 |
|
||||||
| ------------------- | -------------------------------- |
|
| ------------------- | ---------------- |
|
||||||
| `misc_error_dialog` | 错误消息的颜色 |
|
| `misc_error_dialog` | 错误消息的颜色 |
|
||||||
| `misc_info_dialog` | 信息对话框的颜色 |
|
| `misc_info_dialog` | 信息对话框的颜色 |
|
||||||
| `misc_input_dialog` | 输入对话框的颜色(例如复制文件) |
|
| `misc_input_dialog` | 输入对话框的颜色(例如复制文件) |
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ termscp 支持以下协议:SFTP、SCP、FTP/FTPS、Kube、S3、SMB 和 WebDAV
|
|||||||
|
|
||||||
- **顶层的 Activities**:每个“视图”都是一个 Activity,并由 `Activity Manager` 来处理它们。这种方法受 Android 启发。它适用于具有不同视图的 ui,每个视图都有自己的组件和逻辑。Activities 与 `Context` 协作,`Context` 是用于在 activities 之间共享数据的数据持有者。
|
- **顶层的 Activities**:每个“视图”都是一个 Activity,并由 `Activity Manager` 来处理它们。这种方法受 Android 启发。它适用于具有不同视图的 ui,每个视图都有自己的组件和逻辑。Activities 与 `Context` 协作,`Context` 是用于在 activities 之间共享数据的数据持有者。
|
||||||
- **Activities 显示 Applications**:每个 activity 可以显示不同的 **Applications**。一个 application 包含一个 **View**,它基本上是一个 **components** 列表,每个组件都有其属性。view 是组件的门面,同时也处理焦点,即当前处于活动状态的组件。你不能拥有多个活动组件,因此必须对此进行处理;与此同时,如果当前组件被销毁,焦点必须交还给之前处于活动状态的组件。**Application** 负责处理所有这些工作。要了解更多信息,请阅读 <https://github.com/veeso/tui-realm>。
|
- **Activities 显示 Applications**:每个 activity 可以显示不同的 **Applications**。一个 application 包含一个 **View**,它基本上是一个 **components** 列表,每个组件都有其属性。view 是组件的门面,同时也处理焦点,即当前处于活动状态的组件。你不能拥有多个活动组件,因此必须对此进行处理;与此同时,如果当前组件被销毁,焦点必须交还给之前处于活动状态的组件。**Application** 负责处理所有这些工作。要了解更多信息,请阅读 <https://github.com/veeso/tui-realm>。
|
||||||
- **Components**:components 是围绕 tui 构建的,以便复用控件。这是通过 `Component` trait 实现的,该 trait 受 [React](https://reactjs.org/) 启发。每个组件都有其 *Properties*,并且可以拥有其 *States*。每个组件必须处理输入事件、接受新的属性,并提供一个用于**渲染**自身的方法。这一逻辑现在位于 [tui-realm](https://github.com/veeso/tui-realm) 中。
|
- **Components**:components 是围绕 tui 构建的,以便复用控件。这是通过 `Component` trait 实现的,该 trait 受 [React](https://reactjs.org/) 启发。每个组件都有其 _Properties_,并且可以拥有其 _States_。每个组件必须处理输入事件、接受新的属性,并提供一个用于**渲染**自身的方法。这一逻辑现在位于 [tui-realm](https://github.com/veeso/tui-realm) 中。
|
||||||
- **Messages:基于 Elm 的方法**:输入事件采用受 [Elm](https://elm-lang.org/) 启发的方法来处理。在 Elm 中,你使用三个基本函数来实现 ui:**update**、**view** 和 **init**。termscp 将 Elm update 函数的等价实现编写为一个递归函数内部的大型 match 分支,你可以在每个 activity 的 `update.rs` 文件中找到它。这个 match 分支处理组件为响应传入的输入事件而产生的消息,并促使 activity 改变其状态。
|
- **Messages:基于 Elm 的方法**:输入事件采用受 [Elm](https://elm-lang.org/) 启发的方法来处理。在 Elm 中,你使用三个基本函数来实现 ui:**update**、**view** 和 **init**。termscp 将 Elm update 函数的等价实现编写为一个递归函数内部的大型 match 分支,你可以在每个 activity 的 `update.rs` 文件中找到它。这个 match 分支处理组件为响应传入的输入事件而产生的消息,并促使 activity 改变其状态。
|
||||||
|
|
||||||
termscp 实现了一个名为 `Activity` 的 trait,它是 Android activity 的一个大幅精简版本。该 trait 提供以下方法:
|
termscp 实现了一个名为 `Activity` 的 trait,它是 Android activity 的一个大幅精简版本。该 trait 提供以下方法:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
以下按键可在文件浏览器中使用。随时按 `<H|F1>` 可打开应用内帮助。
|
以下按键可在文件浏览器中使用。随时按 `<H|F1>` 可打开应用内帮助。
|
||||||
|
|
||||||
| 按键 | 操作 |
|
| 按键 | 操作 |
|
||||||
| -------------- | ---------------------------------------------------------------------- |
|
| -------------- | --------------------- |
|
||||||
| `<ESC>` | 断开与远程的连接并返回认证页面 |
|
| `<ESC>` | 断开与远程的连接并返回认证页面 |
|
||||||
| `<BACKSPACE>` | 返回导航栈中的上一个目录 |
|
| `<BACKSPACE>` | 返回导航栈中的上一个目录 |
|
||||||
| `<TAB>` | 切换当前活动的浏览器选项卡 |
|
| `<TAB>` | 切换当前活动的浏览器选项卡 |
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://dprint.dev/schemas/v0.json",
|
||||||
|
"indentWidth": 2,
|
||||||
|
"lineWidth": 80,
|
||||||
|
"newLineKind": "lf",
|
||||||
|
"markdown": {
|
||||||
|
"textWrap": "maintain"
|
||||||
|
},
|
||||||
|
"toml": {},
|
||||||
|
"yaml": {},
|
||||||
|
"exec": {
|
||||||
|
"cwd": "${configDir}",
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "rustup run nightly rustfmt --edition 2024",
|
||||||
|
"exts": ["rs"],
|
||||||
|
"cacheKeyFiles": ["rustfmt.toml", "rust-toolchain.toml"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"excludes": [
|
||||||
|
"**/target",
|
||||||
|
"**/node_modules",
|
||||||
|
"**/*-lock.json",
|
||||||
|
"Cargo.lock",
|
||||||
|
"docs/book",
|
||||||
|
"docs/zh-CN/cli/cli.md",
|
||||||
|
"docs/zh-CN/configuration/explorer-format.md",
|
||||||
|
"docs/zh-CN/configuration/themes.md",
|
||||||
|
"docs/zh-CN/usage/keyboard-shortcuts.md",
|
||||||
|
"**/tests/fixtures"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"https://plugins.dprint.dev/markdown-0.22.1.wasm@4906fbb038977732aae0e216e4b0b957e2722f8d79282660ccb36d27dd051f17",
|
||||||
|
"https://plugins.dprint.dev/toml-0.7.0.wasm@0126c8112691542d30b52a639076ecc83e07bace877638cee7c6915fd36b8629",
|
||||||
|
"https://plugins.dprint.dev/g-plane/pretty_yaml-v0.6.0.wasm@40a2fdda7040317eb1b23520f3a00769a5571eedb049c4ca9175c1b9eeba01ae",
|
||||||
|
"https://plugins.dprint.dev/dprint/exec-0.6.2.json@df98f54ffd3092b8a841aedd6d098a2651f16d0a796a40535774f1a8b4b9d463"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Build everything
|
||||||
|
[group('build')]
|
||||||
|
build_all: build_crates
|
||||||
|
|
||||||
|
# Build the Rust crate
|
||||||
|
[group('build')]
|
||||||
|
build_crates args="":
|
||||||
|
cargo build --workspace {{ args }}
|
||||||
|
|
||||||
|
# Build all Rust crates in release mode
|
||||||
|
[group('build')]
|
||||||
|
build_crates_release:
|
||||||
|
just build_crates "--release"
|
||||||
|
|
||||||
|
# Build a release binary for a target triple
|
||||||
|
[group('build')]
|
||||||
|
build_release target features="":
|
||||||
|
cargo build --locked --release --target {{ target }} {{ features }}
|
||||||
|
|
||||||
|
# Package an already-built Linux release as a Debian package
|
||||||
|
[group('build')]
|
||||||
|
package_deb target:
|
||||||
|
cargo deb --no-build --target {{ target }} --features smb-vendored
|
||||||
|
|
||||||
|
# Update Cargo.lock; pass cargo update arguments to scope the update.
|
||||||
|
[group('build')]
|
||||||
|
update_lock args="":
|
||||||
|
cargo update {{ args }}
|
||||||
|
|
||||||
|
# Clean build artifacts
|
||||||
|
[group('build')]
|
||||||
|
[confirm("Are you sure you want to clean the build artifacts?")]
|
||||||
|
clean:
|
||||||
|
cargo clean
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
set positional-arguments
|
||||||
|
|
||||||
|
# Print the unreleased changelog section to stdout (preview only), e.g. `just changelog_preview 8.1.0`
|
||||||
|
[group('changelog')]
|
||||||
|
changelog_preview version:
|
||||||
|
git-cliff --config cliff.toml --unreleased --tag "v$1" --strip all
|
||||||
|
|
||||||
|
# Add a new entry to CHANGELOG.md from the unreleased conventional commits, e.g. `just changelog 8.1.0`
|
||||||
|
[group('changelog')]
|
||||||
|
changelog version:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
version="$1"
|
||||||
|
if [[ ! "$version" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
|
||||||
|
echo "invalid release version: $version (expected MAJOR.MINOR.PATCH)" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
tag="v$version"
|
||||||
|
section="$(git-cliff --config cliff.toml --unreleased --tag "$tag" --strip all)"
|
||||||
|
if [ -z "$section" ]; then
|
||||||
|
echo "No unreleased conventional commits found; nothing to add." >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
anchor="$(printf '%s' "$version" | tr -d '.')"
|
||||||
|
secfile="$(mktemp)"
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
printf '%s\n' "$section" > "$secfile"
|
||||||
|
# Insert a TOC entry before the first existing version entry and the rendered
|
||||||
|
# section before the first existing version heading, keeping the title + TOC.
|
||||||
|
awk -v secfile="$secfile" -v ver="$version" -v anc="$anchor" '
|
||||||
|
!toc_done && /^[[:space:]]*- \[[0-9]/ {
|
||||||
|
print " - [" ver "](#" anc ")"
|
||||||
|
toc_done = 1
|
||||||
|
}
|
||||||
|
!body_done && /^## [0-9]/ {
|
||||||
|
while ((getline line < secfile) > 0) print line
|
||||||
|
print ""
|
||||||
|
body_done = 1
|
||||||
|
}
|
||||||
|
{ print }
|
||||||
|
' CHANGELOG.md > "$tmp"
|
||||||
|
rm -f "$secfile"
|
||||||
|
mv "$tmp" CHANGELOG.md
|
||||||
|
echo "CHANGELOG.md updated for $tag"
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
alias lint := clippy
|
||||||
|
|
||||||
|
# Format all sources (Markdown, TOML, YAML and Rust via nightly rustfmt) with dprint
|
||||||
|
[group('code_check')]
|
||||||
|
fmt args="":
|
||||||
|
dprint fmt {{ args }}
|
||||||
|
|
||||||
|
# Check formatting of all sources with dprint (no writes)
|
||||||
|
[group('code_check')]
|
||||||
|
fmt_check args="":
|
||||||
|
dprint check {{ args }}
|
||||||
|
|
||||||
|
# Run clippy on all targets
|
||||||
|
[group('code_check')]
|
||||||
|
clippy args="":
|
||||||
|
cargo clippy --workspace --all-targets {{ args }}
|
||||||
|
|
||||||
|
# Build the crate documentation, denying warnings
|
||||||
|
[group('code_check')]
|
||||||
|
doc args="":
|
||||||
|
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps {{ args }}
|
||||||
|
|
||||||
|
# Check dependencies for advisories, licenses, bans and sources (cargo-deny)
|
||||||
|
[group('code_check')]
|
||||||
|
deny args="":
|
||||||
|
cargo deny check {{ args }}
|
||||||
|
|
||||||
|
# Scan for secrets with trufflehog (defaults to the whole working tree)
|
||||||
|
[group('code_check')]
|
||||||
|
scan_secrets *args=".":
|
||||||
|
trufflehog filesystem {{ args }} --results=verified,unknown --fail --no-update
|
||||||
|
|
||||||
|
# Point git at the tracked .githooks directory (installs the pre-commit hook)
|
||||||
|
[group('code_check')]
|
||||||
|
setup_githooks:
|
||||||
|
git config core.hooksPath .githooks
|
||||||
|
@echo "git hooks installed: core.hooksPath = .githooks"
|
||||||
|
|
||||||
|
# Lint the install scripts (shellcheck; PowerShell parse when pwsh is available)
|
||||||
|
[group('code_check')]
|
||||||
|
check_install_scripts:
|
||||||
|
sh -n install.sh
|
||||||
|
shellcheck install.sh
|
||||||
|
@if command -v pwsh >/dev/null 2>&1; then \
|
||||||
|
pwsh -NoProfile -Command '$t = $null; $e = $null; $null = [System.Management.Automation.Language.Parser]::ParseFile("install.ps1", [ref]$t, [ref]$e); if ($e) { $e; exit 1 }'; \
|
||||||
|
else \
|
||||||
|
echo "pwsh not found: skipping install.ps1 parse check"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run all code checks. Fails if any check fails
|
||||||
|
[group('code_check')]
|
||||||
|
check_code:
|
||||||
|
just fmt_check
|
||||||
|
just clippy "-- -D warnings"
|
||||||
|
just doc
|
||||||
|
just deny
|
||||||
|
just check_install_scripts
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Publish the termscp crate
|
||||||
|
[group('publish')]
|
||||||
|
publish_crate args="":
|
||||||
|
cargo publish --locked --features smb-vendored {{ args }}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Install website dependencies from the lockfile
|
||||||
|
[group('site')]
|
||||||
|
site_install:
|
||||||
|
cd site && npm ci
|
||||||
|
|
||||||
|
# Check website formatting
|
||||||
|
[group('site')]
|
||||||
|
site_fmt_check:
|
||||||
|
cd site && npm run format:check
|
||||||
|
|
||||||
|
# Run Astro and TypeScript checks
|
||||||
|
[group('site')]
|
||||||
|
site_check:
|
||||||
|
cd site && npm run check
|
||||||
|
|
||||||
|
# Run website tests when the package defines them
|
||||||
|
[group('site')]
|
||||||
|
site_test:
|
||||||
|
cd site && npm test --if-present
|
||||||
|
|
||||||
|
# Build the website
|
||||||
|
[group('site')]
|
||||||
|
site_build:
|
||||||
|
cd site && npm run build
|
||||||
|
|
||||||
|
# Run every website validation step
|
||||||
|
[group('site')]
|
||||||
|
site_ci: site_fmt_check site_check site_test site_build
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Run all tests
|
||||||
|
[group('test')]
|
||||||
|
test_all: test
|
||||||
|
|
||||||
|
# Run the Rust test suite
|
||||||
|
[group('test')]
|
||||||
|
test args="":
|
||||||
|
cargo test --workspace {{ args }}
|
||||||
|
|
||||||
|
# Generate an LCOV code coverage report for the Rust workspace (requires cargo-llvm-cov)
|
||||||
|
[group('test')]
|
||||||
|
coverage output="lcov.info":
|
||||||
|
cargo llvm-cov --workspace --lcov --output-path {{ output }}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "1.98.0"
|
||||||
|
components = ["clippy", "rustfmt"]
|
||||||
@@ -200,7 +200,7 @@ mod tests {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
PathBuf::from("/home/omar/.ssh/beaglebone.key")
|
PathBuf::from("/home/omar/.ssh/beaglebone.key")
|
||||||
);
|
);
|
||||||
assert!(cfg.remote.ssh_keys.get(&String::from("1.1.1.1")).is_none());
|
assert!(!cfg.remote.ssh_keys.contains_key("1.1.1.1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -240,7 +240,7 @@ mod tests {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
PathBuf::from("/home/omar/.ssh/beaglebone.key")
|
PathBuf::from("/home/omar/.ssh/beaglebone.key")
|
||||||
);
|
);
|
||||||
assert!(cfg.remote.ssh_keys.get(&String::from("1.1.1.1")).is_none());
|
assert!(!cfg.remote.ssh_keys.contains_key("1.1.1.1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
+8
-8
@@ -401,7 +401,7 @@ mod tests {
|
|||||||
assert_eq!(explorer.dirstack.len(), 2);
|
assert_eq!(explorer.dirstack.len(), 2);
|
||||||
assert_eq!(*explorer.dirstack.get(1).unwrap(), PathBuf::from("/dev"));
|
assert_eq!(*explorer.dirstack.get(1).unwrap(), PathBuf::from("/dev"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*explorer.dirstack.get(0).unwrap(),
|
*explorer.dirstack.front().unwrap(),
|
||||||
PathBuf::from("/home/omar")
|
PathBuf::from("/home/omar")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -425,7 +425,7 @@ mod tests {
|
|||||||
assert!(explorer.get(100).is_none());
|
assert!(explorer.get(100).is_none());
|
||||||
//assert_eq!(explorer.count(), 6);
|
//assert_eq!(explorer.count(), 6);
|
||||||
// Verify (files are sorted by name)
|
// Verify (files are sorted by name)
|
||||||
assert_eq!(explorer.files.get(0).unwrap().name(), ".git");
|
assert_eq!(explorer.files.first().unwrap().name(), ".git");
|
||||||
// Iter files (all)
|
// Iter files (all)
|
||||||
assert_eq!(explorer.iter_files_all().count(), 6);
|
assert_eq!(explorer.iter_files_all().count(), 6);
|
||||||
// Iter files (hidden excluded) (.git, .gitignore are hidden)
|
// Iter files (hidden excluded) (.git, .gitignore are hidden)
|
||||||
@@ -453,7 +453,7 @@ mod tests {
|
|||||||
]);
|
]);
|
||||||
explorer.sort_by(FileSorting::Name);
|
explorer.sort_by(FileSorting::Name);
|
||||||
// First entry should be "Cargo.lock"
|
// First entry should be "Cargo.lock"
|
||||||
assert_eq!(explorer.files.get(0).unwrap().name(), "Cargo.lock");
|
assert_eq!(explorer.files.first().unwrap().name(), "Cargo.lock");
|
||||||
// Last should be "src"
|
// Last should be "src"
|
||||||
assert_eq!(explorer.files.get(8).unwrap().name(), "src");
|
assert_eq!(explorer.files.get(8).unwrap().name(), "src");
|
||||||
}
|
}
|
||||||
@@ -469,7 +469,7 @@ mod tests {
|
|||||||
explorer.set_files(vec![entry1, entry2]);
|
explorer.set_files(vec![entry1, entry2]);
|
||||||
explorer.sort_by(FileSorting::ModifyTime);
|
explorer.sort_by(FileSorting::ModifyTime);
|
||||||
// First entry should be "CODE_OF_CONDUCT.md"
|
// First entry should be "CODE_OF_CONDUCT.md"
|
||||||
assert_eq!(explorer.files.get(0).unwrap().name(), "CODE_OF_CONDUCT.md");
|
assert_eq!(explorer.files.first().unwrap().name(), "CODE_OF_CONDUCT.md");
|
||||||
// Last should be "src"
|
// Last should be "src"
|
||||||
assert_eq!(explorer.files.get(1).unwrap().name(), "README.md");
|
assert_eq!(explorer.files.get(1).unwrap().name(), "README.md");
|
||||||
}
|
}
|
||||||
@@ -485,7 +485,7 @@ mod tests {
|
|||||||
explorer.set_files(vec![entry1, entry2]);
|
explorer.set_files(vec![entry1, entry2]);
|
||||||
explorer.sort_by(FileSorting::CreationTime);
|
explorer.sort_by(FileSorting::CreationTime);
|
||||||
// First entry should be "CODE_OF_CONDUCT.md"
|
// First entry should be "CODE_OF_CONDUCT.md"
|
||||||
assert_eq!(explorer.files.get(0).unwrap().name(), "CODE_OF_CONDUCT.md");
|
assert_eq!(explorer.files.first().unwrap().name(), "CODE_OF_CONDUCT.md");
|
||||||
// Last should be "src"
|
// Last should be "src"
|
||||||
assert_eq!(explorer.files.get(1).unwrap().name(), "README.md");
|
assert_eq!(explorer.files.get(1).unwrap().name(), "README.md");
|
||||||
}
|
}
|
||||||
@@ -501,7 +501,7 @@ mod tests {
|
|||||||
]);
|
]);
|
||||||
explorer.sort_by(FileSorting::Size);
|
explorer.sort_by(FileSorting::Size);
|
||||||
// Directory has size 4096
|
// Directory has size 4096
|
||||||
assert_eq!(explorer.files.get(0).unwrap().name(), "src");
|
assert_eq!(explorer.files.first().unwrap().name(), "src");
|
||||||
assert_eq!(explorer.files.get(1).unwrap().name(), "README.md");
|
assert_eq!(explorer.files.get(1).unwrap().name(), "README.md");
|
||||||
assert_eq!(explorer.files.get(2).unwrap().name(), "CONTRIBUTING.md");
|
assert_eq!(explorer.files.get(2).unwrap().name(), "CONTRIBUTING.md");
|
||||||
}
|
}
|
||||||
@@ -525,7 +525,7 @@ mod tests {
|
|||||||
explorer.sort_by(FileSorting::Name);
|
explorer.sort_by(FileSorting::Name);
|
||||||
explorer.group_dirs_by(Some(GroupDirs::First));
|
explorer.group_dirs_by(Some(GroupDirs::First));
|
||||||
// First entry should be "docs"
|
// First entry should be "docs"
|
||||||
assert_eq!(explorer.files.get(0).unwrap().name(), "docs");
|
assert_eq!(explorer.files.first().unwrap().name(), "docs");
|
||||||
assert_eq!(explorer.files.get(1).unwrap().name(), "src");
|
assert_eq!(explorer.files.get(1).unwrap().name(), "src");
|
||||||
// 3rd is file first for alphabetical order
|
// 3rd is file first for alphabetical order
|
||||||
assert_eq!(explorer.files.get(2).unwrap().name(), "Cargo.lock");
|
assert_eq!(explorer.files.get(2).unwrap().name(), "Cargo.lock");
|
||||||
@@ -555,7 +555,7 @@ mod tests {
|
|||||||
assert_eq!(explorer.files.get(8).unwrap().name(), "docs");
|
assert_eq!(explorer.files.get(8).unwrap().name(), "docs");
|
||||||
assert_eq!(explorer.files.get(9).unwrap().name(), "src");
|
assert_eq!(explorer.files.get(9).unwrap().name(), "src");
|
||||||
// first is file for alphabetical order
|
// first is file for alphabetical order
|
||||||
assert_eq!(explorer.files.get(0).unwrap().name(), "Cargo.lock");
|
assert_eq!(explorer.files.first().unwrap().name(), "Cargo.lock");
|
||||||
// Last in files should be "README.md" (last file for alphabetical ordening)
|
// Last in files should be "README.md" (last file for alphabetical ordening)
|
||||||
assert_eq!(explorer.files.get(7).unwrap().name(), "README.md");
|
assert_eq!(explorer.files.get(7).unwrap().name(), "README.md");
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-15
@@ -602,9 +602,11 @@ mod tests {
|
|||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::utils::test_helpers::create_sample_file;
|
||||||
|
#[cfg(posix)]
|
||||||
|
use crate::utils::test_helpers::make_file_at;
|
||||||
#[cfg(posix)]
|
#[cfg(posix)]
|
||||||
use crate::utils::test_helpers::make_fsentry;
|
use crate::utils::test_helpers::make_fsentry;
|
||||||
use crate::utils::test_helpers::{create_sample_file, make_file_at};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_host_error_new() {
|
fn test_host_error_new() {
|
||||||
@@ -632,13 +634,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[cfg(win)]
|
#[cfg(win)]
|
||||||
fn test_host_localhost_new() {
|
fn test_host_localhost_new() {
|
||||||
let mut host: Localhost = Localhost::new(PathBuf::from("C:\\users")).ok().unwrap();
|
let host: Localhost = Localhost::new(PathBuf::from("C:\\users")).ok().unwrap();
|
||||||
assert_eq!(host.wrkdir, PathBuf::from("C:\\users"));
|
assert_eq!(host.wrkdir, PathBuf::from("C:\\users"));
|
||||||
// Scan dir
|
// Scan dir
|
||||||
let entries = std::fs::read_dir(PathBuf::from("C:\\users").as_path()).unwrap();
|
let entries = std::fs::read_dir(PathBuf::from("C:\\users").as_path()).unwrap();
|
||||||
let mut counter: usize = 0;
|
let mut counter: usize = 0;
|
||||||
for _ in entries {
|
for _ in entries {
|
||||||
counter = counter + 1;
|
counter += 1;
|
||||||
}
|
}
|
||||||
assert_eq!(host.files.len(), counter);
|
assert_eq!(host.files.len(), counter);
|
||||||
}
|
}
|
||||||
@@ -769,7 +771,7 @@ mod tests {
|
|||||||
let host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
let host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
||||||
let files: Vec<File> = host.files.clone();
|
let files: Vec<File> = host.files.clone();
|
||||||
// Verify files
|
// Verify files
|
||||||
let file_0: &File = files.get(0).unwrap();
|
let file_0: &File = files.first().unwrap();
|
||||||
if file_0.name() == *"foo.txt" {
|
if file_0.name() == *"foo.txt" {
|
||||||
assert!(file_0.metadata.symlink.is_none());
|
assert!(file_0.metadata.symlink.is_none());
|
||||||
} else {
|
} else {
|
||||||
@@ -827,7 +829,7 @@ mod tests {
|
|||||||
let files: Vec<File> = host.files.clone();
|
let files: Vec<File> = host.files.clone();
|
||||||
assert_eq!(files.len(), 1); // There should be 1 file now
|
assert_eq!(files.len(), 1); // There should be 1 file now
|
||||||
// Remove file
|
// Remove file
|
||||||
assert!(host.remove(files.get(0).unwrap()).is_ok());
|
assert!(host.remove(files.first().unwrap()).is_ok());
|
||||||
// There should be 0 files now
|
// There should be 0 files now
|
||||||
let files: Vec<File> = host.files.clone();
|
let files: Vec<File> = host.files.clone();
|
||||||
assert_eq!(files.len(), 0); // There should be 0 files now
|
assert_eq!(files.len(), 0); // There should be 0 files now
|
||||||
@@ -836,7 +838,7 @@ mod tests {
|
|||||||
// Delete directory
|
// Delete directory
|
||||||
let files: Vec<File> = host.files.clone();
|
let files: Vec<File> = host.files.clone();
|
||||||
assert_eq!(files.len(), 1); // There should be 1 file now
|
assert_eq!(files.len(), 1); // There should be 1 file now
|
||||||
assert!(host.remove(files.get(0).unwrap()).is_ok());
|
assert!(host.remove(files.first().unwrap()).is_ok());
|
||||||
// Remove unexisting directory
|
// Remove unexisting directory
|
||||||
assert!(
|
assert!(
|
||||||
host.remove(&make_fsentry(PathBuf::from("/a/b/c/d"), true))
|
host.remove(&make_fsentry(PathBuf::from("/a/b/c/d"), true))
|
||||||
@@ -859,22 +861,22 @@ mod tests {
|
|||||||
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
||||||
let files: Vec<File> = host.files.clone();
|
let files: Vec<File> = host.files.clone();
|
||||||
assert_eq!(files.len(), 1); // There should be 1 file now
|
assert_eq!(files.len(), 1); // There should be 1 file now
|
||||||
assert_eq!(files.get(0).unwrap().name(), "foo.txt");
|
assert_eq!(files.first().unwrap().name(), "foo.txt");
|
||||||
// Rename file
|
// Rename file
|
||||||
let dst_path: PathBuf =
|
let dst_path: PathBuf =
|
||||||
PathBuf::from(format!("{}/bar.txt", tmpdir.path().display()).as_str());
|
PathBuf::from(format!("{}/bar.txt", tmpdir.path().display()).as_str());
|
||||||
assert!(
|
assert!(
|
||||||
host.rename(files.get(0).unwrap(), dst_path.as_path())
|
host.rename(files.first().unwrap(), dst_path.as_path())
|
||||||
.is_ok()
|
.is_ok()
|
||||||
);
|
);
|
||||||
// There should be still 1 file now, but named bar.txt
|
// There should be still 1 file now, but named bar.txt
|
||||||
let files: Vec<File> = host.files.clone();
|
let files: Vec<File> = host.files.clone();
|
||||||
assert_eq!(files.len(), 1); // There should be 0 files now
|
assert_eq!(files.len(), 1); // There should be 0 files now
|
||||||
assert_eq!(files.get(0).unwrap().name(), "bar.txt");
|
assert_eq!(files.first().unwrap().name(), "bar.txt");
|
||||||
// Fail
|
// Fail
|
||||||
let bad_path: PathBuf = PathBuf::from("/asdailsjoidoewojdijow/ashdiuahu");
|
let bad_path: PathBuf = PathBuf::from("/asdailsjoidoewojdijow/ashdiuahu");
|
||||||
assert!(
|
assert!(
|
||||||
host.rename(files.get(0).unwrap(), bad_path.as_path())
|
host.rename(files.first().unwrap(), bad_path.as_path())
|
||||||
.is_err()
|
.is_err()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -939,7 +941,7 @@ mod tests {
|
|||||||
file2_path.push("bar.txt");
|
file2_path.push("bar.txt");
|
||||||
// Create host
|
// Create host
|
||||||
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
||||||
let file1_entry: File = host.files.get(0).unwrap().clone();
|
let file1_entry: File = host.files.first().unwrap().clone();
|
||||||
assert_eq!(file1_entry.name(), String::from("foo.txt"));
|
assert_eq!(file1_entry.name(), String::from("foo.txt"));
|
||||||
// Copy
|
// Copy
|
||||||
assert!(host.copy(&file1_entry, file2_path.as_path()).is_ok());
|
assert!(host.copy(&file1_entry, file2_path.as_path()).is_ok());
|
||||||
@@ -969,7 +971,7 @@ mod tests {
|
|||||||
let file2_path: PathBuf = PathBuf::from("bar.txt");
|
let file2_path: PathBuf = PathBuf::from("bar.txt");
|
||||||
// Create host
|
// Create host
|
||||||
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
||||||
let file1_entry: File = host.files.get(0).unwrap().clone();
|
let file1_entry: File = host.files.first().unwrap().clone();
|
||||||
assert_eq!(file1_entry.name(), String::from("foo.txt"));
|
assert_eq!(file1_entry.name(), String::from("foo.txt"));
|
||||||
// Copy
|
// Copy
|
||||||
assert!(host.copy(&file1_entry, file2_path.as_path()).is_ok());
|
assert!(host.copy(&file1_entry, file2_path.as_path()).is_ok());
|
||||||
@@ -989,7 +991,7 @@ mod tests {
|
|||||||
assert!(file1.write_all(b"Hello world!\n").is_ok());
|
assert!(file1.write_all(b"Hello world!\n").is_ok());
|
||||||
// Create host
|
// Create host
|
||||||
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
||||||
let file1_entry: File = host.files.get(0).unwrap().clone();
|
let file1_entry: File = host.files.first().unwrap().clone();
|
||||||
assert_eq!(file1_entry.name(), String::from("foo.txt"));
|
assert_eq!(file1_entry.name(), String::from("foo.txt"));
|
||||||
// Copy with empty destination -> must fail and leave file untouched
|
// Copy with empty destination -> must fail and leave file untouched
|
||||||
assert!(
|
assert!(
|
||||||
@@ -1022,7 +1024,7 @@ mod tests {
|
|||||||
dir_dest.push("test_dest_dir/");
|
dir_dest.push("test_dest_dir/");
|
||||||
// Create host
|
// Create host
|
||||||
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
||||||
let dir_src_entry: File = host.files.get(0).unwrap().clone();
|
let dir_src_entry: File = host.files.first().unwrap().clone();
|
||||||
assert_eq!(dir_src_entry.name(), String::from("test_dir"));
|
assert_eq!(dir_src_entry.name(), String::from("test_dir"));
|
||||||
// Copy
|
// Copy
|
||||||
assert!(host.copy(&dir_src_entry, dir_dest.as_path()).is_ok());
|
assert!(host.copy(&dir_src_entry, dir_dest.as_path()).is_ok());
|
||||||
@@ -1052,7 +1054,7 @@ mod tests {
|
|||||||
let dir_dest: PathBuf = PathBuf::from("test_dest_dir/");
|
let dir_dest: PathBuf = PathBuf::from("test_dest_dir/");
|
||||||
// Create host
|
// Create host
|
||||||
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
let mut host: Localhost = Localhost::new(PathBuf::from(tmpdir.path())).ok().unwrap();
|
||||||
let dir_src_entry: File = host.files.get(0).unwrap().clone();
|
let dir_src_entry: File = host.files.first().unwrap().clone();
|
||||||
assert_eq!(dir_src_entry.name(), String::from("test_dir"));
|
assert_eq!(dir_src_entry.name(), String::from("test_dir"));
|
||||||
// Copy
|
// Copy
|
||||||
assert!(host.copy(&dir_src_entry, dir_dest.as_path()).is_ok());
|
assert!(host.copy(&dir_src_entry, dir_dest.as_path()).is_ok());
|
||||||
|
|||||||
+1
-7
@@ -88,13 +88,7 @@ fn parse_args(args: Args) -> Result<RunOpts, String> {
|
|||||||
// Match ticks
|
// Match ticks
|
||||||
run_opts.ticks = Duration::from_millis(args.ticks);
|
run_opts.ticks = Duration::from_millis(args.ticks);
|
||||||
// Remote argument
|
// Remote argument
|
||||||
match RemoteArgs::try_from(&args) {
|
run_opts.remote = RemoteArgs::try_from(&args)?;
|
||||||
Err(err) => return Err(err),
|
|
||||||
Ok(remote) => {
|
|
||||||
// Set params
|
|
||||||
run_opts.remote = remote;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set activity based on remote state
|
// set activity based on remote state
|
||||||
run_opts.task = if run_opts.remote.remote.is_none() {
|
run_opts.task = if run_opts.remote.remote.is_none() {
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ impl Update {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether a new version of termscp is available
|
/// Returns whether a new version of termscp is available
|
||||||
/// In case of success returns Ok(Option<Release>), where the Option is Some(new_version);
|
/// In case of success returns `Ok(Option<Release>)`, where the option is
|
||||||
|
/// `Some(new_version)`;
|
||||||
/// otherwise if no version is available, return None
|
/// otherwise if no version is available, return None
|
||||||
/// In case of error returns Error with the error description
|
/// In case of error returns Error with the error description
|
||||||
pub fn is_new_version_available() -> Result<Option<Release>, UpdateError> {
|
pub fn is_new_version_available() -> Result<Option<Release>, UpdateError> {
|
||||||
|
|||||||
@@ -767,7 +767,7 @@ mod tests {
|
|||||||
// Limit is 2
|
// Limit is 2
|
||||||
assert_eq!(client.iter_recents().count(), 2);
|
assert_eq!(client.iter_recents().count(), 2);
|
||||||
// Check that 192.168.1.1 has been removed
|
// Check that 192.168.1.1 has been removed
|
||||||
let key: String = client.iter_recents().next().unwrap().to_string();
|
let key: String = client.iter_recents().next().unwrap().clone();
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
client
|
client
|
||||||
.hosts
|
.hosts
|
||||||
@@ -781,7 +781,7 @@ mod tests {
|
|||||||
.as_str(),
|
.as_str(),
|
||||||
"192.168.1.2" | "192.168.1.3"
|
"192.168.1.2" | "192.168.1.3"
|
||||||
));
|
));
|
||||||
let key: String = client.iter_recents().nth(1).unwrap().to_string();
|
let key: String = client.iter_recents().nth(1).unwrap().clone();
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
client
|
client
|
||||||
.hosts
|
.hosts
|
||||||
@@ -938,7 +938,7 @@ mod tests {
|
|||||||
let protocol = params.protocol;
|
let protocol = params.protocol;
|
||||||
let p = params.params.generic_params().unwrap();
|
let p = params.params.generic_params().unwrap();
|
||||||
(
|
(
|
||||||
p.address.to_string(),
|
p.address.clone(),
|
||||||
p.port,
|
p.port,
|
||||||
protocol,
|
protocol,
|
||||||
p.username.as_ref().cloned().unwrap_or_default(),
|
p.username.as_ref().cloned().unwrap_or_default(),
|
||||||
|
|||||||
@@ -595,7 +595,7 @@ mod tests {
|
|||||||
client.set_local_file_fmt(String::from("{NAME}"));
|
client.set_local_file_fmt(String::from("{NAME}"));
|
||||||
assert_eq!(client.get_local_file_fmt().unwrap(), String::from("{NAME}"));
|
assert_eq!(client.get_local_file_fmt().unwrap(), String::from("{NAME}"));
|
||||||
// Delete
|
// Delete
|
||||||
client.set_local_file_fmt(String::from(""));
|
client.set_local_file_fmt(String::new());
|
||||||
assert_eq!(client.get_local_file_fmt(), None);
|
assert_eq!(client.get_local_file_fmt(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +613,7 @@ mod tests {
|
|||||||
String::from("{NAME}")
|
String::from("{NAME}")
|
||||||
);
|
);
|
||||||
// Delete
|
// Delete
|
||||||
client.set_remote_file_fmt(String::from(""));
|
client.set_remote_file_fmt(String::new());
|
||||||
assert_eq!(client.get_remote_file_fmt(), None);
|
assert_eq!(client.get_remote_file_fmt(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ mod tests {
|
|||||||
let mut f: File = OpenOptions::new()
|
let mut f: File = OpenOptions::new()
|
||||||
.create(true)
|
.create(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
.open(conf_dir.as_path())
|
.open(conf_dir.as_path())
|
||||||
.ok()
|
.ok()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
// unwatch
|
// unwatch
|
||||||
assert!(watcher.unwatch(tempdir.path()).is_ok());
|
assert!(watcher.unwatch(tempdir.path()).is_ok());
|
||||||
assert!(watcher.paths.get(tempdir.path()).is_none());
|
assert!(!watcher.paths.contains_key(tempdir.path()));
|
||||||
// close tempdir
|
// close tempdir
|
||||||
assert!(tempdir.close().is_ok());
|
assert!(tempdir.close().is_ok());
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,7 @@ mod test {
|
|||||||
watcher.unwatch(subdir.as_path()).unwrap().as_path(),
|
watcher.unwatch(subdir.as_path()).unwrap().as_path(),
|
||||||
Path::new(tempdir.path())
|
Path::new(tempdir.path())
|
||||||
);
|
);
|
||||||
assert!(watcher.paths.get(tempdir.path()).is_none());
|
assert!(!watcher.paths.contains_key(tempdir.path()));
|
||||||
// close tempdir
|
// close tempdir
|
||||||
assert!(tempdir.close().is_ok());
|
assert!(tempdir.close().is_ok());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ impl Pane {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::explorer::builder::FileExplorerBuilder;
|
use crate::explorer::builder::FileExplorerBuilder;
|
||||||
use crate::host::Localhost;
|
use crate::host::Localhost;
|
||||||
@@ -52,6 +50,6 @@ mod tests {
|
|||||||
fn test_pane_pwd() {
|
fn test_pane_pwd() {
|
||||||
let mut pane = make_pane();
|
let mut pane = make_pane();
|
||||||
let pwd = pane.fs.pwd().unwrap();
|
let pwd = pane.fs.pwd().unwrap();
|
||||||
assert_eq!(pwd, PathBuf::from(std::env::temp_dir()));
|
assert_eq!(pwd, std::env::temp_dir());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,7 +211,8 @@ impl FileTransferActivity {
|
|||||||
/// Shared scan walk. `remote_side` selects which pane lists directories
|
/// Shared scan walk. `remote_side` selects which pane lists directories
|
||||||
/// (remote for downloads, local for uploads).
|
/// (remote for downloads, local for uploads).
|
||||||
///
|
///
|
||||||
/// The walk is abortable via [`crate::ui::activities::filetransfer::lib::TransferStates::aborted`]
|
/// The walk is abortable via
|
||||||
|
/// [`TransferStates::aborted`](crate::ui::activities::filetransfer::lib::transfer::TransferStates::aborted)
|
||||||
/// and periodically redraws a "Scanning…" popup to keep the UI responsive.
|
/// and periodically redraws a "Scanning…" popup to keep the UI responsive.
|
||||||
fn scan_worklist(
|
fn scan_worklist(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ use super::{Id, IdSsh, IdTheme, SetupActivity, ViewLayout};
|
|||||||
use crate::config::themes::Theme;
|
use crate::config::themes::Theme;
|
||||||
|
|
||||||
impl SetupActivity {
|
impl SetupActivity {
|
||||||
/// On <ESC>, if there are changes in the configuration, the quit dialog must be shown, otherwise
|
/// On `ESC`, if there are changes in the configuration, the quit dialog
|
||||||
/// we can exit without any problem
|
/// must be shown; otherwise, we can exit without any problem.
|
||||||
pub(super) fn action_on_esc(&mut self) {
|
pub(super) fn action_on_esc(&mut self) {
|
||||||
if self.config_changed() {
|
if self.config_changed() {
|
||||||
self.mount_quit();
|
self.mount_quit();
|
||||||
|
|||||||
+4
-2
@@ -43,13 +43,15 @@ pub fn fmt_millis(duration: Duration) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Elide a path if longer than width
|
/// Elide a path if longer than width
|
||||||
/// In this case, the path is formatted to {ANCESTOR[0]}/…/{PARENT[0]}/{BASENAME}
|
/// In this case, the path is formatted to
|
||||||
|
/// `{ANCESTOR[0]}/…/{PARENT[0]}/{BASENAME}`.
|
||||||
pub fn fmt_path_elide(p: &Path, width: usize) -> String {
|
pub fn fmt_path_elide(p: &Path, width: usize) -> String {
|
||||||
fmt_path_elide_ex(p, width, 0)
|
fmt_path_elide_ex(p, width, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Elide a path if longer than width
|
/// Elide a path if longer than width
|
||||||
/// In this case, the path is formatted to {ANCESTOR[0]}/…/{PARENT[0]}/{BASENAME}
|
/// In this case, the path is formatted to
|
||||||
|
/// `{ANCESTOR[0]}/…/{PARENT[0]}/{BASENAME}`.
|
||||||
/// This function allows to specify an extra length to consider to elide path
|
/// This function allows to specify an extra length to consider to elide path
|
||||||
pub fn fmt_path_elide_ex(p: &Path, width: usize, extra_len: usize) -> String {
|
pub fn fmt_path_elide_ex(p: &Path, width: usize, extra_len: usize) -> String {
|
||||||
let fmt_path: String = format!("{}", p.display());
|
let fmt_path: String = format!("{}", p.display());
|
||||||
|
|||||||
+4
-4
@@ -68,7 +68,7 @@ static BYTESIZE_REGEX: Lazy<Regex> = lazy_regex!(r"(:?([0-9])+)( )*(:?[KMGTP])?B
|
|||||||
/// SFTP => 22
|
/// SFTP => 22
|
||||||
/// FTP => 21
|
/// FTP => 21
|
||||||
/// The option string has the following syntax
|
/// The option string has the following syntax
|
||||||
/// [protocol://][username@]{address}[:port][:path]
|
/// `[protocol://][username@]{address}[:port][:path]`
|
||||||
/// The only argument which is mandatory is address
|
/// The only argument which is mandatory is address
|
||||||
/// NOTE: possible strings
|
/// NOTE: possible strings
|
||||||
/// - 172.26.104.1
|
/// - 172.26.104.1
|
||||||
@@ -80,17 +80,17 @@ static BYTESIZE_REGEX: Lazy<Regex> = lazy_regex!(r"(:?([0-9])+)( )*(:?[KMGTP])?B
|
|||||||
///
|
///
|
||||||
/// For s3:
|
/// For s3:
|
||||||
///
|
///
|
||||||
/// s3://<bucket-name>@<region>[:profile][:/wrkdir]
|
/// `s3://<bucket-name>@<region>[:profile][:/wrkdir]`
|
||||||
///
|
///
|
||||||
/// For SMB:
|
/// For SMB:
|
||||||
///
|
///
|
||||||
/// on UNIX derived (macos, linux, ...)
|
/// on UNIX derived (macos, linux, ...)
|
||||||
///
|
///
|
||||||
/// smb://[username@]<address>[:port]/<share>[/path]
|
/// `smb://[username@]<address>[:port]/<share>[/path]`
|
||||||
///
|
///
|
||||||
/// on Windows
|
/// on Windows
|
||||||
///
|
///
|
||||||
/// \\<address>\<share>[\path]
|
/// `\\<address>\<share>[\path]`
|
||||||
///
|
///
|
||||||
pub fn parse_remote_opt(s: &str) -> Result<FileTransferParams, String> {
|
pub fn parse_remote_opt(s: &str) -> Result<FileTransferParams, String> {
|
||||||
remote::parse_remote_opt(s)
|
remote::parse_remote_opt(s)
|
||||||
|
|||||||
Reference in New Issue
Block a user