1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use {EXIT_ERROR, EXIT_SUCCESS, POLLED_TWICE};
use clap::{App, AppSettings, Arg};
use env::{AsyncIoEnvironment, FileDescEnvironment, StringWrapper,
ReportErrorEnvironment, WorkingDirectoryEnvironment};
use io::FileDesc;
use future::{EnvFuture, Poll};
use path::{has_dot_components, NormalizationError, NormalizedPath};
use spawn::ExitResult;
use std::borrow::Borrow;
use std::path::Path;
use void::Void;
impl_generic_builtin_cmd! {
pub struct Pwd;
pub fn pwd();
pub struct SpawnedPwd;
pub struct PwdFuture;
where T: StringWrapper,
E: WorkingDirectoryEnvironment,
}
impl<T, I, E: ?Sized> EnvFuture<E> for SpawnedPwd<I>
where T: StringWrapper,
I: Iterator<Item = T>,
E: AsyncIoEnvironment
+ FileDescEnvironment
+ ReportErrorEnvironment
+ WorkingDirectoryEnvironment,
E::FileHandle: Borrow<FileDesc>,
{
type Item = ExitResult<PwdFuture<E::WriteAll>>;
type Error = Void;
fn poll(&mut self, env: &mut E) -> Poll<Self::Item, Self::Error> {
const PWD: &str = "pwd";
const ARG_LOGICAL: &str = "L";
const ARG_PHYSICAL: &str = "P";
let app = App::new(PWD)
.setting(AppSettings::NoBinaryName)
.setting(AppSettings::DisableVersion)
.about("Prints the absolute path name of the current working directory")
.arg(Arg::with_name(ARG_LOGICAL)
.short(ARG_LOGICAL)
.multiple(true)
.overrides_with(ARG_PHYSICAL)
.help("Display the logical current working directory.")
)
.arg(Arg::with_name(ARG_PHYSICAL)
.short(ARG_PHYSICAL)
.multiple(true)
.overrides_with(ARG_LOGICAL)
.help("Display the physical current working directory (all symbolic links resolved).")
);
let app_args = self.args.take()
.expect(POLLED_TWICE)
.into_iter()
.map(StringWrapper::into_owned);
let matches = try_and_report!(PWD, app.get_matches_from_safe(app_args), env);
generate_and_print_output!(PWD, env, |env| {
let mut cwd_bytes = if matches.is_present(ARG_PHYSICAL) {
physical(env.current_working_dir())
} else {
logical(env.current_working_dir())
};
if let Ok(ref mut bytes) = cwd_bytes {
bytes.push(b'\n');
}
cwd_bytes
})
}
fn cancel(&mut self, _env: &mut E) {
self.args.take();
}
}
fn logical(path: &Path) -> Result<Vec<u8>, NormalizationError> {
if has_dot_components(path) {
physical(path)
} else {
let bytes = path.to_string_lossy().into_owned().into_bytes();
Ok(bytes)
}
}
fn physical(path: &Path) -> Result<Vec<u8>, NormalizationError> {
let mut normalized_path = NormalizedPath::new();
normalized_path.join_normalized_physical(path)
.map(|()| normalized_path.to_string_lossy().into_owned().into_bytes())
}