Compare commits
3 commits
develop
...
feature/fi
Author | SHA1 | Date | |
---|---|---|---|
|
f9ef0775db | ||
|
bd68494f3f | ||
|
8eb4b605c8 |
12 changed files with 98 additions and 31 deletions
|
@ -91,7 +91,7 @@
|
||||||
<div>
|
<div>
|
||||||
<h3 class="body-2 mb-2" :title="model.Name">
|
<h3 class="body-2 mb-2" :title="model.Name">
|
||||||
<button @click.exact="openFile(index)">
|
<button @click.exact="openFile(index)">
|
||||||
{{ model.baseName(19) }}
|
{{ model.baseName() }}
|
||||||
</button>
|
</button>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="caption" title="Info">
|
<div class="caption" title="Info">
|
||||||
|
@ -103,13 +103,10 @@
|
||||||
<div>
|
<div>
|
||||||
<h3 class="body-2 mb-2" :title="model.Title">
|
<h3 class="body-2 mb-2" :title="model.Title">
|
||||||
<button @click.exact="openFile(index)">
|
<button @click.exact="openFile(index)">
|
||||||
{{ model.Title }}
|
{{ model.baseName() }}
|
||||||
</button>
|
</button>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="caption" title="Path" v-if="model.Title !== model.Path">
|
<div class="caption" title="Path">
|
||||||
/{{ model.Path }}
|
|
||||||
</div>
|
|
||||||
<div class="caption" title="Path" v-else>
|
|
||||||
<translate key="Folder">Folder</translate>
|
<translate key="Folder">Folder</translate>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,7 @@ func TestGetFoldersOriginals(t *testing.T) {
|
||||||
t.Run("flat", func(t *testing.T) {
|
t.Run("flat", func(t *testing.T) {
|
||||||
app, router, conf := NewApiTest()
|
app, router, conf := NewApiTest()
|
||||||
_ = conf.CreateDirectories()
|
_ = conf.CreateDirectories()
|
||||||
expected, err := fs.Dirs(conf.OriginalsPath(), false)
|
expected, err := fs.Dirs(conf.OriginalsPath(), false, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -56,7 +56,7 @@ func TestGetFoldersOriginals(t *testing.T) {
|
||||||
t.Run("recursive", func(t *testing.T) {
|
t.Run("recursive", func(t *testing.T) {
|
||||||
app, router, conf := NewApiTest()
|
app, router, conf := NewApiTest()
|
||||||
_ = conf.CreateDirectories()
|
_ = conf.CreateDirectories()
|
||||||
expected, err := fs.Dirs(conf.OriginalsPath(), true)
|
expected, err := fs.Dirs(conf.OriginalsPath(), true, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -96,7 +96,7 @@ func TestGetFoldersImport(t *testing.T) {
|
||||||
t.Run("flat", func(t *testing.T) {
|
t.Run("flat", func(t *testing.T) {
|
||||||
app, router, conf := NewApiTest()
|
app, router, conf := NewApiTest()
|
||||||
_ = conf.CreateDirectories()
|
_ = conf.CreateDirectories()
|
||||||
expected, err := fs.Dirs(conf.ImportPath(), false)
|
expected, err := fs.Dirs(conf.ImportPath(), false, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -140,7 +140,7 @@ func TestGetFoldersImport(t *testing.T) {
|
||||||
t.Run("recursive", func(t *testing.T) {
|
t.Run("recursive", func(t *testing.T) {
|
||||||
app, router, conf := NewApiTest()
|
app, router, conf := NewApiTest()
|
||||||
_ = conf.CreateDirectories()
|
_ = conf.CreateDirectories()
|
||||||
expected, err := fs.Dirs(conf.ImportPath(), true)
|
expected, err := fs.Dirs(conf.ImportPath(), true, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
@ -226,5 +226,5 @@ func (m *File) Panorama() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.FileProjection != ProjectionDefault || m.FileWidth / m.FileHeight > 2
|
return m.FileProjection != ProjectionDefault || m.FileWidth/m.FileHeight > 2
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ type Photo struct {
|
||||||
PhotoPrivate bool `json:"Private"`
|
PhotoPrivate bool `json:"Private"`
|
||||||
PhotoReview bool `json:"Review"`
|
PhotoReview bool `json:"Review"`
|
||||||
PhotoScan bool `json:"Scan"`
|
PhotoScan bool `json:"Scan"`
|
||||||
PhotoPanorama bool `json:"Panorama"`
|
PhotoPanorama bool `json:"Panorama"`
|
||||||
PhotoAltitude int `json:"Altitude"`
|
PhotoAltitude int `json:"Altitude"`
|
||||||
PhotoLat float32 `json:"Lat"`
|
PhotoLat float32 `json:"Lat"`
|
||||||
PhotoLng float32 `json:"Lng"`
|
PhotoLng float32 `json:"Lng"`
|
||||||
|
|
|
@ -176,10 +176,10 @@ func TestLocation_Assign(t *testing.T) {
|
||||||
lat := -21.976301666666668
|
lat := -21.976301666666668
|
||||||
lng := 49.148046666666666
|
lng := 49.148046666666666
|
||||||
id := s2.Token(lat, lng)
|
id := s2.Token(lat, lng)
|
||||||
log.Printf("ID: %s", id)
|
// log.Printf("ID: %s", id)
|
||||||
o, err := places.FindLocation(id)
|
o, err := places.FindLocation(id)
|
||||||
|
|
||||||
log.Printf("Output: %+v", o)
|
// log.Printf("Output: %+v", o)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// FoldersByPath returns a slice of folders in a given directory incl sub directories in recursive mode.
|
// FoldersByPath returns a slice of folders in a given directory incl sub directories in recursive mode.
|
||||||
func FoldersByPath(rootName, rootPath, path string, recursive bool) (folders entity.Folders, err error) {
|
func FoldersByPath(rootName, rootPath, path string, recursive bool) (folders entity.Folders, err error) {
|
||||||
dirs, err := fs.Dirs(filepath.Join(rootPath, path), recursive)
|
dirs, err := fs.Dirs(filepath.Join(rootPath, path), recursive, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return folders, err
|
return folders, err
|
||||||
|
|
|
@ -88,25 +88,51 @@ var ImportPaths = []string{
|
||||||
"~/Import",
|
"~/Import",
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dirs(root string, recursive bool) (result []string, err error) {
|
// Dirs returns a slice of directories in a path, optional recursively and with symlinks.
|
||||||
|
//
|
||||||
|
// Warning: Following symlinks can make the result non-deterministic and hard to test!
|
||||||
|
func Dirs(root string, recursive bool, followLinks bool) (result []string, err error) {
|
||||||
result = []string{}
|
result = []string{}
|
||||||
ignore := NewIgnoreList(".ppignore", true, false)
|
ignore := NewIgnoreList(".ppignore", true, false)
|
||||||
mutex := sync.Mutex{}
|
mutex := sync.Mutex{}
|
||||||
|
|
||||||
err = fastwalk.Walk(root, func(fileName string, info os.FileMode) error {
|
symlinks := make(map[string]bool)
|
||||||
if info.IsDir() {
|
symlinksMutex := sync.Mutex{}
|
||||||
|
|
||||||
|
appendResult := func(fileName string) {
|
||||||
|
fileName = strings.Replace(fileName, root, "", 1)
|
||||||
|
mutex.Lock()
|
||||||
|
defer mutex.Unlock()
|
||||||
|
result = append(result, fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = fastwalk.Walk(root, func(fileName string, typ os.FileMode) error {
|
||||||
|
if typ.IsDir() || typ == os.ModeSymlink && followLinks {
|
||||||
if ignore.Ignore(fileName) {
|
if ignore.Ignore(fileName) {
|
||||||
return filepath.SkipDir
|
return filepath.SkipDir
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileName != root {
|
if fileName != root {
|
||||||
mutex.Lock()
|
|
||||||
fileName = strings.Replace(fileName, root, "", 1)
|
|
||||||
result = append(result, fileName)
|
|
||||||
mutex.Unlock()
|
|
||||||
|
|
||||||
if !recursive {
|
if !recursive {
|
||||||
|
appendResult(fileName)
|
||||||
|
|
||||||
return filepath.SkipDir
|
return filepath.SkipDir
|
||||||
|
} else if typ != os.ModeSymlink {
|
||||||
|
appendResult(fileName)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
} else if resolved, err := filepath.EvalSymlinks(fileName); err == nil {
|
||||||
|
symlinksMutex.Lock()
|
||||||
|
defer symlinksMutex.Unlock()
|
||||||
|
|
||||||
|
if _, ok := symlinks[resolved]; ok {
|
||||||
|
return filepath.SkipDir
|
||||||
|
} else {
|
||||||
|
symlinks[resolved] = true
|
||||||
|
appendResult(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fastwalk.ErrTraverseLink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,27 +9,70 @@ import (
|
||||||
|
|
||||||
func TestDirs(t *testing.T) {
|
func TestDirs(t *testing.T) {
|
||||||
t.Run("recursive", func(t *testing.T) {
|
t.Run("recursive", func(t *testing.T) {
|
||||||
result, err := Dirs("testdata", true)
|
result, err := Dirs("testdata", true, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := []string{"/directory", "/directory/subdirectory", "/linked"}
|
assert.Contains(t, result, "/directory")
|
||||||
|
assert.Contains(t, result, "/directory/subdirectory")
|
||||||
|
assert.Contains(t, result, "/linked")
|
||||||
|
assert.Contains(t, result, "/linked/photoprism")
|
||||||
|
assert.Contains(t, result, "/linked/photoprism/sub")
|
||||||
|
})
|
||||||
|
|
||||||
assert.Equal(t, expected, result)
|
t.Run("recursive no-symlinks", func(t *testing.T) {
|
||||||
|
result, err := Dirs("testdata", true, false)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Contains(t, result, "/directory")
|
||||||
|
assert.Contains(t, result, "/directory/subdirectory")
|
||||||
|
assert.Contains(t, result, "/linked")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("non-recursive", func(t *testing.T) {
|
t.Run("non-recursive", func(t *testing.T) {
|
||||||
result, err := Dirs("testdata", false)
|
result, err := Dirs("testdata", false, true)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := []string{"/directory", "/linked"}
|
assert.Contains(t, result, "/directory")
|
||||||
|
assert.Contains(t, result, "/linked")
|
||||||
|
})
|
||||||
|
|
||||||
assert.Equal(t, expected, result)
|
t.Run("non-recursive no-symlinks", func(t *testing.T) {
|
||||||
|
result, err := Dirs("testdata/directory/subdirectory", false, false)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Contains(t, result, "/bar")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("non-recursive symlinks", func(t *testing.T) {
|
||||||
|
result, err := Dirs("testdata/linked", false, true)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Contains(t, result, "/photoprism")
|
||||||
|
assert.Contains(t, result, "/self")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("no-result", func(t *testing.T) {
|
||||||
|
result, err := Dirs("testdata/linked", false, false)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Empty(t, result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,7 @@ func TestIgnoreList_Ignored(t *testing.T) {
|
||||||
expectIgnored := []string{
|
expectIgnored := []string{
|
||||||
"testdata/directory/bar.txt",
|
"testdata/directory/bar.txt",
|
||||||
"testdata/directory/baz.xml",
|
"testdata/directory/baz.xml",
|
||||||
|
"testdata/directory/subdirectory/bar",
|
||||||
"testdata/directory/subdirectory/example.txt",
|
"testdata/directory/subdirectory/example.txt",
|
||||||
"testdata/directory/subdirectory/foo.txt",
|
"testdata/directory/subdirectory/foo.txt",
|
||||||
}
|
}
|
||||||
|
|
1
pkg/fs/testdata/directory/subdirectory/bar/helloworld.md
vendored
Normal file
1
pkg/fs/testdata/directory/subdirectory/bar/helloworld.md
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Hello World!
|
1
pkg/fs/testdata/linked/photoprism
vendored
Symbolic link
1
pkg/fs/testdata/linked/photoprism
vendored
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../.photoprism
|
|
@ -1,7 +1,6 @@
|
||||||
package txt
|
package txt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -116,7 +115,6 @@ func Time(s string) (result time.Time) {
|
||||||
time.UTC)
|
time.UTC)
|
||||||
} else if found := DatePathRegexp.Find(b); len(found) > 0 { // Is it a date path like "2020/01/03"?
|
} else if found := DatePathRegexp.Find(b); len(found) > 0 { // Is it a date path like "2020/01/03"?
|
||||||
n := DateIntRegexp.FindAll(found, -1)
|
n := DateIntRegexp.FindAll(found, -1)
|
||||||
fmt.Println(n)
|
|
||||||
|
|
||||||
if len(n) < 2 || len(n) > 3 {
|
if len(n) < 2 || len(n) > 3 {
|
||||||
return result
|
return result
|
||||||
|
|
Loading…
Reference in a new issue