Procházet zdrojové kódy

Merge branch 'main' into fix_windows_build

Signed-off-by: Steven Davies <github@steev.me.uk>
Steven Davies před 2 roky
rodič
revize
0f85df3073
9 změnil soubory, kde provedl 258 přidání a 45 odebrání
  1. 3 1
      .envrc
  2. 2 2
      .github/workflows/flake.yml
  3. 1 1
      .github/workflows/stale.yml
  4. 141 17
      Cargo.lock
  5. 4 4
      Cargo.toml
  6. 45 4
      flake.nix
  7. 1 1
      rust-toolchain.toml
  8. 57 12
      src/fs/file.rs
  9. 4 3
      src/options/help.rs

+ 3 - 1
.envrc

@@ -1 +1,3 @@
-use flake .
+if has nix; then
+  use flake .
+fi

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

@@ -10,8 +10,8 @@ jobs:
     steps:
       - uses: actions/checkout@v3
       - name: Check Nix flake inputs
-        uses: DeterminateSystems/flake-checker-action@v4 # This action
+        uses: DeterminateSystems/flake-checker-action@v5 # This action
       - name: Install Nix
-        uses: DeterminateSystems/nix-installer-action@v3
+        uses: DeterminateSystems/nix-installer-action@v4
       - name: Build default package
         run: nix build

+ 1 - 1
.github/workflows/stale.yml

@@ -18,7 +18,7 @@ jobs:
       pull-requests: write
 
     steps:
-    - uses: actions/stale@v5
+    - uses: actions/stale@v8
       with:
         repo-token: ${{ secrets.GITHUB_TOKEN }}
         

+ 141 - 17
Cargo.lock

@@ -19,9 +19,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "bitflags"
-version = "1.2.1"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
 
 [[package]]
 name = "byteorder"
@@ -51,6 +57,27 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "errno"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
 [[package]]
 name = "eza"
 version = "0.10.9"
