Kaynağa Gözat

Merge branch 'main' into cafk-msrv-1.70

Signed-off-by: Christina Sørensen <christina@cafkafk.com>
Christina Sørensen 2 yıl önce
ebeveyn
işleme
65dfe9f7b3
55 değiştirilmiş dosya ile 700 ekleme ve 92 silme
  1. 19 0
      .github/workflows/conventional-commits.yml
  2. 2 2
      .github/workflows/flake.yml
  3. 15 0
      .github/workflows/winget.yml
  4. 143 0
      CHANGELOG.md
  5. 1 1
      Cargo.lock
  6. 3 2
      Cargo.toml
  7. 64 22
      README.md
  8. 44 36
      completions/fish/eza.fish
  9. 43 0
      devtools/generate-trycmd-test.sh
  10. 3 3
      man/eza.1.md
  11. 1 0
      src/fs/dir.rs
  12. 2 0
      src/fs/file.rs
  13. 13 2
      src/main.rs
  14. 3 0
      src/output/details.rs
  15. 2 2
      src/output/render/git.rs
  16. 1 0
      tests/cmd/inexistant_file_unix.stderr
  17. 0 0
      tests/cmd/inexistant_file_unix.stdout
  18. 3 0
      tests/cmd/inexistant_file_unix.toml
  19. 0 0
      tests/cmd/long_binary_bytes_unix.stderr
  20. 21 0
      tests/cmd/long_binary_bytes_unix.stdout
  21. 2 0
      tests/cmd/long_binary_bytes_unix.toml
  22. 0 0
      tests/cmd/long_file_size_unix.stderr
  23. 21 0
      tests/cmd/long_file_size_unix.stdout
  24. 2 0
      tests/cmd/long_file_size_unix.toml
  25. 0 0
      tests/cmd/long_header_unix.stderr
  26. 22 0
      tests/cmd/long_header_unix.stdout
  27. 2 0
      tests/cmd/long_header_unix.toml
  28. 2 0
      tests/cmd/long_links_recurse_unix.toml
  29. 0 0
      tests/cmd/long_recurse_with_level_unix.stderr
  30. 21 0
      tests/cmd/long_recurse_with_level_unix.stdout
  31. 2 0
      tests/cmd/long_recurse_with_level_unix.toml
  32. 21 21
      tests/cmd/long_unix.stdout
  33. 1 1
      tests/cmd/long_unix.toml
  34. 0 0
      tests/cmd/only_dir_recursive_long_unix.stderr
  35. 21 0
      tests/cmd/only_dir_recursive_long_unix.stdout
  36. 2 0
      tests/cmd/only_dir_recursive_long_unix.toml
  37. 0 0
      tests/cmd/only_dir_recursive_unix.stderr
  38. 21 0
      tests/cmd/only_dir_recursive_unix.stdout
  39. 2 0
      tests/cmd/only_dir_recursive_unix.toml
  40. 0 0
      tests/cmd/only_dir_unix.stderr
  41. 2 0
      tests/cmd/only_dir_unix.stdout
  42. 2 0
      tests/cmd/only_dir_unix.toml
  43. 0 0
      tests/cmd/recursive_long_unix.stderr
  44. 47 0
      tests/cmd/recursive_long_unix.stdout
  45. 2 0
      tests/cmd/recursive_long_unix.toml
  46. 0 0
      tests/cmd/recursive_unix.stderr
  47. 47 0
      tests/cmd/recursive_unix.stdout
  48. 2 0
      tests/cmd/recursive_unix.toml
  49. 0 0
      tests/cmd/tree_long_unix.stderr
  50. 34 0
      tests/cmd/tree_long_unix.stdout
  51. 2 0
      tests/cmd/tree_long_unix.toml
  52. 0 0
      tests/cmd/tree_unix.stderr
  53. 34 0
      tests/cmd/tree_unix.stdout
  54. 2 0
      tests/cmd/tree_unix.toml
  55. 1 0
      treefmt.nix

+ 19 - 0
.github/workflows/conventional-commits.yml

@@ -0,0 +1,19 @@
+name: Conventional Commits
+
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+jobs:
+  build:
+    name: Conventional Commits
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+
+      - uses: webiny/action-conventional-commits@v1.1.0
+        # optional, required for private repos
+        # with:
+        #   GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

+ 2 - 2
.github/workflows/flake.yml

@@ -13,5 +13,5 @@ jobs:
         uses: DeterminateSystems/flake-checker-action@v5 # This action
       - name: Install Nix
         uses: DeterminateSystems/nix-installer-action@v4
-      - name: Build default package
-        run: nix build
+      - name: Nix Flake Check
+        run: nix flake check --all-systems

+ 15 - 0
.github/workflows/winget.yml

@@ -0,0 +1,15 @@
+name: Publish to Winget
+
+on:
+  release:
+    types: [released]
+
+jobs:
+  publish:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: vedantmgoyal2009/winget-releaser@v2
+        with:
+          identifier: eza-community.eza
+          installers-regex: '-pc-windows-gnu\.zip$'
+          token: ${{ secrets.WINGET_TOKEN }}

+ 143 - 0
CHANGELOG.md

@@ -2,6 +2,146 @@
 
 All notable changes to this project will be documented in this file.
 
