From 2032b40f2b560b894d5e5e8ed0e5e1e97e7060f1 Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Sun, 3 May 2020 18:00:50 +0200 Subject: [PATCH] Backend: Code clean-up Signed-off-by: Michael Mayer --- go.mod | 4 +-- go.sum | 40 -------------------------- internal/api/album.go | 13 ++++----- internal/api/import.go | 8 +++--- internal/api/index.go | 2 +- internal/api/label.go | 2 +- internal/api/photo_thumbnail.go | 3 +- internal/api/upload.go | 6 ++-- internal/api/zip.go | 8 +++--- internal/classify/gen.go | 3 +- internal/classify/tensorflow.go | 3 +- internal/commands/resample.go | 7 +++-- internal/commands/start.go | 3 +- internal/commands/stop.go | 3 +- internal/config/filenames.go | 5 ++-- internal/config/settings.go | 3 +- internal/entity/photo.go | 6 ++-- internal/entity/place.go | 5 ++-- internal/nsfw/detector.go | 5 ++-- internal/photoprism/import.go | 9 +++--- internal/photoprism/import_worker.go | 21 +++++++------- internal/photoprism/index_location.go | 3 +- internal/photoprism/index_mediafile.go | 2 +- internal/photoprism/index_worker.go | 11 ++++--- internal/photoprism/mediafile.go | 7 +++-- internal/photoprism/resample_test.go | 16 +++++------ internal/query/label.go | 5 ++-- internal/query/photo.go | 8 +++--- internal/query/photo_test.go | 8 ++++-- internal/thumb/create.go | 23 ++++++++------- pkg/fs/fileinfo_test.go | 6 ++-- pkg/txt/quote.go | 15 ++++++++++ pkg/txt/quote_test.go | 16 +++++++++++ 33 files changed, 145 insertions(+), 134 deletions(-) create mode 100644 pkg/txt/quote.go create mode 100644 pkg/txt/quote_test.go diff --git a/go.mod b/go.mod index 1772a4bf1..3663d6418 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,6 @@ require ( github.com/gosimple/slug v1.9.0 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 // indirect github.com/grpc-ecosystem/grpc-gateway v1.5.1 // indirect - github.com/guregu/null v3.4.0+incompatible // indirect github.com/jinzhu/gorm v1.9.5 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect github.com/karrick/godirwalk v1.15.6 @@ -59,7 +58,6 @@ require ( github.com/sirupsen/logrus v1.5.0 github.com/soheilhy/cmux v0.1.4 // indirect github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 // indirect - github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.5.1 github.com/studio-b12/gowebdav v0.0.0-20200303150724-9380631c29a1 github.com/tensorflow/tensorflow v1.15.2 @@ -79,7 +77,7 @@ require ( golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 golang.org/x/sys v0.0.0-20200501052902-10377860bb8e // indirect golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect - golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d + golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d // indirect gopkg.in/stretchr/testify.v1 v1.2.2 // indirect gopkg.in/ugjka/go-tz.v2 v2.0.9 gopkg.in/yaml.v2 v2.2.8 diff --git a/go.sum b/go.sum index b0d37cda9..433f86f93 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,6 @@ github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 h1:Fv9bK1Q+ly/ROk4aJ github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195 h1:c4mLfegoDw6OhSJXTd2jUEQgZUQuJWtocudb97Qn9EM= -github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 h1:TEBmxO80TM04L8IuMWk77SGL1HomBmKTdzdJLLWznxI= github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/beorn7/perks v0.0.0-20160229213445-3ac7bf7a47d1/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -138,12 +136,6 @@ github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= @@ -153,10 +145,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCy github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/open-location-code/go v0.0.0-20191230190541-a6eb95b4d2f9 h1:6ILzS4n0F17S38XvOB1BcyzB+0BtVzU77EyuMtkMffo= @@ -182,8 +170,6 @@ github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20160910222444-6b7015e65d36/ github.com/grpc-ecosystem/grpc-gateway v1.4.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.5.1 h1:3scN4iuXkNOyP98jF55Lv8a9j1o/IwvnDIZ0LHJK1nk= github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/guregu/null v3.4.0+incompatible h1:a4mw37gBO7ypcBlTJeZGuMpSxxFTV9qFfFKgWxQSGaM= -github.com/guregu/null v3.4.0+incompatible/go.mod h1:ePGpQaN9cw0tj45IR5E5ehMvsFlLlQZAkkOXZurJ3NM= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -327,8 +313,6 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sevlyar/go-daemon v0.1.5 h1:Zy/6jLbM8CfqJ4x4RPr7MJlSKt90f00kNM1D401C+Qk= github.com/sevlyar/go-daemon v0.1.5/go.mod h1:6dJpPatBT9eUwM5VCw9Bt6CdX9Tk6UWvhW3MebLDRKE= -github.com/shopspring/decimal v0.0.0-20191130220710-360f2bc03045 h1:8CnFGhoe92Izugjok8nZEGYCNovJwdRFYwrEiLtG6ZQ= -github.com/shopspring/decimal v0.0.0-20191130220710-360f2bc03045/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= @@ -346,8 +330,6 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= @@ -389,8 +371,6 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ulule/deepcopier v0.0.0-20200117111125-792cfb847af8 h1:iCslye9fWwp1ExDu06BcKM8/gjDRAlX9DBL+T8CjuWU= -github.com/ulule/deepcopier v0.0.0-20200117111125-792cfb847af8/go.mod h1:wUZg40sMUnY+1FU5F9rZwwCruLb8h1bHF8HzI09kgok= github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 h1:TtyC78WMafNW8QFfv3TeP3yWNDG+uxNkk9vOrnDu6JA= github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6/go.mod h1:h8272+G2omSmi30fBXiZDMkmHuOgonplfKIKjQWzlfs= github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3/go.mod h1:tu82oB5W2ykJRVioYsB+IQKcft7ryBr7w12qMBUPyXg= @@ -416,15 +396,11 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88= golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1 h1:5h3ngYt7+vXCDZCup/HkCQgW5XwmSvR/nA2JmJ0RErg= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -446,8 +422,6 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8ou golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI= -golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -470,8 +444,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e h1:hq86ru83GdWTlfQFZGO4nZJTU4Bs2wfHl8oFHRaXsfc= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= @@ -482,8 +454,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -495,8 +465,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138 h1:H3uGjxCR/6Ds0Mjgyp7LMK81+LvmbvWWEnJhzk1Pi9E= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200401192744-099440627f01 h1:ysQJ/fU6laLOZJseIeOqXl6Mo+lw5z6b7QHnmUKjW+k= -golang.org/x/tools v0.0.0-20200401192744-099440627f01/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d h1:lzLdP95xJmMpwQ6LUHwrc5V7js93hTiY7gkznu0BgmY= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -516,12 +484,6 @@ google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= gopkg.in/alecthomas/gometalinter.v2 v2.0.12/go.mod h1:NDRytsqEZyolNuAgTzJkZMkSQM7FIKyzVzGhjB/qfYo= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -537,8 +499,6 @@ gopkg.in/stretchr/testify.v1 v1.2.2 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz gopkg.in/stretchr/testify.v1 v1.2.2/go.mod h1:QI5V/q6UbPmuhtm10CaFZxED9NreB8PnFYN9JcR6TxU= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/ugjka/go-tz.v2 v2.0.8 h1:EmQ1tY6aa9upe1EDqyPdyHgM9STimr2fw7+b/CuMQ94= -gopkg.in/ugjka/go-tz.v2 v2.0.8/go.mod h1:l93M5EnjrSTTaABtGKIqNcl+z08IYbVDS7v1VA8+PgU= gopkg.in/ugjka/go-tz.v2 v2.0.9 h1:2ECB40UPBRJ6G53XE6zf7LMsiI038orvYfJKx/eir3g= gopkg.in/ugjka/go-tz.v2 v2.0.9/go.mod h1:1iX2y1/xUdZjNIyGW/dLRRinbWrntuHYc9oIkGWFvz4= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/api/album.go b/internal/api/album.go index 9aa741db9..dda202955 100644 --- a/internal/api/album.go +++ b/internal/api/album.go @@ -96,7 +96,7 @@ func CreateAlbum(router *gin.RouterGroup, conf *config.Config) { if res := conf.Db().Create(m); res.Error != nil { log.Error(res.Error.Error()) - c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("\"%s\" already exists", m.AlbumName)}) + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("%s already exists", txt.Quote(m.AlbumName))}) return } @@ -180,7 +180,7 @@ func DeleteAlbum(router *gin.RouterGroup, conf *config.Config) { conf.Db().Delete(&m) event.Publish("config.updated", event.Data(conf.ClientConfig())) - event.Success(fmt.Sprintf("album \"%s\" deleted", m.AlbumName)) + event.Success(fmt.Sprintf("album %s deleted", txt.Quote(m.AlbumName))) c.JSON(http.StatusOK, m) }) @@ -396,16 +396,15 @@ func DownloadAlbum(router *gin.RouterGroup, conf *config.Config) { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": txt.UcFirst("failed to create zip file")}) return } - log.Infof("album: added \"%s\" as \"%s\"", f.FileName, fileAlias) + log.Infof("album: added %s as %s", txt.Quote(f.FileName), txt.Quote(fileAlias)) } else { - log.Warnf("album: \"%s\" is missing", f.FileName) + log.Warnf("album: %s is missing", txt.Quote(f.FileName)) f.FileMissing = true conf.Db().Save(&f) } } - log.Infof("album: archive \"%s\" created in %s", zipBaseName, time.Since(start)) - + log.Infof("album: archive %s created in %s", txt.Quote(zipBaseName), time.Since(start)) zipWriter.Close() newZipFile.Close() @@ -420,7 +419,7 @@ func DownloadAlbum(router *gin.RouterGroup, conf *config.Config) { c.File(zipFileName) if err := os.Remove(zipFileName); err != nil { - log.Errorf("album: could not remove \"%s\" %s", zipFileName, err.Error()) + log.Errorf("album: could not remove %s (%s)", txt.Quote(zipFileName), err.Error()) } }) } diff --git a/internal/api/import.go b/internal/api/import.go index c71d67d35..01d52ebe3 100644 --- a/internal/api/import.go +++ b/internal/api/import.go @@ -56,10 +56,10 @@ func StartImport(router *gin.RouterGroup, conf *config.Config) { var opt photoprism.ImportOptions if f.Move { - event.Info(fmt.Sprintf("moving files from \"%s\"", filepath.Base(path))) + event.Info(fmt.Sprintf("moving files from %s", txt.Quote(filepath.Base(path)))) opt = photoprism.ImportOptionsMove(path) } else { - event.Info(fmt.Sprintf("copying files from \"%s\"", filepath.Base(path))) + event.Info(fmt.Sprintf("copying files from %s", txt.Quote(filepath.Base(path)))) opt = photoprism.ImportOptionsCopy(path) } @@ -67,9 +67,9 @@ func StartImport(router *gin.RouterGroup, conf *config.Config) { if subPath != "" && path != conf.ImportPath() && fs.IsEmpty(path) { if err := os.Remove(path); err != nil { - log.Errorf("import: could not deleted empty directory \"%s\": %s", path, err) + log.Errorf("import: could not deleted empty directory %s: %s", txt.Quote(path), err) } else { - log.Infof("import: deleted empty directory \"%s\"", path) + log.Infof("import: deleted empty directory %s", txt.Quote(path)) } } diff --git a/internal/api/index.go b/internal/api/index.go index 1b9c207ba..c5ba1dc5e 100644 --- a/internal/api/index.go +++ b/internal/api/index.go @@ -34,7 +34,7 @@ func StartIndexing(router *gin.RouterGroup, conf *config.Config) { path := conf.OriginalsPath() - event.Info(fmt.Sprintf("indexing photos in \"%s\"", filepath.Base(path))) + event.Info(fmt.Sprintf("indexing photos in %s", txt.Quote(filepath.Base(path)))) cancel := func(err error) { log.Error(err.Error()) diff --git a/internal/api/label.go b/internal/api/label.go index 987b40f65..5837540dc 100644 --- a/internal/api/label.go +++ b/internal/api/label.go @@ -175,7 +175,7 @@ func LabelThumbnail(router *gin.RouterGroup, conf *config.Config) { thumbType, ok := thumb.Types[typeName] if !ok { - log.Errorf("label: invalid thumb type \"%s\"", typeName) + log.Errorf("label: invalid thumb type %s", txt.Quote(typeName)) c.Data(http.StatusOK, "image/svg+xml", labelIconSvg) return } diff --git a/internal/api/photo_thumbnail.go b/internal/api/photo_thumbnail.go index f765402d9..460929eb5 100644 --- a/internal/api/photo_thumbnail.go +++ b/internal/api/photo_thumbnail.go @@ -10,6 +10,7 @@ import ( "github.com/photoprism/photoprism/internal/query" "github.com/photoprism/photoprism/internal/thumb" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" ) // GET /api/v1/thumbnails/:hash/:type @@ -25,7 +26,7 @@ func GetThumbnail(router *gin.RouterGroup, conf *config.Config) { thumbType, ok := thumb.Types[typeName] if !ok { - log.Errorf("photo: invalid thumb type \"%s\"", typeName) + log.Errorf("photo: invalid thumb type %s", txt.Quote(typeName)) c.Data(http.StatusBadRequest, "image/svg+xml", photoIconSvg) return } diff --git a/internal/api/upload.go b/internal/api/upload.go index ce5640df2..d7418364f 100644 --- a/internal/api/upload.go +++ b/internal/api/upload.go @@ -55,7 +55,7 @@ func Upload(router *gin.RouterGroup, conf *config.Config) { for _, file := range files { filename := path.Join(p, filepath.Base(file.Filename)) - log.Debugf("upload: saving file \"%s\"", file.Filename) + log.Debugf("upload: saving file %s", txt.Quote(file.Filename)) if err := c.SaveUploadedFile(file, filename); err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": txt.UcFirst(err.Error())}) @@ -82,7 +82,7 @@ func Upload(router *gin.RouterGroup, conf *config.Config) { continue } - log.Infof("nsfw: \"%s\" might be offensive", filename) + log.Infof("nsfw: %s might be offensive", txt.Quote(filename)) containsNSFW = true } @@ -90,7 +90,7 @@ func Upload(router *gin.RouterGroup, conf *config.Config) { if containsNSFW { for _, filename := range uploads { if err := os.Remove(filename); err != nil { - log.Errorf("nsfw: could not delete \"%s\"", filename) + log.Errorf("nsfw: could not delete %s", txt.Quote(filename)) } } diff --git a/internal/api/zip.go b/internal/api/zip.go index df4a87ca4..5400bb0fb 100644 --- a/internal/api/zip.go +++ b/internal/api/zip.go @@ -90,9 +90,9 @@ func CreateZip(router *gin.RouterGroup, conf *config.Config) { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": txt.UcFirst("failed to create zip file")}) return } - log.Infof("zip: added \"%s\" as \"%s\"", f.FileName, fileAlias) + log.Infof("zip: added %s as %s", txt.Quote(f.FileName), txt.Quote(fileAlias)) } else { - log.Warnf("zip: \"%s\" is missing", f.FileName) + log.Warnf("zip: %s is missing", txt.Quote(f.FileName)) f.FileMissing = true conf.Db().Save(&f) } @@ -100,7 +100,7 @@ func CreateZip(router *gin.RouterGroup, conf *config.Config) { elapsed := int(time.Since(start).Seconds()) - log.Infof("zip: archive \"%s\" created in %s", zipBaseName, time.Since(start)) + log.Infof("zip: archive %s created in %s", txt.Quote(zipBaseName), time.Since(start)) c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("zip created in %d s", elapsed), "filename": zipBaseName}) }) @@ -124,7 +124,7 @@ func DownloadZip(router *gin.RouterGroup, conf *config.Config) { c.File(zipFileName) if err := os.Remove(zipFileName); err != nil { - log.Errorf("zip: could not remove \"%s\" %s", zipFileName, err.Error()) + log.Errorf("zip: could not remove %s (%s)", txt.Quote(zipFileName), err.Error()) } }) } diff --git a/internal/classify/gen.go b/internal/classify/gen.go index 67db1ee77..f5f86058d 100644 --- a/internal/classify/gen.go +++ b/internal/classify/gen.go @@ -12,6 +12,7 @@ import ( "unicode" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" "gopkg.in/yaml.v2" ) @@ -33,7 +34,7 @@ func main() { fileName := "rules.yml" if !fs.FileExists(fileName) { - log.Panicf("tensorflow: label rules file not found in \"%s\"", filepath.Base(fileName)) + log.Panicf("tensorflow: label rules file not found in %s", txt.Quote(filepath.Base(fileName))) } yamlConfig, err := ioutil.ReadFile(fileName) diff --git a/internal/classify/tensorflow.go b/internal/classify/tensorflow.go index df6cc3cb4..979b0b303 100644 --- a/internal/classify/tensorflow.go +++ b/internal/classify/tensorflow.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/disintegration/imaging" + "github.com/photoprism/photoprism/pkg/txt" tf "github.com/tensorflow/tensorflow/tensorflow/go" ) @@ -142,7 +143,7 @@ func (t *TensorFlow) loadModel() error { modelPath := path.Join(t.modelsPath, t.modelName) - log.Infof("tensorflow: loading image classification model from \"%s\"", filepath.Base(modelPath)) + log.Infof("tensorflow: loading image classification model from %s", txt.Quote(filepath.Base(modelPath))) // Load model model, err := tf.LoadSavedModel(modelPath, t.modelTags, nil) diff --git a/internal/commands/resample.go b/internal/commands/resample.go index d6af502aa..6785b01d3 100644 --- a/internal/commands/resample.go +++ b/internal/commands/resample.go @@ -5,14 +5,15 @@ import ( "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/service" + "github.com/photoprism/photoprism/pkg/txt" "github.com/urfave/cli" ) // ResampleCommand is used to register the thumbs cli command var ResampleCommand = cli.Command{ - Name: "resample", + Name: "resample", Aliases: []string{"thumbs"}, - Usage: "Pre-renders thumbnails (significantly reduces memory and cpu usage)", + Usage: "Pre-renders thumbnails (significantly reduces memory and cpu usage)", Flags: []cli.Flag{ cli.BoolFlag{ Name: "force, f", @@ -33,7 +34,7 @@ func resampleAction(ctx *cli.Context) error { return err } - log.Infof("creating thumbnails in \"%s\"", conf.ThumbnailsPath()) + log.Infof("creating thumbnails in %s", txt.Quote(conf.ThumbnailsPath())) rs := service.Resample() diff --git a/internal/commands/start.go b/internal/commands/start.go index 9a2ccec22..1ac8e698b 100644 --- a/internal/commands/start.go +++ b/internal/commands/start.go @@ -14,6 +14,7 @@ import ( "github.com/photoprism/photoprism/internal/service" "github.com/photoprism/photoprism/internal/workers" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" "github.com/sevlyar/go-daemon" "github.com/urfave/cli" ) @@ -104,7 +105,7 @@ func startAction(ctx *cli.Context) error { if child != nil { if !fs.Overwrite(conf.PIDFilename(), []byte(strconv.Itoa(child.Pid))) { - log.Fatalf("failed writing process id to \"%s\"", conf.PIDFilename()) + log.Fatalf("failed writing process id to %s", txt.Quote(conf.PIDFilename())) } log.Infof("daemon started with process id %v\n", child.Pid) diff --git a/internal/commands/stop.go b/internal/commands/stop.go index 7239737fa..6ffe62cde 100644 --- a/internal/commands/stop.go +++ b/internal/commands/stop.go @@ -4,6 +4,7 @@ import ( "syscall" "github.com/photoprism/photoprism/internal/config" + "github.com/photoprism/photoprism/pkg/txt" "github.com/sevlyar/go-daemon" "github.com/urfave/cli" ) @@ -20,7 +21,7 @@ var StopCommand = cli.Command{ func stopAction(ctx *cli.Context) error { conf := config.NewConfig(ctx) - log.Infof("looking for pid in \"%s\"", conf.PIDFilename()) + log.Infof("looking for pid in %s", txt.Quote(conf.PIDFilename())) dcxt := new(daemon.Context) dcxt.PidFileName = conf.PIDFilename() diff --git a/internal/config/filenames.go b/internal/config/filenames.go index 060452c4a..95b2046a0 100644 --- a/internal/config/filenames.go +++ b/internal/config/filenames.go @@ -7,6 +7,7 @@ import ( "path/filepath" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" ) func findExecutable(configBin, defaultBin string) (result string) { @@ -31,9 +32,9 @@ func findExecutable(configBin, defaultBin string) (result string) { func (c *Config) CreateDirectories() error { createError := func(path string, err error) (result error) { if fs.FileExists(path) { - result = fmt.Errorf("\"%s\" is a file, not a directory: please check your configuration", path) + result = fmt.Errorf("%s is a file, not a directory: please check your configuration", txt.Quote(path)) } else { - result = fmt.Errorf("can't create \"%s\": please check configuration and permissions", path) + result = fmt.Errorf("can't create %s: please check configuration and permissions", txt.Quote(path)) } log.Debug(err) diff --git a/internal/config/settings.go b/internal/config/settings.go index 4bbc87d2a..4fdc3d416 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -6,6 +6,7 @@ import ( "os" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" "gopkg.in/yaml.v2" ) @@ -88,7 +89,7 @@ func (s *Settings) Propagate() { // Load uses a yaml config file to initiate the configuration entity. func (s *Settings) Load(fileName string) error { if !fs.FileExists(fileName) { - return fmt.Errorf("settings file not found: \"%s\"", fileName) + return fmt.Errorf("settings file not found: %s", txt.Quote(fileName)) } yamlConfig, err := ioutil.ReadFile(fileName) diff --git a/internal/entity/photo.go b/internal/entity/photo.go index ed8b1c5dd..b71bf2e67 100644 --- a/internal/entity/photo.go +++ b/internal/entity/photo.go @@ -332,7 +332,7 @@ func (m *Photo) UpdateTitle(labels classify.Labels) error { loc := m.Location if title := labels.Title(loc.Name()); title != "" { // TODO: User defined title format - log.Infof("photo: using label \"%s\" to create photo title", title) + log.Infof("photo: using label %s to create photo title", txt.Quote(title)) if loc.NoCity() || loc.LongCity() || loc.CityContains(title) { m.SetTitle(fmt.Sprintf("%s / %s / %s", txt.Title(title), loc.CountryName(), m.TakenAt.Format("2006")), SrcAuto) } else { @@ -364,9 +364,9 @@ func (m *Photo) UpdateTitle(labels classify.Labels) error { m.SetTitle("Unknown", SrcAuto) } - log.Infof("photo: changed photo title to \"%s\"", m.PhotoTitle) + log.Infof("photo: changed photo title to %s", txt.Quote(m.PhotoTitle)) } else { - log.Infof("photo: new title is \"%s\"", m.PhotoTitle) + log.Infof("photo: new title is %s", txt.Quote(m.PhotoTitle)) } return nil diff --git a/internal/entity/place.go b/internal/entity/place.go index cae873a62..2e810ec24 100644 --- a/internal/entity/place.go +++ b/internal/entity/place.go @@ -5,6 +5,7 @@ import ( "github.com/jinzhu/gorm" "github.com/photoprism/photoprism/internal/maps" + "github.com/photoprism/photoprism/pkg/txt" ) // Place used to associate photos to places @@ -49,7 +50,7 @@ func FindPlaceByLabel(id string, label string) *Place { place := &Place{} if err := Db().First(place, "id = ? OR loc_label = ?", id, label).Error; err != nil { - log.Debugf("place: %s for id %s or label \"%s\"", err.Error(), id, label) + log.Debugf("place: %s for id %s or label %s", err.Error(), id, txt.Quote(label)) return nil } @@ -68,7 +69,7 @@ func (m *Place) Find() error { // FirstOrCreate checks if the place already exists in the database func (m *Place) FirstOrCreate() *Place { if err := Db().FirstOrCreate(m, "id = ? OR loc_label = ?", m.ID, m.LocLabel).Error; err != nil { - log.Debugf("place: %s for token %s or label \"%s\"", err.Error(), m.ID, m.LocLabel) + log.Debugf("place: %s for token %s or label %s", err.Error(), m.ID, txt.Quote(m.LocLabel)) } return m diff --git a/internal/nsfw/detector.go b/internal/nsfw/detector.go index 0c3162daf..1e940766a 100644 --- a/internal/nsfw/detector.go +++ b/internal/nsfw/detector.go @@ -10,6 +10,7 @@ import ( "sync" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" tf "github.com/tensorflow/tensorflow/tensorflow/go" "github.com/tensorflow/tensorflow/tensorflow/go/op" ) @@ -31,7 +32,7 @@ func New(modelPath string) *Detector { // File returns matching labels for a jpeg media file. func (t *Detector) File(filename string) (result Labels, err error) { if fs.MimeType(filename) != "image/jpeg" { - return result, fmt.Errorf("nsfw: \"%s\" is not a jpeg file", filename) + return result, fmt.Errorf("nsfw: %s is not a jpeg file", txt.Quote(filepath.Base(filename))) } imageBuffer, err := ioutil.ReadFile(filename) @@ -121,7 +122,7 @@ func (t *Detector) loadModel() error { return nil } - log.Infof("tensorflow: loading image classification model from \"%s\"", filepath.Base(t.modelPath)) + log.Infof("tensorflow: loading image classification model from %s", txt.Quote(filepath.Base(t.modelPath))) // Load model model, err := tf.LoadSavedModel(t.modelPath, t.modelTags, nil) diff --git a/internal/photoprism/import.go b/internal/photoprism/import.go index 2a6e85ff9..d7ed6d679 100644 --- a/internal/photoprism/import.go +++ b/internal/photoprism/import.go @@ -14,6 +14,7 @@ import ( "github.com/photoprism/photoprism/internal/event" "github.com/photoprism/photoprism/internal/mutex" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" ) // Import represents an importer that can copy/move MediaFiles to the originals directory. @@ -167,9 +168,9 @@ func (imp *Import) Start(opt ImportOptions) { for _, directory := range directories { if fs.IsEmpty(directory) { if err := os.Remove(directory); err != nil { - log.Errorf("import: could not deleted empty directory %s (%s)", directory, err) + log.Errorf("import: could not deleted empty directory %s (%s)", fs.RelativeName(directory, importPath), err) } else { - log.Infof("import: deleted empty directory %s", directory) + log.Infof("import: deleted empty directory %s", fs.RelativeName(directory, importPath)) } } } @@ -183,7 +184,7 @@ func (imp *Import) Start(opt ImportOptions) { } if err := os.Remove(file); err != nil { - log.Errorf("import: could not remove \"%s\" (%s)", file, err.Error()) + log.Errorf("import: could not remove %s (%s)", txt.Quote(fs.RelativeName(file, importPath)), err.Error()) } } } @@ -207,7 +208,7 @@ func (imp *Import) DestinationFilename(mainFile *MediaFile, mediaFile *MediaFile if !mediaFile.IsSidecar() { if f, err := entity.FirstFileByHash(mediaFile.Hash()); err == nil { existingFilename := imp.conf.OriginalsPath() + string(os.PathSeparator) + f.FileName - return existingFilename, fmt.Errorf("\"%s\" is identical to \"%s\" (%s)", mediaFile.FileName(), f.FileName, mediaFile.Hash()) + return existingFilename, fmt.Errorf("%s is identical to %s (sha1 %s)", txt.Quote(mediaFile.FileName()), txt.Quote(f.FileName), mediaFile.Hash()) } } diff --git a/internal/photoprism/import_worker.go b/internal/photoprism/import_worker.go index a72682452..83c400269 100644 --- a/internal/photoprism/import_worker.go +++ b/internal/photoprism/import_worker.go @@ -7,6 +7,7 @@ import ( "github.com/photoprism/photoprism/internal/event" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" ) type ImportJob struct { @@ -48,25 +49,25 @@ func ImportWorker(jobs <-chan ImportJob) { if related.Main.HasSameName(f) { destinationMainFilename = destinationFilename - log.Infof("import: moving main %s file \"%s\" to \"%s\"", f.FileType(), relativeFilename, fs.RelativeName(destinationFilename, imp.originalsPath())) + log.Infof("import: moving main %s file %s to %s", f.FileType(), txt.Quote(relativeFilename), txt.Quote(fs.RelativeName(destinationFilename, imp.originalsPath()))) } else { - log.Infof("import: moving related %s file \"%s\" to \"%s\"", f.FileType(), relativeFilename, fs.RelativeName(destinationFilename, imp.originalsPath())) + log.Infof("import: moving related %s file %s to %s", f.FileType(), txt.Quote(relativeFilename), txt.Quote(fs.RelativeName(destinationFilename, imp.originalsPath()))) } if opt.Move { if err := f.Move(destinationFilename); err != nil { - log.Errorf("import: could not move file to %s (%s)", fs.RelativeName(destinationMainFilename, imp.originalsPath()), err.Error()) + log.Errorf("import: could not move file to %s (%s)", txt.Quote(fs.RelativeName(destinationMainFilename, imp.originalsPath())), err.Error()) } } else { if err := f.Copy(destinationFilename); err != nil { - log.Errorf("import: could not copy file to %s (%s)", fs.RelativeName(destinationMainFilename, imp.originalsPath()), err.Error()) + log.Errorf("import: could not copy file to %s (%s)", txt.Quote(fs.RelativeName(destinationMainFilename, imp.originalsPath())), err.Error()) } } } else if opt.RemoveExistingFiles { if err := f.Remove(); err != nil { - log.Errorf("import: could not delete %s (%s)",fs.RelativeName(f.FileName(), importPath), err.Error()) + log.Errorf("import: could not delete %s (%s)", txt.Quote(fs.RelativeName(f.FileName(), importPath)), err.Error()) } else { - log.Infof("import: deleted %s (already exists)", relativeFilename) + log.Infof("import: deleted %s (already exists)", txt.Quote(relativeFilename)) } } } @@ -75,7 +76,7 @@ func ImportWorker(jobs <-chan ImportJob) { importedMainFile, err := NewMediaFile(destinationMainFilename) if err != nil { - log.Errorf("import: could not index \"%s\" (%s)", fs.RelativeName(destinationMainFilename, imp.originalsPath()), err.Error()) + log.Errorf("import: could not index %s (%s)", txt.Quote(fs.RelativeName(destinationMainFilename, imp.originalsPath())), err.Error()) continue } @@ -97,7 +98,7 @@ func ImportWorker(jobs <-chan ImportJob) { related, err := importedMainFile.RelatedFiles(imp.conf.Settings().Library.GroupRelated) if err != nil { - log.Errorf("import: could not index \"%s\" (%s)", fs.RelativeName(destinationMainFilename, imp.originalsPath()), err.Error()) + log.Errorf("import: could not index %s (%s)", txt.Quote(fs.RelativeName(destinationMainFilename, imp.originalsPath())), err.Error()) continue } @@ -107,7 +108,7 @@ func ImportWorker(jobs <-chan ImportJob) { if related.Main != nil { res := ind.MediaFile(related.Main, indexOpt, originalName) - log.Infof("import: %s main %s file \"%s\"", res, related.Main.FileType(), related.Main.RelativeName(ind.originalsPath())) + log.Infof("import: %s main %s file %s", res, related.Main.FileType(), txt.Quote(related.Main.RelativeName(ind.originalsPath()))) done[related.Main.FileName()] = true } else { log.Warnf("import: no main file for %s (conversion to jpeg failed?)", fs.RelativeName(destinationMainFilename, imp.originalsPath())) @@ -125,7 +126,7 @@ func ImportWorker(jobs <-chan ImportJob) { res := ind.MediaFile(f, indexOpt, "") done[f.FileName()] = true - log.Infof("import: %s related %s file \"%s\"", res, f.FileType(), f.RelativeName(ind.originalsPath())) + log.Infof("import: %s related %s file %s", res, f.FileType(), txt.Quote(f.RelativeName(ind.originalsPath()))) } } } diff --git a/internal/photoprism/index_location.go b/internal/photoprism/index_location.go index eac569836..817444dad 100644 --- a/internal/photoprism/index_location.go +++ b/internal/photoprism/index_location.go @@ -3,6 +3,7 @@ package photoprism import ( "github.com/jinzhu/gorm" "github.com/photoprism/photoprism/internal/entity" + "github.com/photoprism/photoprism/pkg/txt" ) func (ind *Index) estimateLocation(photo *entity.Photo) { @@ -13,7 +14,7 @@ func (ind *Index) estimateLocation(photo *entity.Photo) { photo.Place = recentPhoto.Place photo.PhotoCountry = photo.Place.LocCountry photo.LocationSrc = entity.SrcAuto - log.Debugf("index: approximate location is \"%s\"", recentPhoto.Place.Label()) + log.Debugf("index: approximate location is %s", txt.Quote(recentPhoto.Place.Label())) } } } diff --git a/internal/photoprism/index_mediafile.go b/internal/photoprism/index_mediafile.go index 08b736bf8..3516bd245 100644 --- a/internal/photoprism/index_mediafile.go +++ b/internal/photoprism/index_mediafile.go @@ -184,7 +184,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) ( } if len(metaData.UniqueID) > 15 { - log.Debugf("index: file uuid \"%s\"", metaData.UniqueID) + log.Debugf("index: file uuid %s", txt.Quote(metaData.UniqueID)) file.FileUUID = metaData.UniqueID } diff --git a/internal/photoprism/index_worker.go b/internal/photoprism/index_worker.go index edae83dda..a1da6c73a 100644 --- a/internal/photoprism/index_worker.go +++ b/internal/photoprism/index_worker.go @@ -1,6 +1,9 @@ package photoprism -import "github.com/photoprism/photoprism/pkg/fs" +import ( + "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" +) type IndexJob struct { FileName string @@ -20,9 +23,9 @@ func IndexWorker(jobs <-chan IndexJob) { res := ind.MediaFile(related.Main, opt, "") done[related.Main.FileName()] = true - log.Infof("index: %s main %s file \"%s\"", res, related.Main.FileType(), related.Main.RelativeName(ind.originalsPath())) + log.Infof("index: %s main %s file %s", res, related.Main.FileType(), txt.Quote(related.Main.RelativeName(ind.originalsPath()))) } else { - log.Warnf("index: no main file for %s (conversion to jpeg failed?)", fs.RelativeName(job.FileName, ind.originalsPath())) + log.Warnf("index: no main file for %s (conversion failed?)", txt.Quote(fs.RelativeName(job.FileName, ind.originalsPath()))) } for _, f := range related.Files { @@ -33,7 +36,7 @@ func IndexWorker(jobs <-chan IndexJob) { res := ind.MediaFile(f, opt, "") done[f.FileName()] = true - log.Infof("index: %s related %s file \"%s\"", res, f.FileType(), f.RelativeName(ind.originalsPath())) + log.Infof("index: %s related %s file %s", res, f.FileType(), txt.Quote(f.RelativeName(ind.originalsPath()))) } } } diff --git a/internal/photoprism/mediafile.go b/internal/photoprism/mediafile.go index ba8dad686..79f11df44 100644 --- a/internal/photoprism/mediafile.go +++ b/internal/photoprism/mediafile.go @@ -19,6 +19,7 @@ import ( "github.com/photoprism/photoprism/internal/thumb" "github.com/photoprism/photoprism/pkg/capture" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" ) // MediaFile represents a single photo, video or sidecar file. @@ -725,7 +726,7 @@ func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) { } if fileName, err := thumb.Filename(hash, thumbPath, thumbType.Width, thumbType.Height, thumbType.Options...); err != nil { - log.Errorf("mediafile: could not create \"%s\" (%s)", name, err) + log.Errorf("mediafile: could not create %s (%s)", txt.Quote(name), err) return err } else { @@ -737,7 +738,7 @@ func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) { img, err := imaging.Open(m.FileName(), imaging.AutoOrientation(true)) if err != nil { - log.Errorf("mediafile: can't open \"%s\" (%s)", m.FileName(), err.Error()) + log.Errorf("mediafile: can't open %s (%s)", txt.Quote(m.FileName()), err.Error()) return err } @@ -756,7 +757,7 @@ func (m *MediaFile) ResampleDefault(thumbPath string, force bool) (err error) { } if err != nil { - log.Errorf("mediafile: could not create \"%s\" (%s)", name, err) + log.Errorf("mediafile: could not create %s (%s)", txt.Quote(name), err) return err } diff --git a/internal/photoprism/resample_test.go b/internal/photoprism/resample_test.go index 6c889d135..75e1aa96e 100644 --- a/internal/photoprism/resample_test.go +++ b/internal/photoprism/resample_test.go @@ -70,21 +70,21 @@ func TestThumb_Filename(t *testing.T) { t.FailNow() } - assert.Equal(t, "thumbs: file hash is empty or too short (\"999\")", err.Error()) + assert.Equal(t, "resample: file hash is empty or too short (999)", err.Error()) }) t.Run("invalid width", func(t *testing.T) { _, err := thumb.Filename("99988", thumbsPath, -4, 150, thumb.ResampleFit, thumb.ResampleNearestNeighbor) if err == nil { t.FailNow() } - assert.Equal(t, "thumbs: width exceeds limit (-4)", err.Error()) + assert.Equal(t, "resample: width exceeds limit (-4)", err.Error()) }) t.Run("invalid height", func(t *testing.T) { _, err := thumb.Filename("99988", thumbsPath, 200, -1, thumb.ResampleFit, thumb.ResampleNearestNeighbor) if err == nil { t.FailNow() } - assert.Equal(t, "thumbs: height exceeds limit (-1)", err.Error()) + assert.Equal(t, "resample: height exceeds limit (-1)", err.Error()) }) t.Run("empty thumbpath", func(t *testing.T) { path := "" @@ -92,7 +92,7 @@ func TestThumb_Filename(t *testing.T) { if err == nil { t.FailNow() } - assert.Equal(t, "thumbs: path is empty", err.Error()) + assert.Equal(t, "resample: path is empty", err.Error()) }) } @@ -130,7 +130,7 @@ func TestThumb_FromFile(t *testing.T) { t.Fatal("err should NOT be nil") } - assert.Equal(t, "thumbs: file hash is empty or too short (\"123\")", err.Error()) + assert.Equal(t, "resample: file hash is empty or too short (123)", err.Error()) }) t.Run("filename too short", func(t *testing.T) { fileModel := &entity.File{ @@ -142,7 +142,7 @@ func TestThumb_FromFile(t *testing.T) { if err == nil { t.FailNow() } - assert.Equal(t, "thumbs: image filename is empty or too short (\"xxx\")", err.Error()) + assert.Equal(t, "resample: image filename is empty or too short (xxx)", err.Error()) }) } @@ -209,7 +209,7 @@ func TestThumb_Create(t *testing.T) { thumbnail := *res - assert.Equal(t, "thumbs: width has an invalid value (-1)", err.Error()) + assert.Equal(t, "resample: width has an invalid value (-1)", err.Error()) bounds := thumbnail.Bounds() assert.NotEqual(t, 150, bounds.Dx()) }) @@ -235,7 +235,7 @@ func TestThumb_Create(t *testing.T) { thumbnail := *res - assert.Equal(t, "thumbs: height has an invalid value (-1)", err.Error()) + assert.Equal(t, "resample: height has an invalid value (-1)", err.Error()) bounds := thumbnail.Bounds() assert.NotEqual(t, 150, bounds.Dx()) }) diff --git a/internal/query/label.go b/internal/query/label.go index 1db2c2cda..5c88f0838 100644 --- a/internal/query/label.go +++ b/internal/query/label.go @@ -9,6 +9,7 @@ import ( "github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/pkg/capture" + "github.com/photoprism/photoprism/pkg/txt" ) // LabelResult contains found labels @@ -132,7 +133,7 @@ func (q *Query) Labels(f form.LabelSearch) (results []LabelResult, err error) { likeString := "%" + strings.ToLower(f.Query) + "%" if result := q.db.First(&label, "label_slug = ? OR custom_slug = ?", slugString, slugString); result.Error != nil { - log.Infof("search: label \"%s\" not found", f.Query) + log.Infof("search: label %s not found", txt.Quote(f.Query)) s = s.Where("LOWER(labels.label_name) LIKE ?", likeString) } else { @@ -144,7 +145,7 @@ func (q *Query) Labels(f form.LabelSearch) (results []LabelResult, err error) { labelIds = append(labelIds, category.LabelID) } - log.Infof("search: label \"%s\" includes %d categories", label.LabelName, len(labelIds)) + log.Infof("search: label %s includes %d categories", txt.Quote(label.LabelName), len(labelIds)) s = s.Where("labels.id IN (?)", labelIds) } diff --git a/internal/query/photo.go b/internal/query/photo.go index 1cc5cd3bd..594312cee 100644 --- a/internal/query/photo.go +++ b/internal/query/photo.go @@ -188,8 +188,8 @@ func (q *Query) Photos(f form.PhotoSearch) (results PhotoResults, count int, err if f.Label != "" { slugString := strings.ToLower(f.Label) if result := q.db.First(&label, "label_slug =? OR custom_slug = ?", slugString, slugString); result.Error != nil { - log.Errorf("search: label \"%s\" not found", f.Label) - return results, 0, fmt.Errorf("label \"%s\" not found", f.Label) + log.Errorf("search: label %s not found", txt.Quote(f.Label)) + return results, 0, fmt.Errorf("label %s not found", txt.Quote(f.Label)) } else { labelIds = append(labelIds, label.ID) @@ -224,7 +224,7 @@ func (q *Query) Photos(f form.PhotoSearch) (results PhotoResults, count int, err Joins("LEFT JOIN keywords ON photos_keywords.keyword_id = keywords.id") if result := q.db.First(&label, "label_slug = ? OR custom_slug = ?", slugString, slugString); result.Error != nil { - log.Infof("search: label \"%s\" not found, using fuzzy search", f.Query) + log.Infof("search: label %s not found, using fuzzy search", txt.Quote(f.Query)) s = s.Where("keywords.keyword LIKE ?", likeString) } else { @@ -236,7 +236,7 @@ func (q *Query) Photos(f form.PhotoSearch) (results PhotoResults, count int, err labelIds = append(labelIds, category.LabelID) } - log.Infof("search: label \"%s\" includes %d categories", label.LabelName, len(labelIds)) + log.Infof("search: label %s includes %d categories", txt.Quote(label.LabelName), len(labelIds)) s = s.Where("photos_labels.label_id IN (?) OR keywords.keyword LIKE ?", labelIds, likeString) } diff --git a/internal/query/photo_test.go b/internal/query/photo_test.go index 965bd070a..198b84c5e 100644 --- a/internal/query/photo_test.go +++ b/internal/query/photo_test.go @@ -114,6 +114,7 @@ func TestSearch_Photos(t *testing.T) { if err != nil { // TODO: Add database fixtures to avoid failing queries t.Logf("query failed: %s", err.Error()) + // t.Fatal(err) } t.Logf("results: %+v", photos) @@ -126,9 +127,12 @@ func TestSearch_Photos(t *testing.T) { photos, _, err := search.Photos(f) - assert.Equal(t, err.Error(), "label \"xxx\" not found") + assert.Error(t, err) + assert.Empty(t, photos) - t.Logf("results: %+v", photos) + if err != nil { + assert.Equal(t, err.Error(), "label xxx not found") + } }) t.Run("form.location true", func(t *testing.T) { var f form.PhotoSearch diff --git a/internal/thumb/create.go b/internal/thumb/create.go index b936076da..ab7a20b1b 100644 --- a/internal/thumb/create.go +++ b/internal/thumb/create.go @@ -10,6 +10,7 @@ import ( "path/filepath" "github.com/photoprism/photoprism/pkg/fs" + "github.com/photoprism/photoprism/pkg/txt" "github.com/disintegration/imaging" ) @@ -75,19 +76,19 @@ func Postfix(width, height int, opts ...ResampleOption) (result string) { func Filename(hash string, thumbPath string, width, height int, opts ...ResampleOption) (filename string, err error) { if width < 0 || width > MaxRenderSize { - return "", fmt.Errorf("thumbs: width exceeds limit (%d)", width) + return "", fmt.Errorf("resample: width exceeds limit (%d)", width) } if height < 0 || height > MaxRenderSize { - return "", fmt.Errorf("thumbs: height exceeds limit (%d)", height) + return "", fmt.Errorf("resample: height exceeds limit (%d)", height) } if len(hash) < 4 { - return "", fmt.Errorf("thumbs: file hash is empty or too short (\"%s\")", hash) + return "", fmt.Errorf("resample: file hash is empty or too short (%s)", txt.Quote(hash)) } if len(thumbPath) == 0 { - return "", errors.New("thumbs: path is empty") + return "", errors.New("resample: path is empty") } postfix := Postfix(width, height, opts...) @@ -104,17 +105,17 @@ func Filename(hash string, thumbPath string, width, height int, opts ...Resample func FromFile(imageFilename string, hash string, thumbPath string, width, height int, opts ...ResampleOption) (fileName string, err error) { if len(hash) < 4 { - return "", fmt.Errorf("thumbs: file hash is empty or too short (\"%s\")", hash) + return "", fmt.Errorf("resample: file hash is empty or too short (%s)", txt.Quote(hash)) } if len(imageFilename) < 4 { - return "", fmt.Errorf("thumbs: image filename is empty or too short (\"%s\")", imageFilename) + return "", fmt.Errorf("resample: image filename is empty or too short (%s)", txt.Quote(imageFilename)) } fileName, err = Filename(hash, thumbPath, width, height, opts...) if err != nil { - log.Errorf("thumbs: can't determine filename (%s)", err) + log.Errorf("resample: can't determine filename (%s)", err) return "", err } @@ -125,7 +126,7 @@ func FromFile(imageFilename string, hash string, thumbPath string, width, height img, err := imaging.Open(imageFilename, imaging.AutoOrientation(true)) if err != nil { - log.Errorf("thumbs: can't open \"%s\" (%s)", imageFilename, err.Error()) + log.Errorf("resample: can't open %s (%s)", txt.Quote(imageFilename), err.Error()) return "", err } @@ -138,11 +139,11 @@ func FromFile(imageFilename string, hash string, thumbPath string, width, height func Create(img *image.Image, fileName string, width, height int, opts ...ResampleOption) (result *image.Image, err error) { if width < 0 || width > MaxRenderSize { - return img, fmt.Errorf("thumbs: width has an invalid value (%d)", width) + return img, fmt.Errorf("resample: width has an invalid value (%d)", width) } if height < 0 || height > MaxRenderSize { - return img, fmt.Errorf("thumbs: height has an invalid value (%d)", height) + return img, fmt.Errorf("resample: height has an invalid value (%d)", height) } result = Resample(img, width, height, opts...) @@ -160,7 +161,7 @@ func Create(img *image.Image, fileName string, width, height int, opts ...Resamp err = imaging.Save(*result, fileName, saveOption) if err != nil { - log.Errorf("thumbs: failed to save %s", fileName) + log.Errorf("resample: failed to save %s", fileName) return result, err } diff --git a/pkg/fs/fileinfo_test.go b/pkg/fs/fileinfo_test.go index 610de4f13..73992761f 100644 --- a/pkg/fs/fileinfo_test.go +++ b/pkg/fs/fileinfo_test.go @@ -39,10 +39,10 @@ func TestNewFileInfos(t *testing.T) { } expected := map[string]FileInfo{ - "test.jpg": {Abs: "/test.jpg", Size: 10990, Dir: false}, + "test.jpg": {Abs: "/test.jpg", Size: 10990, Dir: false}, "CATYELLOW.jpg": {Abs: "/CATYELLOW.jpg", Size: 70790, Dir: false}, - "directory": {Abs: "/directory", Size: 4096, Dir: true}, - "linked": {Abs: "/linked", Size: 4096, Dir: true}, + "directory": {Abs: "/directory", Size: 4096, Dir: true}, + "linked": {Abs: "/linked", Size: 4096, Dir: true}, } for _, file := range result { diff --git a/pkg/txt/quote.go b/pkg/txt/quote.go new file mode 100644 index 000000000..60daa2689 --- /dev/null +++ b/pkg/txt/quote.go @@ -0,0 +1,15 @@ +package txt + +import ( + "fmt" + "strings" +) + +// Quote adds quotation marks to a string if needed. +func Quote(text string) string { + if strings.ContainsAny(text, " \n'\"") { + return fmt.Sprintf("“%s”", text) + } + + return text +} diff --git a/pkg/txt/quote_test.go b/pkg/txt/quote_test.go new file mode 100644 index 000000000..db76975bd --- /dev/null +++ b/pkg/txt/quote_test.go @@ -0,0 +1,16 @@ +package txt + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestQuote(t *testing.T) { + t.Run("The quick brown fox.", func(t *testing.T) { + assert.Equal(t, "“The quick brown fox.”", Quote("The quick brown fox.")) + }) + t.Run("filename.txt", func(t *testing.T) { + assert.Equal(t, "filename.txt", Quote("filename.txt")) + }) +}