diff --git a/.gitignore b/.gitignore index 6d621e2..38977bb 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,7 @@ ginkgo.report .task/ src/i18n/out/en-US/active.en-GB.json +test/data/storage/scientist/ +.DS_Store +thumbs.db diff --git a/go.mod b/go.mod index a686b61..d6e2163 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,12 @@ module github.com/snivilised/pixa go 1.21 require ( - github.com/onsi/ginkgo/v2 v2.13.0 - github.com/onsi/gomega v1.29.0 + github.com/onsi/ginkgo/v2 v2.13.1 + github.com/onsi/gomega v1.30.0 github.com/pkg/errors v0.9.1 github.com/samber/lo v1.38.1 - github.com/snivilised/extendio v0.3.0 - github.com/snivilised/lorax v0.4.1 + github.com/snivilised/extendio v0.4.0 + github.com/snivilised/lorax v0.4.2 github.com/spf13/cobra v1.7.0 github.com/spf13/viper v1.17.0 go.uber.org/zap v1.26.0 @@ -16,11 +16,12 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/avfs/avfs v0.33.0 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/pprof v0.0.0-20230406165453-00490a63f317 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/sagikazarmark/locafero v0.3.0 // indirect @@ -28,7 +29,7 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/tools v0.14.0 // indirect ) require ( @@ -47,8 +48,8 @@ require ( github.com/spf13/pflag v1.0.5 github.com/subosito/gotenv v1.6.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 + golang.org/x/sys v0.14.0 // indirect + golang.org/x/text v0.14.0 gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 2289e87..0a94f26 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,8 @@ github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/avfs/avfs v0.33.0 h1:5WQXbUbr6VS7aani39ZN2Vrd/s3wLnyih1Sc4ExWTxs= +github.com/avfs/avfs v0.33.0/go.mod h1:Q59flcFRYe9KYkNMfrLUJney3yeKGQpcWRyxsDBW7vI= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -73,8 +75,8 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= @@ -135,8 +137,8 @@ github.com/google/pprof v0.0.0-20230406165453-00490a63f317 h1:hFhpt7CTmR3DX+b4R1 github.com/google/pprof v0.0.0-20230406165453-00490a63f317/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -177,12 +179,12 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU= +github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= -github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -204,10 +206,10 @@ github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/snivilised/cobrass v0.3.6 h1:sd8bTT5RWIUh61udWDpU77lu4l7H+nZz10oIaTRmKck= github.com/snivilised/cobrass v0.3.6/go.mod h1:i08Cgz6ZZ8vIzP9HhJ7ZjOqffWRLAo4cPxLyfqW+cas= -github.com/snivilised/extendio v0.3.0 h1:lGy33940icaEd20gaDp6nm4ch3FfpMXJUrqpyvWax0E= -github.com/snivilised/extendio v0.3.0/go.mod h1:GZI0mupBlnKu7qXvmvD/slpCa6CxQgQLdD5mvmtsbig= -github.com/snivilised/lorax v0.4.1 h1:4WBPYFeAObXXloBGDnzQPMMS3nb+XuuhdCeaVF2aHLM= -github.com/snivilised/lorax v0.4.1/go.mod h1:dFRNvQzKSewjabVEfnigGETf0Xx1cD21+d01QNwIbWM= +github.com/snivilised/extendio v0.4.0 h1:dc43lUO3eFxfqjE1EjNN2+GP8xiqqse3cuHxUC8Q3kk= +github.com/snivilised/extendio v0.4.0/go.mod h1:zL8elN5UpBQOIcvHHh4lWpEuQmnE90VknqcdIyk9C4I= +github.com/snivilised/lorax v0.4.2 h1:jPo+o4cP/BUYBkR6sg3oLybHx0j2R+0wMLnvOf/gh0g= +github.com/snivilised/lorax v0.4.2/go.mod h1:vyhM905Fc4fzShAXPvykS8ZRnO6B85hd0emJgZE4iNY= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= @@ -294,8 +296,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -396,8 +398,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -409,8 +411,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -463,8 +465,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/app/command/bootstrap.go b/src/app/command/bootstrap.go index 971176b..8ba05db 100644 --- a/src/app/command/bootstrap.go +++ b/src/app/command/bootstrap.go @@ -107,7 +107,7 @@ func (b *Bootstrap) Root(options ...ConfigureOptionFn) *cobra.Command { Name: "magick", } - fmt.Printf("===> ⚠️⚠️⚠️ USING DUMMY EXECUTOR !!!!\n") + fmt.Printf("===> 💥💥💥 USING DUMMY EXECUTOR !!!!\n") b.Container = assistant.NewCobraContainer( &cobra.Command{ diff --git a/src/app/command/bootstrap_test.go b/src/app/command/bootstrap_test.go index 8f87a98..1df09ce 100644 --- a/src/app/command/bootstrap_test.go +++ b/src/app/command/bootstrap_test.go @@ -1,12 +1,14 @@ package command_test import ( + "path/filepath" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/snivilised/extendio/xfs/utils" + "github.com/snivilised/extendio/xfs/storage" "github.com/snivilised/pixa/src/app/command" "github.com/snivilised/pixa/src/internal/helpers" - + "github.com/snivilised/pixa/src/internal/matchers" "golang.org/x/text/language" ) @@ -38,12 +40,14 @@ var _ = Describe("Bootstrap", Ordered, func() { var ( repo string l10nPath string + nfs storage.VirtualFS ) BeforeAll(func() { - repo = helpers.Repo("../..") - l10nPath = helpers.Path(repo, "test/data/l10n") - Expect(utils.FolderExists(l10nPath)).To(BeTrue()) + nfs = storage.UseNativeFS() + repo = helpers.Repo(filepath.Join("..", "..", "..")) + l10nPath = helpers.Path(repo, filepath.Join("test", "data", "l10n")) + Expect(matchers.AsDirectory(l10nPath)).To(matchers.ExistInFS(nfs)) }) Context("given: root defined with magick sub-command", func() { @@ -55,7 +59,7 @@ var _ = Describe("Bootstrap", Ordered, func() { Name: "magick", } co.Config.Name = "pixa-test" - co.Config.ConfigPath = "../../test/data/configuration" + co.Config.ConfigPath = filepath.Join(repo, "test", "data", "configuration") }) Expect(rootCmd).NotTo(BeNil()) }) diff --git a/src/app/command/magick-cmd_test.go b/src/app/command/magick-cmd_test.go index 978fff8..c679d63 100644 --- a/src/app/command/magick-cmd_test.go +++ b/src/app/command/magick-cmd_test.go @@ -1,31 +1,32 @@ package command_test import ( - "fmt" + "path/filepath" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ci18n "github.com/snivilised/cobrass/src/assistant/i18n" xi18n "github.com/snivilised/extendio/i18n" - "github.com/snivilised/extendio/xfs/utils" + "github.com/snivilised/extendio/xfs/storage" "github.com/snivilised/pixa/src/app/command" "github.com/snivilised/pixa/src/i18n" "github.com/snivilised/pixa/src/internal/helpers" + "github.com/snivilised/pixa/src/internal/matchers" ) var _ = Describe("MagickCmd", Ordered, func() { var ( repo string l10nPath string + nfs storage.VirtualFS ) BeforeAll(func() { - repo = helpers.Repo("../../..") - l10nPath = helpers.Path(repo, "src/test/data/l10n") - Expect(utils.FolderExists(l10nPath)).To(BeTrue(), - fmt.Sprintf("💥 l10Path: '%v' does not exist", l10nPath), - ) + nfs = storage.UseNativeFS() + repo = helpers.Repo(filepath.Join("..", "..", "..")) + l10nPath = helpers.Path(repo, filepath.Join("test", "data", "l10n")) + Expect(matchers.AsDirectory(l10nPath)).To(matchers.ExistInFS(nfs)) }) BeforeEach(func() { diff --git a/src/app/command/root-cmd_test.go b/src/app/command/root-cmd_test.go index fea9cc8..222f52e 100644 --- a/src/app/command/root-cmd_test.go +++ b/src/app/command/root-cmd_test.go @@ -2,13 +2,15 @@ package command_test import ( "fmt" + "path/filepath" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/snivilised/extendio/xfs/utils" + "github.com/snivilised/extendio/xfs/storage" "github.com/snivilised/pixa/src/app/command" "github.com/snivilised/pixa/src/internal/helpers" + "github.com/snivilised/pixa/src/internal/matchers" ) type rootTE struct { @@ -20,15 +22,15 @@ var _ = Describe("RootCmd", Ordered, func() { var ( repo string l10nPath string - - tester helpers.CommandTester + nfs storage.VirtualFS + tester helpers.CommandTester ) BeforeAll(func() { - repo = helpers.Repo("../..") - l10nPath = helpers.Path(repo, "test/data/l10n") - Expect(utils.FolderExists(l10nPath)).To(BeTrue()) - + nfs = storage.UseNativeFS() + repo = helpers.Repo(filepath.Join("..", "..", "..")) + l10nPath = helpers.Path(repo, filepath.Join("test", "data", "l10n")) + Expect(matchers.AsDirectory(l10nPath)).To(matchers.ExistInFS(nfs)) }) BeforeEach(func() { diff --git a/src/app/command/shrink-cmd_test.go b/src/app/command/shrink-cmd_test.go index 545e5ef..aa63b2d 100644 --- a/src/app/command/shrink-cmd_test.go +++ b/src/app/command/shrink-cmd_test.go @@ -2,6 +2,7 @@ package command_test import ( "fmt" + "path/filepath" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -10,9 +11,10 @@ import ( "github.com/snivilised/pixa/src/app/command" "github.com/snivilised/pixa/src/i18n" "github.com/snivilised/pixa/src/internal/helpers" + "github.com/snivilised/pixa/src/internal/matchers" xi18n "github.com/snivilised/extendio/i18n" - "github.com/snivilised/extendio/xfs/utils" + "github.com/snivilised/extendio/xfs/storage" ) type commandTE struct { @@ -38,6 +40,7 @@ func expectValidShrinkCmdInvocation(entry *shrinkTE) { "--dry-run", "--mode", "tidy", }...) + repo := helpers.Repo(filepath.Join("..", "..", "..")) tester := helpers.CommandTester{ Args: append(options, entry.args...), Root: bootstrap.Root(func(co *command.ConfigureOptionsInfo) { @@ -46,7 +49,7 @@ func expectValidShrinkCmdInvocation(entry *shrinkTE) { Name: "magick", } co.Config.Name = "pixa-test" - co.Config.ConfigPath = "../../test/data/configuration" + co.Config.ConfigPath = filepath.Join(repo, "test", "data", "configuration") }), } @@ -60,14 +63,14 @@ var _ = Describe("ShrinkCmd", Ordered, func() { var ( repo string l10nPath string + nfs storage.VirtualFS ) BeforeAll(func() { - repo = helpers.Repo("../../..") - l10nPath = helpers.Path(repo, "src/test/data/l10n") - Expect(utils.FolderExists(l10nPath)).To(BeTrue(), - fmt.Sprintf("💥 l10Path: '%v' does not exist", l10nPath), - ) + nfs = storage.UseNativeFS() + repo = helpers.Repo(filepath.Join("..", "..", "..")) + l10nPath = helpers.Path(repo, filepath.Join("test", "data", "l10n")) + Expect(matchers.AsDirectory(l10nPath)).To(matchers.ExistInFS(nfs)) }) BeforeEach(func() { diff --git a/src/app/proxy/config_test.go b/src/app/proxy/config_test.go index 8ce741f..cb404ba 100644 --- a/src/app/proxy/config_test.go +++ b/src/app/proxy/config_test.go @@ -3,6 +3,7 @@ package proxy_test import ( "fmt" "os" + "path/filepath" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -17,7 +18,7 @@ import ( ) const ( - relative = "../../test/data/configuration" + relative = "../test/data/configuration" prog = "magick" ) @@ -31,6 +32,7 @@ func expectValidShrinkCmdInvocation(entry *configTE) { "--profile", entry.profile, } + repo := helpers.Repo(filepath.Join("..", "..", "..")) tester := helpers.CommandTester{ Args: append(options, entry.args...), Root: bootstrap.Root(func(co *command.ConfigureOptionsInfo) { @@ -39,7 +41,7 @@ func expectValidShrinkCmdInvocation(entry *configTE) { Name: prog, } co.Config.Name = "pixa-test" - co.Config.ConfigPath = "../../test/data/configuration" + co.Config.ConfigPath = filepath.Join(repo, "test", "data", "configuration") }), } @@ -123,7 +125,7 @@ var _ = Describe("Config", func() { ) }, - Entry(nil, &configTE{ + XEntry(nil, &configTE{ message: "adaptive", comm: "shrink", file: "cover.nfr.lana-del-rey.jpg", diff --git a/src/app/proxy/enter-root.go b/src/app/proxy/enter-root.go index a2cfc8e..90f6f7f 100644 --- a/src/app/proxy/enter-root.go +++ b/src/app/proxy/enter-root.go @@ -12,7 +12,7 @@ import ( ) type configProfile struct { - args []string `mapstructure:"string_slice"` + args []string } type Executor interface { @@ -37,7 +37,7 @@ type RootEntry struct { func (e *RootEntry) principalFn(item *nav.TraverseItem) error { depth := item.Extension.Depth - indicator := lo.Ternary(len(item.Children) > 0, "☀️", "🌊") + indicator := lo.Ternary(len(item.Children) > 0, "🔆", "🌊") for _, entry := range item.Children { fullPath := filepath.Join(item.Path, entry.Name()) @@ -68,18 +68,19 @@ func (e *RootEntry) ConfigureOptions(o *nav.TraverseOptions) { Fn: e.principalFn, } o.Store.Subscription = nav.SubscribeFoldersWithFiles - o.Store.DoExtend = true e.EntryBase.ConfigureOptions(o) } func (e *RootEntry) run() error { runnerWith := composeWith(e.Inputs.ParamSet) - var nilResumption *nav.Resumption // root does not need to support resume + // root does not need to support resume + // + var nilResumption *nav.Resumption after := func(result *nav.TraverseResult, err error) { for _, file := range e.files { - fmt.Printf(" ===> 🔆 candidate file: '%v'\n", file) + fmt.Printf(" ===> 📒 candidate file: '%v'\n", file) } } @@ -115,7 +116,7 @@ func EnterRoot( program Executor, config configuration.ViperConfig, ) error { - fmt.Printf("---> 🦠🦠🦠 Directory: '%v'\n", inputs.ParamSet.Native.Directory) + fmt.Printf("---> 📁📁📁 Directory: '%v'\n", inputs.ParamSet.Native.Directory) entry := &RootEntry{ EntryBase: EntryBase{ diff --git a/src/app/proxy/enter-shrink.go b/src/app/proxy/enter-shrink.go index e5931b0..8c29d16 100644 --- a/src/app/proxy/enter-shrink.go +++ b/src/app/proxy/enter-shrink.go @@ -100,7 +100,6 @@ func (e *ShrinkEntry) ConfigureOptions(o *nav.TraverseOptions) { ) } o.Store.Subscription = nav.SubscribeFiles - o.Store.DoExtend = true e.EntryBase.ConfigureOptions(o) } diff --git a/src/app/proxy/entry-base.go b/src/app/proxy/entry-base.go index e453754..971fc3a 100644 --- a/src/app/proxy/entry-base.go +++ b/src/app/proxy/entry-base.go @@ -52,7 +52,7 @@ func (e *EntryBase) ConfigureOptions(o *nav.TraverseOptions) { Type: nav.FilterTypeGlobEn, Description: fmt.Sprintf("--files-gb(G): '%v'", e.Inputs.ParamSet.Native.FilesGlob), Pattern: e.Inputs.ParamSet.Native.FilesGlob, - Scope: nav.ScopeLeafEn, + Scope: nav.ScopeFileEn, }, } @@ -62,7 +62,7 @@ func (e *EntryBase) ConfigureOptions(o *nav.TraverseOptions) { Type: nav.FilterTypeRegexEn, Description: fmt.Sprintf("--files-rx(X): '%v'", e.Inputs.ParamSet.Native.FilesRexEx), Pattern: e.Inputs.ParamSet.Native.FilesRexEx, - Scope: nav.ScopeLeafEn, + Scope: nav.ScopeFileEn, }, } diff --git a/src/app/proxy/path-finder.go b/src/app/proxy/path-finder.go new file mode 100644 index 0000000..7587d99 --- /dev/null +++ b/src/app/proxy/path-finder.go @@ -0,0 +1,89 @@ +package proxy + +type PathFinder struct{} + +/* programming-percy how to impl ddd in go +- in ddd, a value object has no behaviour it just holds some state (ie +it is a placeholder for some information). it is considered immutable +and is unidentifiable. + +- an entity is identifiable (by an ID) + +- so inside the traversal callback, we create a value-object that then +allows us the create th path-finder and whatever else is needed + +- functionality does not go inside entity objects, they should be inside +an aggregate. an aggregate combines multiple entities to create a full object. +to create an aggregate, you must identify which of the entities is the root +entity. an aggregate can also contain value-objects + +- aggregates do not contain the marshalling/persistence tags (json/xml) for +each of its members. the aggregate is not supposed to be ab to define the +formatting of its members. +the reasons are: +* aggregates are stored by repositories (see repository pattern). the repository +(typically hidden behind an interface) is a compound object which will contain +many aggregates of a type. you might have a repository for mongo-db, another +for ms-sql etc... ~ dao. Personally, I would do this a bit different; I would +prefer a single repository that could be configured with different data access +providers. + +- a service is a higher level of abstraction than the repository. the repository +will contain just a single type of entity, but typically in a system, we need many +repositories. a service will couple together these repositories. + +- use functional composition as a helper for creating factories (configuration pattern) + +- sample needs an execution chain of objects to complete work, because multiple +executions of magick with varying parameters will be required. In the full run, +this chain is a chain of 1. +*/ + +/* +mode: tidy | preserve + +*** item-handler + +contains: +- the Program +- positional args +- third party CL +- path-manager + +*** path-manager needs to provide the following paths +- output directory (inline | mirror) +- trash file location (central or local) +- for sampling scheme, we use profile name as part of the relative output path +- output root (depends on mirror) + +behaviour of naming output files: +- output filename (same as input file with a suffix | backup input, replace input file) + +- this is where the extension mapper will be implemented + + +*** file-manager: perform file system operations such as moving files around +- there will be a file-system service that can perform fs operations. it +will contain the path-finder +- contains file manager as a member +- is populated with the current traversal item + +Also, needs to use promptui: https://github.com/manifoldco/promptui + + +the sample mode is a bit tricky because for 1 file it will do multiple things + +we need to capture that concept somehow + +- foreach incoming file +FULL: => a single output file +SAMPLE: => multiple files, foreach each profile in the sample create an output + + +- need to be able to sample files per directory (we may need new extendio functionality); +or rather, we need a way to return a code that means we're done with the current directory +so stop calling me for the same directory file content => SKIP-DIR + +- for parallel version, we need some shared state and that is we need to know +when to ret +*/ diff --git a/src/app/proxy/path-finder_test.go b/src/app/proxy/path-finder_test.go new file mode 100644 index 0000000..a01af70 --- /dev/null +++ b/src/app/proxy/path-finder_test.go @@ -0,0 +1,33 @@ +package proxy_test + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/snivilised/pixa/src/app/proxy" +) + +var _ = Describe("PathFinder", func() { + // the PathFinder should not be aware of profile/sample, it only + // know about paths. So it knows about: + // - mirror-path + // - item-path (full-path to current file item) + // - input: parent dir of item + // - current + // - output: is the parent dir of the output, it may be the same as input + // - subpath (this incorporates profile & sample) + // - trash + + // - segments: "profile-name", "sample-scheme" + // + // * mirror (if mirror-path is "" => LOCALISED-MODE else CENTRALISED-MODE): + // - localised (trash-dir=pwd+"__trash") + // - centralised (trash-dir=pwd) + + Context("foo", func() { + It("should:", func() { + _ = proxy.PathFinder{} + Expect(1).To(Equal(1)) + }) + }) +}) diff --git a/src/internal/matchers/exists-in-fs.go b/src/internal/matchers/exists-in-fs.go new file mode 100644 index 0000000..55ea741 --- /dev/null +++ b/src/internal/matchers/exists-in-fs.go @@ -0,0 +1,46 @@ +package matchers + +import ( + "fmt" + + "github.com/onsi/gomega/types" + "github.com/snivilised/extendio/xfs/storage" +) + +type PathExistsMatcher struct { + vfs interface{} +} + +type AsDirectory string +type AsFile string + +func ExistInFS(fs interface{}) types.GomegaMatcher { + return &PathExistsMatcher{ + vfs: fs, + } +} + +func (m *PathExistsMatcher) Match(actual interface{}) (bool, error) { + vfs, fileSystemOK := m.vfs.(storage.VirtualFS) + if !fileSystemOK { + return false, fmt.Errorf("❌ matcher expected a VirtualFS instance (%T)", vfs) + } + + if actualPath, dirOK := actual.(AsDirectory); dirOK { + return vfs.DirectoryExists(string(actualPath)), nil + } + + if actualPath, fileOK := actual.(AsFile); fileOK { + return vfs.FileExists(string(actualPath)), nil + } + + return false, fmt.Errorf("❌ matcher expected an AsDirectory or AsFile instance (%T)", actual) +} + +func (m *PathExistsMatcher) FailureMessage(actual interface{}) string { + return fmt.Sprintf("🔥 Expected\n\t%v\npath to exist", actual) +} + +func (m *PathExistsMatcher) NegatedFailureMessage(actual interface{}) string { + return fmt.Sprintf("🔥 Expected\n\t%v\npath NOT to exist\n", actual) +} diff --git a/src/test/data/configuration/pixa-test.yml b/test/data/configuration/pixa-test.yml similarity index 70% rename from src/test/data/configuration/pixa-test.yml rename to test/data/configuration/pixa-test.yml index 0ca14ac..a9f1289 100644 --- a/src/test/data/configuration/pixa-test.yml +++ b/test/data/configuration/pixa-test.yml @@ -21,3 +21,12 @@ profiles: "--adaptive-resize", "60", ] +samplers: + schemes: + - foo: + profiles: ["blur", "sf"] + blah: 0 + - bar: + profiles: ["adaptive", "sf"] + - baz: + profiles: ["adaptive", "blur"] diff --git a/src/test/data/l10n/test.arcadia.active.en-US.json b/test/data/l10n/test.arcadia.active.en-US.json similarity index 100% rename from src/test/data/l10n/test.arcadia.active.en-US.json rename to test/data/l10n/test.arcadia.active.en-US.json diff --git a/src/test/data/l10n/test.graffico.active.en-US.json b/test/data/l10n/test.graffico.active.en-US.json similarity index 100% rename from src/test/data/l10n/test.graffico.active.en-US.json rename to test/data/l10n/test.graffico.active.en-US.json diff --git a/test/data/storage/citizen-scientist-index.xml b/test/data/storage/citizen-scientist-index.xml new file mode 100644 index 0000000..ab1a8b7 --- /dev/null +++ b/test/data/storage/citizen-scientist-index.xml @@ -0,0 +1,653 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 177 + 656 + + \ No newline at end of file diff --git a/src/test/helpers/cobra.go b/test/helpers/cobra.go similarity index 100% rename from src/test/helpers/cobra.go rename to test/helpers/cobra.go diff --git a/test/helpers/directory-tree-builder.go b/test/helpers/directory-tree-builder.go new file mode 100644 index 0000000..159801a --- /dev/null +++ b/test/helpers/directory-tree-builder.go @@ -0,0 +1,186 @@ +package helpers + +import ( + "bytes" + "encoding/xml" + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + + "github.com/samber/lo" + "github.com/snivilised/extendio/collections" + + "github.com/snivilised/extendio/xfs/utils" +) + +const offset = 2 +const tabSize = 2 + +type DirectoryTreeBuilder struct { + root string + full string + stack *collections.Stack[string] + index string + write bool + depth int + padding string +} + +func Path(parent, relative string) string { + segments := strings.Split(relative, "/") + return filepath.Join(append([]string{parent}, segments...)...) // !!! +} + +func Repo(relative string) string { + _, filename, _, _ := runtime.Caller(0) //nolint:dogsled // use of 3 _ is out of our control + + return Path(filepath.Dir(filename), relative) +} + +func (r *DirectoryTreeBuilder) read() (*Directory, error) { + data, err := os.ReadFile(r.index) + + if err != nil { + return nil, err + } + + var tree Tree + err = xml.Unmarshal(data, &tree) + + if err != nil { + return nil, err + } + + return &tree.Root, nil +} + +func (r *DirectoryTreeBuilder) status(path string) string { + return lo.Ternary(utils.Exists(path), "✔️", "❌") +} + +func (r *DirectoryTreeBuilder) pad() string { + return string(bytes.Repeat([]byte{' '}, (r.depth+offset)*tabSize)) +} + +func (r *DirectoryTreeBuilder) refill() string { + segments := r.stack.Content() + return filepath.Join(segments...) +} + +func (r *DirectoryTreeBuilder) inc(name string) { + r.stack.Push(name) + r.full = r.refill() + + r.depth++ + r.padding = r.pad() +} + +func (r *DirectoryTreeBuilder) dec() { + _, _ = r.stack.Pop() + r.full = r.refill() + + r.depth-- + r.padding = r.pad() +} + +func (r *DirectoryTreeBuilder) show(path, indicator, name string) { + status := r.status(path) + fmt.Printf("%v(depth: '%v') (%v) %v: -> '%v' (🔥 %v)\n", + r.padding, r.depth, status, indicator, name, r.full, + ) +} + +func (r *DirectoryTreeBuilder) walk() error { + fmt.Printf("\n🤖 re-generating tree at '%v'\n", r.root) + + top, err := r.read() + + if err != nil { + return err + } + + r.full = r.root + + return r.dir(*top) +} + +func (r *DirectoryTreeBuilder) dir(dir Directory) error { //nolint:gocritic // performance is not an issue + r.inc(dir.Name) + + _, dn := utils.SplitParent(dir.Name) + + if r.write { + err := os.MkdirAll(r.full, os.ModePerm) + + if err != nil { + return err + } + } + + r.show(r.full, "📂", dn) + + for _, directory := range dir.Directories { + err := r.dir(directory) + if err != nil { + return err + } + } + + for _, file := range dir.Files { + fp := Path(r.full, file.Name) + + if r.write { + err := os.WriteFile(fp, []byte(file.Text), os.ModePerm) + if err != nil { + return err + } + } + + r.show(fp, " 📜", file.Name) + } + + r.dec() + + return nil +} + +type Tree struct { + XMLName xml.Name `xml:"tree"` + Root Directory `xml:"directory"` +} + +type Directory struct { + XMLName xml.Name `xml:"directory"` + Name string `xml:"name,attr"` + Files []File `xml:"file"` + Directories []Directory `xml:"directory"` +} + +type File struct { + XMLName xml.Name `xml:"file"` + Name string `xml:"name,attr"` + Text string `xml:",chardata"` +} + +const doWrite = true + +func Ensure(root string) error { + repo := Repo("../..") + index := Path(repo, "Test/data/musico-index.xml") + + if utils.FolderExists(root) { + return nil + } + + parent, _ := utils.SplitParent(root) + builder := DirectoryTreeBuilder{ + root: root, + stack: collections.NewStackWith([]string{parent}), + index: index, + write: doWrite, + } + + return builder.walk() +}