Skip to content

Commit

Permalink
Merge pull request #3294 from jfinkels/df-file-column
Browse files Browse the repository at this point in the history
df: implement the File column
  • Loading branch information
sylvestre authored Mar 27, 2022
2 parents c932236 + ab717ce commit d5d6bc3
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 7 deletions.
5 changes: 4 additions & 1 deletion src/uu/df/src/df.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,10 @@ fn get_all_filesystems(opt: &Options) -> Vec<Filesystem> {

// 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.
Expand Down
18 changes: 15 additions & 3 deletions src/uu/df/src/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,

/// Information about the mounted device, mount directory, and related options.
pub mount_info: MountInfo,

Expand Down Expand Up @@ -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<Self> {
pub(crate) fn new(mount_info: MountInfo, file: Option<String>) -> Option<Self> {
let _stat_path = if !mount_info.mount_dir.is_empty() {
mount_info.mount_dir.clone()
} else {
Expand All @@ -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.
Expand All @@ -107,11 +118,12 @@ impl Filesystem {
where
P: AsRef<Path>,
{
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))
}
}

Expand Down
17 changes: 15 additions & 2 deletions src/uu/df/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,

/// Name of the device on which the filesystem lives.
fs_device: String,

Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -145,6 +150,7 @@ impl From<Filesystem> for Row {
..
} = fs.usage;
Self {
file: fs.file,
fs_device: dev_name,
fs_type,
fs_mount: mount_dir,
Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
43 changes: 42 additions & 1 deletion tests/by-util/test_df.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
]
);
}

0 comments on commit d5d6bc3

Please sign in to comment.