fix: sync DirMatchesOneOf

relates to 2038
This commit is contained in:
Jan De Dobbeleer 2022-04-06 09:05:17 +02:00 committed by Jan De Dobbeleer
parent be06c89627
commit 303793632b
8 changed files with 87 additions and 153 deletions

View file

@ -197,7 +197,7 @@ func (segment *Segment) cwdIncluded() bool {
return true
}
return environment.DirMatchesOneOf(segment.env, segment.env.Pwd(), list)
return segment.env.DirMatchesOneOf(segment.env.Pwd(), list)
}
func (segment *Segment) cwdExcluded() bool {
@ -206,7 +206,7 @@ func (segment *Segment) cwdExcluded() bool {
value = segment.Properties[properties.IgnoreFolders]
}
list := properties.ParseStringArray(value)
return environment.DirMatchesOneOf(segment.env, segment.env.Pwd(), list)
return segment.env.DirMatchesOneOf(segment.env.Pwd(), list)
}
func (segment *Segment) shouldInvokeWithTip(tip string) bool {

View file

@ -59,38 +59,27 @@ func TestParseTestConfig(t *testing.T) {
func TestShouldIncludeFolder(t *testing.T) {
cases := []struct {
Case string
IncludeFolders []string
ExcludeFolders []string
Expected bool
Case string
Included bool
Excluded bool
Expected bool
}{
{Case: "Base Case", IncludeFolders: nil, ExcludeFolders: nil, Expected: true},
{Case: "Base Case Empty Arrays", IncludeFolders: []string{}, ExcludeFolders: []string{}, Expected: true},
{Case: "Include", IncludeFolders: []string{"Projects/oh-my-posh"}, ExcludeFolders: nil, Expected: true},
{Case: "Include Regex", IncludeFolders: []string{"Projects.*"}, ExcludeFolders: nil, Expected: true},
{Case: "Include Mismatch", IncludeFolders: []string{"Projects/nope"}, ExcludeFolders: nil, Expected: false},
{Case: "Include Regex Mismatch", IncludeFolders: []string{"zProjects.*"}, ExcludeFolders: nil, Expected: false},
{Case: "Exclude", IncludeFolders: nil, ExcludeFolders: []string{"Projects/oh-my-posh"}, Expected: false},
{Case: "Exclude Regex", IncludeFolders: nil, ExcludeFolders: []string{"Projects.*"}, Expected: false},
{Case: "Exclude Mismatch", IncludeFolders: nil, ExcludeFolders: []string{"Projects/nope"}, Expected: true},
{Case: "Exclude Regex Mismatch", IncludeFolders: nil, ExcludeFolders: []string{"zProjects.*"}, Expected: true},
{Case: "Include Match / Exclude Match", IncludeFolders: []string{"Projects.*"}, ExcludeFolders: []string{"Projects/oh-my-posh"}, Expected: false},
{Case: "Include Match / Exclude Mismatch", IncludeFolders: []string{"Projects.*"}, ExcludeFolders: []string{"Projects/nope"}, Expected: true},
{Case: "Include Mismatch / Exclude Match", IncludeFolders: []string{"zProjects.*"}, ExcludeFolders: []string{"Projects/oh-my-posh"}, Expected: false},
{Case: "Include Mismatch / Exclude Mismatch", IncludeFolders: []string{"zProjects.*"}, ExcludeFolders: []string{"Projects/nope"}, Expected: false},
{Case: "Include", Included: true, Excluded: false, Expected: true},
{Case: "Exclude", Included: false, Excluded: true, Expected: false},
{Case: "Include & Exclude", Included: true, Excluded: true, Expected: false},
{Case: "!Include & !Exclude", Included: false, Excluded: false, Expected: false},
}
for _, tc := range cases {
env := new(mock.MockedEnvironment)
env.On("GOOS").Return(environment.LinuxPlatform)
env.On("Home").Return("")
env.On("Pwd").Return(cwd)
env.On("DirMatchesOneOf", cwd, []string{"Projects/oh-my-posh"}).Return(tc.Included)
env.On("DirMatchesOneOf", cwd, []string{"Projects/nope"}).Return(tc.Excluded)
segment := &Segment{
Properties: properties.Map{
properties.IncludeFolders: tc.IncludeFolders,
properties.ExcludeFolders: tc.ExcludeFolders,
properties.IncludeFolders: []string{"Projects/oh-my-posh"},
properties.ExcludeFolders: []string{"Projects/nope"},
},
env: env,
}
@ -99,48 +88,6 @@ func TestShouldIncludeFolder(t *testing.T) {
}
}
func TestShouldIncludeFolderRegexInverted(t *testing.T) {
env := new(mock.MockedEnvironment)
env.On("GOOS").Return(environment.LinuxPlatform)
env.On("Home").Return("")
env.On("Pwd").Return(cwd)
segment := &Segment{
Properties: properties.Map{
properties.ExcludeFolders: []string{"(?!Projects[\\/]).*"},
},
env: env,
}
// detect panic(thrown by MustCompile)
defer func() {
if err := recover(); err != nil {
// display a message explaining omp failed(with the err)
assert.Equal(t, "regexp: Compile(`^(?!Projects[\\/]).*$`): error parsing regexp: invalid or unsupported Perl syntax: `(?!`", err)
}
}()
segment.shouldIncludeFolder()
}
func TestShouldIncludeFolderRegexInvertedNonEscaped(t *testing.T) {
env := new(mock.MockedEnvironment)
env.On("GOOS").Return(environment.LinuxPlatform)
env.On("Home").Return("")
env.On("Pwd").Return(cwd)
segment := &Segment{
Properties: properties.Map{
properties.ExcludeFolders: []string{"(?!Projects/).*"},
},
env: env,
}
// detect panic(thrown by MustCompile)
defer func() {
if err := recover(); err != nil {
// display a message explaining omp failed(with the err)
assert.Equal(t, "regexp: Compile(`^(?!Projects/).*$`): error parsing regexp: invalid or unsupported Perl syntax: `(?!`", err)
}
}()
segment.shouldIncludeFolder()
}
func TestGetColors(t *testing.T) {
cases := []struct {
Case string

View file

@ -16,6 +16,7 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"time"
"github.com/distatus/battery"
@ -134,6 +135,7 @@ type Environment interface {
HasFolder(folder string) bool
HasParentFilePath(path string) (fileInfo *FileInfo, err error)
HasFileInParentDirs(pattern string, depth uint) bool
DirMatchesOneOf(dir string, regexes []string) bool
HasCommand(command string) bool
FileContent(file string) string
FolderList(path string) []string
@ -185,14 +187,16 @@ const (
)
type ShellEnvironment struct {
CmdFlags *Flags
Version string
CmdFlags *Flags
Version string
cwd string
cmdCache *commandCache
fileCache *fileCache
tmplCache *TemplateCache
logBuilder strings.Builder
debug bool
lock sync.Mutex
}
func (env *ShellEnvironment) Init(debug bool) {
@ -720,9 +724,15 @@ func (env *ShellEnvironment) TemplateCache() *TemplateCache {
return tmplCache
}
func DirMatchesOneOf(env Environment, dir string, regexes []string) bool {
func (env *ShellEnvironment) DirMatchesOneOf(dir string, regexes []string) bool {
env.lock.Lock()
defer env.lock.Unlock()
return dirMatchesOneOf(dir, env.Home(), env.GOOS(), regexes)
}
func dirMatchesOneOf(dir, home, goos string, regexes []string) bool {
normalizedCwd := strings.ReplaceAll(dir, "\\", "/")
normalizedHomeDir := strings.ReplaceAll(env.Home(), "\\", "/")
normalizedHomeDir := strings.ReplaceAll(home, "\\", "/")
for _, element := range regexes {
normalizedElement := strings.ReplaceAll(element, "\\\\", "/")
@ -730,7 +740,6 @@ func DirMatchesOneOf(env Environment, dir string, regexes []string) bool {
normalizedElement = strings.Replace(normalizedElement, "~", normalizedHomeDir, 1)
}
pattern := fmt.Sprintf("^%s$", normalizedElement)
goos := env.GOOS()
if goos == WindowsPlatform || goos == DarwinPlatform {
pattern = "(?i)" + pattern
}

View file

@ -44,3 +44,56 @@ func TestWindowsPathWithDriveLetter(t *testing.T) {
assert.Equal(t, env.Pwd(), tc.Expected)
}
}
func TestDirMatchesOneOf(t *testing.T) {
cases := []struct {
GOOS string
HomeDir string
Dir string
Pattern string
Expected bool
}{
{GOOS: LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill", Pattern: "/home/bill", Expected: true},
{GOOS: LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/foo", Expected: true},
{GOOS: LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/Foo", Expected: false},
{GOOS: LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~\\\\foo", Expected: true},
{GOOS: LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo/bar", Pattern: "~/fo.*", Expected: true},
{GOOS: LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/fo\\w", Expected: true},
{GOOS: WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "C:\\\\Users\\\\Bill", Expected: true},
{GOOS: WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "C:/Users/Bill", Expected: true},
{GOOS: WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "c:/users/bill", Expected: true},
{GOOS: WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "~", Expected: true},
{GOOS: WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/Foo", Expected: true},
{GOOS: WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/foo", Expected: true},
{GOOS: WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo\\Bar", Pattern: "~/fo.*", Expected: true},
{GOOS: WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/fo\\w", Expected: true},
}
for _, tc := range cases {
got := dirMatchesOneOf(tc.Dir, tc.HomeDir, tc.GOOS, []string{tc.Pattern})
assert.Equal(t, tc.Expected, got)
}
}
func TestDirMatchesOneOfRegexInverted(t *testing.T) {
// detect panic(thrown by MustCompile)
defer func() {
if err := recover(); err != nil {
// display a message explaining omp failed(with the err)
assert.Equal(t, "regexp: Compile(`^(?!Projects[\\/]).*$`): error parsing regexp: invalid or unsupported Perl syntax: `(?!`", err)
}
}()
_ = dirMatchesOneOf("Projects/oh-my-posh", "", LinuxPlatform, []string{"(?!Projects[\\/]).*"})
}
func TestDirMatchesOneOfRegexInvertedNonEscaped(t *testing.T) {
// detect panic(thrown by MustCompile)
defer func() {
if err := recover(); err != nil {
// display a message explaining omp failed(with the err)
assert.Equal(t, "regexp: Compile(`^(?!Projects/).*$`): error parsing regexp: invalid or unsupported Perl syntax: `(?!`", err)
}
}()
_ = dirMatchesOneOf("Projects/oh-my-posh", "", LinuxPlatform, []string{"(?!Projects/).*"})
}

View file

@ -1,46 +0,0 @@
package main
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"testing"
"github.com/stretchr/testify/assert"
)
// This can only be tested here due to circular dependencies
// Which might be an indaction of a fault architecture but
// I honestly could not figure out how to do this better
// without making the solution worse.
func TestDirMatchesOneOf(t *testing.T) {
cases := []struct {
GOOS string
HomeDir string
Dir string
Pattern string
Expected bool
}{
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill", Pattern: "/home/bill", Expected: true},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/foo", Expected: true},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/Foo", Expected: false},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~\\\\foo", Expected: true},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo/bar", Pattern: "~/fo.*", Expected: true},
{GOOS: environment.LinuxPlatform, HomeDir: "/home/bill", Dir: "/home/bill/foo", Pattern: "~/fo\\w", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "C:\\\\Users\\\\Bill", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "C:/Users/Bill", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "c:/users/bill", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill", Pattern: "~", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/Foo", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/foo", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo\\Bar", Pattern: "~/fo.*", Expected: true},
{GOOS: environment.WindowsPlatform, HomeDir: "C:\\Users\\Bill", Dir: "C:\\Users\\Bill\\Foo", Pattern: "~/fo\\w", Expected: true},
}
for _, tc := range cases {
env := new(mock.MockedEnvironment)
env.On("GOOS").Return(tc.GOOS)
env.On("Home").Return(tc.HomeDir)
got := environment.DirMatchesOneOf(env, tc.Dir, []string{tc.Pattern})
assert.Equal(t, tc.Expected, got)
}
}

View file

@ -214,3 +214,8 @@ func (env *MockedEnvironment) HasFileInParentDirs(pattern string, depth uint) bo
args := env.Called(pattern, depth)
return args.Bool(0)
}
func (env *MockedEnvironment) DirMatchesOneOf(dir string, regexes []string) bool {
args := env.Called(dir, regexes)
return args.Bool(0)
}

View file

@ -74,7 +74,7 @@ func (s *scm) shouldIgnoreRootRepository(rootDir string) bool {
if len(excludedFolders) == 0 {
return false
}
return environment.DirMatchesOneOf(s.env, rootDir, excludedFolders)
return s.env.DirMatchesOneOf(rootDir, excludedFolders)
}
func (s *scm) FileContents(folder, file string) string {

View file

@ -1,8 +1,6 @@
package segments
import (
"oh-my-posh/environment"
"oh-my-posh/mock"
"oh-my-posh/properties"
"testing"
@ -156,35 +154,3 @@ func TestTruncateBranchWithSymbol(t *testing.T) {
assert.Equal(t, tc.Expected, p.truncateBranch(tc.Branch), tc.Case)
}
}
func TestScmShouldIgnoreRootRepository(t *testing.T) {
cases := []struct {
Case string
Dir string
Expected bool
}{
{Case: "inside excluded", Dir: "/home/bill/repo"},
{Case: "oustide excluded", Dir: "/home/melinda"},
{Case: "excluded exact match", Dir: "/home/gates", Expected: true},
{Case: "excluded inside match", Dir: "/home/gates/bill", Expected: true},
}
for _, tc := range cases {
excludeFolders := []string{
"/home/bill",
"/home/gates.*",
}
props := properties.Map{
properties.ExcludeFolders: excludeFolders,
}
env := new(mock.MockedEnvironment)
env.On("Home").Return("/home/bill")
env.On("GOOS").Return(environment.WindowsPlatform)
s := &scm{
props: props,
env: env,
}
got := s.shouldIgnoreRootRepository(tc.Dir)
assert.Equal(t, tc.Expected, got, tc.Case)
}
}