diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index 934a40a3db1..6dd5ad43d20 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -243,7 +243,10 @@ fn get_all_filesystems(opt: &Options) -> Vec { // Convert each `MountInfo` into a `Filesystem`, which contains // both the mount information and usage information. - mounts.into_iter().filter_map(Filesystem::new).collect() + mounts + .into_iter() + .filter_map(|m| Filesystem::new(m, None)) + .collect() } /// For each path, get the filesystem that contains that path. diff --git a/src/uu/df/src/filesystem.rs b/src/uu/df/src/filesystem.rs index bd9ff34eba8..00b81007317 100644 --- a/src/uu/df/src/filesystem.rs +++ b/src/uu/df/src/filesystem.rs @@ -23,6 +23,13 @@ use uucore::fsext::{FsUsage, MountInfo}; /// space available on the filesystem and the amount of space used. #[derive(Debug, Clone)] pub(crate) struct Filesystem { + /// The file given on the command line if any. + /// + /// When invoking `df` with a positional argument, it displays + /// usage information for the filesystem that contains the given + /// file. If given, this field contains that filename. + pub file: Option, + /// Information about the mounted device, mount directory, and related options. pub mount_info: MountInfo, @@ -66,7 +73,7 @@ where impl Filesystem { // TODO: resolve uuid in `mount_info.dev_name` if exists - pub(crate) fn new(mount_info: MountInfo) -> Option { + pub(crate) fn new(mount_info: MountInfo, file: Option) -> Option { let _stat_path = if !mount_info.mount_dir.is_empty() { mount_info.mount_dir.clone() } else { @@ -84,7 +91,11 @@ impl Filesystem { let usage = FsUsage::new(statfs(_stat_path).ok()?); #[cfg(windows)] let usage = FsUsage::new(Path::new(&_stat_path)); - Some(Self { mount_info, usage }) + Some(Self { + mount_info, + usage, + file, + }) } /// Find and create the filesystem that best matches a given path. @@ -107,11 +118,12 @@ impl Filesystem { where P: AsRef, { + let file = path.as_ref().display().to_string(); let canonicalize = true; let mount_info = mount_info_from_path(mounts, path, canonicalize)?; // TODO Make it so that we do not need to clone the `mount_info`. let mount_info = (*mount_info).clone(); - Self::new(mount_info) + Self::new(mount_info, Some(file)) } } diff --git a/src/uu/df/src/table.rs b/src/uu/df/src/table.rs index 00fe31cafdf..63e39ea215f 100644 --- a/src/uu/df/src/table.rs +++ b/src/uu/df/src/table.rs @@ -24,6 +24,9 @@ use std::ops::AddAssign; /// A row comprises several pieces of information, including the /// filesystem device, the mountpoint, the number of bytes used, etc. pub(crate) struct Row { + /// The filename given on the command-line, if given. + file: Option, + /// Name of the device on which the filesystem lives. fs_device: String, @@ -73,6 +76,7 @@ pub(crate) struct Row { impl Row { pub(crate) fn new(source: &str) -> Self { Self { + file: None, fs_device: source.into(), fs_type: "-".into(), fs_mount: "-".into(), @@ -101,6 +105,7 @@ impl AddAssign for Row { let inodes = self.inodes + rhs.inodes; let inodes_used = self.inodes_used + rhs.inodes_used; *self = Self { + file: None, fs_device: "total".into(), fs_type: "-".into(), fs_mount: "-".into(), @@ -145,6 +150,7 @@ impl From for Row { .. } = fs.usage; Self { + file: fs.file, fs_device: dev_name, fs_type, fs_mount: mount_dir, @@ -246,8 +252,9 @@ impl fmt::Display for DisplayRow<'_> { Column::Ipcent => { write!(f, "{0: >5} ", DisplayRow::percentage(self.row.inodes_usage))?; } - // TODO Implement this. - Column::File => {} + Column::File => { + write!(f, "{0: <16}", self.row.file.as_ref().unwrap_or(&"-".into()))? + } Column::Fstype => write!(f, "{0: <5} ", self.row.fs_type)?, #[cfg(target_os = "macos")] Column::Capacity => write!( @@ -406,6 +413,7 @@ mod tests { ..Default::default() }; let row = Row { + file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), @@ -437,6 +445,7 @@ mod tests { ..Default::default() }; let row = Row { + file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), @@ -468,6 +477,7 @@ mod tests { ..Default::default() }; let row = Row { + file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), @@ -499,6 +509,7 @@ mod tests { ..Default::default() }; let row = Row { + file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), @@ -530,6 +541,7 @@ mod tests { ..Default::default() }; let row = Row { + file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), @@ -560,6 +572,7 @@ mod tests { ..Default::default() }; let row = Row { + file: Some("/path/to/file".to_string()), fs_device: "my_device".to_string(), fs_type: "my_type".to_string(), fs_mount: "my_mount".to_string(), diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index 4ba76385c29..24277890d5e 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -222,4 +222,45 @@ fn test_output_selects_columns() { ); } -// ToDO: more tests... +// TODO Fix the spacing. +#[test] +fn test_output_file_all_filesystems() { + // When run with no positional arguments, `df` lets "-" represent + // the "File" entry for each row. + let output = new_ucmd!() + .arg("--output=file") + .succeeds() + .stdout_move_str(); + let mut lines = output.lines(); + assert_eq!(lines.next().unwrap(), "File "); + for line in lines { + assert_eq!(line, "- "); + } +} + +// TODO Fix the spacing. +#[test] +fn test_output_file_specific_files() { + // Create three files. + let (at, mut ucmd) = at_and_ucmd!(); + at.touch("a"); + at.touch("b"); + at.touch("c"); + + // When run with positional arguments, the filesystems should + // appear in the "File" column. + let output = ucmd + .args(&["--output=file", "a", "b", "c"]) + .succeeds() + .stdout_move_str(); + let actual: Vec<&str> = output.lines().collect(); + assert_eq!( + actual, + vec![ + "File ", + "a ", + "b ", + "c " + ] + ); +}