Skip to content

Commit 5bb5f8e

Browse files
committed
Improved documentation and examples.
- deprecated NewPosition() - added String() to TokenType
1 parent 385b06a commit 5bb5f8e

16 files changed

+246
-129
lines changed

cache.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@ import (
66

77
// Cache is the interface for the GitIgnore cache
88
type Cache interface {
9-
Set(string, GitIgnore)
10-
Get(string) GitIgnore
11-
} // Cache{}
9+
// Set stores the GitIgnore ignore against its path.
10+
Set(path string, ig GitIgnore)
11+
12+
// Get attempts to retrieve an GitIgnore instance associated with the given
13+
// path. If the path is not known nil is returned.
14+
Get(path string) GitIgnore
15+
}
1216

1317
// cache is the default thread-safe cache implementation
1418
type cache struct {
1519
_i map[string]GitIgnore
1620
_lock sync.Mutex
17-
} // cache{}
21+
}
1822

1923
// NewCache returns a Cache instance. This is a thread-safe, in-memory cache
2024
// for GitIgnore instances.

defn_test.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -168,26 +168,26 @@ git-sample-3/foo/*
168168
var (
169169
// define the positions of the bad patterns
170170
_GITBADPOSITION = []gitignore.Position{
171-
gitignore.NewPosition("", 17, 19, 189),
172-
gitignore.NewPosition("", 18, 14, 219),
173-
gitignore.NewPosition("", 19, 8, 233),
174-
gitignore.NewPosition("", 20, 8, 248),
171+
gitignore.Position{"", 17, 19, 189},
172+
gitignore.Position{"", 18, 14, 219},
173+
gitignore.Position{"", 19, 8, 233},
174+
gitignore.Position{"", 20, 8, 248},
175175
}
176176

177177
// define the positions of the good patterns
178178
_GITPOSITION = []gitignore.Position{
179-
gitignore.NewPosition("", 4, 1, 23),
180-
gitignore.NewPosition("", 6, 1, 30),
181-
gitignore.NewPosition("", 7, 1, 34),
182-
gitignore.NewPosition("", 9, 1, 39),
183-
gitignore.NewPosition("", 12, 1, 104),
184-
gitignore.NewPosition("", 13, 1, 132),
185-
gitignore.NewPosition("", 15, 1, 150),
186-
gitignore.NewPosition("", 22, 1, 256),
187-
gitignore.NewPosition("", 23, 1, 280),
188-
gitignore.NewPosition("", 25, 1, 283),
189-
gitignore.NewPosition("", 26, 1, 295),
190-
gitignore.NewPosition("", 27, 1, 317),
179+
gitignore.Position{"", 4, 1, 23},
180+
gitignore.Position{"", 6, 1, 30},
181+
gitignore.Position{"", 7, 1, 34},
182+
gitignore.Position{"", 9, 1, 39},
183+
gitignore.Position{"", 12, 1, 104},
184+
gitignore.Position{"", 13, 1, 132},
185+
gitignore.Position{"", 15, 1, 150},
186+
gitignore.Position{"", 22, 1, 256},
187+
gitignore.Position{"", 23, 1, 280},
188+
gitignore.Position{"", 25, 1, 283},
189+
gitignore.Position{"", 26, 1, 295},
190+
gitignore.Position{"", 27, 1, 317},
191191
}
192192

193193
// define the token stream for the _GITIGNORE .gitignore
@@ -535,7 +535,7 @@ var (
535535
}
536536

537537
// define the beginning position for the parser & lexer
538-
_BEGINNING = gitignore.NewPosition("", 1, 1, 0)
538+
_BEGINNING = gitignore.Position{"", 1, 1, 0}
539539

540540
// define the tokens from the invalid .gitignore above
541541
_TOKENSINVALID = []token{

doc.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/*
2+
Package gitignore provides an interface for parsing .gitignore files, and
3+
matching paths against the retrieved patterns. gitignore uses fnmatch for
4+
pattern matching as specified by git (see https://git-scm.com/docs/gitignore).
5+
*/
6+
package gitignore

error.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@ package gitignore
22

33
type Error interface {
44
error
5+
6+
// Position returns the position of the error within the .gitignore file
7+
// (if any)
58
Position() Position
9+
10+
// Underlying returns the underlying error, permitting direct comparison
11+
// against the wrapped error.
612
Underlying() error
713
}
814