+## [0.12.0] - 2023-09-14
+
+### Bug Fixes
+
+- Expand `--all` help
+- RUSTSEC-2020-0071
+- Generalize gitignore to ignore all eza deb packages
+- Canonicalize errors when the destination of a symbolic link is bad
+- Handle other canonicalize errors in hyperlinks and git
+- Fix windows build when canonicalize returns an error
+- Change trycmd config to use test/itest folder for testing
+- Revert to old apt install command suggestion and add hint
+- Remove stray backslashes
+- Is_some_and is an unstable Rust feature until 1.70
+- Revert "Support for Windows Hidden Files"
+- Shellcheck warnings
+- Revert "Support for Windows Hidden Files"
+- Shellcheck warnings
+- Exit 13 on os error 13
+- Rewrite comment
+- Improve trace strings
+- Tracing typo
+
+### Documentation
+
+- Expand `--all` documentation
+- Add pthorpe92 gist
+- Remove xtests section from readme
+- Add deprecation warning to xtests/readme
+- Add deprecation warning to just xtest commands
+- Add deprecation warning to vagrantfile
+- Add MacPorts install info
+- Add gentoo
+- Fix gentoo install
+- Add docs for --git-repos & --git-repos-no-status
+- Fix gpg armor flag for deb release in readme
+- Add better explanation of git repos + no status
+- Add scoop install info
+- Remove color specifications. change unknown git repo status to `~`
+- Fix missing color specification from man page
+
+### Features
+
+- Add audit workflow
+- Add trycmd as dev-dependency
+- Add minimal trycmd binary
+- Add a few trycmd tests as example
+- Document and change output for --git-repos
+- Add apt installation workflow
+- Adds filtering on Windows hidden files
+- Adds filtering on Windows hidden files
+- Adds filtering on Windows hidden files
+- Added shellcheck to treefmt
+- Adds filtering on Windows hidden files
+- Add PERMISSION_DENIED exit code
+
+### Miscellaneous Tasks
+
+- Bump chrono from 0.4.27 to 0.4.30
+- Removal of xtests
+- Removal of vagrant
+- Remove deprecated devtools
+- Run spellcheck
+
+### Refactor
+
+- Over-engineer deb-package.sh
+- Hide xtests folder
+- Split trycmd into tests for all, unix and windows
+- Limit unit-tests run on workflow change to unit-tests itself
+- Moved generateTest.sh to devtools/
+- Renamed the file
+- Add tracing to various code parts
+- Make std::process::exit global
+
+### Revert
+
+- "Support for Windows Hidden Files"
+
+### Styling
+
+- Remove TODO message on the absolute_path property
+- Fix shellcheck issues in deb-package.sh
+- Fix shellcheck issues in deb-package.sh
+- Fix shellcheck issues in deb-package.sh
+
+### Testing
+
+- Remove vhs from flake
+- Remove vhs-runner files
+- Dump trycmd from nix sandbox
+- Fix name of trydump
+- Add trycmd
+- Add nix feature
+- Add example long tests for sandbox
+- Set itests files to unix epoch
+- Set itest files to unix epoch
+- Refactor setting unix epoch
+- Auto discard old definitions
+- Fix test reference
+- Add long_all_nix.toml
+- Add long_blocksize_nix.toml
+- Add long_extended_nix.toml
+- Add long_git_nix.toml
+- Add long_git_repos_nix.toml
+- Add long_git_repos_no_status_nix.toml
+- Add long_grid_nix.toml
+- Add long_header_nix.toml
+- Add long_icons_nix.toml
+- Add long_octal_nix.toml
+- Add long_time_style_relative_nix.toml
+- Freeze nix tests
+- Fix trydump when no files to delete
+- Adding more content to test
+- Modified unix and all tests
+- Regenerate nix tests
+- Convert windows tests with new itest dir
+- Fixed windows tests being wrong
+- Added a test generator
+- Add more unix_tests
+- Fixed unix tests to remove any distro specific
+- Removed git test breaking on nix
+
+### Build
+
+- Add compression, checksum gen for bin
+- Update flake.lock, cargo.lock
+- Add deny.toml
+- Remove org warnings
+- Remove itest
+- Update flake.lock
+- Add itest, idump
+- Make trycmd part of checks
+
+### Ci
+
+- Don't use nix feature on ci
+- Enforce conventional commits
+- Enforce conventional commits
+
 ## [0.11.1] - 2023-09-11
 
 ### Bug Fixes
@@ -37,6 +177,8 @@ All notable changes to this project will be documented in this file.
 ### Miscellaneous Tasks
 
 - Bump actions/checkout from 3 to 4
+- Bump uzers to v0.11.3
+- Release 0.11.1
 
 ### Testing
 
@@ -174,6 +316,7 @@ All notable changes to this project will be documented in this file.
 - Cafkafk -> eza-community
 - Add gpg public key for the deb repository
 - Add section about debian and ubuntu installation
+- Add guidelines for commit messages
 
 ### Features
 

+ 1 - 1
Cargo.lock

