Compare commits

..

3 Commits

Author SHA1 Message Date
Seednode ebb5e48d9a Move regex compilation to global variable 2024-01-10 13:07:50 -06:00
Seednode 9e458aa0bb Move regex compilation to global variable 2024-01-10 13:07:24 -06:00
Seednode d568d10e78 Move walkPath() defers out to calling function, for more intuitive readability 2024-01-10 11:58:55 -06:00
5 changed files with 56 additions and 75 deletions

View File

@ -24,10 +24,9 @@ import (
"seedno.de/seednode/roulette/types" "seedno.de/seednode/roulette/types"
) )
type regexes struct { var (
alphanumeric *regexp.Regexp filename = regexp.MustCompile(`(.+?)([0-9]*)(\..+)`)
filename *regexp.Regexp )
}
type scanStats struct { type scanStats struct {
filesMatched chan int filesMatched chan int
@ -79,14 +78,14 @@ func kill(path string, index *fileIndex) error {
return nil return nil
} }
func newFile(list []string, sortOrder string, regexes *regexes, formats types.Types) (string, error) { func newFile(list []string, sortOrder string, formats types.Types) (string, error) {
path, err := pickFile(list) path, err := pickFile(list)
if err != nil { if err != nil {
return "", err return "", err
} }
if sortOrder == "asc" || sortOrder == "desc" { if sortOrder == "asc" || sortOrder == "desc" {
splitPath, err := split(path, regexes) splitPath, err := split(path)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -125,8 +124,8 @@ func newFile(list []string, sortOrder string, regexes *regexes, formats types.Ty
return path, nil return path, nil
} }
func nextFile(filePath, sortOrder string, regexes *regexes, formats types.Types) (string, error) { func nextFile(filePath, sortOrder string, formats types.Types) (string, error) {
splitPath, err := split(filePath, regexes) splitPath, err := split(filePath)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -241,10 +240,6 @@ func hasSupportedFiles(path string, formats types.Types) (bool, error) {
} }
func walkPath(path string, fileChannel chan<- string, wg1 *sync.WaitGroup, stats *scanStats, limit chan struct{}, formats types.Types, errorChannel chan<- error) { func walkPath(path string, fileChannel chan<- string, wg1 *sync.WaitGroup, stats *scanStats, limit chan struct{}, formats types.Types, errorChannel chan<- error) {
defer func() {
wg1.Done()
}()
limit <- struct{}{} limit <- struct{}{}
defer func() { defer func() {
@ -265,11 +260,13 @@ func walkPath(path string, fileChannel chan<- string, wg1 *sync.WaitGroup, stats
var skipDir = false var skipDir = false
for _, node := range nodes { for _, node := range nodes {
if Ignore && !node.IsDir() && node.Name() == IgnoreFile { if !node.IsDir() {
files++
if Ignore && node.Name() == IgnoreFile {
skipDir = true skipDir = true
} }
}
files++
} }
var skipFiles = false var skipFiles = false
@ -297,18 +294,19 @@ func walkPath(path string, fileChannel chan<- string, wg1 *sync.WaitGroup, stats
case node.IsDir() && Recursive: case node.IsDir() && Recursive:
wg1.Add(1) wg1.Add(1)
go func() {
defer wg1.Done()
walkPath(fullPath, fileChannel, wg1, stats, limit, formats, errorChannel) walkPath(fullPath, fileChannel, wg1, stats, limit, formats, errorChannel)
}()
case !node.IsDir() && !skipFiles: case !node.IsDir() && !skipFiles:
path, err := normalizePath(fullPath) path, err := normalizePath(fullPath)
if err != nil {
switch {
case err != nil:
errorChannel <- err errorChannel <- err
case formats.Validate(path) || Fallback:
stats.filesSkipped <- 1
return
}
if formats.Validate(path) || Fallback {
fileChannel <- path fileChannel <- path
stats.filesMatched <- 1 stats.filesMatched <- 1
@ -421,6 +419,8 @@ func scanPaths(paths []string, sort string, index *fileIndex, formats types.Type
wg1.Add(1) wg1.Add(1)
go func(i int) { go func(i int) {
defer wg1.Done()
walkPath(paths[i], fileChannel, &wg1, stats, limit, formats, errorChannel) walkPath(paths[i], fileChannel, &wg1, stats, limit, formats, errorChannel)
}(i) }(i)
} }

View File

@ -6,6 +6,7 @@ package cmd
import ( import (
"fmt" "fmt"
"log"
"math" "math"
"os" "os"
"regexp" "regexp"
@ -17,7 +18,7 @@ import (
const ( const (
AllowedCharacters string = `^[A-z0-9.\-_]+$` AllowedCharacters string = `^[A-z0-9.\-_]+$`
ReleaseVersion string = "5.0.2" ReleaseVersion string = "5.0.4"
) )
var ( var (
@ -167,8 +168,6 @@ func init() {
rootCmd.Flags().SetInterspersed(true) rootCmd.Flags().SetInterspersed(true)
rootCmd.MarkFlagsMutuallyExclusive("debug", "exit-on-error")
rootCmd.MarkFlagsOneRequired(RequiredArgs...) rootCmd.MarkFlagsOneRequired(RequiredArgs...)
rootCmd.SetHelpCommand(&cobra.Command{ rootCmd.SetHelpCommand(&cobra.Command{
@ -180,4 +179,6 @@ func init() {
rootCmd.SilenceErrors = true rootCmd.SilenceErrors = true
rootCmd.Version = ReleaseVersion rootCmd.Version = ReleaseVersion
log.SetFlags(0)
} }

View File

@ -38,8 +38,8 @@ func (splitPath *splitPath) decrement() string {
return fmt.Sprintf("%0*d", len(splitPath.number), asInt-1) return fmt.Sprintf("%0*d", len(splitPath.number), asInt-1)
} }
func split(path string, regexes *regexes) (*splitPath, error) { func split(path string) (*splitPath, error) {
split := regexes.filename.FindAllStringSubmatch(path, -1) split := filename.FindAllStringSubmatch(path, -1)
if len(split) < 1 || len(split[0]) < 3 { if len(split) < 1 || len(split[0]) < 3 {
return &splitPath{}, nil return &splitPath{}, nil
@ -54,8 +54,8 @@ func split(path string, regexes *regexes) (*splitPath, error) {
return p, nil return p, nil
} }
func getRange(path string, regexes *regexes, index *fileIndex) (string, string, error) { func getRange(path string, index *fileIndex) (string, string, error) {
splitPath, err := split(path, regexes) splitPath, err := split(path)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -70,7 +70,7 @@ func getRange(path string, regexes *regexes, index *fileIndex) (string, string,
Loop: Loop:
for _, val := range list { for _, val := range list {
splitVal, err := split(val, regexes) splitVal, err := split(val)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -94,8 +94,8 @@ func pathUrlEscape(path string) string {
return strings.Replace(path, `'`, `%27`, -1) return strings.Replace(path, `'`, `%27`, -1)
} }
func paginateSorted(path, first, last, queryParams string, regexes *regexes, formats types.Types) (string, error) { func paginateSorted(path, first, last, queryParams string, formats types.Types) (string, error) {
split, err := split(path, regexes) split, err := split(path)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -21,7 +21,7 @@ func sortOrder(r *http.Request) string {
return "" return ""
} }
func splitQueryParams(query string, regexes *regexes) []string { func splitQueryParams(query string) []string {
results := []string{} results := []string{}
if query == "" { if query == "" {

View File

@ -6,16 +6,13 @@ package cmd
import ( import (
"bytes" "bytes"
"context"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"log"
"net" "net"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@ -171,7 +168,7 @@ func serveStaticFile(paths []string, index *fileIndex, errorChannel chan<- error
} }
} }
func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types.Types, errorChannel chan<- error) httprouter.Handle { func serveRoot(paths []string, index *fileIndex, formats types.Types, errorChannel chan<- error) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
refererUri, err := stripQueryParams(refererToUri(r.Referer())) refererUri, err := stripQueryParams(refererToUri(r.Referer()))
if err != nil { if err != nil {
@ -185,8 +182,8 @@ func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types
strippedRefererUri := strings.TrimPrefix(refererUri, Prefix+mediaPrefix) strippedRefererUri := strings.TrimPrefix(refererUri, Prefix+mediaPrefix)
filters := &filters{ filters := &filters{
included: splitQueryParams(r.URL.Query().Get("include"), regexes), included: splitQueryParams(r.URL.Query().Get("include")),
excluded: splitQueryParams(r.URL.Query().Get("exclude"), regexes), excluded: splitQueryParams(r.URL.Query().Get("exclude")),
} }
sortOrder := sortOrder(r) sortOrder := sortOrder(r)
@ -196,7 +193,7 @@ func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types
var path string var path string
if refererUri != "" { if refererUri != "" {
path, err = nextFile(strippedRefererUri, sortOrder, regexes, formats) path, err = nextFile(strippedRefererUri, sortOrder, formats)
if err != nil { if err != nil {
errorChannel <- err errorChannel <- err
@ -220,7 +217,7 @@ func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types
break loop break loop
} }
path, err = newFile(list, sortOrder, regexes, formats) path, err = newFile(list, sortOrder, formats)
switch { switch {
case path == "": case path == "":
noFiles(w, r) noFiles(w, r)
@ -251,13 +248,13 @@ func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types
} }
} }
func serveMedia(paths []string, regexes *regexes, index *fileIndex, formats types.Types, errorChannel chan<- error) httprouter.Handle { func serveMedia(paths []string, index *fileIndex, formats types.Types, errorChannel chan<- error) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
startTime := time.Now() startTime := time.Now()
filters := &filters{ filters := &filters{
included: splitQueryParams(r.URL.Query().Get("include"), regexes), included: splitQueryParams(r.URL.Query().Get("include")),
excluded: splitQueryParams(r.URL.Query().Get("exclude"), regexes), excluded: splitQueryParams(r.URL.Query().Get("exclude")),
} }
sortOrder := sortOrder(r) sortOrder := sortOrder(r)
@ -347,7 +344,7 @@ func serveMedia(paths []string, regexes *regexes, index *fileIndex, formats type
var first, last string var first, last string
if Index && sortOrder != "" { if Index && sortOrder != "" {
first, last, err = getRange(path, regexes, index) first, last, err = getRange(path, index)
if err != nil { if err != nil {
errorChannel <- err errorChannel <- err
@ -358,7 +355,7 @@ func serveMedia(paths []string, regexes *regexes, index *fileIndex, formats type
} }
if Index && !DisableButtons && sortOrder != "" { if Index && !DisableButtons && sortOrder != "" {
paginate, err := paginateSorted(path, first, last, queryParams, regexes, formats) paginate, err := paginateSorted(path, first, last, queryParams, formats)
if err != nil { if err != nil {
errorChannel <- err errorChannel <- err
@ -478,8 +475,6 @@ func redirectRoot() httprouter.Handle {
} }
func ServePage(args []string) error { func ServePage(args []string) error {
log.SetFlags(0)
timeZone := os.Getenv("TZ") timeZone := os.Getenv("TZ")
if timeZone != "" { if timeZone != "" {
var err error var err error
@ -541,11 +536,6 @@ func ServePage(args []string) error {
return ErrNoMediaFound return ErrNoMediaFound
} }
regexes := &regexes{
filename: regexp.MustCompile(`(.+?)([0-9]*)(\..+)`),
alphanumeric: regexp.MustCompile(`^[A-z0-9]*$`),
}
if !strings.HasSuffix(Prefix, "/") { if !strings.HasSuffix(Prefix, "/") {
Prefix = Prefix + "/" Prefix = Prefix + "/"
} }
@ -573,30 +563,20 @@ func ServePage(args []string) error {
go func() { go func() {
for err := range errorChannel { for err := range errorChannel {
prefix := "ERROR"
switch { switch {
case errors.Is(err, os.ErrNotExist) && Debug: case ExitOnError:
prefix = "DEBUG" fmt.Printf("%s | FATAL: %v\n", time.Now().Format(logDate), err)
case errors.Is(err, os.ErrNotExist): case Debug && errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission):
fmt.Printf("%s | DEBUG: %v\n", time.Now().Format(logDate), err)
case errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission):
continue continue
case errors.Is(err, os.ErrPermission) && Debug: default:
prefix = "DEBUG" fmt.Printf("%s | ERROR: %v\n", time.Now().Format(logDate), err)
case errors.Is(err, os.ErrPermission):
continue
}
fmt.Printf("%s | %s: %v\n", time.Now().Format(logDate), prefix, err)
if ExitOnError {
fmt.Printf("%s | %s: Shutting down...\n", time.Now().Format(logDate), prefix)
srv.Shutdown(context.Background())
} }
} }
}() }()
registerHandler(mux, Prefix, serveRoot(paths, regexes, index, formats, errorChannel)) registerHandler(mux, Prefix, serveRoot(paths, index, formats, errorChannel))
Prefix = strings.TrimSuffix(Prefix, "/") Prefix = strings.TrimSuffix(Prefix, "/")
@ -608,7 +588,7 @@ func ServePage(args []string) error {
registerHandler(mux, Prefix+"/favicon.ico", serveFavicons(errorChannel)) registerHandler(mux, Prefix+"/favicon.ico", serveFavicons(errorChannel))
registerHandler(mux, Prefix+mediaPrefix+"/*media", serveMedia(paths, regexes, index, formats, errorChannel)) registerHandler(mux, Prefix+mediaPrefix+"/*media", serveMedia(paths, index, formats, errorChannel))
registerHandler(mux, Prefix+sourcePrefix+"/*static", serveStaticFile(paths, index, errorChannel)) registerHandler(mux, Prefix+sourcePrefix+"/*static", serveStaticFile(paths, index, errorChannel))