9-
// err extends the standard error to include a Position within the parsed
10-
// .gitignore file
1115
type err struct {
1216
error
1317
_position Position
@@ -18,15 +22,9 @@ func NewError(e error, p Position) Error {
1822
return &err{error: e, _position: p}
1923
} // NewError()
2024

21-
// Position returns the position of the error (i.e. the location within the
22-
// .gitignore file)
2325
func (e *err) Position() Position { return e._position }
2426

25-
// Underlying returns the underlying error, permitting direct comparison
26-
// against the wrapped error.
27-
func (e *err) Underlying() error {
28-
return e.error
29-
} // Underlying()
27+
func (e *err) Underlying() error { return e.error }
3028

3129
// ensure err satisfies the Error interface
3230
var _ Error = &err{}

example_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package gitignore_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/denormal/go-gitignore"
8+
)
9+
10+
func ExampleNewFromFile(t *testing.T) {
11+
ignore, err := gitignore.NewFromFile("/my/project/.gitignore")
12+
if err != nil {
13+
panic(err)
14+
}
15+
16+
// attempt to match an absolute path
17+
match := ignore.Match("/my/project/src/file.go")
18+
if match != nil {
19+
if match.Ignore() {
20+
fmt.Println("ignore file.go")
21+
}
22+
}
23+
24+
// attempt to match a relative path
25+
// - this is equivalent to the call above
26+
match = ignore.Relative("src/file.go", false)
27+
if match != nil {
28+
if match.Include() {
29+
fmt.Println("include file.go")
30+
}
31+
}
32+
} // ExampleNewFromFile()
33+
34+
func ExampleNewRepository(t *testing.T) {
35+
ignore, err := gitignore.NewRepository("/my/project")
36+
if err != nil {
37+
panic(err)
38+
}
39+
40+
// attempt to match a directory in the repository
41+
match := ignore.Relative("src/examples", true)
42+
if match != nil {
43+
if match.Ignore() {
44+
fmt.Printf(
45+
"ignore src/examples because of pattern %q at %s",
46+
match, match.Position(),
47+
)
48+
}
49+
}
50+
51+
// if we have an absolute path, or a path relative to the current
52+
// working directory we can use the short-hand methods
53+
if ignore.Include("/my/project/etc/service.conf") {
54+
fmt.Println("include the service configuration")
55+
}
56+
} // ExampleNewRepository()

gitignore.go

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,38 @@ var empty = &ignore{}
1515
// methods for testing files for matching the .gitignore file, and then
1616
// determining whether a file should be ignored or included.
1717
type GitIgnore interface {
18+
// Base returns the directory containing the .gitignore file.
1819
Base() string
1920

20-
Match(string) Match
21+
// Match attempts to match the path against this GitIgnore, and will
22+
// return its Match if successful. Match will invoke the GitIgnore error
23+
// handler (if defined) if it is not possible to determine the absolute
24+
// path of the given path, or if its not possible to determine if the
25+
// path represents a file or a directory. If an error occurs, Match
26+
// returns nil and the error handler (if defined via New, NewWithErrors
27+
// or NewWithCache) will be invoked.
28+
Match(path string) Match
29+
30+
// Absolute attempts to match an absolute path against this GitIgnore. If
31+
// the path is not located under the base directory of this GitIgnore, or
32+
// is not matched by this GitIgnore, nil is returned.
2133
Absolute(string, bool) Match
22-
Relative(string, bool) Match
2334

24-
Ignore(string) bool
25-
Include(string) bool
35+
// Relative attempts to match a path relative to the GitIgnore base
36+
// directory. isdir is used to indicate whether the path represents a file
37+
// or a directory. If the path is not matched by the GitIgnore, nil is
38+
// returned.
39+
Relative(path string, isdir bool) Match
40+
41+
// Ignore returns true if the path is ignored by this GitIgnore. Paths
42+
// that are not matched by this GitIgnore are not ignored. Internally,
43+
// Ignore uses Match, and will return false if Match() returns nil for path.
44+
Ignore(path string) bool
45+
46+
// Include returns true if the path is included by this GitIgnore. Paths
47+
// that are not matched by this GitIgnore are always included. Internally,
48+
// Include uses Match, and will return true if Match() returns nil for path.
49+
Include(path string) bool
2650
}
2751

2852
// ignore is the implementation of a .gitignore file.
@@ -187,13 +211,13 @@ func (i *ignore) Base() string {
187211
return i._base
188212
} // Base()
189213

