mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
docs(ssh): record why Match blocks are skipped, where they are skipped
`Match` is dropped along with everything under it, and nothing in the code said whether that was a decision or an oversight. It is a decision -- `docs/remote/ssh.mdx` lists "No `Match` or `canonicalize*` directives" under what is not supported -- and it took a run of `ssh -G` against a config to establish that, which is a reason for the next reader not to have to. The comment also says why reading them is more than parsing them: `Match host` tests the *resolved* hostname, so it needs the pass it sits in; `Match exec` runs a command, which importing a config file should not do; `Match canonical` wants canonicalisation, which is on the same unsupported list. The test holds the documented shape: `ssh -G` answers `user alice` and `port 2222` for that config, tty7 answers the defaults, and the profile is still imported from its `Host` block. It is a limitation rather than a behaviour, so it is worth a test only because failing it means the page has to change in the same commit.
This commit is contained in:
@@ -622,6 +622,19 @@ fn parse_config_file(
|
||||
options: Vec::new(),
|
||||
});
|
||||
} else if key.eq_ignore_ascii_case("match") {
|
||||
// Everything until the next `Host` is skipped, on purpose:
|
||||
// "No `Match` or `canonicalize*` directives" is what
|
||||
// `docs/remote/ssh.mdx` promises, and this is where that is kept.
|
||||
//
|
||||
// Reading them would mean more than parsing them. `Match host`
|
||||
// tests the *resolved* hostname, so it needs the pass this one is
|
||||
// producing; `Match exec` runs a command, which is not something an
|
||||
// import of a config file should do; `Match canonical` needs
|
||||
// canonicalisation, which is on the same list of things tty7 does
|
||||
// not do. A profile imported from a config with a `Match` block
|
||||
// therefore carries the `Host` block's answer alone — `ssh -G`
|
||||
// would say `user alice`, and this says the default — which is the
|
||||
// documented shape rather than an oversight.
|
||||
if let Some(block) = current.take() {
|
||||
blocks.push(block);
|
||||
}
|
||||
@@ -1023,6 +1036,41 @@ mod tests {
|
||||
/// own directory agrees for `~/.ssh/config` and diverges one level down,
|
||||
/// where `Include extra.conf` inside `~/.ssh/conf.d/x.conf` would reach
|
||||
/// `~/.ssh/conf.d/extra.conf` instead of the file ssh reads.
|
||||
/// A `Match` block's settings do not reach an imported profile.
|
||||
///
|
||||
/// `docs/remote/ssh.mdx` lists "No `Match` or `canonicalize*` directives"
|
||||
/// under what is not supported, and `ssh -G` on this config answers
|
||||
/// `user alice` and `port 2222` where tty7 answers the defaults. That gap
|
||||
/// is the documented one.
|
||||
///
|
||||
/// If this ever fails because `Match` was implemented, the page saying it
|
||||
/// is not supported has to change in the same commit — which is the only
|
||||
/// reason to hold a limitation in a test.
|
||||
#[test]
|
||||
fn a_match_block_is_not_read_into_a_profile() {
|
||||
let root = temp_root("match-block");
|
||||
let ssh = root.join(".ssh");
|
||||
std::fs::create_dir_all(&ssh).unwrap();
|
||||
std::fs::write(
|
||||
ssh.join("config"),
|
||||
"Host work\n HostName work.example\n\n\
|
||||
Match host work.example\n User alice\n Port 2222\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let imported = import_profiles_from(ssh.join("config"), &root);
|
||||
let work = imported
|
||||
.iter()
|
||||
.find(|p| p.profile.name == "work")
|
||||
.expect("the Host block still imports");
|
||||
assert_eq!(work.profile.host, "work.example");
|
||||
assert_eq!(
|
||||
(work.profile.user.as_str(), work.profile.port),
|
||||
("", 22),
|
||||
"a Match block reached the profile; docs/remote/ssh.mdx says it does not"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_nested_include_resolves_against_ssh_not_the_including_file() {
|
||||
let root = temp_root("nested-includes");
|
||||
|
||||
Reference in New Issue
Block a user