Skip to content

Commit

Permalink
Merge pull request securego#98 from endophage/recursive
Browse files Browse the repository at this point in the history
adding support for arbitrary paths with ellipses
  • Loading branch information
gcmurphy committed Dec 2, 2016
2 parents 365e9f6 + 1a481fa commit b5308ff
Show file tree
Hide file tree
Showing 8 changed files with 490 additions and 83 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ _testmain.go
*.prof

.DS_Store

.vscode
68 changes: 33 additions & 35 deletions filelist.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,60 +15,58 @@
package main

import (
"fmt"
"os"
"path/filepath"
"log"
"strings"

"github.com/ryanuber/go-glob"
)

type filelist struct {
paths map[string]bool
globs []string
// fileList uses a map for patterns to ensure each pattern only
// appears once
type fileList struct {
patterns map[string]struct{}
}

func newFileList(paths ...string) *filelist {

f := &filelist{
make(map[string]bool),
make([]string, 0),
func newFileList(paths ...string) *fileList {
f := &fileList{
patterns: make(map[string]struct{}),
}

for _, path := range paths {
if e := f.Set(path); e != nil {
// #nosec
fmt.Fprintf(os.Stderr, "Unable to add %s to filelist: %s\n", path, e)
}
for _, p := range paths {
f.patterns[p] = struct{}{}
}
return f
}

func (f *filelist) String() string {
return strings.Join(f.globs, ", ")
func (f *fileList) String() string {
ps := make([]string, 0, len(f.patterns))
for p := range f.patterns {
ps = append(ps, p)
}
return strings.Join(ps, ", ")
}

func (f *filelist) Set(path string) error {
f.globs = append(f.globs, path)
matches, e := filepath.Glob(path)
if e != nil {
return e
}
for _, each := range matches {
abs, e := filepath.Abs(each)
if e != nil {
return e
}
f.paths[abs] = true
func (f *fileList) Set(path string) error {
if path == "" {
// don't bother adding the empty path
return nil
}
f.patterns[path] = struct{}{}
return nil
}

func (f filelist) Contains(path string) bool {
_, present := f.paths[path]
return present
func (f fileList) Contains(path string) bool {
for p := range f.patterns {
if glob.Glob(p, path) {
log.Printf("excluding: %s\n", path)
return true
}
}
log.Printf("including: %s\n", path)
return false
}

/*
func (f filelist) Dump() {
func (f fileList) Dump() {
for k, _ := range f.paths {
println(k)
}
Expand Down
245 changes: 245 additions & 0 deletions filelist_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
package main

import (
"reflect"
"testing"
)

func Test_newFileList(t *testing.T) {
type args struct {
paths []string
}
tests := []struct {
name string
args args
want *fileList
}{
{
name: "nil paths",
args: args{paths: nil},
want: &fileList{patterns: map[string]struct{}{}},
},
{
name: "empty paths",
args: args{paths: []string{}},
want: &fileList{patterns: map[string]struct{}{}},
},
{
name: "have paths",
args: args{paths: []string{"*_test.go"}},
want: &fileList{patterns: map[string]struct{}{
"*_test.go": struct{}{},
}},
},
}
for _, tt := range tests {
if got := newFileList(tt.args.paths...); !reflect.DeepEqual(got, tt.want) {
t.Errorf("%q. newFileList() = %v, want %v", tt.name, got, tt.want)
}
}
}

func Test_fileList_String(t *testing.T) {
type fields struct {
patterns []string
}
tests := []struct {
name string
fields fields
want string
}{
{
name: "nil patterns",
fields: fields{patterns: nil},
want: "",
},
{
name: "empty patterns",
fields: fields{patterns: []string{}},
want: "",
},
{
name: "one pattern",
fields: fields{patterns: []string{"foo"}},
want: "foo",
},
{
name: "two patterns",
fields: fields{patterns: []string{"foo", "bar"}},
want: "foo, bar",
},
}
for _, tt := range tests {
f := newFileList(tt.fields.patterns...)
if got := f.String(); got != tt.want {
t.Errorf("%q. fileList.String() = %v, want %v", tt.name, got, tt.want)
}
}
}

func Test_fileList_Set(t *testing.T) {
type fields struct {
patterns []string
}
type args struct {
path string
}
tests := []struct {
name string
fields fields
args args
want map[string]struct{}
wantErr bool
}{
{
name: "add empty path",
fields: fields{patterns: nil},
args: args{path: ""},
want: map[string]struct{}{},
wantErr: false,
},
{
name: "add path to nil patterns",
fields: fields{patterns: nil},
args: args{path: "foo"},
want: map[string]struct{}{
"foo": struct{}{},
},
wantErr: false,
},
{
name: "add path to empty patterns",
fields: fields{patterns: []string{}},
args: args{path: "foo"},
want: map[string]struct{}{
"foo": struct{}{},
},
wantErr: false,
},
{
name: "add path to populated patterns",
fields: fields{patterns: []string{"foo"}},
args: args{path: "bar"},
want: map[string]struct{}{
"foo": struct{}{},
"bar": struct{}{},
},
wantErr: false,
},
}
for _, tt := range tests {
f := newFileList(tt.fields.patterns...)
if err := f.Set(tt.args.path); (err != nil) != tt.wantErr {
t.Errorf("%q. fileList.Set() error = %v, wantErr %v", tt.name, err, tt.wantErr)
}
if !reflect.DeepEqual(f.patterns, tt.want) {
t.Errorf("%q. got state fileList.patterns = %v, want state %v", tt.name, f.patterns, tt.want)
}
}
}

func Test_fileList_Contains(t *testing.T) {
type fields struct {
patterns []string
}
type args struct {
path string
}
tests := []struct {
name string
fields fields
args args
want bool
}{
{
name: "nil patterns",
fields: fields{patterns: nil},
args: args{path: "foo"},
want: false,
},
{
name: "empty patterns",
fields: fields{patterns: nil},
args: args{path: "foo"},
want: false,
},
{
name: "one pattern, no wildcard, no match",
fields: fields{patterns: []string{"foo"}},
args: args{path: "bar"},
want: false,
},
{
name: "one pattern, no wildcard, match",
fields: fields{patterns: []string{"foo"}},
args: args{path: "foo"},
want: true,
},
{
name: "one pattern, wildcard prefix, match",
fields: fields{patterns: []string{"*foo"}},
args: args{path: "foo"},
want: true,
},
{
name: "one pattern, wildcard suffix, match",
fields: fields{patterns: []string{"foo*"}},
args: args{path: "foo"},
want: true,
},
{
name: "one pattern, wildcard both ends, match",
fields: fields{patterns: []string{"*foo*"}},
args: args{path: "foo"},
want: true,
},
{
name: "default test match 1",
fields: fields{patterns: []string{"*_test.go"}},
args: args{path: "foo_test.go"},
want: true,
},
{
name: "default test match 2",
fields: fields{patterns: []string{"*_test.go"}},
args: args{path: "bar/foo_test.go"},
want: true,
},
{
name: "default test match 3",
fields: fields{patterns: []string{"*_test.go"}},
args: args{path: "/bar/foo_test.go"},
want: true,
},
{
name: "default test match 4",
fields: fields{patterns: []string{"*_test.go"}},
args: args{path: "baz/bar/foo_test.go"},
want: true,
},
{
name: "default test match 5",
fields: fields{patterns: []string{"*_test.go"}},
args: args{path: "/baz/bar/foo_test.go"},
want: true,
},
{
name: "many patterns, no match",
fields: fields{patterns: []string{"*_one.go", "*_two.go"}},
args: args{path: "/baz/bar/foo_test.go"},
want: false,
},
{
name: "many patterns, match",
fields: fields{patterns: []string{"*_one.go", "*_two.go", "*_test.go"}},
args: args{path: "/baz/bar/foo_test.go"},
want: true,
},
}
for _, tt := range tests {
f := newFileList(tt.fields.patterns...)
if got := f.Contains(tt.args.path); got != tt.want {
t.Errorf("%q. fileList.Contains() = %v, want %v", tt.name, got, tt.want)
}
}
}

0 comments on commit b5308ff

Please sign in to comment.