diff --git a/g/container/garray/garray_func.go b/g/container/garray/garray_func.go index a6375eab0..7ae0822b3 100644 --- a/g/container/garray/garray_func.go +++ b/g/container/garray/garray_func.go @@ -5,3 +5,63 @@ // You can obtain one at https://github.com/gogf/gf. package garray + +import "strings" + +func defaultComparatorInt(a, b int) int { + if a < b { + return -1 + } + if a > b { + return 1 + } + return 0 +} + +func defaultComparatorStr(a, b string) int { + return strings.Compare(a, b) +} + +// quickSortInt is the quick-sorting algorithm implements for int. +func quickSortInt(values []int, comparator func(a, b int) int) { + if len(values) <= 1 { + return + } + mid, i := values[0], 1 + head, tail := 0, len(values)-1 + for head < tail { + if comparator(values[i], mid) > 0 { + values[i], values[tail] = values[tail], values[i] + tail-- + } else { + values[i], values[head] = values[head], values[i] + head++ + i++ + } + } + values[head] = mid + quickSortInt(values[:head], comparator) + quickSortInt(values[head+1:], comparator) +} + +// quickSortStr is the quick-sorting algorithm implements for string. +func quickSortStr(values []string, comparator func(a, b string) int) { + if len(values) <= 1 { + return + } + mid, i := values[0], 1 + head, tail := 0, len(values)-1 + for head < tail { + if comparator(values[i], mid) > 0 { + values[i], values[tail] = values[tail], values[i] + tail-- + } else { + values[i], values[head] = values[head], values[i] + head++ + i++ + } + } + values[head] = mid + quickSortStr(values[:head], comparator) + quickSortStr(values[head+1:], comparator) +} diff --git a/g/container/garray/garray_sorted_int.go b/g/container/garray/garray_sorted_int.go index e9609720e..632bc1f75 100644 --- a/g/container/garray/garray_sorted_int.go +++ b/g/container/garray/garray_sorted_int.go @@ -22,8 +22,8 @@ import ( type SortedIntArray struct { mu *rwmutex.RWMutex array []int - unique *gtype.Bool // Whether enable unique feature(false) - comparator func(v1, v2 int) int // Comparison function(it returns -1: v1 < v2; 0: v1 == v2; 1: v1 > v2) + unique *gtype.Bool // Whether enable unique feature(false) + comparator func(a, b int) int // Comparison function(it returns -1: a < b; 0: a == b; 1: a > b) } // NewSortedIntArray creates and returns an empty sorted array. @@ -33,23 +33,23 @@ func NewSortedIntArray(safe ...bool) *SortedIntArray { return NewSortedIntArraySize(0, safe...) } +// NewSortedIntArrayComparator creates and returns an empty sorted array with specified comparator. +// The parameter used to specify whether using array in concurrent-safety which is false in default. +func NewSortedIntArrayComparator(comparator func(a, b int) int, safe ...bool) *SortedIntArray { + array := NewSortedIntArray(safe...) + array.comparator = comparator + return array +} + // NewSortedIntArraySize create and returns an sorted array with given size and cap. // The parameter used to specify whether using array in concurrent-safety, // which is false in default. func NewSortedIntArraySize(cap int, safe ...bool) *SortedIntArray { return &SortedIntArray{ - mu: rwmutex.New(safe...), - array: make([]int, 0, cap), - unique: gtype.NewBool(), - comparator: func(v1, v2 int) int { - if v1 < v2 { - return -1 - } - if v1 > v2 { - return 1 - } - return 0 - }, + mu: rwmutex.New(safe...), + array: make([]int, 0, cap), + unique: gtype.NewBool(), + comparator: defaultComparatorInt, } } diff --git a/g/container/garray/garray_sorted_interface.go b/g/container/garray/garray_sorted_interface.go index 8962aeca7..382fe5b1d 100644 --- a/g/container/garray/garray_sorted_interface.go +++ b/g/container/garray/garray_sorted_interface.go @@ -22,8 +22,8 @@ import ( type SortedArray struct { mu *rwmutex.RWMutex array []interface{} - unique *gtype.Bool // Whether enable unique feature(false) - comparator func(v1, v2 interface{}) int // Comparison function(it returns -1: v1 < v2; 0: v1 == v2; 1: v1 > v2) + unique *gtype.Bool // Whether enable unique feature(false) + comparator func(a, b interface{}) int // Comparison function(it returns -1: a < b; 0: a == b; 1: a > b) } // NewSortedArray creates and returns an empty sorted array. @@ -32,14 +32,14 @@ type SortedArray struct { // if it returns value < 0, means v1 < v2; // if it returns value = 0, means v1 = v2; // if it returns value > 0, means v1 > v2; -func NewSortedArray(comparator func(v1, v2 interface{}) int, safe ...bool) *SortedArray { +func NewSortedArray(comparator func(a, b interface{}) int, safe ...bool) *SortedArray { return NewSortedArraySize(0, comparator, safe...) } // NewSortedArraySize create and returns an sorted array with given size and cap. // The parameter used to specify whether using array in concurrent-safety, // which is false in default. -func NewSortedArraySize(cap int, comparator func(v1, v2 interface{}) int, safe ...bool) *SortedArray { +func NewSortedArraySize(cap int, comparator func(a, b interface{}) int, safe ...bool) *SortedArray { return &SortedArray{ mu: rwmutex.New(safe...), unique: gtype.NewBool(), @@ -51,7 +51,7 @@ func NewSortedArraySize(cap int, comparator func(v1, v2 interface{}) int, safe . // NewSortedArrayFrom creates and returns an sorted array with given slice . // The parameter used to specify whether using array in concurrent-safety, // which is false in default. -func NewSortedArrayFrom(array []interface{}, comparator func(v1, v2 interface{}) int, safe ...bool) *SortedArray { +func NewSortedArrayFrom(array []interface{}, comparator func(a, b interface{}) int, safe ...bool) *SortedArray { a := NewSortedArraySize(0, comparator, safe...) a.array = array sort.Slice(a.array, func(i, j int) bool { @@ -63,7 +63,7 @@ func NewSortedArrayFrom(array []interface{}, comparator func(v1, v2 interface{}) // NewSortedArrayFromCopy creates and returns an sorted array from a copy of given slice . // The parameter used to specify whether using array in concurrent-safety, // which is false in default. -func NewSortedArrayFromCopy(array []interface{}, comparator func(v1, v2 interface{}) int, safe ...bool) *SortedArray { +func NewSortedArrayFromCopy(array []interface{}, comparator func(a, b interface{}) int, safe ...bool) *SortedArray { newArray := make([]interface{}, len(array)) copy(newArray, array) return NewSortedArrayFrom(newArray, comparator, safe...) diff --git a/g/container/garray/garray_sorted_string.go b/g/container/garray/garray_sorted_string.go index 601307e35..085db2732 100644 --- a/g/container/garray/garray_sorted_string.go +++ b/g/container/garray/garray_sorted_string.go @@ -10,8 +10,6 @@ import ( "bytes" "encoding/json" "math" - "sort" - "strings" "github.com/gogf/gf/g/container/gtype" "github.com/gogf/gf/g/internal/rwmutex" @@ -23,8 +21,8 @@ import ( type SortedStringArray struct { mu *rwmutex.RWMutex array []string - unique *gtype.Bool // Whether enable unique feature(false) - comparator func(v1, v2 string) int // Comparison function(it returns -1: v1 < v2; 0: v1 == v2; 1: v1 > v2) + unique *gtype.Bool // Whether enable unique feature(false) + comparator func(a, b string) int // Comparison function(it returns -1: a < b; 0: a == b; 1: a > b) } // NewSortedStringArray creates and returns an empty sorted array. @@ -34,17 +32,23 @@ func NewSortedStringArray(safe ...bool) *SortedStringArray { return NewSortedStringArraySize(0, safe...) } +// NewSortedStringArrayComparator creates and returns an empty sorted array with specified comparator. +// The parameter used to specify whether using array in concurrent-safety which is false in default. +func NewSortedStringArrayComparator(comparator func(a, b string) int, safe ...bool) *SortedStringArray { + array := NewSortedStringArray(safe...) + array.comparator = comparator + return array +} + // NewSortedStringArraySize create and returns an sorted array with given size and cap. // The parameter used to specify whether using array in concurrent-safety, // which is false in default. func NewSortedStringArraySize(cap int, safe ...bool) *SortedStringArray { return &SortedStringArray{ - mu: rwmutex.New(safe...), - array: make([]string, 0, cap), - unique: gtype.NewBool(), - comparator: func(v1, v2 string) int { - return strings.Compare(v1, v2) - }, + mu: rwmutex.New(safe...), + array: make([]string, 0, cap), + unique: gtype.NewBool(), + comparator: defaultComparatorStr, } } @@ -54,7 +58,7 @@ func NewSortedStringArraySize(cap int, safe ...bool) *SortedStringArray { func NewSortedStringArrayFrom(array []string, safe ...bool) *SortedStringArray { a := NewSortedStringArraySize(0, safe...) a.array = array - sort.Strings(a.array) + quickSortStr(a.array, a.comparator) return a } @@ -72,7 +76,7 @@ func (a *SortedStringArray) SetArray(array []string) *SortedStringArray { a.mu.Lock() defer a.mu.Unlock() a.array = array - sort.Strings(a.array) + quickSortStr(a.array, a.comparator) return a } @@ -82,7 +86,7 @@ func (a *SortedStringArray) SetArray(array []string) *SortedStringArray { func (a *SortedStringArray) Sort() *SortedStringArray { a.mu.Lock() defer a.mu.Unlock() - sort.Strings(a.array) + quickSortStr(a.array, a.comparator) return a } diff --git a/g/internal/debug/stack.go b/g/internal/debug/debug.go similarity index 93% rename from g/internal/debug/stack.go rename to g/internal/debug/debug.go index 82e4a7aa5..d564e5b28 100644 --- a/g/internal/debug/stack.go +++ b/g/internal/debug/debug.go @@ -17,7 +17,7 @@ import ( const ( gMAX_DEPTH = 1000 - gFILTER_KEY = "/g/internal/debug/stack.go" + gFILTER_KEY = "/g/internal/debug/debug.go" ) var ( @@ -84,14 +84,14 @@ func StackWithFilter(filter string, skip ...int) string { } // CallerPath returns the absolute file path along with its line number of the caller. -func Caller(skip ...int) string { +func Caller(skip ...int) (path string, line int) { return CallerWithFilter("", skip...) } // CallerPathWithFilter returns the absolute file path along with its line number of the caller. // // The parameter is used to filter the path of the caller. -func CallerWithFilter(filter string, skip ...int) string { +func CallerWithFilter(filter string, skip ...int) (path string, line int) { number := 0 if len(skip) > 0 { number = skip[0] @@ -104,12 +104,12 @@ func CallerWithFilter(filter string, skip ...int) string { if strings.Contains(file, gFILTER_KEY) { continue } - return fmt.Sprintf(`%s:%d`, file, line) + return file, line } else { break } } - return "" + return "", -1 } // callerFromIndex returns the caller position exclusive of the debug package. diff --git a/g/os/gfile/gfile.go b/g/os/gfile/gfile.go index 5be544322..6ba032b36 100644 --- a/g/os/gfile/gfile.go +++ b/g/os/gfile/gfile.go @@ -18,21 +18,16 @@ import ( "os/user" "path/filepath" "runtime" - "sort" "strings" "time" "github.com/gogf/gf/g/container/gtype" - "github.com/gogf/gf/g/text/gregex" - "github.com/gogf/gf/g/text/gstr" "github.com/gogf/gf/g/util/gconv" ) const ( - // Separator for file system. - Separator = string(filepath.Separator) - // Default perm for file opening. - gDEFAULT_PERM = 0666 + Separator = string(filepath.Separator) // Separator for file system. + gDEFAULT_PERM = 0666 // Default perm for file opening. ) var ( @@ -333,58 +328,6 @@ func Chmod(path string, mode os.FileMode) error { return os.Chmod(path, mode) } -// ScanDir returns all sub-files with absolute paths of given , -// It scans directory recursively if given parameter is true. -func ScanDir(path string, pattern string, recursive ...bool) ([]string, error) { - list, err := doScanDir(path, pattern, recursive...) - if err != nil { - return nil, err - } - if len(list) > 0 { - sort.Strings(list) - } - return list, nil -} - -// doScanDir is an internal method which scans directory -// and returns the absolute path list of files that are not sorted. -// -// The pattern parameter supports multiple file name patterns, -// using the ',' symbol to separate multiple patterns. -// -// It scans directory recursively if given parameter is true. -func doScanDir(path string, pattern string, recursive ...bool) ([]string, error) { - list := ([]string)(nil) - file, err := os.Open(path) - if err != nil { - return nil, err - } - defer file.Close() - names, err := file.Readdirnames(-1) - if err != nil { - return nil, err - } - for _, name := range names { - path := fmt.Sprintf("%s%s%s", path, Separator, name) - if IsDir(path) && len(recursive) > 0 && recursive[0] { - array, _ := doScanDir(path, pattern, true) - if len(array) > 0 { - list = append(list, array...) - } - } - // If it meets pattern, then add it to the result list. - for _, p := range strings.Split(pattern, ",") { - if match, err := filepath.Match(strings.TrimSpace(p), name); err == nil && match { - path = Abs(path) - if path != "" { - list = append(list, path) - } - } - } - } - return list, nil -} - // Abs returns an absolute representation of path. // If the path is not absolute it will be joined with the current // working directory to turn it into an absolute path. The absolute @@ -516,54 +459,6 @@ func homeWindows() (string, error) { return home, nil } -// MainPkgPath returns absolute file path of package main, -// which contains the entrance function main. -// -// It's only available in develop environment. -// -// Note1: Only valid for source development environments, -// IE only valid for systems that generate this executable. -// Note2: When the method is called for the first time, if it is in an asynchronous goroutine, -// the method may not get the main package path. -func MainPkgPath() string { - path := mainPkgPath.Val() - if path != "" { - if path == "-" { - return "" - } - return path - } - for i := 1; i < 10000; i++ { - if _, file, _, ok := runtime.Caller(i); ok { - // is separated by '/' - if gstr.Contains(file, "/gf/g/") { - continue - } - if Ext(file) != ".go" { - continue - } - // separator of '/' will be converted to Separator. - for path = Dir(file); len(path) > 1 && Exists(path) && path[len(path)-1] != os.PathSeparator; { - files, _ := ScanDir(path, "*.go") - for _, v := range files { - if gregex.IsMatchString(`package\s+main`, GetContents(v)) { - mainPkgPath.Set(path) - return path - } - } - path = Dir(path) - } - - } else { - break - } - } - // If it fails finding the path, then mark it as "-", - // which means it will never do this search again. - mainPkgPath.Set("-") - return "" -} - // See os.TempDir(). func TempDir() string { return os.TempDir() diff --git a/g/os/gfile/gfile_replace.go b/g/os/gfile/gfile_replace.go index 4829eab08..523e9ace2 100644 --- a/g/os/gfile/gfile_replace.go +++ b/g/os/gfile/gfile_replace.go @@ -29,7 +29,7 @@ func Replace(search, replace, path, pattern string, recursive ...bool) error { // ReplaceFunc replaces content for files under with callback function . // The parameter specifies the file pattern which matches to be replaced. // It does replacement recursively if given parameter is true. -func ReplaceFunc(f func(content string) string, path, pattern string, recursive ...bool) error { +func ReplaceFunc(f func(path, content string) string, path, pattern string, recursive ...bool) error { files, err := ScanDir(path, pattern, recursive...) if err != nil { return err @@ -38,7 +38,7 @@ func ReplaceFunc(f func(content string) string, path, pattern string, recursive result := "" for _, file := range files { data = GetContents(file) - result = f(data) + result = f(file, data) if data != result { if err = PutContents(file, result); err != nil { return err diff --git a/g/os/gfile/gfile_scan.go b/g/os/gfile/gfile_scan.go new file mode 100644 index 000000000..38da283a8 --- /dev/null +++ b/g/os/gfile/gfile_scan.go @@ -0,0 +1,96 @@ +// Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gfile + +import ( + "os" + "path/filepath" + "sort" + "strings" +) + +// ScanDir returns all sub-files with absolute paths of given , +// It scans directory recursively if given parameter is true. +func ScanDir(path string, pattern string, recursive ...bool) ([]string, error) { + isRecursive := true + if len(recursive) > 0 { + isRecursive = recursive[0] + } + list, err := doScanDir(path, pattern, isRecursive, false) + if err != nil { + return nil, err + } + if len(list) > 0 { + sort.Strings(list) + } + return list, nil +} + +// ScanDirFile returns all sub-files with absolute paths of given , +// It scans directory recursively if given parameter is true. +// +// Note that it returns only files, exclusive of directories. +func ScanDirFile(path string, pattern string, recursive ...bool) ([]string, error) { + isRecursive := true + if len(recursive) > 0 { + isRecursive = recursive[0] + } + list, err := doScanDir(path, pattern, isRecursive, true) + if err != nil { + return nil, err + } + if len(list) > 0 { + sort.Strings(list) + } + return list, nil +} + +// doScanDir is an internal method which scans directory +// and returns the absolute path list of files that are not sorted. +// +// The pattern parameter supports multiple file name patterns, +// using the ',' symbol to separate multiple patterns. +// +// It scans directory recursively if given parameter is true. +func doScanDir(path string, pattern string, recursive bool, onlyFile bool) ([]string, error) { + list := ([]string)(nil) + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + names, err := file.Readdirnames(-1) + if err != nil { + return nil, err + } + filePath := "" + isDir := false + for _, name := range names { + filePath = path + Separator + name + isDir = IsDir(filePath) + if isDir && recursive { + array, _ := doScanDir(filePath, pattern, true, onlyFile) + if len(array) > 0 { + list = append(list, array...) + } + } + // It returns only files. + if isDir && onlyFile { + continue + } + // If it meets pattern, then add it to the result list. + for _, p := range strings.Split(pattern, ",") { + if match, err := filepath.Match(strings.TrimSpace(p), name); err == nil && match { + filePath = Abs(filePath) + if filePath != "" { + list = append(list, filePath) + } + } + } + } + return list, nil +} diff --git a/g/os/gfile/gfile_sort.go b/g/os/gfile/gfile_sort.go new file mode 100644 index 000000000..41b7eda92 --- /dev/null +++ b/g/os/gfile/gfile_sort.go @@ -0,0 +1,40 @@ +// Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gfile + +import ( + "strings" + + "github.com/gogf/gf/g/container/garray" +) + +// fileSortFunc is the comparison function for files. +// It sorts the array in order of: directory -> file. +// If and are the same type, it then sorts them as strings. +func fileSortFunc(path1, path2 string) int { + isDirPath1 := IsDir(path1) + isDirPath2 := IsDir(path2) + if isDirPath1 && !isDirPath2 { + return -1 + } + if !isDirPath1 && isDirPath2 { + return 1 + } + if n := strings.Compare(path1, path2); n != 0 { + return n + } else { + return -1 + } +} + +// SortFiles sorts the in order of: directory -> file. +// Note that the item of should be absolute path. +func SortFiles(files []string) []string { + array := garray.NewSortedStringArrayComparator(fileSortFunc) + array.Add(files...) + return array.Slice() +} diff --git a/g/os/gfile/gfile_source.go b/g/os/gfile/gfile_source.go new file mode 100644 index 000000000..b0126cdf0 --- /dev/null +++ b/g/os/gfile/gfile_source.go @@ -0,0 +1,77 @@ +// Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gfile + +import ( + "os" + "runtime" + + "github.com/gogf/gf/g/internal/debug" + "github.com/gogf/gf/g/text/gregex" + "github.com/gogf/gf/g/text/gstr" +) + +const ( + gPATH_FILTER_KEY = "/g/os/gfile/gfile_source.go" +) + +// SourcePath returns absolute file path of the current source file path. +// +// Note that it's only available in develop environment. +func SourcePath(skip ...int) string { + path, _ := debug.CallerWithFilter(gPATH_FILTER_KEY, skip...) + return path +} + +// MainPkgPath returns absolute file path of package main, +// which contains the entrance function main. +// +// It's only available in develop environment. +// +// Note1: Only valid for source development environments, +// IE only valid for systems that generate this executable. +// +// Note2: When the method is called for the first time, if it is in an asynchronous goroutine, +// the method may not get the main package path. +func MainPkgPath() string { + path := mainPkgPath.Val() + if path != "" { + if path == "-" { + return "" + } + return path + } + for i := 1; i < 10000; i++ { + if _, file, _, ok := runtime.Caller(i); ok { + // is separated by '/' + if gstr.Contains(file, "/gf/g/") { + continue + } + if Ext(file) != ".go" { + continue + } + // separator of '/' will be converted to Separator. + for path = Dir(file); len(path) > 1 && Exists(path) && path[len(path)-1] != os.PathSeparator; { + files, _ := ScanDir(path, "*.go") + for _, v := range files { + if gregex.IsMatchString(`package\s+main`, GetContents(v)) { + mainPkgPath.Set(path) + return path + } + } + path = Dir(path) + } + + } else { + break + } + } + // If it fails finding the path, then mark it as "-", + // which means it will never do this search again. + mainPkgPath.Set("-") + return "" +} diff --git a/g/os/gfile/gfile_z_contents_test.go b/g/os/gfile/gfile_z_contents_test.go index c066b7d1d..a67eaff48 100644 --- a/g/os/gfile/gfile_z_contents_test.go +++ b/g/os/gfile/gfile_z_contents_test.go @@ -1,13 +1,14 @@ package gfile_test import ( - "github.com/gogf/gf/g/os/gfile" - "github.com/gogf/gf/g/test/gtest" "io/ioutil" "os" "path/filepath" "strings" "testing" + + "github.com/gogf/gf/g/os/gfile" + "github.com/gogf/gf/g/test/gtest" ) // 创建测试文件 @@ -50,7 +51,7 @@ func testpath() string { return os.TempDir() } -func TestGetContents(t *testing.T) { +func Test_GetContents(t *testing.T) { gtest.Case(t, func() { var ( @@ -65,7 +66,7 @@ func TestGetContents(t *testing.T) { }) } -func TestGetBinContents(t *testing.T) { +func Test_GetBinContents(t *testing.T) { gtest.Case(t, func() { var ( filepaths1 string = "/testfile_t1.txt" // 文件存在时 @@ -87,7 +88,7 @@ func TestGetBinContents(t *testing.T) { } // 截断文件为指定的大小 -func TestTruncate(t *testing.T) { +func Test_Truncate(t *testing.T) { gtest.Case(t, func() { var ( filepaths1 string = "/testfile_GetContentsyyui.txt" //文件存在时 @@ -114,7 +115,7 @@ func TestTruncate(t *testing.T) { }) } -func TestPutContents(t *testing.T) { +func Test_PutContents(t *testing.T) { gtest.Case(t, func() { var ( filepaths string = "/testfile_PutContents.txt" @@ -138,7 +139,7 @@ func TestPutContents(t *testing.T) { }) } -func TestPutContentsAppend(t *testing.T) { +func Test_PutContentsAppend(t *testing.T) { gtest.Case(t, func() { var ( filepaths string = "/testfile_PutContents.txt" @@ -163,7 +164,7 @@ func TestPutContentsAppend(t *testing.T) { } -func TestPutBinContents(t *testing.T) { +func Test_PutBinContents(t *testing.T) { gtest.Case(t, func() { var ( filepaths string = "/testfile_PutContents.txt" @@ -187,7 +188,7 @@ func TestPutBinContents(t *testing.T) { }) } -func TestPutBinContentsAppend(t *testing.T) { +func Test_PutBinContentsAppend(t *testing.T) { gtest.Case(t, func() { var ( filepaths string = "/testfile_PutContents.txt" //原文件内容: yy @@ -210,7 +211,7 @@ func TestPutBinContentsAppend(t *testing.T) { }) } -func TestGetBinContentsByTwoOffsetsByPath(t *testing.T) { +func Test_GetBinContentsByTwoOffsetsByPath(t *testing.T) { gtest.Case(t, func() { var ( filepaths string = "/testfile_GetContents.txt" // 文件内容: abcdefghijk @@ -230,7 +231,7 @@ func TestGetBinContentsByTwoOffsetsByPath(t *testing.T) { } -func TestGetNextCharOffsetByPath(t *testing.T) { +func Test_GetNextCharOffsetByPath(t *testing.T) { gtest.Case(t, func() { var ( filepaths string = "/testfile_GetContents.txt" // 文件内容: abcdefghijk @@ -247,7 +248,7 @@ func TestGetNextCharOffsetByPath(t *testing.T) { }) } -func TestGetNextCharOffset(t *testing.T) { +func Test_GetNextCharOffset(t *testing.T) { gtest.Case(t, func() { var ( localindex int64 @@ -263,7 +264,7 @@ func TestGetNextCharOffset(t *testing.T) { }) } -func TestGetBinContentsByTwoOffsets(t *testing.T) { +func Test_GetBinContentsByTwoOffsets(t *testing.T) { gtest.Case(t, func() { var ( reads []byte @@ -279,7 +280,7 @@ func TestGetBinContentsByTwoOffsets(t *testing.T) { }) } -func TestGetBinContentsTilChar(t *testing.T) { +func Test_GetBinContentsTilChar(t *testing.T) { gtest.Case(t, func() { var ( reads []byte @@ -296,7 +297,7 @@ func TestGetBinContentsTilChar(t *testing.T) { }) } -func TestGetBinContentsTilCharByPath(t *testing.T) { +func Test_GetBinContentsTilCharByPath(t *testing.T) { gtest.Case(t, func() { var ( reads []byte @@ -319,7 +320,7 @@ func TestGetBinContentsTilCharByPath(t *testing.T) { }) } -func TestHome(t *testing.T) { +func Test_Home(t *testing.T) { gtest.Case(t, func() { var ( reads string diff --git a/g/os/gfile/gfile_z_scan_test.go b/g/os/gfile/gfile_z_scan_test.go new file mode 100644 index 000000000..119ac6614 --- /dev/null +++ b/g/os/gfile/gfile_z_scan_test.go @@ -0,0 +1,28 @@ +package gfile_test + +import ( + "testing" + + "github.com/gogf/gf/g/os/gfile" + + "github.com/gogf/gf/g/test/gtest" +) + +func Test_Scan(t *testing.T) { + teatPath := gfile.Dir(gfile.SourcePath()) + gfile.Separator + "testdata" + gtest.Case(t, func() { + files, err := gfile.ScanDir(teatPath, "*", false) + gtest.Assert(err, nil) + gtest.AssertIN(teatPath+gfile.Separator+"dir1", files) + gtest.AssertIN(teatPath+gfile.Separator+"dir2", files) + gtest.AssertNE(teatPath+gfile.Separator+"dir1"+gfile.Separator+"file1", files) + }) + gtest.Case(t, func() { + files, err := gfile.ScanDir(teatPath, "*", true) + gtest.Assert(err, nil) + gtest.AssertNE(teatPath+gfile.Separator+"dir1", files) + gtest.AssertNE(teatPath+gfile.Separator+"dir2", files) + gtest.AssertIN(teatPath+gfile.Separator+"dir1"+gfile.Separator+"file1", files) + gtest.AssertIN(teatPath+gfile.Separator+"dir2"+gfile.Separator+"file2", files) + }) +} diff --git a/g/os/gfile/gfile_z_search_test.go b/g/os/gfile/gfile_z_search_test.go index ca6018a24..5442ba2c5 100644 --- a/g/os/gfile/gfile_z_search_test.go +++ b/g/os/gfile/gfile_z_search_test.go @@ -1,13 +1,14 @@ package gfile_test import ( - "github.com/gogf/gf/g/os/gfile" - "github.com/gogf/gf/g/test/gtest" "path/filepath" "testing" + + "github.com/gogf/gf/g/os/gfile" + "github.com/gogf/gf/g/test/gtest" ) -func TestSearch(t *testing.T) { +func Test_Search(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfiless" diff --git a/g/os/gfile/gfile_z_size_test.go b/g/os/gfile/gfile_z_size_test.go index 9f738366d..3aafba956 100644 --- a/g/os/gfile/gfile_z_size_test.go +++ b/g/os/gfile/gfile_z_size_test.go @@ -1,12 +1,13 @@ package gfile_test import ( + "testing" + "github.com/gogf/gf/g/os/gfile" "github.com/gogf/gf/g/test/gtest" - "testing" ) -func TestSize(t *testing.T) { +func Test_Size(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfile_t1.txt" @@ -25,7 +26,7 @@ func TestSize(t *testing.T) { }) } -func TestFormatSize(t *testing.T) { +func Test_FormatSize(t *testing.T) { gtest.Case(t, func() { gtest.Assert(gfile.FormatSize(0), "0.00B") gtest.Assert(gfile.FormatSize(16), "16.00B") @@ -38,13 +39,10 @@ func TestFormatSize(t *testing.T) { gtest.Assert(gfile.FormatSize(9600000000000), "8.73T") gtest.Assert(gfile.FormatSize(9600000000000000), "8.53P") - - gtest.Assert(gfile.FormatSize(9600000000000000000), "TooLarge") - }) } -func TestReadableSize(t *testing.T) { +func Test_ReadableSize(t *testing.T) { gtest.Case(t, func() { var ( diff --git a/g/os/gfile/gfile_z_test.go b/g/os/gfile/gfile_z_test.go index 44b8008ed..57fe1862e 100644 --- a/g/os/gfile/gfile_z_test.go +++ b/g/os/gfile/gfile_z_test.go @@ -10,7 +10,7 @@ import ( "github.com/gogf/gf/g/test/gtest" ) -func TestIsDir(t *testing.T) { +func Test_IsDir(t *testing.T) { gtest.Case(t, func() { paths := "/testfile" @@ -26,7 +26,7 @@ func TestIsDir(t *testing.T) { } -func TestCreate(t *testing.T) { +func Test_Create(t *testing.T) { gtest.Case(t, func() { var ( err error @@ -49,7 +49,7 @@ func TestCreate(t *testing.T) { } -func TestOpen(t *testing.T) { +func Test_Open(t *testing.T) { gtest.Case(t, func() { var ( err error @@ -82,7 +82,7 @@ func TestOpen(t *testing.T) { }) } -func TestOpenFile(t *testing.T) { +func Test_OpenFile(t *testing.T) { gtest.Case(t, func() { var ( err error @@ -115,7 +115,7 @@ func TestOpenFile(t *testing.T) { }) } -func TestOpenWithFlag(t *testing.T) { +func Test_OpenWithFlag(t *testing.T) { gtest.Case(t, func() { var ( err error @@ -147,7 +147,7 @@ func TestOpenWithFlag(t *testing.T) { }) } -func TestOpenWithFlagPerm(t *testing.T) { +func Test_OpenWithFlagPerm(t *testing.T) { gtest.Case(t, func() { var ( err error @@ -178,7 +178,7 @@ func TestOpenWithFlagPerm(t *testing.T) { }) } -func TestExists(t *testing.T) { +func Test_Exists(t *testing.T) { gtest.Case(t, func() { var ( @@ -210,7 +210,7 @@ func TestExists(t *testing.T) { }) } -func TestPwd(t *testing.T) { +func Test_Pwd(t *testing.T) { gtest.Case(t, func() { paths, err := os.Getwd() gtest.Assert(err, nil) @@ -219,7 +219,7 @@ func TestPwd(t *testing.T) { }) } -func TestIsFile(t *testing.T) { +func Test_IsFile(t *testing.T) { gtest.Case(t, func() { var ( flag bool @@ -255,7 +255,7 @@ func TestIsFile(t *testing.T) { }) } -func TestInfo(t *testing.T) { +func Test_Info(t *testing.T) { gtest.Case(t, func() { var ( err error @@ -277,7 +277,7 @@ func TestInfo(t *testing.T) { }) } -func TestMove(t *testing.T) { +func Test_Move(t *testing.T) { gtest.Case(t, func() { var ( paths string = "/ovetest" @@ -301,7 +301,7 @@ func TestMove(t *testing.T) { }) } -func TestRename(t *testing.T) { +func Test_Rename(t *testing.T) { gtest.Case(t, func() { var ( paths string = "/testfiles" @@ -324,7 +324,7 @@ func TestRename(t *testing.T) { } -func TestCopy(t *testing.T) { +func Test_Copy(t *testing.T) { gtest.Case(t, func() { var ( paths string = "/testfile_copyfile1.txt" @@ -342,7 +342,7 @@ func TestCopy(t *testing.T) { }) } -func TestDirNames(t *testing.T) { +func Test_DirNames(t *testing.T) { gtest.Case(t, func() { var ( paths string = "/testdirs" @@ -372,7 +372,7 @@ func TestDirNames(t *testing.T) { }) } -func TestGlob(t *testing.T) { +func Test_Glob(t *testing.T) { gtest.Case(t, func() { var ( paths string = "/testfiles/*.txt" @@ -413,7 +413,7 @@ func TestGlob(t *testing.T) { }) } -func TestRemove(t *testing.T) { +func Test_Remove(t *testing.T) { gtest.Case(t, func() { var ( paths string = "/testfile_t1.txt" @@ -428,7 +428,7 @@ func TestRemove(t *testing.T) { }) } -func TestIsReadable(t *testing.T) { +func Test_IsReadable(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfile_GetContents.txt" @@ -444,7 +444,7 @@ func TestIsReadable(t *testing.T) { }) } -func TestIsWritable(t *testing.T) { +func Test_IsWritable(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfile_GetContents.txt" @@ -459,7 +459,7 @@ func TestIsWritable(t *testing.T) { }) } -func TestChmod(t *testing.T) { +func Test_Chmod(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfile_GetContents.txt" @@ -474,7 +474,7 @@ func TestChmod(t *testing.T) { }) } -func TestScanDir(t *testing.T) { +func Test_ScanDir(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfiledirs" @@ -505,7 +505,7 @@ func TestScanDir(t *testing.T) { } // 获取绝对目录地址 -func TestRealPath(t *testing.T) { +func Test_RealPath(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfile_files" @@ -529,7 +529,7 @@ func TestRealPath(t *testing.T) { } // 获取当前执行文件的目录 -func TestSelfPath(t *testing.T) { +func Test_SelfPath(t *testing.T) { gtest.Case(t, func() { var ( paths1 string @@ -548,7 +548,7 @@ func TestSelfPath(t *testing.T) { }) } -func TestSelfDir(t *testing.T) { +func Test_SelfDir(t *testing.T) { gtest.Case(t, func() { var ( paths1 string @@ -565,7 +565,7 @@ func TestSelfDir(t *testing.T) { }) } -func TestBasename(t *testing.T) { +func Test_Basename(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfilerr_GetContents.txt" @@ -581,7 +581,7 @@ func TestBasename(t *testing.T) { }) } -func TestDir(t *testing.T) { +func Test_Dir(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfiless" @@ -598,7 +598,7 @@ func TestDir(t *testing.T) { } // 获取文件名 -func TestExt(t *testing.T) { +func Test_Ext(t *testing.T) { gtest.Case(t, func() { var ( paths1 string = "/testfile_GetContents.txt" @@ -616,7 +616,7 @@ func TestExt(t *testing.T) { }) } -func TestTempDir(t *testing.T) { +func Test_TempDir(t *testing.T) { gtest.Case(t, func() { var ( tpath string @@ -628,7 +628,7 @@ func TestTempDir(t *testing.T) { }) } -func TestMkdir(t *testing.T) { +func Test_Mkdir(t *testing.T) { gtest.Case(t, func() { var ( tpath string = "/testfile/createdir" @@ -649,7 +649,7 @@ func TestMkdir(t *testing.T) { }) } -func TestStat(t *testing.T) { +func Test_Stat(t *testing.T) { gtest.Case(t, func() { var ( tpath1 = "/testfile_t1.txt" @@ -672,14 +672,14 @@ func TestStat(t *testing.T) { }) } -func TestMainPkgPath(t *testing.T) { +func Test_MainPkgPath(t *testing.T) { gtest.Case(t, func() { reads := gfile.MainPkgPath() gtest.Assert(reads, "") }) } -func TestCopyFile(t *testing.T) { +func Test_CopyFile(t *testing.T) { gtest.Case(t, func() { var ( paths string = "/testfile_copyfile1.txt" @@ -697,7 +697,7 @@ func TestCopyFile(t *testing.T) { }) } -func TestCopyDir(t *testing.T) { +func Test_CopyDir(t *testing.T) { gtest.Case(t, func() { var ( dirpath1 string = "/testcopydir1" diff --git a/g/os/gfile/gfile_z_time_test.go b/g/os/gfile/gfile_z_time_test.go index b2e8c5f31..c61bf6d2e 100644 --- a/g/os/gfile/gfile_z_time_test.go +++ b/g/os/gfile/gfile_z_time_test.go @@ -1,13 +1,14 @@ package gfile_test import ( - "github.com/gogf/gf/g/os/gfile" - "github.com/gogf/gf/g/test/gtest" "os" "testing" + + "github.com/gogf/gf/g/os/gfile" + "github.com/gogf/gf/g/test/gtest" ) -func TestMTime(t *testing.T) { +func Test_MTime(t *testing.T) { gtest.Case(t, func() { var ( @@ -26,7 +27,7 @@ func TestMTime(t *testing.T) { }) } -func TestMTimeMillisecond(t *testing.T) { +func Test_MTimeMillisecond(t *testing.T) { gtest.Case(t, func() { var ( file1 string = "/testfile_t1.txt" diff --git a/g/os/gfile/testdata/dir1/file1 b/g/os/gfile/testdata/dir1/file1 new file mode 100644 index 000000000..e69de29bb diff --git a/g/os/gfile/testdata/dir2/file2 b/g/os/gfile/testdata/dir2/file2 new file mode 100644 index 000000000..e69de29bb diff --git a/g/os/glog/glog_logger.go b/g/os/glog/glog_logger.go index 0390ab40d..bd22fccbe 100644 --- a/g/os/glog/glog_logger.go +++ b/g/os/glog/glog_logger.go @@ -244,10 +244,12 @@ func (l *Logger) print(std io.Writer, lead string, value ...interface{}) { // Caller path. callerPath := "" if l.flags&F_FILE_LONG > 0 { - callerPath = debug.CallerWithFilter(gPATH_FILTER_KEY, l.stSkip) + ": " + path, line := debug.CallerWithFilter(gPATH_FILTER_KEY, l.stSkip) + callerPath = fmt.Sprintf(`%s:%d: `, path, line) } if l.flags&F_FILE_SHORT > 0 { - callerPath = gfile.Basename(debug.CallerWithFilter(gPATH_FILTER_KEY, l.stSkip)) + ": " + path, line := debug.CallerWithFilter(gPATH_FILTER_KEY, l.stSkip) + callerPath = fmt.Sprintf(`%s:%d: `, gfile.Basename(path), line) } if len(callerPath) > 0 { buffer.WriteString(callerPath) diff --git a/geg/os/gfile/gfile_scan.go b/geg/os/gfile/gfile_scan.go index 6d7929982..31c25b29e 100644 --- a/geg/os/gfile/gfile_scan.go +++ b/geg/os/gfile/gfile_scan.go @@ -6,6 +6,6 @@ import ( ) func main() { - gutil.Dump(gfile.ScanDir("/home/john/Documents", "*")) + gutil.Dump(gfile.ScanDir("/Users/john/Documents", "*.*")) gutil.Dump(gfile.ScanDir("/home/john/temp/newproject", "*", true)) } diff --git a/geg/other/test.go b/geg/other/test.go index c9ed507ac..790580777 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,10 +1,5 @@ package main -import ( - "fmt" - "path/filepath" -) - func main() { - fmt.Println(filepath.Abs("s/s/s/s/s")) + }