Skip to content
Open
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
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ Wherever possible we try to implement the specification as documented in
the `ssh_config` manpage. Unimplemented features should be present in the
[issues][issues] list.

Notably, the `Match` directive is currently unsupported.

[issues]: https://github.com/kevinburke/ssh_config/issues

## Errata
Expand Down
5 changes: 2 additions & 3 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
//
// // Write the cfg back to disk:
// fmt.Println(cfg.String())
//
// BUG: the Match directive is currently unsupported; parsing a config with
// a Match directive will trigger an error.
package ssh_config

import (
Expand Down Expand Up @@ -538,6 +535,8 @@ type Host struct {
EOLComment string
// Whitespace if any between the Host declaration and a trailing comment.
spaceBeforeComment string
// Whether this Host block was created by a Match directive
isMatch bool

hasEquals bool
leadingSpace int // TODO: handle spaces vs tabs here.
Expand Down
4 changes: 2 additions & 2 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ func TestMatches(t *testing.T) {
}
}

func TestMatchUnsupported(t *testing.T) {
func TestMatchSupported(t *testing.T) {
us := &UserSettings{
userConfigFinder: testConfigFinder("testdata/match-directive"),
}
Expand All @@ -397,7 +397,7 @@ func TestMatchUnsupported(t *testing.T) {
if err == nil {
t.Fatal("expected Match directive to error, didn't")
}
if !strings.Contains(err.Error(), "ssh_config: Match directive parsing is unsupported") {
if strings.Contains(err.Error(), "ssh_config: Match directive parsing is now supported") {
t.Errorf("wrong error: %v", err)
}
}
Expand Down
42 changes: 39 additions & 3 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,45 @@ func (p *sshParser) parseKV() sshParserStateFn {
comment = tok.val
}
if strings.ToLower(key.val) == "match" {
// https://github.com/kevinburke/ssh_config/issues/6
p.raiseErrorf(val, "ssh_config: Match directive parsing is unsupported")
return nil
// Split the value into criteria
criteria := strings.Fields(val.val)
if len(criteria) < 2 {
p.raiseErrorf(val, "ssh_config: Match directive requires at least one criterion")
return nil
}

// Currently only supporting Host criterion
criterion := strings.ToLower(criteria[0])
if criterion != "host" {
p.raiseErrorf(val, "ssh_config: Only Match Host is currently supported, got %s", criterion)
return nil
}

// Parse the host patterns
patterns := make([]*Pattern, 0)
for _, strPattern := range criteria[1:] {
if strPattern == "" {
continue
}
pat, err := NewPattern(strPattern)
if err != nil {
p.raiseErrorf(val, "Invalid host pattern: %v", err)
return nil
}
patterns = append(patterns, pat)
}

// Create a new Host block for this Match directive
spaceBeforeComment := val.val[len(strings.TrimRightFunc(val.val, unicode.IsSpace)):]
p.config.Hosts = append(p.config.Hosts, &Host{
Patterns: patterns,
Nodes: make([]Node, 0),
EOLComment: comment,
spaceBeforeComment: spaceBeforeComment,
hasEquals: hasEquals,
isMatch: true,
})
return p.parseStart
}
if strings.ToLower(key.val) == "host" {
strPatterns := strings.Split(val.val, " ")
Expand Down
Loading