Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

df: implement the File column #3294

Merged
merged 1 commit into from
Mar 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 "
]
);
}