@@ -247,7 +247,7 @@ dependencies = [
 
 [[package]]
 name = "eza"
-version = "0.11.1"
+version = "0.12.0"
 dependencies = [
  "ansiterm",
  "chrono",

+ 3 - 2
Cargo.toml

@@ -5,12 +5,12 @@ authors = ["Christina Sørensen <christina@cafkafk.com>"]
 categories = ["command-line-utilities"]
 edition = "2021"
 rust-version = "1.70.0"
-exclude = ["/devtools/*", "/Justfile", "/Vagrantfile", "/screenshots.png"]
+exclude = ["/devtools/*", "/Justfile", "/Vagrantfile", "/screenshots.png", "/tests"]
 readme = "README.md"
 homepage = "https://github.com/eza-community/eza"
 license = "MIT"
 repository = "https://github.com/eza-community/eza"
-version = "0.11.1"
+version = "0.12.0"
 
 
 [package.metadata.deb]
@@ -25,6 +25,7 @@ assets = [
     [ "target/release/eza", "/usr/bin/eza", "0755" ],
     [ "target/release/../man/eza.1", "/usr/share/man/man1/eza.1", "0644" ],
     [ "target/release/../man/eza_colors.5", "/usr/share/man/man5/eza_colors.5", "0644" ],
+    [ "target/release/../man/eza_colors-explanation.5", "/usr/share/man/man5/eza_colors-explanation.5", "0644" ],
     [ "completions/bash/eza", "/usr/share/bash-completion/completions/eza", "0644" ],
     [ "completions/zsh/_eza", "/usr/share/zsh/site-functions/_eza", "0644" ],
     [ "completions/fish/eza.fish", "/usr/share/fish/vendor_completions.d/eza.fish", "0644" ],

+ 64 - 22
README.md

@@ -27,20 +27,20 @@ And it’s **small**, **fast**, and just **one single binary**.
 
 By deliberately making some decisions differently, eza attempts to be a more featureful, more user-friendly version of `ls`.
 
-
 ---
 
 **eza** features not in exa (non-exhaustive):
 
- -   Fixes [“The Grid Bug”](https://github.com/eza-community/eza/issues/66#issuecomment-1656758327) introduced in exa 2021.
- -   Hyperlink support.
- -   Mount point details.
- -   Selinux context output.
- -   Git repo status output.
- -   Human readable relative dates.
- -   Several security fixes.
- -   Many smaller bug fixes/changes!
- -   Support for `bright` terminal colours.
+- Fixes [“The Grid Bug”](https://github.com/eza-community/eza/issues/66#issuecomment-1656758327) introduced in exa 2021.
+- Hyperlink support.
+- Mount point details.
+- Selinux context output.
+- Git repo status output.
+- Human readable relative dates.
+- Several security fixes.
+- Support for `bright` terminal colours.
+- Many smaller bug fixes/changes!
+
 ---
 
 <a id="try-it">
@@ -53,7 +53,7 @@ If you already have Nix setup with flake support, you can try out eza with the `
 
     nix run github:eza-community/eza
 
-Nix will build eza and run it. 
+Nix will build eza and run it.
 
 If you want to pass arguments this way, use e.g. `nix run github:eza-community/eza -- -ol`.
 
@@ -99,6 +99,7 @@ Eza is available from [deb.gierens.de](http://deb.gierens.de). The GPG public
 key is in this repo under [deb.asc](/deb.asc).
 
 To install eza from this repo use:
+
 ```bash
 wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | sudo tee /etc/apt/trusted.gpg.d/gierens.asc
 echo "deb http://deb.gierens.de stable main" | sudo tee /etc/apt/sources.list.d/gierens.list
@@ -108,9 +109,11 @@ sudo apt install -y eza
 
 **Note:** on some systems like Docker containers apt might require the key
 to be in dearmored format, then use this command instead:
+
 ```bash
 wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/gierens.asc
 ```
+
 before proceeding with the others from above.
 
 ### Nix (Linux, MacOS)
@@ -175,7 +178,6 @@ The preceding repository also contains the Bash, Fish, and Zsh completions.
 
 [![Homebrew package](https://repology.org/badge/version-for-repo/homebrew/eza.svg)](https://repology.org/project/eza/versions)
 
-
 Eza is available from [Homebrew](https://formulae.brew.sh/formula/eza#default).
 
 To install eza, run:
@@ -196,11 +198,23 @@ To install eza, run:
 sudo port install eza
 ```
 
+### Winget (Windows)
+
+[![Windows package](https://repology.org/badge/version-for-repo/winget/eza.svg)](https://repology.org/project/eza/versions)
+
+
+Eza is available on Winget.
+
+To install eza, run:
+
+```shell
+winget install eza-community.eza
+```
+
 ### Scoop (Windows)
 
 [![Windows package](https://repology.org/badge/version-for-repo/scoop/eza.svg)](https://repology.org/project/eza/versions)
 
-
 Eza is available from [Scoop](https://scoop.sh/#/apps?q=eza&id=a52070d25f94bbcc884f80bef53eb47ed1268198).
 
 To install eza, run:
@@ -209,7 +223,35 @@ To install eza, run:
 scoop install eza
 ```
 
+### Completions
+
+#### For zsh:
+
+> **Note**
+> Change `~/.zshrc` to your preferred zsh config file.
+
+##### Clone the repository:
+   
+```sh
+git clone https://github.com/eza-community/eza.git
+```
+
+##### Add the completion path to your zsh configuration:
+   
+Replace `<path_to_eza>` with the actual path where you cloned the `eza` repository.
+
+```sh
+echo 'export FPATH="<path_to_eza>/completions/zsh:$FPATH"' >> ~/.zshrc
+```
+
+##### Reload your zsh configuration:
+   
+```sh
+source ~/.zshrc
+```
+
 ---
+
 Click sections to expand.
 
 <a id="options">
@@ -310,22 +352,22 @@ Once Rust is installed, you can compile eza with Cargo:
     cargo test
 
 - The [just](https://github.com/casey/just) command runner can be used to run some helpful development commands, in a manner similar to `make`.
-Run `just --list` to get an overview of what’s available.
+  Run `just --list` to get an overview of what’s available.
 
 - If you are compiling a copy for yourself, be sure to run `cargo build --release` or `just build-release` to benefit from release-mode optimisations.
-Copy the resulting binary, which will be in the `target/release` directory, into a folder in your `$PATH`.
-`/usr/local/bin` is usually a good choice.
+  Copy the resulting binary, which will be in the `target/release` directory, into a folder in your `$PATH`.
+  `/usr/local/bin` is usually a good choice.
 
 - To compile and install the manual pages, you will need [pandoc](https://pandoc.org/).
-The `just man` command will compile the Markdown into manual pages, which it will place in the `target/man` directory.
-To use them, copy them into a directory that `man` will read.
-`/usr/local/share/man` is usually a good choice.
+  The `just man` command will compile the Markdown into manual pages, which it will place in the `target/man` directory.
+  To use them, copy them into a directory that `man` will read.
+  `/usr/local/share/man` is usually a good choice.
 
 - eza depends on [libgit2](https://github.com/rust-lang/git2-rs) for certain features.
-If you’re unable to compile libgit2, you can opt out of Git support by running `cargo build --no-default-features`.
+  If you’re unable to compile libgit2, you can opt out of Git support by running `cargo build --no-default-features`.
 
 - If you intend to compile for musl, you will need to use the flag `vendored-openssl` if you want to get the Git feature working.
-The full command is `cargo build --release --target=x86_64-unknown-linux-musl --features vendored-openssl,git`.
+  The full command is `cargo build --release --target=x86_64-unknown-linux-musl --features vendored-openssl,git`.
 
 ### Developing on Nix (experimental) ❄️
 
@@ -334,12 +376,12 @@ If you have a working Nix installation with flake support, you can use nix to ma
     nix develop
 
 The Nix Flake has a few features:
+
 - Run `nix flake check` to run `treefmt` on the repo.
 - Run `nix build` and manually test `./results/bin/eza -- <arguments>` for easy debugging.
 - Run `nix build .#test` to run `cargo test` via the flake.
 - Run `nix build .#clippy` to lint with clippy (still work in progress).
 
-
 ## Star History
 
 [![Star History Chart](https://api.star-history.com/svg?repos=eza-community/eza&type=Date)](https://star-history.com/#eza-community/eza&Date)

+ 44 - 36
completions/fish/eza.fish

@@ -9,7 +9,7 @@ TAG=$(git describe --tags --abbrev=0)
 VERSION=${TAG:1}
 
 echo "checkout tag ${TAG}"
-git checkout --quiet ${TAG}
+git checkout --quiet "${TAG}"
 
 echo "build man pages"
 just man
@@ -20,7 +20,7 @@ TARGETS["arm64"]="aarch64-unknown-linux-gnu"
 TARGETS["armhf"]="arm-unknown-linux-gnueabihf"
 
 echo "download release notes"
-RELEASE_NOTES=$(curl -s ${REPO_URL}/releases/tag/${TAG})
+RELEASE_NOTES=$(curl -s "${REPO_URL}/releases/tag/${TAG}")
 
 for ARCH in "${!TARGETS[@]}"; do
     echo "building ${ARCH} package:"
@@ -40,29 +40,37 @@ for ARCH in "${!TARGETS[@]}"; do
     echo "    checksum ok"
 
     echo " -> creating directory structure"
-    mkdir -p ${DEB_TMP_DIR}
-    mkdir -p ${DEB_TMP_DIR}${DESTDIR}
-    mkdir -p ${DEB_TMP_DIR}${DOCDIR}
-    mkdir -p ${DEB_TMP_DIR}${DOCDIR}/man1
-    mkdir -p ${DEB_TMP_DIR}${DOCDIR}/man5
-    mkdir -p ${DEB_TMP_DIR}/DEBIAN
-    mkdir -p ${DEB_TMP_DIR}/usr/share/doc/${NAME}
-    chmod 755 -R ${DEB_TMP_DIR}
-    
+    mkdir -p "${DEB_TMP_DIR}"
+    mkdir -p "${DEB_TMP_DIR}${DESTDIR}"
+    mkdir -p "${DEB_TMP_DIR}${DOCDIR}"
+    mkdir -p "${DEB_TMP_DIR}${DOCDIR}/man1"
+    mkdir -p "${DEB_TMP_DIR}${DOCDIR}/man5"
+    mkdir -p "${DEB_TMP_DIR}/DEBIAN"
+    mkdir -p "${DEB_TMP_DIR}/usr/share/doc/${NAME}"
+    mkdir -p "${DEB_TMP_DIR}/usr/share/bash-completion/completions/"
+    mkdir -p "${DEB_TMP_DIR}/usr/share/fish/vendor_completions.d/"
+    mkdir -p "${DEB_TMP_DIR}/usr/share/zsh/vendor-completions/"
+    chmod 755 -R "${DEB_TMP_DIR}"
+
     echo " -> extract executable"
     tar -xzf "${ARCH}.tar.gz"
-    cp ${NAME} ${DEB_TMP_DIR}${DESTDIR}
-    chmod 755 ${DEB_TMP_DIR}${DESTDIR}/${NAME}
+    cp ${NAME} "${DEB_TMP_DIR}${DESTDIR}"
+    chmod 755 "${DEB_TMP_DIR}${DESTDIR}/${NAME}"
 
     echo " -> compress man pages"
-    gzip -cn9 target/man/eza.1 > ${DEB_TMP_DIR}${DOCDIR}man1/eza.1.gz
-    gzip -cn9 target/man/eza_colors.5 > ${DEB_TMP_DIR}${DOCDIR}man5/eza_colors.5.gz
-    gzip -cn9 target/man/eza_colors-explanation.5 > ${DEB_TMP_DIR}${DOCDIR}man5/eza_colors-explanation.5.gz
-    chmod 644 ${DEB_TMP_DIR}${DOCDIR}/**/*.gz
-    
+    gzip -cn9 target/man/eza.1 > "${DEB_TMP_DIR}${DOCDIR}man1/eza.1.gz"
+    gzip -cn9 target/man/eza_colors.5 > "${DEB_TMP_DIR}${DOCDIR}man5/eza_colors.5.gz"
+    gzip -cn9 target/man/eza_colors-explanation.5 > "${DEB_TMP_DIR}${DOCDIR}man5/eza_colors-explanation.5.gz"
+    chmod 644 "${DEB_TMP_DIR}${DOCDIR}"/**/*.gz
+
+    echo " -> copy completions"
+    cp completions/bash/eza "${DEB_TMP_DIR}/usr/share/bash-completion/completions/"
+    cp completions/fish/eza.fish "${DEB_TMP_DIR}/usr/share/fish/vendor_completions.d/"
+    cp completions/zsh/_eza "${DEB_TMP_DIR}/usr/share/zsh/vendor-completions/"
+
     echo " -> create control file"
-    touch ${DEB_TMP_DIR}/DEBIAN/control
-    cat > ${DEB_TMP_DIR}/DEBIAN/control <<EOM
+    touch "${DEB_TMP_DIR}/DEBIAN/control"
+    cat > "${DEB_TMP_DIR}/DEBIAN/control" <<EOM
 Package: ${NAME}
 Version: ${VERSION}
 Section: utils
@@ -78,17 +86,17 @@ Description: Modern replacement for ls
  It also has extra features not present in the original ls, such as viewing the
  Git status for a directory, or recursing into directories with a tree view.
 EOM
-    chmod 644 ${DEB_TMP_DIR}/DEBIAN/control
-    
+    chmod 644 "${DEB_TMP_DIR}/DEBIAN/control"
+
     echo " -> copy changelog"
-    cp CHANGELOG.md ${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog
-    gzip -cn9 ${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog > ${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog.gz
-    rm ${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog
-    chmod 644 ${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog.gz
-    
+    cp CHANGELOG.md "${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog"
+    gzip -cn9 "${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog" > "${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog.gz"
+    rm "${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog"
+    chmod 644 "${DEB_TMP_DIR}/usr/share/doc/${NAME}/changelog.gz"
+
     echo " -> create copyright file"
-    touch ${DEB_TMP_DIR}/usr/share/doc/${NAME}/copyright
-    cat > ${DEB_TMP_DIR}/usr/share/doc/${NAME}/copyright << EOM
+    touch "${DEB_TMP_DIR}/usr/share/doc/${NAME}/copyright"
+    cat > "${DEB_TMP_DIR}/usr/share/doc/${NAME}/copyright" << EOM
 Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 Upstream-Name: ${NAME}
 Upstream-Contact: Christina Sørensen <christina@cafkafk.com>
@@ -121,16 +129,16 @@ License: MIT
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
 EOM
-    chmod 644 ${DEB_TMP_DIR}/usr/share/doc/${NAME}/copyright
-    
+    chmod 644 "${DEB_TMP_DIR}/usr/share/doc/${NAME}/copyright"
+
     echo " -> build ${ARCH} package"
-    dpkg-deb --build --root-owner-group ${DEB_TMP_DIR} > /dev/null
-    
+    dpkg-deb --build --root-owner-group "${DEB_TMP_DIR}" > /dev/null
+
     echo " -> cleanup"
-    rm -rf ${DEB_TMP_DIR} ${ARCH}.tar.gz ${NAME}
-    
+    rm -rf "${DEB_TMP_DIR}" "${ARCH}.tar.gz" "${NAME}"
+
     # gierens: this does not work on my arch at the moment and
     #          i'm verifying on the repo host anyway thus the || true
     echo " -> lint ${ARCH} package"
-    lintian ${DEB_PACKAGE} || true
+    lintian "${DEB_PACKAGE}" || true
 done

+ 43 - 0
devtools/generate-trycmd-test.sh

@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Generate test data for the program
+
+if [ $# -ne 2 ]; then
+    echo "Usage: $0 <test name> <test argument>"
+    exit 1
+fi
+
+# Clean up previous test data
+
+if [ -f tests/cmd/"$1".toml ]; then
+    rm tests/cmd/"$1".toml
+fi
+
+if [ -f tests/cmd/"$1".stdout ]; then
+    rm tests/cmd/"$1".stdout
+fi
+
+if [ -f tests/cmd/"$1".stderr ]; then
+    rm tests/cmd/"$1".stderr
+fi
+
+# Generate test data
+
+touch tests/cmd/"$1".toml
+
+echo 'bin.name = "eza"' >> tests/cmd/"$1".toml
+echo 'args = "'"$2"'"' >> tests/cmd/"$1".toml
+
+# Generate expected output
+
+if [ -f target/debug/eza ]; then
+    target/debug/eza "$2" > tests/cmd/"$1".stdout 2> tests/cmd/"$1".stderr
+    returncode=$?
+    if [ $returncode -ne 0 ]; then
+        echo -e 'status.code = '$returncode'' >> tests/cmd/"$1".toml
+        exit 0
+    fi
+else
+    echo "Please build the program first"
+    exit 1
+fi

+ 3 - 3
man/eza.1.md

@@ -197,16 +197,16 @@ These options are available when running with `--long` (`-l`):
 
 `--git`  [if eza was built with git support]
 : List each file’s Git status, if tracked.
+This adds a two-character column indicating the staged and unstaged statuses respectively. The status character can be ‘`-`’ for not modified, ‘`M`’ for a modified file, ‘`N`’ for a new file, ‘`D`’ for deleted, ‘`R`’ for renamed, ‘`T`’ for type-change, ‘`I`’ for ignored, and ‘`U`’ for conflicted. :Directories will be shown to have the status of their contents, which is how ‘deleted’ is possible if a directory contains a file that has a certain status, it will be shown to have that status.  
 
 `--git-repos` [if eza was built with git support]
 : List each directory’s Git status, if tracked.
+Symbols shown are `|`= clean, `+`= dirty, and `~`= for unknown.
 
 `--git-repos-no-status` [if eza was built with git support]
 : List if a directory is a Git repository, but not its status.
+All Git repository directories will be shown as (themed) `-` without status indicated.
 
-This adds a two-character column indicating the staged and unstaged statuses respectively. The status character can be ‘`-`’ for not modified, ‘`M`’ for a modified file, ‘`N`’ for a new file, ‘`D`’ for deleted, ‘`R`’ for renamed, ‘`T`’ for type-change, ‘`I`’ for ignored, and ‘`U`’ for conflicted.
-
-Directories will be shown to have the status of their contents, which is how ‘deleted’ is possible: if a directory contains a file that has a certain status, it will be shown to have that status.
 
 `--no-git`
 : Don't show Git status (always overrides `--git`, `--git-repos`, `--git-repos-no-status`)

+ 1 - 0
src/fs/dir.rs

@@ -42,6 +42,7 @@ impl Dir {
                           .map(|result| result.map(|entry| entry.path()))
                           .collect::<Result<_, _>>()?;
 
+        info!("Read directory success {:?}", &path);
         Ok(Self { contents, path })
     }
 

+ 2 - 0
src/fs/file.rs

@@ -204,6 +204,7 @@ impl<'dir> File<'dir> {
     /// Returns an IO error upon failure, but this shouldn’t be used to check
     /// if a `File` is a directory or not! For that, just use `is_directory()`.
     pub fn to_dir(&self) -> io::Result<Dir> {
+        trace!("to_dir: reading dir");
         Dir::read_dir(self.path.clone())
     }
 
@@ -531,6 +532,7 @@ impl<'dir> File<'dir> {
     /// but as mentioned in the size function comment above, different filesystems
     /// make it difficult to get any info about a dir by it's size, so this may be it.
     fn is_empty_directory(&self) -> bool {
+        trace!("is_empty_directory: reading dir");
         match Dir::read_dir(self.path.clone()) {
             // . & .. are skipped, if the returned iterator has .next(), it's not empty
             Ok(has_files) => has_files.files(super::DotFilter::Dotfiles, None, false, false).next().is_none(),

+ 13 - 2
src/main.rs

@@ -27,6 +27,7 @@ use std::env;
 use std::ffi::{OsStr, OsString};
 use std::io::{self, Write, ErrorKind};
 use std::path::{Component, PathBuf};
+use std::process::exit;
 
 use ansiterm::{ANSIStrings, Style};
 
@@ -87,8 +88,6 @@ lazy_static! {
 }
 
 fn main() {
-    use std::process::exit;
-
     #[cfg(unix)]
     unsafe {
         libc::signal(libc::SIGPIPE, libc::SIG_DFL);
@@ -118,8 +117,11 @@ fn main() {
             let theme = options.theme.to_theme(terminal_size::terminal_size().is_some());
             let exa = Exa { options, writer, input_paths, theme, console_width, git };
 
+
+            info!("matching on exa.run");
             match exa.run() {
                 Ok(exit_status) => {
+                    trace!("exa.run: exit Ok(exit_status)");
                     exit(exit_status);
                 }
 
@@ -130,6 +132,7 @@ fn main() {
 
                 Err(e) => {
                     eprintln!("{e}");
+                    trace!("exa.run: exit RUNTIME_ERROR");
                     exit(exits::RUNTIME_ERROR);
                 }
             }
@@ -225,8 +228,13 @@ impl<'args> Exa<'args> {
 
                 Ok(f) => {
                     if f.points_to_directory() && ! self.options.dir_action.treat_dirs_as_files() {
+                        trace!("matching on to_dir");
                         match f.to_dir() {
                             Ok(d)   => dirs.push(d),
+                            Err(e) if e.kind() == ErrorKind::PermissionDenied => {
+                                warn!("Permission Denied: {e}");
+                                exit(exits::PERMISSION_DENIED);
+                            },
                             Err(e)  => writeln!(io::stderr(), "{file_path:?}: {e}")?,
                         }
                     }
@@ -378,4 +386,7 @@ mod exits {
 
     /// Exit code for when the command-line options are invalid.
     pub const OPTIONS_ERROR: i32 = 3;
+
+    /// Exit code for missing file permissions
+    pub const PERMISSION_DENIED: i32 = 13;
 }

+ 3 - 0
src/output/details.rs

@@ -68,6 +68,8 @@ use std::vec::IntoIter as VecIntoIter;
 use ansiterm::Style;
 use scoped_threadpool::Pool;
 
+use log::*;
+
 use crate::fs::{Dir, File};
 use crate::fs::dir_action::RecurseOptions;
 use crate::fs::feature::git::GitCache;
@@ -261,6 +263,7 @@ impl<'a> Render<'a> {
                     let mut dir = None;
                     if let Some(r) = self.recurse {
                         if file.is_directory() && r.tree && ! r.is_too_deep(depth.0) {
+                            trace!("matching on to_dir");
                             match file.to_dir() {
                                 Ok(d) => {
                                     dir = Some(d);

+ 2 - 2
src/output/render/git.rs

@@ -31,8 +31,8 @@ impl f::SubdirGitRepo {
         let s = match self.status {
             f::SubdirGitRepoStatus::NoRepo => style.paint("- "),
             f::SubdirGitRepoStatus::GitClean => style.fg(Color::Green).paint("| "),
-            f::SubdirGitRepoStatus::GitDirty => style.bold().fg(Color::Red).paint("- "),
-            f::SubdirGitRepoStatus::GitUnknown => style.paint("- "),
+            f::SubdirGitRepoStatus::GitDirty => style.bold().fg(Color::Red).paint("+ "),
+            f::SubdirGitRepoStatus::GitUnknown => style.fg(Color::Green).bold().paint("~ "),
         };
 
         TextCell {

+ 1 - 0
tests/cmd/inexistant_file_unix.stderr

@@ -0,0 +1 @@
+"nonexistentdir": No such file or directory (os error 2)

+ 0 - 0
tests/cmd/inexistant_file_unix.stdout


+ 3 - 0
tests/cmd/inexistant_file_unix.toml

@@ -0,0 +1,3 @@
+bin.name = "eza"
+args = "nonexistentdir"
+status.code = 2

+ 0 - 0
tests/cmd/long_binary_bytes_unix.stderr


+ 21 - 0
tests/cmd/long_binary_bytes_unix.stdout

@@ -0,0 +1,21 @@
+ 0 a
+ 0 b
+ 0 c
+ 0 d
+ 0 e
+ - exa
+ 0 f
+ 0 g
+ 0 h
+ 0 i
+ 0 image.jpg.img.c.rs.log.png
+19 index.svg
+ 0 j
+ 0 k
+ 0 l
+ 0 m
+ 0 n
+ 0 o
+ 0 p
+ 0 q
+ - vagrant

+ 2 - 0
tests/cmd/long_binary_bytes_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --long --no-user --no-time --no-permissions --binary"

+ 0 - 0
tests/cmd/long_file_size_unix.stderr


+ 21 - 0
tests/cmd/long_file_size_unix.stdout

@@ -0,0 +1,21 @@
+ 0 a
+ 0 b
+ 0 c
+ 0 d
+ 0 e
+ - exa
+ 0 f
+ 0 g
+ 0 h
+ 0 i
+ 0 image.jpg.img.c.rs.log.png
+19 index.svg
+ 0 j
+ 0 k
+ 0 l
+ 0 m
+ 0 n
+ 0 o
+ 0 p
+ 0 q
+ - vagrant

+ 2 - 0
tests/cmd/long_file_size_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --long --no-user --no-time --no-permissions"

+ 0 - 0
tests/cmd/long_header_unix.stderr


+ 22 - 0
tests/cmd/long_header_unix.stdout

@@ -0,0 +1,22 @@
+Size Name
+   0 a
+   0 b
+   0 c
+   0 d
+   0 e
+   - exa
+   0 f
+   0 g
+   0 h
+   0 i
+   0 image.jpg.img.c.rs.log.png
+  19 index.svg
+   0 j
+   0 k
+   0 l
+   0 m
+   0 n
+   0 o
+   0 p
+   0 q
+   - vagrant

+ 2 - 0
tests/cmd/long_header_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --long --no-user --no-time --header --no-permissions"

+ 2 - 0
tests/cmd/long_links_recurse_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --long --no-user --no-time --no-filesize --no-permissions --recurse --links"

+ 0 - 0
tests/cmd/long_recurse_with_level_unix.stderr


+ 21 - 0
tests/cmd/long_recurse_with_level_unix.stdout

@@ -0,0 +1,21 @@
+a
+b
+c
+d
+e
+exa
+f
+g
+h
+i
+image.jpg.img.c.rs.log.png
+index.svg
+j
+k
+l
+m
+n
+o
+p
+q
+vagrant

+ 2 - 0
tests/cmd/long_recurse_with_level_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --long --no-user --no-permissions --no-time --no-filesize --recurse --level 2"

+ 21 - 21
tests/cmd/long_unix.stdout

@@ -1,21 +1,21 @@
-.rw-r--r-- a
-.rw-r--r-- b
-.rw-r--r-- c
-.rw-r--r-- d
-.rw-r--r-- e
-drwxr-xr-x exa
-.rw-r--r-- f
-.rw-r--r-- g
-.rw-r--r-- h
-.rw-r--r-- i
-.rw-r--r-- image.jpg.img.c.rs.log.png
-.rw-r--r-- index.svg
-.rw-r--r-- j
-.rw-r--r-- k
-.rw-r--r-- l
-.rw-r--r-- m
-.rw-r--r-- n
-.rw-r--r-- o
-.rw-r--r-- p
-.rw-r--r-- q
-drwxr-xr-x vagrant
+a
+b
+c
+d
+e
+exa
+f
+g
+h
+i
+image.jpg.img.c.rs.log.png
+index.svg
+j
+k
+l
+m
+n
+o
+p
+q
+vagrant

+ 1 - 1
tests/cmd/long_unix.toml

@@ -1,2 +1,2 @@
 bin.name = "eza"
-args = "tests/itest --long --no-user --no-time --no-filesize"
+args = "tests/itest --long --no-user --no-time --no-filesize --no-permissions"

+ 0 - 0
tests/cmd/only_dir_recursive_long_unix.stderr


+ 21 - 0
tests/cmd/only_dir_recursive_long_unix.stdout

@@ -0,0 +1,21 @@
+exa
+vagrant
+
+tests/itest/exa:
+sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
+
+tests/itest/exa/sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss:
+
+tests/itest/vagrant:
+debug
+dev
+log
+
+tests/itest/vagrant/debug:
+
+tests/itest/vagrant/dev:
+
+tests/itest/vagrant/log:
+run
+
+tests/itest/vagrant/log/run:

+ 2 - 0
tests/cmd/only_dir_recursive_long_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --recurse --long --no-user --no-time --no-filesize --no-permissions --only-dirs"

+ 0 - 0
tests/cmd/only_dir_recursive_unix.stderr


+ 21 - 0
tests/cmd/only_dir_recursive_unix.stdout

@@ -0,0 +1,21 @@
+exa
+vagrant
+
+tests/itest/exa:
+sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
+
+tests/itest/exa/sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss:
+
+tests/itest/vagrant:
+debug
+dev
+log
+
+tests/itest/vagrant/debug:
+
+tests/itest/vagrant/dev:
+
+tests/itest/vagrant/log:
+run
+
+tests/itest/vagrant/log/run:

+ 2 - 0
tests/cmd/only_dir_recursive_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --only-dirs --recurse"

+ 0 - 0
tests/cmd/only_dir_unix.stderr


+ 2 - 0
tests/cmd/only_dir_unix.stdout

@@ -0,0 +1,2 @@
+exa
+vagrant

+ 2 - 0
tests/cmd/only_dir_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --only-dirs"

+ 0 - 0
tests/cmd/recursive_long_unix.stderr


+ 47 - 0
tests/cmd/recursive_long_unix.stdout

@@ -0,0 +1,47 @@
+a
+b
+c
+d
+e
+exa
+f
+g
+h
+i
+image.jpg.img.c.rs.log.png
+index.svg
+j
+k
+l
+m
+n
+o
+p
+q
+vagrant
+
+tests/itest/exa:
+file.c -> djihisudjuhfius
+sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
+
+tests/itest/exa/sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss:
+Makefile
+
+tests/itest/vagrant:
+debug
+dev
+log
+
+tests/itest/vagrant/debug:
+symlinking -> a
+
+tests/itest/vagrant/dev:
+main.bf
+
+tests/itest/vagrant/log:
+file.png
+run
+
+tests/itest/vagrant/log/run:
+run.log.text
+sps.log.text

+ 2 - 0
tests/cmd/recursive_long_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --recurse --long --no-user --no-time --no-filesize --no-permissions"

+ 0 - 0
tests/cmd/recursive_unix.stderr


+ 47 - 0
tests/cmd/recursive_unix.stdout

@@ -0,0 +1,47 @@
+a
+b
+c
+d
+e
+exa
+f
+g
+h
+i
+image.jpg.img.c.rs.log.png
+index.svg
+j
+k
+l
+m
+n
+o
+p
+q
+vagrant
+
+tests/itest/exa:
+file.c -> djihisudjuhfius
+sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
+
+tests/itest/exa/sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss:
+Makefile
+
+tests/itest/vagrant:
+debug
+dev
+log
+
+tests/itest/vagrant/debug:
+symlinking -> a
+
+tests/itest/vagrant/dev:
+main.bf
+
+tests/itest/vagrant/log:
+file.png
+run
+
+tests/itest/vagrant/log/run:
+run.log.text
+sps.log.text

+ 2 - 0
tests/cmd/recursive_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --recurse"

+ 0 - 0
tests/cmd/tree_long_unix.stderr


+ 34 - 0
tests/cmd/tree_long_unix.stdout

@@ -0,0 +1,34 @@
+tests/itest
+├── a
+├── b
+├── c
+├── d
+├── e
+├── exa
+│  ├── file.c -> djihisudjuhfius
+│  └── sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
+│     └── Makefile
+├── f
+├── g
+├── h
+├── i
+├── image.jpg.img.c.rs.log.png
+├── index.svg
+├── j
+├── k
+├── l
+├── m
+├── n
+├── o
+├── p
+├── q
+└── vagrant
+   ├── debug
+   │  └── symlinking -> a
+   ├── dev
+   │  └── main.bf
+   └── log
+      ├── file.png
+      └── run
+         ├── run.log.text
+         └── sps.log.text

+ 2 - 0
tests/cmd/tree_long_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --tree --long --no-user --no-time --no-filesize --no-permissions"

+ 0 - 0
tests/cmd/tree_unix.stderr


+ 34 - 0
tests/cmd/tree_unix.stdout

@@ -0,0 +1,34 @@
+tests/itest
+├── a
+├── b
+├── c
+├── d
+├── e
+├── exa
+│  ├── file.c -> djihisudjuhfius
+│  └── sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
+│     └── Makefile
+├── f
+├── g
+├── h
+├── i
+├── image.jpg.img.c.rs.log.png
+├── index.svg
+├── j
+├── k
+├── l
+├── m
+├── n
+├── o
+├── p
+├── q
+└── vagrant
+   ├── debug
+   │  └── symlinking -> a
+   ├── dev
+   │  └── main.bf
+   └── log
+      ├── file.png
+      └── run
+         ├── run.log.text
+         └── sps.log.text

+ 2 - 0
tests/cmd/tree_unix.toml

@@ -0,0 +1,2 @@
+bin.name = "eza"
+args = "tests/itest --tree"

+ 1 - 0
treefmt.nix

@@ -3,5 +3,6 @@
   programs = {
     alejandra.enable = true;
     rustfmt.enable = true;
+    shellcheck.enable = true;
   };
 }