@@ -87,11 +114,11 @@ dependencies = [
 
 [[package]]
 name = "git2"
-version = "0.17.2"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b989d6a7ca95a362cf2cfc5ad688b3a467be1f87e480b8dad07fee8c79b0044"
+checksum = "12ef350ba88a33b4d524b1d1c79096c9ade5ef8c59395df0e60d1e1889414c0e"
 dependencies = [
- "bitflags",
+ "bitflags 2.4.0",
  "libc",
  "libgit2-sys",
  "log",
@@ -101,9 +128,9 @@ dependencies = [
 
 [[package]]
 name = "glob"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
 
 [[package]]
 name = "hermit-abi"
@@ -122,6 +149,17 @@ dependencies = [
  "unicode-normalization",
 ]
 
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "windows-sys",
+]
+
 [[package]]
 name = "jobserver"
 version = "0.1.22"
@@ -145,9 +183,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
 
 [[package]]
 name = "libgit2-sys"
-version = "0.15.2+1.6.4"
+version = "0.16.1+1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a80df2e11fb4a61f4ba2ab42dbe7f74468da143f1a75c74e11dee7c813f694fa"
+checksum = "f2a2bb3680b094add03bb3732ec520ece34da31a8cd2d633d1389d0f0fb60d0c"
 dependencies = [
  "cc",
  "libc",
@@ -168,6 +206,12 @@ dependencies = [
  "vcpkg",
 ]
 
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
 [[package]]
 name = "locale"
 version = "0.2.2"
@@ -261,6 +305,20 @@ version = "0.1.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
 
+[[package]]
+name = "rustix"
+version = "0.37.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
+dependencies = [
+ "bitflags 1.3.2",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
 [[package]]
 name = "scoped_threadpool"
 version = "0.1.9"
@@ -278,19 +336,19 @@ dependencies = [
 
 [[package]]
 name = "terminal_size"
-version = "0.1.16"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406"
+checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
 dependencies = [
- "libc",
- "winapi",
+ "rustix",
+ "windows-sys",
 ]
 
 [[package]]
 name = "timeago"
-version = "0.3.1"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ec32dde57efb15c035ac074118d7f32820451395f28cb0524a01d4e94983b26"
+checksum = "5082dc942361cdfb74eab98bf995762d6015e5bb3a20bf7c5c71213778b4fcb4"
 
 [[package]]
 name = "tinyvec"
@@ -345,9 +403,9 @@ dependencies = [
 
 [[package]]
 name = "uzers"
-version = "0.11.1"
+version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76f77f08efdd6dfbf13363b13db3649431d35d682f1c074edc476a04afaba466"
+checksum = "49546562f3f91dcad51aab95b9664113f099dd829c5dcd8ba1486fddb7d3bccc"
 dependencies = [
  "libc",
  "log",
@@ -381,6 +439,72 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
 [[package]]
 name = "zoneinfo_compiled"
 version = "0.5.1"

+ 4 - 4
Cargo.toml

@@ -47,8 +47,8 @@ num_cpus = "1.16"
 number_prefix = "0.4"
 scoped_threadpool = "0.1"
 term_grid = "0.1"
-terminal_size = "0.1.16"
-timeago = { version = "0.3.1", default-features = false }
+terminal_size = "0.2.6"
+timeago = { version = "0.4.1", default-features = false }
 unicode-width = "0.1"
 zoneinfo_compiled = "0.5.1"
 
@@ -58,12 +58,12 @@ default-features = false
 features = ["format"]
 
 [dependencies.git2]
-version = "0.17"
+version = "0.18"
 optional = true
 default-features = false
 
 [target.'cfg(unix)'.dependencies]
-uzers = "0.11.1"
+uzers = "0.11.2"
 
 [build-dependencies.datetime]
 version = "0.5.2"

+ 45 - 4
flake.nix

@@ -40,11 +40,52 @@
         formatter = treefmtEval.config.build.wrapper;
 
         packages = {
-          # For `nix build` & `nix run`:
+          # For `nix build` `nix run`, & `nix profile install`:
           default = naersk'.buildPackage {
+            pname = "eza";
+            version = "latest";
+
             src = ./.;
             doCheck = true; # run `cargo test` on build
-            inherit buildInputs;
+
+            # buildInputs = with pkgs; [ zlib ]
+            #   ++ lib.optionals stdenv.isDarwin [ libiconv Security ];
+            buildInputs = buildInputs ++ (with pkgs; [zlib]);
+
+            nativeBuildInputs = with pkgs; [cmake pkg-config installShellFiles pandoc];
+
+            buildNoDefaultFeatures = true;
+            # buildFeatures = lib.optional gitSupport "git";
+            buildFeatures = "git";
+
+            # outputs = [ "out" "man" ];
+
+            postInstall = ''
+              pandoc --standalone -f markdown -t man man/eza.1.md > man/eza.1
+              pandoc --standalone -f markdown -t man man/eza_colors.5.md > man/eza_colors.5
+              pandoc --standalone -f markdown -t man man/eza_colors-explanation.5.md > man/eza_colors-explanation.5
+              installManPage man/eza.1 man/eza_colors.5 man/eza_colors-explanation.5
+              installShellCompletion \
+                --bash completions/bash/eza \
+                --fish completions/fish/eza.fish \
+                --zsh completions/zsh/_eza
+            '';
+
+            meta = with pkgs.lib; {
+              description = "A modern, maintained replacement for ls";
+              longDescription = ''
+                eza is a modern replacement for ls. It uses colours for information by
+                default, helping you distinguish between many types of files, such as
+                whether you are the owner, or in the owning group. 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. eza is
+                written in Rust, so it’s small, fast, and portable.
+              '';
+              homepage = "https://github.com/eza-community/eza";
+              license = licenses.mit;
+              mainProgram = "eza";
+              maintainers = with maintainers; [cafkafk];
+            };
           };
 
           # Run `nix build .#check` to check code
@@ -71,10 +112,10 @@
 
         # For `nix develop`:
         devShells.default = pkgs.mkShell {
-          nativeBuildInputs = with pkgs; [ toolchain just pandoc vhs convco ];
+          nativeBuildInputs = with pkgs; [toolchain just pandoc vhs convco];
         };
 
-        # for `nix flake check`
+        # For `nix flake check`
         checks = {
           formatting = treefmtEval.config.build.check self;
           build = packages.check;

+ 1 - 1
rust-toolchain.toml

@@ -1,4 +1,4 @@
 [toolchain]
-channel = "nightly"
+channel = "stable"
 components = [ "rustfmt", "rustc", "rust-src", "rust-analyzer", "cargo", "clippy" ]
 profile = "minimal"

+ 57 - 12
src/fs/file.rs

@@ -431,29 +431,74 @@ impl<'dir> File<'dir> {
         }
     }
 
-    // To display icons for empty folders.
-    // The naive approach, as one would think that this info may have been cached.
-    // 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.
+    /// Returns the size of the file or indicates no size if it's a directory.
+    ///
+    /// For Windows platforms, the size of directories is not computed and will 
+    /// return `Size::None`.
+    #[cfg(windows)]
+    pub fn size(&self) -> f::Size {
+        if self.is_directory() {
+            f::Size::None
+        }
+        else {
+            f::Size::Some(self.metadata.len())
+        }
+    }
+
+    /// Determines if the directory is empty or not.
+    ///
+    /// For Unix platforms, this function first checks the link count to quickly 
+    /// determine non-empty directories. On most UNIX filesystems the link count
+    /// is two plus the number of subdirectories. If the link count is less than
+    /// or equal to 2, it then checks the directory contents to determine if
+    /// it's truly empty. The naive approach used here checks the contents
+    /// directly, as certain filesystems make it difficult to infer emptiness
+    /// based on directory size alone.
+    #[cfg(unix)]
     pub fn is_empty_dir(&self) -> bool {
         if self.is_directory() {
-            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(),
-                Err(_) => false,
+            if self.metadata.nlink() > 2 {
+                // Directories will have a link count of two if they do not have any subdirectories.
+                // The '.' entry is a link to itself and the '..' is a link to the parent directory.
+                // A subdirectory will have a link to its parent directory increasing the link count
+                // above two.  This will avoid the expensive read_dir call below when a directory
+                // has subdirectories.
+                false
+            } else {
+                self.is_empty_directory()
             }
         } else {
             false
         }
     }
 
+    /// Determines if the directory is empty or not.
+    ///
+    /// For Windows platforms, this function checks the directory contents directly 
+    /// to determine if it's empty. Since certain filesystems on Windows make it 
+    /// challenging to infer emptiness based on directory size, this approach is used.
     #[cfg(windows)]
-    pub fn size(&self) -> f::Size {
+    pub fn is_empty_dir(&self) -> bool {
         if self.is_directory() {
-            f::Size::None
+            self.is_empty_directory()
+        } else {
+            false
         }
-        else {
-            f::Size::Some(self.metadata.len())
+    }
+
+    /// Checks the contents of the directory to determine if it's empty.
+    ///
+    /// This function avoids counting '.' and '..' when determining if the directory is 
+    /// empty. If any other entries are found, it returns `false`.
+    ///
+    /// The naive approach, as one would think that this info may have been cached.
+    /// 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 {
+        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(),
+            Err(_) => false,
         }
     }
 

+ 4 - 3
src/options/help.rs

@@ -37,7 +37,10 @@ FILTERING AND SORTING OPTIONS
   -D, --only-dirs            list only directories
   -I, --ignore-glob GLOBS    glob patterns (pipe-separated) of files to ignore";
 
-  static USAGE_PART2: &str = "  \
+static GIT_FILTER_HELP: &str = "  \
+  --git-ignore               ignore files mentioned in '.gitignore'";
+
+static USAGE_PART2: &str = "  \
   Valid sort fields:         name, Name, extension, Extension, size, type,
                              modified, accessed, created, inode, and none.
                              date, time, old, and new all refer to modified.
@@ -63,8 +66,6 @@ LONG VIEW OPTIONS
   --no-user                suppress the user field
   --no-time                suppress the time field";
 
-static GIT_FILTER_HELP: &str = "  \
-  --git-ignore             ignore files mentioned in '.gitignore'";
 static GIT_VIEW_HELP:   &str = "  \
   --git                    list each file's Git status, if tracked or ignored
   --no-git                 suppress Git status (always overrides --git, --git-repos, --git-repos-no-status)