Cleanup for public release
- Test Include string representation - Add docs and examples
This commit is contained in:
48
config.go
48
config.go
@@ -297,20 +297,21 @@ func special(b byte) bool {
|
|||||||
return bytes.IndexByte(specialBytes, b) >= 0
|
return bytes.IndexByte(specialBytes, b) >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPattern creates a new Pattern for matching hosts.
|
// NewPattern creates a new Pattern for matching hosts. NewPattern("*") creates
|
||||||
|
// a Pattern that matches all hosts.
|
||||||
|
//
|
||||||
|
// From the manpage, a pattern consists of zero or more non-whitespace
|
||||||
|
// characters, `*' (a wildcard that matches zero or more characters), or `?' (a
|
||||||
|
// wildcard that matches exactly one character). For example, to specify a set
|
||||||
|
// of declarations for any host in the ".co.uk" set of domains, the following
|
||||||
|
// pattern could be used:
|
||||||
|
//
|
||||||
|
// Host *.co.uk
|
||||||
|
//
|
||||||
|
// The following pattern would match any host in the 192.168.0.[0-9] network range:
|
||||||
|
//
|
||||||
|
// Host 192.168.0.?
|
||||||
func NewPattern(s string) (*Pattern, error) {
|
func NewPattern(s string) (*Pattern, error) {
|
||||||
// From the manpage:
|
|
||||||
// A pattern consists of zero or more non-whitespace characters,
|
|
||||||
// `*' (a wildcard that matches zero or more characters),
|
|
||||||
// or `?' (a wildcard that matches exactly one character).
|
|
||||||
// For example, to specify a set of declarations for any host in the
|
|
||||||
// ".co.uk" set of domains, the following pattern could be used:
|
|
||||||
//
|
|
||||||
// Host *.co.uk
|
|
||||||
//
|
|
||||||
// The following pattern would match any host in the 192.168.0.[0-9] network range:
|
|
||||||
//
|
|
||||||
// Host 192.168.0.?
|
|
||||||
if s == "" {
|
if s == "" {
|
||||||
return nil, errors.New("ssh_config: empty pattern")
|
return nil, errors.New("ssh_config: empty pattern")
|
||||||
}
|
}
|
||||||
@@ -344,6 +345,7 @@ func NewPattern(s string) (*Pattern, error) {
|
|||||||
return &Pattern{str: s, regex: r, not: negated}, nil
|
return &Pattern{str: s, regex: r, not: negated}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Host describes a Host directive and the keywords that follow it.
|
||||||
type Host struct {
|
type Host struct {
|
||||||
// A list of host patterns that should match this host.
|
// A list of host patterns that should match this host.
|
||||||
Patterns []*Pattern
|
Patterns []*Pattern
|
||||||
@@ -492,6 +494,7 @@ type Include struct {
|
|||||||
leadingSpace uint16
|
leadingSpace uint16
|
||||||
position Position
|
position Position
|
||||||
depth uint8
|
depth uint8
|
||||||
|
hasEquals bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxRecurseDepth = 5
|
const maxRecurseDepth = 5
|
||||||
@@ -519,7 +522,7 @@ func removeDups(arr []string) []string {
|
|||||||
// Configuration files are parsed greedily (e.g. as soon as this function runs).
|
// Configuration files are parsed greedily (e.g. as soon as this function runs).
|
||||||
// Any error encountered while parsing nested configuration files will be
|
// Any error encountered while parsing nested configuration files will be
|
||||||
// returned.
|
// returned.
|
||||||
func NewInclude(directives []string, comment string, system bool, depth uint8) (*Include, error) {
|
func NewInclude(directives []string, hasEquals bool, pos Position, comment string, system bool, depth uint8) (*Include, error) {
|
||||||
if depth > maxRecurseDepth {
|
if depth > maxRecurseDepth {
|
||||||
return nil, ErrDepthExceeded
|
return nil, ErrDepthExceeded
|
||||||
}
|
}
|
||||||
@@ -527,7 +530,10 @@ func NewInclude(directives []string, comment string, system bool, depth uint8) (
|
|||||||
Comment: comment,
|
Comment: comment,
|
||||||
directives: directives,
|
directives: directives,
|
||||||
files: make(map[string]*Config),
|
files: make(map[string]*Config),
|
||||||
|
position: pos,
|
||||||
|
leadingSpace: uint16(pos.Col) - 1,
|
||||||
depth: depth,
|
depth: depth,
|
||||||
|
hasEquals: hasEquals,
|
||||||
}
|
}
|
||||||
// no need for inc.mu.Lock() since nothing else can access this inc
|
// no need for inc.mu.Lock() since nothing else can access this inc
|
||||||
matches := make([]string, 0)
|
matches := make([]string, 0)
|
||||||
@@ -582,8 +588,18 @@ func (inc *Include) Get(alias, key string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Include) String() string {
|
// String prints out a string representation of this Include directive. Note
|
||||||
return "TODO"
|
// included Config files are not printed as part of this representation.
|
||||||
|
func (inc *Include) String() string {
|
||||||
|
equals := " "
|
||||||
|
if inc.hasEquals {
|
||||||
|
equals = " = "
|
||||||
|
}
|
||||||
|
line := fmt.Sprintf("%sInclude%s%s", strings.Repeat(" ", int(inc.leadingSpace)), equals, strings.Join(inc.directives, " "))
|
||||||
|
if inc.Comment != "" {
|
||||||
|
line += " #" + inc.Comment
|
||||||
|
}
|
||||||
|
return line
|
||||||
}
|
}
|
||||||
|
|
||||||
var matchAll *Pattern
|
var matchAll *Pattern
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package ssh_config
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -253,6 +254,24 @@ func TestIncludeRecursive(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIncludeString(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("skipping fs write in short mode")
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadFile("testdata/include")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
c, err := Decode(bytes.NewReader(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
s := c.String()
|
||||||
|
if s != string(data) {
|
||||||
|
t.Errorf("mismatch: got %q\nwant %q", s, string(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var matchTests = []struct {
|
var matchTests = []struct {
|
||||||
in []string
|
in []string
|
||||||
alias string
|
alias string
|
||||||
|
|||||||
@@ -11,3 +11,13 @@ func ExampleHost_Matches() {
|
|||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExamplePattern() {
|
||||||
|
pat, _ := NewPattern("*")
|
||||||
|
host := &Host{Patterns: []*Pattern{pat}}
|
||||||
|
fmt.Println(host.Matches("test.stage.example.com"))
|
||||||
|
fmt.Println(host.Matches("othersubdomain.any.any"))
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ func (p *sshParser) parseKV() sshParserStateFn {
|
|||||||
}
|
}
|
||||||
lastHost := p.config.Hosts[len(p.config.Hosts)-1]
|
lastHost := p.config.Hosts[len(p.config.Hosts)-1]
|
||||||
if strings.ToLower(key.val) == "include" {
|
if strings.ToLower(key.val) == "include" {
|
||||||
inc, err := NewInclude(strings.Split(val.val, " "), comment, p.system, p.depth+1)
|
inc, err := NewInclude(strings.Split(val.val, " "), hasEquals, key.Position, comment, p.system, p.depth+1)
|
||||||
if err == ErrDepthExceeded {
|
if err == ErrDepthExceeded {
|
||||||
p.raiseError(val, err)
|
p.raiseError(val, err)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user