[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/disk-usage e3d0a0f 2/5: Also take hard-links into accou
From: |
Stefan Monnier |
Subject: |
[elpa] externals/disk-usage e3d0a0f 2/5: Also take hard-links into account when calculating dir size in pure Emacs. |
Date: |
Wed, 17 Mar 2021 18:41:15 -0400 (EDT) |
branch: externals/disk-usage
commit e3d0a0fe7c7dad2f57366da2a5db7ec3dc349366
Author: Pierre Neidhardt <mail@ambrevar.xyz>
Commit: Pierre Neidhardt <mail@ambrevar.xyz>
Also take hard-links into account when calculating dir size in pure Emacs.
---
disk-usage.el | 31 ++++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/disk-usage.el b/disk-usage.el
index 505e6fc..c9d7865 100644
--- a/disk-usage.el
+++ b/disk-usage.el
@@ -156,6 +156,8 @@
(:constructor disk-usage--file-info-make))
size
name
+ (device 0) ; Used to identify hard links.
+ (inode 0) ; Used to identify hard links.
(children 0)
(marked nil))
@@ -273,6 +275,8 @@ See `disk-usage-add-filters' and
`disk-usage-remove-filters'.")
if (null (file-attribute-type attributes))
collect (disk-usage--file-info-make
:name path
+ :inode (file-attribute-inode-number attributes)
+ :device (file-attribute-device-number attributes)
:size (file-attribute-size attributes))
;; Symlinks
else if (stringp (file-attribute-type attributes))
@@ -313,12 +317,15 @@ $ find . -type f -exec du -sb {} +"
'nosort)
for name = (car file)
for attributes = (cdr file)
+ do (message "FILE %s" file)
when (and attributes
- (not (file-attribute-type attributes))
+ (not (file-attribute-type attributes))
; We discard non-files.
(cl-loop for filter in
disk-usage-filters
always (funcall filter name
attributes)))
collect (disk-usage--file-info-make
:name name
+ :inode (file-attribute-inode-number
attributes)
+ :device (file-attribute-device-number
attributes)
:size (file-attribute-size
attributes))))))
(defcustom disk-usage-list-function #'disk-usage--list
@@ -338,8 +345,18 @@ It takes the directory to scan as argument."
(tabulated-list-revert))
(defun disk-usage--total (listing)
- (cl-loop for file in listing
- sum (disk-usage--file-info-size file)))
+ "Return the total size of all files in LISTING.
+Hard-links are taken into account."
+ (let ((map (make-hash-table :test #'equal)))
+ (cl-loop with map = (make-hash-table :test #'equal)
+ for file in listing
+ for index = (and (/= 0 (disk-usage--file-info-inode file))
+ (list (disk-usage--file-info-inode file)
+ (disk-usage--file-info-device file)))
+ unless (gethash index map)
+ sum (disk-usage--file-info-size file)
+ when index
+ do (puthash index t map))))
(defun disk-usage--directory-size (path)
(let ((size (unless current-prefix-arg
@@ -354,8 +371,12 @@ It takes the directory to scan as argument."
(defun disk-usage-directory-size-with-emacs (path)
"Return the total disk usage of directory PATH as a number.
-This is slow but does not require any external process."
- (disk-usage--total (disk-usage--list path)))
+This is slow but does not require any external process.
+Hard-links are taken into account."
+ ;; `disk-usage--list' won't do since we need to detect hard-links across
+ ;; subdirectories. This is unfortunately slower, but since we have the fast
+ ;; `disk-usage-directory-size-with-du' it's not worth optimizing.
+ (disk-usage--total (disk-usage--list-recursively path)))
(defalias 'disk-usage--directory-size-with-emacs
'disk-usage-directory-size-with-emacs)
(defun disk-usage-directory-size-with-du (path)