190-
// Match attempts to match the path against this GitIgnore. If the path is
191-
// matched by a GitIgnore pattern, its Match will be returned. Match will
192-
// invoke the error handler (if defined) if its not possible to determine the
193-
// absolute path of the given path, or if its not possible to determine if the
194-
// path represents a file or a directory. If an error occurs, Match returns nil
195-
// and the error handler (if defined via New, NewWithErrors or NewWithCache)
196-
// will be invoked.
214+
// Match attempts to match the path against this GitIgnore, and will
215+
// return its Match if successful. Match will invoke the GitIgnore error
216+
// handler (if defined) if it is not possible to determine the absolute
217+
// path of the given path, or if its not possible to determine if the
218+
// path represents a file or a directory. If an error occurs, Match
219+
// returns nil and the error handler (if defined via New, NewWithErrors
220+
// or NewWithCache) will be invoked.
197221
func (i *ignore) Match(path string) Match {
198222
// ensure we have the absolute path for the given file
199223
_path, _err := filepath.Abs(path)
@@ -214,9 +238,9 @@ func (i *ignore) Match(path string) Match {
214238
return i.Absolute(_path, _isdir)
215239
} // Match()
216240

217-
// Absolute attempts to match an absolute path against this GitIgnore. If the
218-
// path is not located under the base directory of this GitIgnore, or is not
219-
// matched by this GitIgnore, nil is returned.
241+
// Absolute attempts to match an absolute path against this GitIgnore. If
242+
// the path is not located under the base directory of this GitIgnore, or
243+
// is not matched by this GitIgnore, nil is returned.
220244
func (i *ignore) Absolute(path string, isdir bool) Match {
221245
// does the file share the same directory as this ignore file?
222246
if !strings.HasPrefix(path, i._base) {
@@ -229,8 +253,10 @@ func (i *ignore) Absolute(path string, isdir bool) Match {
229253
return i.Relative(_rel, isdir)
230254
} // Absolute()
231255

232-
// Relative attempts to match a path relative to the GitIgnore base directory.
233-
// If the path is not matched by the GitIgnore, nil is returned.
256+
// Relative attempts to match a path relative to the GitIgnore base
257+
// directory. isdir is used to indicate whether the path represents a file
258+
// or a directory. If the path is not matched by the GitIgnore, nil is
259+
// returned.
234260
func (i *ignore) Relative(path string, isdir bool) Match {
235261
// if we are on Windows, then translate the path to Unix form
236262
_rel := path
@@ -251,9 +277,9 @@ func (i *ignore) Relative(path string, isdir bool) Match {
251277
return nil
252278
} // Relative()
253279

254-
// Ignore returns true if the path is ignored by this GitIgnore. Paths that are
255-
// not matched by this GitIgnore are not ignored. Internally, Ignore uses
256-
// Match, and will return false if Match() returns nil for path.
280+
// Ignore returns true if the path is ignored by this GitIgnore. Paths
281+
// that are not matched by this GitIgnore are not ignored. Internally,
282+
// Ignore uses Match, and will return false if Match() returns nil for path.
257283
func (i *ignore) Ignore(path string) bool {
258284
_match := i.Match(path)
259285
if _match != nil {
@@ -264,9 +290,9 @@ func (i *ignore) Ignore(path string) bool {
264290
return false
265291
} // Ignore()
266292

267-
// Include returns true if the path is included by this GitIgnore. Paths that
268-
// are not matched by this GitIgnore are always included. Internally, Include
269-
// uses Match, and will return true if Match() returns nil for path.
293+
// Include returns true if the path is included by this GitIgnore. Paths
294+
// that are not matched by this GitIgnore are always included. Internally,
295+
// Include uses Match, and will return true if Match() returns nil for path.
270296
func (i *ignore) Include(path string) bool {
271297
_match := i.Match(path)
272298
if _match != nil {

lexer.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,18 @@ type lexer struct {
2121

2222
// Lexer is the interface to the lexical analyser for .gitignore files
2323
type Lexer interface {
24+
// Next returns the next Token from the Lexer reader. If an error is
25+
// encountered, it will be returned as an Error instance, detailing the
26+
// error and its position within the stream.
2427
Next() (*Token, Error)
2528

29+
// Position returns the current position of the Lexer.
2630
Position() Position
31+
32+
// String returns the string representation of the current position of the
33+
// Lexer.
2734
String() string
28-
} // Lexer{}
35+
}
2936

3037
// NewLexer returns a Lexer instance for the io.Reader r.
3138
func NewLexer(r io.Reader) Lexer {
@@ -117,7 +124,7 @@ func (l *lexer) Next() (*Token, Error) {
117124

118125
// Position returns the current position of the Lexer.
119126
func (l *lexer) Position() Position {
120-
return NewPosition("", l._line, l._column, l._offset)
127+
return Position{"", l._line, l._column, l._offset}
121128
} // Position()
122129

123130
// String returns the string representation of the current position of the
@@ -424,7 +431,7 @@ func (l *lexer) token(type_ TokenType, word []rune, e Error) (*Token, Error) {
424431
_word := len(word)
425432
_column := l._column - _word
426433
_offset := l._offset - _word
427-
position := NewPosition("", l._line, _column, _offset)
434+
position := Position{"", l._line, _column, _offset}
428435

429436
// if this is a newline token, we adjust the line & column counts
430437
if type_ == EOL {

lexer_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ func lexer(t *testing.T, lines []string, eol string, tokens []token, e error) {
136136
// ensure the token position matches the expected position
137137
// - since we will be testing with different line endings, we
138138
// have to choose the correct offset
139-
_position := gitignore.NewPosition(
139+
_position := gitignore.Position{
140140
"", _expected.Line, _expected.Column, _expected.NewLine,
141-
)
141+
}
142142
if eol == "\r\n" {
143143
_position.Offset = _expected.CarriageReturn
144144
}

match.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,18 @@ package gitignore
66
// pattern), and to extract the position of the pattern within the .gitignore,
77
// and a string representation of the pattern.
88
type Match interface {
9+
// Ignore returns true if the match pattern describes files or paths that
10+
// should be ignored.
911
Ignore() bool
12+
13+
// Include returns true if the match pattern describes files or paths that
14+
// should be included.
1015
Include() bool
16+
17+
// String returns a string representation of the matched pattern.
1118
String() string
19+
20+
// Position returns the position in the .gitignore file at which the
21+
// matching pattern was defined.
1222
Position() Position
13-
} // Match{}
23+
}

0 commit comments

Comments
 (0)