diff --git a/cmd/photoprism/photoprism.go b/cmd/photoprism/photoprism.go index d8ef97999..c2549acc7 100644 --- a/cmd/photoprism/photoprism.go +++ b/cmd/photoprism/photoprism.go @@ -4,7 +4,8 @@ import ( "os" "github.com/photoprism/photoprism/internal/commands" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" + log "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -17,7 +18,7 @@ func main() { app.Version = version app.Copyright = "(c) 2018-2019 The PhotoPrism contributors " app.EnableBashCompletion = true - app.Flags = context.GlobalFlags + app.Flags = config.GlobalFlags app.Commands = []cli.Command{ commands.ConfigCommand, @@ -31,5 +32,7 @@ func main() { commands.VersionCommand, } - app.Run(os.Args) + if err := app.Run(os.Args); err != nil { + log.Error(err) + } } diff --git a/internal/api/api_test.go b/internal/api/api_test.go index a4cb07c89..774115c3a 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -5,18 +5,18 @@ import ( "net/http/httptest" "github.com/gin-gonic/gin" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" ) // API test helper -func NewApiTest() (app *gin.Engine, router *gin.RouterGroup, ctx *context.Context) { - ctx = context.TestContext() +func NewApiTest() (app *gin.Engine, router *gin.RouterGroup, conf *config.Config) { + conf = config.TestConfig() gin.SetMode(gin.TestMode) app = gin.New() router = app.Group("/api/v1") - return app, router, ctx + return app, router, conf } // See https://medium.com/@craigchilds94/testing-gin-json-responses-1f258ce3b0b1 diff --git a/internal/api/photos.go b/internal/api/photos.go index b1c84e163..62c9d8a10 100644 --- a/internal/api/photos.go +++ b/internal/api/photos.go @@ -4,7 +4,7 @@ import ( "net/http" "strconv" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" log "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -27,10 +27,10 @@ import ( // before: date Find photos taken before (format: "2006-01-02") // after: date Find photos taken after (format: "2006-01-02") // favorites: bool Find favorites only -func GetPhotos(router *gin.RouterGroup, ctx *context.Context) { +func GetPhotos(router *gin.RouterGroup, conf *config.Config) { router.GET("/photos", func(c *gin.Context) { var form forms.PhotoSearchForm - search := photoprism.NewSearch(ctx.OriginalsPath(), ctx.Db()) + search := photoprism.NewSearch(conf.OriginalsPath(), conf.Db()) err := c.MustBindWith(&form, binding.Form) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) @@ -53,9 +53,9 @@ func GetPhotos(router *gin.RouterGroup, ctx *context.Context) { // // Parameters: // id: int Photo ID as returned by the API -func LikePhoto(router *gin.RouterGroup, ctx *context.Context) { +func LikePhoto(router *gin.RouterGroup, conf *config.Config) { router.POST("/photos/:id/like", func(c *gin.Context) { - search := photoprism.NewSearch(ctx.OriginalsPath(), ctx.Db()) + search := photoprism.NewSearch(conf.OriginalsPath(), conf.Db()) photoID, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { log.Errorf("could not find image for id: %s", err.Error()) @@ -71,7 +71,7 @@ func LikePhoto(router *gin.RouterGroup, ctx *context.Context) { } photo.PhotoFavorite = true - ctx.Db().Save(&photo) + conf.Db().Save(&photo) c.JSON(http.StatusOK, http.Response{}) }) } @@ -80,9 +80,9 @@ func LikePhoto(router *gin.RouterGroup, ctx *context.Context) { // // Parameters: // id: int Photo ID as returned by the API -func DislikePhoto(router *gin.RouterGroup, ctx *context.Context) { +func DislikePhoto(router *gin.RouterGroup, conf *config.Config) { router.DELETE("/photos/:id/like", func(c *gin.Context) { - search := photoprism.NewSearch(ctx.OriginalsPath(), ctx.Db()) + search := photoprism.NewSearch(conf.OriginalsPath(), conf.Db()) id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { log.Errorf("could not find image for id: %s", err.Error()) @@ -98,7 +98,7 @@ func DislikePhoto(router *gin.RouterGroup, ctx *context.Context) { } photo.PhotoFavorite = false - ctx.Db().Save(&photo) + conf.Db().Save(&photo) c.JSON(http.StatusOK, http.Response{}) }) } diff --git a/internal/api/thumbnails.go b/internal/api/thumbnails.go index 411a64c77..5575b0062 100644 --- a/internal/api/thumbnails.go +++ b/internal/api/thumbnails.go @@ -4,7 +4,7 @@ import ( "fmt" "strconv" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" log "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" @@ -23,7 +23,7 @@ var photoIconSvg = []byte(` // type: string Format, either "fit" or "square" // size: int Size in pixels // hash: string The file hash as returned by the search API -func GetThumbnail(router *gin.RouterGroup, ctx *context.Context) { +func GetThumbnail(router *gin.RouterGroup, conf *config.Config) { router.GET("/thumbnails/:type/:size/:hash", func(c *gin.Context) { fileHash := c.Param("hash") thumbnailType := c.Param("type") @@ -34,7 +34,7 @@ func GetThumbnail(router *gin.RouterGroup, ctx *context.Context) { return } - search := photoprism.NewSearch(ctx.OriginalsPath(), ctx.Db()) + search := photoprism.NewSearch(conf.OriginalsPath(), conf.Db()) file, err := search.FindFileByHash(fileHash) if err != nil { @@ -42,7 +42,7 @@ func GetThumbnail(router *gin.RouterGroup, ctx *context.Context) { return } - fileName := fmt.Sprintf("%s/%s", ctx.OriginalsPath(), file.FileName) + fileName := fmt.Sprintf("%s/%s", conf.OriginalsPath(), file.FileName) mediaFile, err := photoprism.NewMediaFile(fileName) if err != nil { @@ -51,20 +51,20 @@ func GetThumbnail(router *gin.RouterGroup, ctx *context.Context) { // Set missing flag so that the file doesn't show up in search results anymore file.FileMissing = true - ctx.Db().Save(&file) + conf.Db().Save(&file) return } switch thumbnailType { case "fit": - if thumbnail, err := mediaFile.Thumbnail(ctx.ThumbnailsPath(), size); err == nil { + if thumbnail, err := mediaFile.Thumbnail(conf.ThumbnailsPath(), size); err == nil { c.File(thumbnail.Filename()) } else { log.Errorf("could not create thumbnail: %s", err.Error()) c.Data(400, "image/svg+xml", photoIconSvg) } case "square": - if thumbnail, err := mediaFile.SquareThumbnail(ctx.ThumbnailsPath(), size); err == nil { + if thumbnail, err := mediaFile.SquareThumbnail(conf.ThumbnailsPath(), size); err == nil { c.File(thumbnail.Filename()) } else { log.Errorf("could not create square thumbnail: %s", err.Error()) diff --git a/internal/commands/config.go b/internal/commands/config.go index 4ab41d2e8..a3a5e39d7 100644 --- a/internal/commands/config.go +++ b/internal/commands/config.go @@ -3,7 +3,7 @@ package commands import ( "fmt" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/urfave/cli" ) @@ -15,42 +15,42 @@ var ConfigCommand = cli.Command{ } func configAction(ctx *cli.Context) error { - app := context.NewContext(ctx) + conf := config.NewConfig(ctx) fmt.Printf("NAME VALUE\n") - fmt.Printf("name %s\n", app.Name()) - fmt.Printf("version %s\n", app.Version()) - fmt.Printf("copyright %s\n", app.Copyright()) - fmt.Printf("debug %t\n", app.Debug()) - fmt.Printf("read-only %t\n", app.ReadOnly()) - fmt.Printf("log-level %s\n", app.LogLevel()) - fmt.Printf("config-file %s\n", app.ConfigFile()) + fmt.Printf("name %s\n", conf.Name()) + fmt.Printf("version %s\n", conf.Version()) + fmt.Printf("copyright %s\n", conf.Copyright()) + fmt.Printf("debug %t\n", conf.Debug()) + fmt.Printf("read-only %t\n", conf.ReadOnly()) + fmt.Printf("log-level %s\n", conf.LogLevel()) + fmt.Printf("config-file %s\n", conf.ConfigFile()) - fmt.Printf("database-driver %s\n", app.DatabaseDriver()) - fmt.Printf("database-dsn %s\n", app.DatabaseDsn()) + fmt.Printf("database-driver %s\n", conf.DatabaseDriver()) + fmt.Printf("database-dsn %s\n", conf.DatabaseDsn()) - fmt.Printf("http-host %s\n", app.HttpServerHost()) - fmt.Printf("http-port %d\n", app.HttpServerPort()) - fmt.Printf("http-mode %s\n", app.HttpServerMode()) + fmt.Printf("http-host %s\n", conf.HttpServerHost()) + fmt.Printf("http-port %d\n", conf.HttpServerPort()) + fmt.Printf("http-mode %s\n", conf.HttpServerMode()) - fmt.Printf("sql-host %s\n", app.SqlServerHost()) - fmt.Printf("sql-port %d\n", app.SqlServerPort()) - fmt.Printf("sql-password %s\n", app.SqlServerPassword()) - fmt.Printf("sql-path %s\n", app.SqlServerPath()) + fmt.Printf("sql-host %s\n", conf.SqlServerHost()) + fmt.Printf("sql-port %d\n", conf.SqlServerPort()) + fmt.Printf("sql-password %s\n", conf.SqlServerPassword()) + fmt.Printf("sql-path %s\n", conf.SqlServerPath()) - fmt.Printf("assets-path %s\n", app.AssetsPath()) - fmt.Printf("originals-path %s\n", app.OriginalsPath()) - fmt.Printf("import-path %s\n", app.ImportPath()) - fmt.Printf("export-path %s\n", app.ExportPath()) - fmt.Printf("cache-path %s\n", app.CachePath()) - fmt.Printf("thumbnails-path %s\n", app.ThumbnailsPath()) - fmt.Printf("tf-model-path %s\n", app.TensorFlowModelPath()) - fmt.Printf("templates-path %s\n", app.HttpTemplatesPath()) - fmt.Printf("favicons-path %s\n", app.HttpFaviconsPath()) - fmt.Printf("public-path %s\n", app.HttpPublicPath()) - fmt.Printf("public-build-path %s\n", app.HttpPublicBuildPath()) + fmt.Printf("assets-path %s\n", conf.AssetsPath()) + fmt.Printf("originals-path %s\n", conf.OriginalsPath()) + fmt.Printf("import-path %s\n", conf.ImportPath()) + fmt.Printf("export-path %s\n", conf.ExportPath()) + fmt.Printf("cache-path %s\n", conf.CachePath()) + fmt.Printf("thumbnails-path %s\n", conf.ThumbnailsPath()) + fmt.Printf("tf-model-path %s\n", conf.TensorFlowModelPath()) + fmt.Printf("templates-path %s\n", conf.HttpTemplatesPath()) + fmt.Printf("favicons-path %s\n", conf.HttpFaviconsPath()) + fmt.Printf("public-path %s\n", conf.HttpPublicPath()) + fmt.Printf("public-build-path %s\n", conf.HttpPublicBuildPath()) - fmt.Printf("darktable-cli %s\n", app.DarktableCli()) + fmt.Printf("darktable-cli %s\n", conf.DarktableCli()) return nil } diff --git a/internal/commands/config_test.go b/internal/commands/config_test.go index fdd5faf9b..314c50e46 100644 --- a/internal/commands/config_test.go +++ b/internal/commands/config_test.go @@ -3,16 +3,17 @@ package commands import ( "testing" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" + "github.com/photoprism/photoprism/internal/util" "github.com/stretchr/testify/assert" ) func TestConfigCommand(t *testing.T) { var err error - ctx := context.CliTestContext() + ctx := config.CliTestContext() - output := context.CaptureOutput(func() { + output := util.CaptureOutput(func() { err = ConfigCommand.Run(ctx) }) diff --git a/internal/commands/convert.go b/internal/commands/convert.go index 30c44b5cb..660df6824 100644 --- a/internal/commands/convert.go +++ b/internal/commands/convert.go @@ -1,7 +1,7 @@ package commands import ( - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/photoprism" log "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -15,17 +15,17 @@ var ConvertCommand = cli.Command{ } func convertAction(ctx *cli.Context) error { - app := context.NewContext(ctx) + conf := config.NewConfig(ctx) - if err := app.CreateDirectories(); err != nil { + if err := conf.CreateDirectories(); err != nil { return err } - log.Infof("converting RAW images in %s to JPEG", app.OriginalsPath()) + log.Infof("converting RAW images in %s to JPEG", conf.OriginalsPath()) - converter := photoprism.NewConverter(app.DarktableCli()) + converter := photoprism.NewConverter(conf.DarktableCli()) - converter.ConvertAll(app.OriginalsPath()) + converter.ConvertAll(conf.OriginalsPath()) log.Infof("image conversion complete") diff --git a/internal/commands/export.go b/internal/commands/export.go index fa72a1ab9..a751600e1 100644 --- a/internal/commands/export.go +++ b/internal/commands/export.go @@ -6,7 +6,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/araddon/dateparse" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/photoprism" "github.com/urfave/cli" ) @@ -40,9 +40,9 @@ var exportFlags = []cli.Flag{ } func exportAction(ctx *cli.Context) error { - app := context.NewContext(ctx) + conf := config.NewConfig(ctx) - if err := app.CreateDirectories(); err != nil { + if err := conf.CreateDirectories(); err != nil { return err } @@ -70,15 +70,17 @@ func exportAction(ctx *cli.Context) error { } } - exportPath := fmt.Sprintf("%s/%s", app.ExportPath(), name) + exportPath := fmt.Sprintf("%s/%s", conf.ExportPath(), name) size := ctx.Int("size") - originals := photoprism.FindOriginalsByDate(app.OriginalsPath(), afterDate, beforeDate) + originals := photoprism.FindOriginalsByDate(conf.OriginalsPath(), afterDate, beforeDate) log.Infof("exporting photos to %s", exportPath) - photoprism.ExportPhotosFromOriginals(originals, app.ThumbnailsPath(), exportPath, size) - - log.Infof("photo export complete") + if err := photoprism.ExportPhotosFromOriginals(originals, conf.ThumbnailsPath(), exportPath, size); err != nil { + log.Error(err) + } else { + log.Infof("photo export complete") + } return nil } diff --git a/internal/commands/import.go b/internal/commands/import.go index 36a97ebfd..527553079 100644 --- a/internal/commands/import.go +++ b/internal/commands/import.go @@ -1,7 +1,7 @@ package commands import ( - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/photoprism" log "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -15,25 +15,25 @@ var ImportCommand = cli.Command{ } func importAction(ctx *cli.Context) error { - app := context.NewContext(ctx) + conf := config.NewConfig(ctx) - if err := app.CreateDirectories(); err != nil { + if err := conf.CreateDirectories(); err != nil { return err } - app.MigrateDb() + conf.MigrateDb() - log.Infof("importing photos from %s", app.ImportPath()) + log.Infof("importing photos from %s", conf.ImportPath()) - tensorFlow := photoprism.NewTensorFlow(app.TensorFlowModelPath()) + tensorFlow := photoprism.NewTensorFlow(conf.TensorFlowModelPath()) - indexer := photoprism.NewIndexer(app.OriginalsPath(), tensorFlow, app.Db()) + indexer := photoprism.NewIndexer(conf.OriginalsPath(), tensorFlow, conf.Db()) - converter := photoprism.NewConverter(app.DarktableCli()) + converter := photoprism.NewConverter(conf.DarktableCli()) - importer := photoprism.NewImporter(app.OriginalsPath(), indexer, converter) + importer := photoprism.NewImporter(conf.OriginalsPath(), indexer, converter) - importer.ImportPhotosFromDirectory(app.ImportPath()) + importer.ImportPhotosFromDirectory(conf.ImportPath()) log.Info("photo import complete") diff --git a/internal/commands/index.go b/internal/commands/index.go index 8dba94152..afdf1e2ff 100644 --- a/internal/commands/index.go +++ b/internal/commands/index.go @@ -1,7 +1,7 @@ package commands import ( - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/photoprism" log "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -15,25 +15,25 @@ var IndexCommand = cli.Command{ } func indexAction(ctx *cli.Context) error { - app := context.NewContext(ctx) + conf := config.NewConfig(ctx) - if err := app.CreateDirectories(); err != nil { + if err := conf.CreateDirectories(); err != nil { return err } - app.MigrateDb() + conf.MigrateDb() - log.Infof("indexing photos in %s", app.OriginalsPath()) + log.Infof("indexing photos in %s", conf.OriginalsPath()) - tensorFlow := photoprism.NewTensorFlow(app.TensorFlowModelPath()) + tensorFlow := photoprism.NewTensorFlow(conf.TensorFlowModelPath()) - indexer := photoprism.NewIndexer(app.OriginalsPath(), tensorFlow, app.Db()) + indexer := photoprism.NewIndexer(conf.OriginalsPath(), tensorFlow, conf.Db()) files := indexer.IndexAll() log.Infof("indexed %d files", len(files)) - app.Shutdown() + conf.Shutdown() return nil } diff --git a/internal/commands/migrate.go b/internal/commands/migrate.go index 5feacadad..0dc9f0189 100644 --- a/internal/commands/migrate.go +++ b/internal/commands/migrate.go @@ -1,7 +1,7 @@ package commands import ( - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" log "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -14,15 +14,15 @@ var MigrateCommand = cli.Command{ } func migrateAction(ctx *cli.Context) error { - app := context.NewContext(ctx) + conf := config.NewConfig(ctx) log.Infoln("migrating database") - app.MigrateDb() + conf.MigrateDb() log.Infoln("database migration complete") - app.Shutdown() + conf.Shutdown() return nil } diff --git a/internal/commands/start.go b/internal/commands/start.go index a8510496d..0b83c1b1f 100644 --- a/internal/commands/start.go +++ b/internal/commands/start.go @@ -3,7 +3,7 @@ package commands import ( log "github.com/sirupsen/logrus" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/server" "github.com/urfave/cli" ) @@ -38,21 +38,21 @@ var startFlags = []cli.Flag{ } func startAction(ctx *cli.Context) error { - app := context.NewContext(ctx) + conf := config.NewConfig(ctx) - if app.HttpServerPort() < 1 { + if conf.HttpServerPort() < 1 { log.Fatal("server port must be a positive integer") } - if err := app.CreateDirectories(); err != nil { + if err := conf.CreateDirectories(); err != nil { log.Fatal(err) } - app.MigrateDb() + conf.MigrateDb() - log.Infof("starting web server at %s:%d", app.HttpServerHost(), app.HttpServerPort()) + log.Infof("starting web server at %s:%d", conf.HttpServerHost(), conf.HttpServerPort()) - server.Start(app) + server.Start(conf) return nil } diff --git a/internal/commands/thumbnails.go b/internal/commands/thumbnails.go index 841554c97..2f0cac311 100644 --- a/internal/commands/thumbnails.go +++ b/internal/commands/thumbnails.go @@ -1,7 +1,7 @@ package commands import ( - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/photoprism" log "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -29,13 +29,13 @@ var ThumbnailsCommand = cli.Command{ } func thumbnailsAction(ctx *cli.Context) error { - app := context.NewContext(ctx) + conf := config.NewConfig(ctx) - if err := app.CreateDirectories(); err != nil { + if err := conf.CreateDirectories(); err != nil { return err } - log.Infof("creating thumbnails in \"%s\"", app.ThumbnailsPath()) + log.Infof("creating thumbnails in \"%s\"", conf.ThumbnailsPath()) sizes := ctx.IntSlice("size") @@ -49,7 +49,7 @@ func thumbnailsAction(ctx *cli.Context) error { } for _, size := range sizes { - photoprism.CreateThumbnailsFromOriginals(app.OriginalsPath(), app.ThumbnailsPath(), size, ctx.Bool("square")) + photoprism.CreateThumbnailsFromOriginals(conf.OriginalsPath(), conf.ThumbnailsPath(), size, ctx.Bool("square")) } log.Info("thumbnails created") diff --git a/internal/commands/version.go b/internal/commands/version.go index 57868aea8..cc6bec0e4 100644 --- a/internal/commands/version.go +++ b/internal/commands/version.go @@ -3,7 +3,7 @@ package commands import ( "fmt" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/urfave/cli" ) @@ -15,9 +15,9 @@ var VersionCommand = cli.Command{ } func versionAction(ctx *cli.Context) error { - app := context.NewContext(ctx) + conf := config.NewConfig(ctx) - fmt.Println(app.Version()) + fmt.Println(conf.Version()) return nil } diff --git a/internal/context/client_config.go b/internal/config/client_config.go similarity index 83% rename from internal/context/client_config.go rename to internal/config/client_config.go index e7cd35d0e..8b761978b 100644 --- a/internal/context/client_config.go +++ b/internal/config/client_config.go @@ -1,4 +1,4 @@ -package context +package config // HTTP client / Web UI config values type ClientConfig map[string]interface{} diff --git a/internal/context/context.go b/internal/config/config.go similarity index 79% rename from internal/context/context.go rename to internal/config/config.go index cb9d8291f..130bb51af 100644 --- a/internal/context/context.go +++ b/internal/config/config.go @@ -1,4 +1,4 @@ -package context +package config import ( "errors" @@ -8,16 +8,16 @@ import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" _ "github.com/jinzhu/gorm/dialects/sqlite" - "github.com/photoprism/photoprism/internal/fsutil" "github.com/photoprism/photoprism/internal/models" "github.com/photoprism/photoprism/internal/tidb" + "github.com/photoprism/photoprism/internal/util" log "github.com/sirupsen/logrus" "github.com/urfave/cli" ) -type Context struct { +type Config struct { db *gorm.DB - config *Config + config *Params } func initLogger(debug bool) { @@ -33,10 +33,10 @@ func initLogger(debug bool) { } } -func NewContext(ctx *cli.Context) *Context { +func NewConfig(ctx *cli.Context) *Config { initLogger(ctx.GlobalBool("debug")) - c := &Context{config: NewConfig(ctx)} + c := &Config{config: NewParams(ctx)} log.SetLevel(c.LogLevel()) @@ -48,7 +48,7 @@ func NewContext(ctx *cli.Context) *Context { // ThumbnailsPath // ImportPath // ExportPath -func (c *Context) CreateDirectories() error { +func (c *Config) CreateDirectories() error { if err := os.MkdirAll(c.OriginalsPath(), os.ModePerm); err != nil { return err } @@ -83,7 +83,7 @@ func (c *Context) CreateDirectories() error { // connectToDatabase establishes a database connection. // When used with the internal driver, it may create a new database server instance. // It tries to do this 12 times with a 5 second sleep interval in between. -func (c *Context) connectToDatabase() error { +func (c *Config) connectToDatabase() error { dbDriver := c.DatabaseDriver() dbDsn := c.DatabaseDsn() @@ -143,32 +143,32 @@ func (c *Context) connectToDatabase() error { } // Name returns the application name. -func (c *Context) Name() string { +func (c *Config) Name() string { return c.config.Name } // Version returns the application version. -func (c *Context) Version() string { +func (c *Config) Version() string { return c.config.Version } // Copyright returns the application copyright. -func (c *Context) Copyright() string { +func (c *Config) Copyright() string { return c.config.Copyright } // Debug returns true if Debug mode is on. -func (c *Context) Debug() bool { +func (c *Config) Debug() bool { return c.config.Debug } // ReadOnly returns true if photo directories are write protected. -func (c *Context) ReadOnly() bool { +func (c *Config) ReadOnly() bool { return c.config.ReadOnly } // LogLevel returns the logrus log level. -func (c *Context) LogLevel() log.Level { +func (c *Config) LogLevel() log.Level { if c.Debug() { c.config.LogLevel = "debug" } @@ -181,22 +181,22 @@ func (c *Context) LogLevel() log.Level { } // TestConfigFile returns the config file name. -func (c *Context) ConfigFile() string { +func (c *Config) ConfigFile() string { return c.config.ConfigFile } // SqlServerHost returns the built-in SQL server host name or IP address (empty for all interfaces). -func (c *Context) SqlServerHost() string { +func (c *Config) SqlServerHost() string { return c.config.SqlServerHost } // SqlServerPort returns the built-in SQL server port. -func (c *Context) SqlServerPort() uint { +func (c *Config) SqlServerPort() uint { return c.config.SqlServerPort } // SqlServerPath returns the database storage path for TiDB. -func (c *Context) SqlServerPath() string { +func (c *Config) SqlServerPath() string { if c.config.SqlServerPath != "" { return c.config.SqlServerPath } @@ -205,12 +205,12 @@ func (c *Context) SqlServerPath() string { } // SqlServerPassword returns the password for the built-in database server. -func (c *Context) SqlServerPassword() string { +func (c *Config) SqlServerPassword() string { return c.config.SqlServerPassword } // HttpServerHost returns the built-in HTTP server host name or IP address (empty for all interfaces). -func (c *Context) HttpServerHost() string { +func (c *Config) HttpServerHost() string { if c.config.HttpServerHost == "" { return "0.0.0.0" } @@ -219,37 +219,37 @@ func (c *Context) HttpServerHost() string { } // HttpServerPort returns the built-in HTTP server port. -func (c *Context) HttpServerPort() int { +func (c *Config) HttpServerPort() int { return c.config.HttpServerPort } // HttpServerMode returns the server mode. -func (c *Context) HttpServerMode() string { +func (c *Config) HttpServerMode() string { return c.config.HttpServerMode } // HttpServerPassword returns the password for the user interface (optional). -func (c *Context) HttpServerPassword() string { +func (c *Config) HttpServerPassword() string { return c.config.HttpServerPassword } // OriginalsPath returns the originals. -func (c *Context) OriginalsPath() string { +func (c *Config) OriginalsPath() string { return c.config.OriginalsPath } // ImportPath returns the import directory. -func (c *Context) ImportPath() string { +func (c *Config) ImportPath() string { return c.config.ImportPath } // ExportPath returns the export directory. -func (c *Context) ExportPath() string { +func (c *Config) ExportPath() string { return c.config.ExportPath } // DarktableCli returns the darktable-cli binary file name. -func (c *Context) DarktableCli() string { +func (c *Config) DarktableCli() string { if c.config.DarktableCli == "" { return "/usr/bin/darktable-cli" } @@ -257,7 +257,7 @@ func (c *Context) DarktableCli() string { } // DatabaseDriver returns the database driver name. -func (c *Context) DatabaseDriver() string { +func (c *Config) DatabaseDriver() string { if c.config.DatabaseDriver == "" { return DbTiDB } @@ -266,7 +266,7 @@ func (c *Context) DatabaseDriver() string { } // DatabaseDsn returns the database data source name (DSN). -func (c *Context) DatabaseDsn() string { +func (c *Config) DatabaseDsn() string { if c.config.DatabaseDsn == "" { return "root:photoprism@tcp(localhost:4000)/photoprism?parseTime=true" } @@ -275,52 +275,52 @@ func (c *Context) DatabaseDsn() string { } // CachePath returns the path to the cache. -func (c *Context) CachePath() string { +func (c *Config) CachePath() string { return c.config.CachePath } // ThumbnailsPath returns the path to the cached thumbnails. -func (c *Context) ThumbnailsPath() string { +func (c *Config) ThumbnailsPath() string { return c.CachePath() + "/thumbnails" } // AssetsPath returns the path to the assets. -func (c *Context) AssetsPath() string { +func (c *Config) AssetsPath() string { return c.config.AssetsPath } // TensorFlowModelPath returns the tensorflow model path. -func (c *Context) TensorFlowModelPath() string { +func (c *Config) TensorFlowModelPath() string { return c.AssetsPath() + "/tensorflow" } // ServerPath returns the server assets path (public files, favicons, templates,...). -func (c *Context) ServerPath() string { +func (c *Config) ServerPath() string { return c.AssetsPath() + "/server" } // HttpTemplatesPath returns the server templates path. -func (c *Context) HttpTemplatesPath() string { +func (c *Config) HttpTemplatesPath() string { return c.ServerPath() + "/templates" } // HttpFaviconsPath returns the favicons path. -func (c *Context) HttpFaviconsPath() string { +func (c *Config) HttpFaviconsPath() string { return c.HttpPublicPath() + "/favicons" } // HttpPublicPath returns the public server path (//server/assets/*). -func (c *Context) HttpPublicPath() string { +func (c *Config) HttpPublicPath() string { return c.ServerPath() + "/public" } // HttpPublicBuildPath returns the public build path (//server/assets/build/*). -func (c *Context) HttpPublicBuildPath() string { +func (c *Config) HttpPublicBuildPath() string { return c.HttpPublicPath() + "/build" } // Db returns the db connection. -func (c *Context) Db() *gorm.DB { +func (c *Config) Db() *gorm.DB { if c.db == nil { if err := c.connectToDatabase(); err != nil { log.Fatal(err) @@ -331,7 +331,7 @@ func (c *Context) Db() *gorm.DB { } // CloseDb closes the db connection (if any). -func (c *Context) CloseDb() error { +func (c *Config) CloseDb() error { if c.db != nil { if err := c.db.Close(); err == nil { c.db = nil @@ -344,7 +344,7 @@ func (c *Context) CloseDb() error { } // MigrateDb will start a migration process. -func (c *Context) MigrateDb() { +func (c *Config) MigrateDb() { db := c.Db() db.AutoMigrate( @@ -361,7 +361,7 @@ func (c *Context) MigrateDb() { } // ClientConfig returns a loaded and set configuration entity. -func (c *Context) ClientConfig() ClientConfig { +func (c *Config) ClientConfig() ClientConfig { db := c.Db() var cameras []*models.Camera @@ -377,8 +377,8 @@ func (c *Context) ClientConfig() ClientConfig { db.Where("deleted_at IS NULL").Limit(1000).Order("camera_model").Find(&cameras) - jsHash := fsutil.Hash(c.HttpPublicBuildPath() + "/app.js") - cssHash := fsutil.Hash(c.HttpPublicBuildPath() + "/app.css") + jsHash := util.Hash(c.HttpPublicBuildPath() + "/app.js") + cssHash := util.Hash(c.HttpPublicBuildPath() + "/app.css") result := ClientConfig{ "name": c.Name(), @@ -395,7 +395,7 @@ func (c *Context) ClientConfig() ClientConfig { return result } -func (c *Context) Shutdown() { +func (c *Config) Shutdown() { if err := c.CloseDb(); err != nil { log.Errorf("could not close database connection: %s", err) } else { diff --git a/internal/config/config_test.go b/internal/config/config_test.go new file mode 100644 index 000000000..b6d51bc22 --- /dev/null +++ b/internal/config/config_test.go @@ -0,0 +1,23 @@ +package config + +import ( + "testing" + + "github.com/photoprism/photoprism/internal/util" + "github.com/stretchr/testify/assert" +) + +func TestNewConfig(t *testing.T) { + ctx := CliTestContext() + + assert.True(t, ctx.IsSet("assets-path")) + assert.False(t, ctx.Bool("debug")) + + c := NewConfig(ctx) + + assert.IsType(t, new(Config), c) + + assert.Equal(t, util.ExpandedFilename("../../assets"), c.AssetsPath()) + assert.False(t, c.Debug()) + assert.False(t, c.ReadOnly()) +} diff --git a/internal/context/doc.go b/internal/config/doc.go similarity index 57% rename from internal/context/doc.go rename to internal/config/doc.go index b768c4bf8..b1ebd9fb9 100644 --- a/internal/context/doc.go +++ b/internal/config/doc.go @@ -1,8 +1,8 @@ /* -Package context contains CLI context related config functionality. +Package config contains CLI config related config functionality. Additional information can be found in our Developer Guide: https://github.com/photoprism/photoprism/wiki */ -package context +package config diff --git a/internal/context/flags.go b/internal/config/flags.go similarity index 99% rename from internal/context/flags.go rename to internal/config/flags.go index 0e231c4c0..6fc959df6 100644 --- a/internal/context/flags.go +++ b/internal/config/flags.go @@ -1,4 +1,4 @@ -package context +package config import "github.com/urfave/cli" diff --git a/internal/context/config.go b/internal/config/params.go similarity index 80% rename from internal/context/config.go rename to internal/config/params.go index e703ffab7..889a44430 100644 --- a/internal/context/config.go +++ b/internal/config/params.go @@ -1,4 +1,4 @@ -package context +package config import ( "errors" @@ -8,7 +8,7 @@ import ( _ "github.com/jinzhu/gorm/dialects/mysql" _ "github.com/jinzhu/gorm/dialects/sqlite" - "github.com/photoprism/photoprism/internal/fsutil" + "github.com/photoprism/photoprism/internal/util" log "github.com/sirupsen/logrus" "github.com/urfave/cli" "gopkg.in/yaml.v2" @@ -19,7 +19,7 @@ const ( DbMySQL = "mysql" ) -// Config provides a struct in which application configuration is stored. +// Params provides a struct in which application configuration is stored. // Application code must use functions to get config values, for two reasons: // // 1. Some values are computed and we don't want to leak implementation details (aims at reducing refactoring overhead). @@ -27,7 +27,7 @@ const ( // 2. Paths might actually be dynamic later (if we build a multi-user version). // // See https://github.com/photoprism/photoprism/issues/50#issuecomment-433856358 -type Config struct { +type Params struct { Name string Version string Copyright string @@ -53,20 +53,20 @@ type Config struct { DatabaseDsn string `yaml:"database-dsn" flag:"database-dsn"` } -// NewConfig() creates a new configuration entity by using two methods: +// NewParams() creates a new configuration entity by using two methods: // // 1. SetValuesFromFile: This will initialize values from a yaml config file. // // 2. SetValuesFromCliContext: Which comes after SetValuesFromFile and overrides // any previous values giving an option two override file configs through the CLI. -func NewConfig(ctx *cli.Context) *Config { - c := &Config{} +func NewParams(ctx *cli.Context) *Params { + c := &Params{} c.Name = ctx.App.Name c.Copyright = ctx.App.Copyright c.Version = ctx.App.Version - if err := c.SetValuesFromFile(fsutil.ExpandedFilename(ctx.GlobalString("config-file"))); err != nil { + if err := c.SetValuesFromFile(util.ExpandedFilename(ctx.GlobalString("config-file"))); err != nil { log.Debug(err) } @@ -79,19 +79,19 @@ func NewConfig(ctx *cli.Context) *Config { return c } -func (c *Config) expandFilenames() { - c.AssetsPath = fsutil.ExpandedFilename(c.AssetsPath) - c.CachePath = fsutil.ExpandedFilename(c.CachePath) - c.OriginalsPath = fsutil.ExpandedFilename(c.OriginalsPath) - c.ImportPath = fsutil.ExpandedFilename(c.ImportPath) - c.ExportPath = fsutil.ExpandedFilename(c.ExportPath) - c.DarktableCli = fsutil.ExpandedFilename(c.DarktableCli) - c.SqlServerPath = fsutil.ExpandedFilename(c.SqlServerPath) +func (c *Params) expandFilenames() { + c.AssetsPath = util.ExpandedFilename(c.AssetsPath) + c.CachePath = util.ExpandedFilename(c.CachePath) + c.OriginalsPath = util.ExpandedFilename(c.OriginalsPath) + c.ImportPath = util.ExpandedFilename(c.ImportPath) + c.ExportPath = util.ExpandedFilename(c.ExportPath) + c.DarktableCli = util.ExpandedFilename(c.DarktableCli) + c.SqlServerPath = util.ExpandedFilename(c.SqlServerPath) } // SetValuesFromFile uses a yaml config file to initiate the configuration entity. -func (c *Config) SetValuesFromFile(fileName string) error { - if !fsutil.Exists(fileName) { +func (c *Params) SetValuesFromFile(fileName string) error { + if !util.Exists(fileName) { return errors.New(fmt.Sprintf("config file not found: \"%s\"", fileName)) } @@ -106,7 +106,7 @@ func (c *Config) SetValuesFromFile(fileName string) error { // SetValuesFromCliContext uses values from the CLI to setup configuration overrides // for the entity. -func (c *Config) SetValuesFromCliContext(ctx *cli.Context) error { +func (c *Params) SetValuesFromCliContext(ctx *cli.Context) error { v := reflect.ValueOf(c).Elem() // Iterate through all config fields diff --git a/internal/context/config_test.go b/internal/config/params_test.go similarity index 72% rename from internal/context/config_test.go rename to internal/config/params_test.go index 16fb9a97a..c7dafdae1 100644 --- a/internal/context/config_test.go +++ b/internal/config/params_test.go @@ -1,29 +1,29 @@ -package context +package config import ( "testing" - "github.com/photoprism/photoprism/internal/fsutil" + "github.com/photoprism/photoprism/internal/util" "github.com/stretchr/testify/assert" ) -func TestNewConfig(t *testing.T) { +func TestNewParams(t *testing.T) { ctx := CliTestContext() assert.True(t, ctx.IsSet("assets-path")) assert.False(t, ctx.Bool("debug")) - c := NewConfig(ctx) + c := NewParams(ctx) - assert.IsType(t, new(Config), c) + assert.IsType(t, new(Params), c) - assert.Equal(t, fsutil.ExpandedFilename("../../assets"), c.AssetsPath) + assert.Equal(t, util.ExpandedFilename("../../assets"), c.AssetsPath) assert.False(t, c.Debug) assert.False(t, c.ReadOnly) } -func TestConfig_SetValuesFromFile(t *testing.T) { - c := NewConfig(CliTestContext()) +func TestParams_SetValuesFromFile(t *testing.T) { + c := NewParams(CliTestContext()) err := c.SetValuesFromFile("testdata/config.yml") diff --git a/internal/context/test_context.go b/internal/config/test.go similarity index 71% rename from internal/context/test_context.go rename to internal/config/test.go index ee56e8c1f..1052f8c42 100644 --- a/internal/context/test_context.go +++ b/internal/config/test.go @@ -1,4 +1,4 @@ -package context +package config import ( "flag" @@ -8,7 +8,7 @@ import ( _ "github.com/jinzhu/gorm/dialects/mysql" _ "github.com/jinzhu/gorm/dialects/sqlite" - "github.com/photoprism/photoprism/internal/fsutil" + "github.com/photoprism/photoprism/internal/util" "github.com/urfave/cli" log "github.com/sirupsen/logrus" @@ -20,18 +20,18 @@ const ( TestDataHash = "1a59b358b80221ab3e76efb683ad72402f0b0844" ) -var testContext *Context +var testConfig *Config func testDataPath(assetsPath string) string { return assetsPath + "/testdata" } -func NewTestConfig() *Config { - assetsPath := fsutil.ExpandedFilename("../../assets") +func NewTestParams() *Params { + assetsPath := util.ExpandedFilename("../../assets") testDataPath := testDataPath(assetsPath) - c := &Config{ + c := &Params{ DarktableCli: "/usr/bin/darktable-cli", AssetsPath: assetsPath, CachePath: testDataPath + "/cache", @@ -45,27 +45,27 @@ func NewTestConfig() *Config { return c } -func TestContext() *Context { - if testContext == nil { - testContext = NewTestContext() +func TestConfig() *Config { + if testConfig == nil { + testConfig = NewTestConfig() } - return testContext + return testConfig } -func NewTestContext() *Context { +func NewTestConfig() *Config { log.SetLevel(log.DebugLevel) - c := &Context{config: NewTestConfig()} + c := &Config{config: NewTestParams()} c.MigrateDb() return c } -// Returns example cli context for testing +// Returns example cli config for testing func CliTestContext() *cli.Context { - config := NewTestConfig() + config := NewTestParams() globalSet := flag.NewFlagSet("test", 0) globalSet.Bool("debug", false, "doc") @@ -86,16 +86,16 @@ func CliTestContext() *cli.Context { return c } -func (c *Context) RemoveTestData(t *testing.T) { +func (c *Config) RemoveTestData(t *testing.T) { os.RemoveAll(c.ImportPath()) os.RemoveAll(c.ExportPath()) os.RemoveAll(c.OriginalsPath()) os.RemoveAll(c.CachePath()) } -func (c *Context) DownloadTestData(t *testing.T) { - if fsutil.Exists(TestDataZip) { - hash := fsutil.Hash(TestDataZip) +func (c *Config) DownloadTestData(t *testing.T) { + if util.Exists(TestDataZip) { + hash := util.Hash(TestDataZip) if hash != TestDataHash { os.Remove(TestDataZip) @@ -103,22 +103,22 @@ func (c *Context) DownloadTestData(t *testing.T) { } } - if !fsutil.Exists(TestDataZip) { + if !util.Exists(TestDataZip) { fmt.Printf("downloading latest test data zip file from %s\n", TestDataURL) - if err := fsutil.Download(TestDataZip, TestDataURL); err != nil { + if err := util.Download(TestDataZip, TestDataURL); err != nil { fmt.Printf("Download failed: %s\n", err.Error()) } } } -func (c *Context) UnzipTestData(t *testing.T) { - if _, err := fsutil.Unzip(TestDataZip, testDataPath(c.AssetsPath())); err != nil { +func (c *Config) UnzipTestData(t *testing.T) { + if _, err := util.Unzip(TestDataZip, testDataPath(c.AssetsPath())); err != nil { t.Logf("could not unzip test data: %s\n", err.Error()) } } -func (c *Context) InitializeTestData(t *testing.T) { +func (c *Config) InitializeTestData(t *testing.T) { t.Log("initializing test data") c.RemoveTestData(t) diff --git a/internal/context/test_context_test.go b/internal/config/test_test.go similarity index 52% rename from internal/context/test_context_test.go rename to internal/config/test_test.go index 6d41d8aa7..d3c21fbaf 100644 --- a/internal/context/test_context_test.go +++ b/internal/config/test_test.go @@ -1,10 +1,10 @@ -package context +package config import ( "testing" "github.com/jinzhu/gorm" - "github.com/photoprism/photoprism/internal/fsutil" + "github.com/photoprism/photoprism/internal/util" "github.com/stretchr/testify/assert" "github.com/urfave/cli" ) @@ -15,24 +15,24 @@ func TestTestCliContext(t *testing.T) { assert.IsType(t, new(cli.Context), result) } -func TestTestContext(t *testing.T) { - result := TestContext() +func TestTestConfig(t *testing.T) { + result := TestConfig() - assert.IsType(t, new(Context), result) + assert.IsType(t, new(Config), result) +} + +func TestNewTestParams(t *testing.T) { + c := NewTestParams() + + assert.IsType(t, new(Params), c) + + assert.Equal(t, util.ExpandedFilename("../../assets"), c.AssetsPath) + assert.False(t, c.Debug) } func TestNewTestConfig(t *testing.T) { c := NewTestConfig() - assert.IsType(t, new(Config), c) - - assert.Equal(t, fsutil.ExpandedFilename("../../assets"), c.AssetsPath) - assert.False(t, c.Debug) -} - -func TestNewTestContext_Db(t *testing.T) { - c := NewTestContext() - db := c.Db() assert.IsType(t, &gorm.DB{}, db) diff --git a/internal/context/testdata/config.yml b/internal/config/testdata/config.yml similarity index 100% rename from internal/context/testdata/config.yml rename to internal/config/testdata/config.yml diff --git a/internal/context/context_test.go b/internal/context/context_test.go deleted file mode 100644 index f6074770c..000000000 --- a/internal/context/context_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package context - -import ( - "testing" - - "github.com/photoprism/photoprism/internal/fsutil" - "github.com/stretchr/testify/assert" -) - -func TestNewContext(t *testing.T) { - ctx := CliTestContext() - - assert.True(t, ctx.IsSet("assets-path")) - assert.False(t, ctx.Bool("debug")) - - c := NewContext(ctx) - - assert.IsType(t, new(Context), c) - - assert.Equal(t, fsutil.ExpandedFilename("../../assets"), c.AssetsPath()) - assert.False(t, c.Debug()) - assert.False(t, c.ReadOnly()) -} diff --git a/internal/photoprism/colors_test.go b/internal/photoprism/colors_test.go index 811061b35..c98d7f2ad 100644 --- a/internal/photoprism/colors_test.go +++ b/internal/photoprism/colors_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/stretchr/testify/assert" ) @@ -80,7 +80,7 @@ func TestMediaFile_Colors_Testdata(t *testing.T) { } func TestMediaFile_Colors(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) diff --git a/internal/photoprism/converter_test.go b/internal/photoprism/converter_test.go index 2c044a94e..5785b898d 100644 --- a/internal/photoprism/converter_test.go +++ b/internal/photoprism/converter_test.go @@ -4,13 +4,13 @@ import ( "os" "testing" - "github.com/photoprism/photoprism/internal/context" - "github.com/photoprism/photoprism/internal/fsutil" + "github.com/photoprism/photoprism/internal/config" + "github.com/photoprism/photoprism/internal/util" "github.com/stretchr/testify/assert" ) func TestNewConverter(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() converter := NewConverter(ctx.DarktableCli()) @@ -22,7 +22,7 @@ func TestConverter_ConvertToJpeg(t *testing.T) { t.Skip("skipping test in short mode.") } - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -30,7 +30,7 @@ func TestConverter_ConvertToJpeg(t *testing.T) { jpegFilename := ctx.ImportPath() + "/iphone/IMG_6788.JPG" - assert.Truef(t, fsutil.Exists(jpegFilename), "file does not exist: %s", jpegFilename) + assert.Truef(t, util.Exists(jpegFilename), "file does not exist: %s", jpegFilename) t.Logf("Testing RAW to JPEG converter with %s", jpegFilename) @@ -62,7 +62,7 @@ func TestConverter_ConvertToJpeg(t *testing.T) { imageRaw, _ := converter.ConvertToJpeg(rawMediaFile) - assert.True(t, fsutil.Exists(ctx.ImportPath()+"/raw/IMG_1435.jpg"), "Jpeg file was not found - is Darktable installed?") + assert.True(t, util.Exists(ctx.ImportPath()+"/raw/IMG_1435.jpg"), "Jpeg file was not found - is Darktable installed?") assert.NotEqual(t, rawFilemame, imageRaw.filename) @@ -78,7 +78,7 @@ func TestConverter_ConvertAll(t *testing.T) { t.Skip("skipping test in short mode.") } - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -88,7 +88,7 @@ func TestConverter_ConvertAll(t *testing.T) { jpegFilename := ctx.ImportPath() + "/raw/IMG_1435.jpg" - assert.True(t, fsutil.Exists(jpegFilename), "Jpeg file was not found - is Darktable installed?") + assert.True(t, util.Exists(jpegFilename), "Jpeg file was not found - is Darktable installed?") image, err := NewMediaFile(jpegFilename) @@ -104,15 +104,15 @@ func TestConverter_ConvertAll(t *testing.T) { existingJpegFilename := ctx.ImportPath() + "/raw/20140717_154212_1EC48F8489.jpg" - oldHash := fsutil.Hash(existingJpegFilename) + oldHash := util.Hash(existingJpegFilename) os.Remove(existingJpegFilename) converter.ConvertAll(ctx.ImportPath()) - newHash := fsutil.Hash(existingJpegFilename) + newHash := util.Hash(existingJpegFilename) - assert.True(t, fsutil.Exists(existingJpegFilename), "Jpeg file was not found - is Darktable installed?") + assert.True(t, util.Exists(existingJpegFilename), "Jpeg file was not found - is Darktable installed?") assert.NotEqual(t, oldHash, newHash, "Fingerprint of old and new JPEG file must not be the same") } diff --git a/internal/photoprism/exif_test.go b/internal/photoprism/exif_test.go index baa4b75e0..fbf9aa8c2 100644 --- a/internal/photoprism/exif_test.go +++ b/internal/photoprism/exif_test.go @@ -3,12 +3,12 @@ package photoprism import ( "testing" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/stretchr/testify/assert" ) func TestMediaFile_ExifData(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -30,7 +30,7 @@ func TestMediaFile_ExifData_Slow(t *testing.T) { t.Skip("skipping test in short mode.") } - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) diff --git a/internal/photoprism/importer.go b/internal/photoprism/importer.go index 1b9114057..2a7a3e8cb 100644 --- a/internal/photoprism/importer.go +++ b/internal/photoprism/importer.go @@ -11,7 +11,7 @@ import ( log "github.com/sirupsen/logrus" - "github.com/photoprism/photoprism/internal/fsutil" + "github.com/photoprism/photoprism/internal/util" ) // Importer todo: Fill me. @@ -149,8 +149,8 @@ func (i *Importer) DestinationFilename(mainFile *MediaFile, mediaFile *MediaFile result := pathName + "/" + canonicalName + fileExtension - for fsutil.Exists(result) { - if mediaFile.Hash() == fsutil.Hash(result) { + for util.Exists(result) { + if mediaFile.Hash() == util.Hash(result) { return result, fmt.Errorf("file already exists: %s", result) } diff --git a/internal/photoprism/importer_test.go b/internal/photoprism/importer_test.go index 8be9dd37f..14f98415b 100644 --- a/internal/photoprism/importer_test.go +++ b/internal/photoprism/importer_test.go @@ -3,12 +3,12 @@ package photoprism import ( "testing" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/stretchr/testify/assert" ) func TestNewImporter(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() tensorFlow := NewTensorFlow(ctx.TensorFlowModelPath()) @@ -22,7 +22,7 @@ func TestNewImporter(t *testing.T) { } func TestImporter_DestinationFilename(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -50,7 +50,7 @@ func TestImporter_ImportPhotosFromDirectory(t *testing.T) { t.Skip("skipping test in short mode.") } - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) diff --git a/internal/photoprism/indexer.go b/internal/photoprism/indexer.go index fdfe19588..7295c858d 100644 --- a/internal/photoprism/indexer.go +++ b/internal/photoprism/indexer.go @@ -150,7 +150,7 @@ func (i *Indexer) indexMediaFile(mediaFile *MediaFile) string { photo.PhotoTitle = fmt.Sprintf("%s / %s", strings.Title(photo.Tags[0].TagLabel), mediaFile.DateCreated().Format("2006")) } else if photo.Country != nil && photo.Country.CountryName != "" { photo.PhotoTitle = fmt.Sprintf("%s / %s", strings.Title(photo.Country.CountryName), mediaFile.DateCreated().Format("2006")) - } else if photo.Camera.String() != "" && photo.Camera.String() != "Unknown" { + } else if photo.Camera.String() != "" && photo.Camera.String() != "Unknown" { photo.PhotoTitle = fmt.Sprintf("%s / %s", photo.Camera, mediaFile.DateCreated().Format("January 2006")) } else { var daytimeString string diff --git a/internal/photoprism/mediafile.go b/internal/photoprism/mediafile.go index b1c677029..088cfa97f 100644 --- a/internal/photoprism/mediafile.go +++ b/internal/photoprism/mediafile.go @@ -18,8 +18,8 @@ import ( log "github.com/sirupsen/logrus" "github.com/djherbis/times" - "github.com/photoprism/photoprism/internal/fsutil" "github.com/photoprism/photoprism/internal/models" + "github.com/photoprism/photoprism/internal/util" ) const ( @@ -119,7 +119,7 @@ type MediaFile struct { // NewMediaFile returns a new MediaFile. func NewMediaFile(filename string) (*MediaFile, error) { - if !fsutil.Exists(filename) { + if !util.Exists(filename) { return nil, fmt.Errorf("file does not exist: %s", filename) } @@ -279,7 +279,7 @@ func (m *MediaFile) CanonicalNameFromFileWithDirectory() string { // Hash return a sha1 hash of a mediafile based on the filename. func (m *MediaFile) Hash() string { if len(m.hash) == 0 { - m.hash = fsutil.Hash(m.Filename()) + m.hash = util.Hash(m.Filename()) } return m.hash @@ -306,7 +306,7 @@ func (m *MediaFile) RelatedFiles() (result MediaFiles, mainFile *MediaFile, err return result, nil, err } - if editedFilename := m.EditedFilename(); editedFilename != "" && fsutil.Exists(editedFilename) { + if editedFilename := m.EditedFilename(); editedFilename != "" && util.Exists(editedFilename) { matches = append(matches, editedFilename) } @@ -406,7 +406,7 @@ func (m *MediaFile) openFile() (*os.File, error) { // Exists checks if a mediafile exists by filename. func (m *MediaFile) Exists() bool { - return fsutil.Exists(m.Filename()) + return util.Exists(m.Filename()) } // Remove a mediafile. @@ -514,7 +514,7 @@ func (m *MediaFile) Jpeg() (*MediaFile, error) { jpegFilename := m.CanonicalNameFromFileWithDirectory() + ".jpg" - if !fsutil.Exists(jpegFilename) { + if !util.Exists(jpegFilename) { return nil, fmt.Errorf("jpeg file does not exist: %s", jpegFilename) } diff --git a/internal/photoprism/mediafile_test.go b/internal/photoprism/mediafile_test.go index 600ee767b..6859cc570 100644 --- a/internal/photoprism/mediafile_test.go +++ b/internal/photoprism/mediafile_test.go @@ -3,12 +3,12 @@ package photoprism import ( "testing" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/stretchr/testify/assert" ) func TestMediaFile_RelatedFiles(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -38,7 +38,7 @@ func TestMediaFile_RelatedFiles(t *testing.T) { } func TestMediaFile_RelatedFiles_Ordering(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -59,7 +59,7 @@ func TestMediaFile_RelatedFiles_Ordering(t *testing.T) { } func TestMediaFile_EditedFilename(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -79,7 +79,7 @@ func TestMediaFile_EditedFilename(t *testing.T) { } func TestMediaFile_MimeType(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -93,7 +93,7 @@ func TestMediaFile_MimeType(t *testing.T) { } func TestMediaFile_Exists(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() mediaFile, err := NewMediaFile(ctx.ImportPath() + "/iphone/IMG_6788.JPG") assert.Nil(t, err) diff --git a/internal/photoprism/search_test.go b/internal/photoprism/search_test.go index a0764cf3d..31ac6f058 100644 --- a/internal/photoprism/search_test.go +++ b/internal/photoprism/search_test.go @@ -3,12 +3,12 @@ package photoprism import ( "testing" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/forms" ) func TestSearch_Photos_Query(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.CreateDirectories() @@ -41,7 +41,7 @@ func TestSearch_Photos_Query(t *testing.T) { } func TestSearch_Photos_Camera(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.CreateDirectories() diff --git a/internal/photoprism/tensorflow.go b/internal/photoprism/tensorflow.go index 685cb6bae..1dc7d5917 100644 --- a/internal/photoprism/tensorflow.go +++ b/internal/photoprism/tensorflow.go @@ -147,7 +147,9 @@ func (t *TensorFlow) findBestLabels(probabilities []float32) []TensorFlowLabel { break } - if p < 0.08 { continue } + if p < 0.08 { + continue + } result = append(result, TensorFlowLabel{Label: t.labels[i], Probability: p}) } diff --git a/internal/photoprism/tensorflow_test.go b/internal/photoprism/tensorflow_test.go index 8c3d74aa8..e92f9d017 100644 --- a/internal/photoprism/tensorflow_test.go +++ b/internal/photoprism/tensorflow_test.go @@ -4,12 +4,12 @@ import ( "io/ioutil" "testing" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/stretchr/testify/assert" ) func TestTensorFlow_GetImageTagsFromFile(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -42,7 +42,7 @@ func TestTensorFlow_GetImageTags(t *testing.T) { t.Skip("skipping test in short mode.") } - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) @@ -74,7 +74,7 @@ func TestTensorFlow_GetImageTags_Dog(t *testing.T) { t.Skip("skipping test in short mode.") } - ctx := context.TestContext() + ctx := config.TestConfig() ctx.InitializeTestData(t) diff --git a/internal/photoprism/thumbnails.go b/internal/photoprism/thumbnails.go index 739045dbc..f2a8fe95a 100644 --- a/internal/photoprism/thumbnails.go +++ b/internal/photoprism/thumbnails.go @@ -9,7 +9,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/disintegration/imaging" - "github.com/photoprism/photoprism/internal/fsutil" + "github.com/photoprism/photoprism/internal/util" ) // CreateThumbnailsFromOriginals create thumbnails. @@ -58,7 +58,7 @@ func (m *MediaFile) Thumbnail(path string, size int) (result *MediaFile, err err thumbnailFilename := fmt.Sprintf("%s/%s_%dpx.jpg", thumbnailPath, canonicalName, size) - if fsutil.Exists(thumbnailFilename) { + if util.Exists(thumbnailFilename) { return NewMediaFile(thumbnailFilename) } @@ -97,7 +97,7 @@ func (m *MediaFile) SquareThumbnail(path string, size int) (result *MediaFile, e thumbnailFilename := fmt.Sprintf("%s/%s_square_%dpx.jpg", thumbnailPath, canonicalName, size) - if fsutil.Exists(thumbnailFilename) { + if util.Exists(thumbnailFilename) { return NewMediaFile(thumbnailFilename) } diff --git a/internal/photoprism/thumbnails_test.go b/internal/photoprism/thumbnails_test.go index 6dbddec70..3938f2fcb 100644 --- a/internal/photoprism/thumbnails_test.go +++ b/internal/photoprism/thumbnails_test.go @@ -3,12 +3,12 @@ package photoprism import ( "testing" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" "github.com/stretchr/testify/assert" ) func TestMediaFile_Thumbnail(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.CreateDirectories() @@ -25,7 +25,7 @@ func TestMediaFile_Thumbnail(t *testing.T) { } func TestMediaFile_SquareThumbnail(t *testing.T) { - ctx := context.TestContext() + ctx := config.TestConfig() ctx.CreateDirectories() @@ -46,7 +46,7 @@ func TestCreateThumbnailsFromOriginals(t *testing.T) { t.Skip("skipping test in short mode.") } - ctx := context.TestContext() + ctx := config.TestConfig() ctx.CreateDirectories() diff --git a/internal/server/routes.go b/internal/server/routes.go index e41c42c4f..37e550b1a 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -5,27 +5,27 @@ import ( "github.com/gin-gonic/gin" "github.com/photoprism/photoprism/internal/api" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" ) -func registerRoutes(router *gin.Engine, ctx *context.Context) { +func registerRoutes(router *gin.Engine, conf *config.Config) { // Favicon - router.StaticFile("/favicon.ico", ctx.HttpFaviconsPath()+"/favicon.ico") + router.StaticFile("/favicon.ico", conf.HttpFaviconsPath()+"/favicon.ico") // Static assets like js and css files - router.Static("/assets", ctx.HttpPublicPath()) + router.Static("/assets", conf.HttpPublicPath()) // JSON-REST API Version 1 v1 := router.Group("/api/v1") { - api.GetPhotos(v1, ctx) - api.GetThumbnail(v1, ctx) - api.LikePhoto(v1, ctx) - api.DislikePhoto(v1, ctx) + api.GetPhotos(v1, conf) + api.GetThumbnail(v1, conf) + api.LikePhoto(v1, conf) + api.DislikePhoto(v1, conf) } // Default HTML page (client-side routing implemented via Vue.js) router.NoRoute(func(c *gin.Context) { - c.HTML(http.StatusOK, "index.tmpl", ctx.ClientConfig()) + c.HTML(http.StatusOK, "index.tmpl", conf.ClientConfig()) }) } diff --git a/internal/server/server.go b/internal/server/server.go index 23cb6f54b..080f062df 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -9,15 +9,15 @@ import ( "time" "github.com/gin-gonic/gin" - "github.com/photoprism/photoprism/internal/context" + "github.com/photoprism/photoprism/internal/config" log "github.com/sirupsen/logrus" ) // Start the REST API server using the configuration provided -func Start(ctx *context.Context) { - if ctx.HttpServerMode() != "" { - gin.SetMode(ctx.HttpServerMode()) - } else if ctx.Debug() == false { +func Start(conf *config.Config) { + if conf.HttpServerMode() != "" { + gin.SetMode(conf.HttpServerMode()) + } else if conf.Debug() == false { gin.SetMode(gin.ReleaseMode) } @@ -25,19 +25,19 @@ func Start(ctx *context.Context) { router.Use(gin.Logger(), gin.Recovery()) // Set template directory - router.LoadHTMLGlob(ctx.HttpTemplatesPath() + "/*") + router.LoadHTMLGlob(conf.HttpTemplatesPath() + "/*") - registerRoutes(router, ctx) + registerRoutes(router, conf) server := &http.Server{ - Addr: fmt.Sprintf("%s:%d", ctx.HttpServerHost(), ctx.HttpServerPort()), + Addr: fmt.Sprintf("%s:%d", conf.HttpServerHost(), conf.HttpServerPort()), Handler: router, } quit := make(chan os.Signal) /* - TODO: Use context for graceful shutdown of all services and add HTTP / TiDB server tests + TODO: Use config for graceful shutdown of all services and add HTTP / TiDB server tests See - https://github.com/gin-gonic/gin/blob/dfe37ea6f1b9127be4cff4822a1308b4349444e0/examples/graceful-shutdown/graceful-shutdown/server.go @@ -50,7 +50,7 @@ func Start(ctx *context.Context) { <-quit log.Info("received interrupt signal - shutting down") - ctx.Shutdown() + conf.Shutdown() if err := server.Close(); err != nil { log.Errorf("server close: %s", err) diff --git a/internal/tidb/server.go b/internal/tidb/server.go index 64f8b8542..c442ff602 100644 --- a/internal/tidb/server.go +++ b/internal/tidb/server.go @@ -106,7 +106,7 @@ func Start(path string, port uint, host string, debug bool) { createServer() /* - TODO: Use context for graceful shutdown of all services and add HTTP / TiDB server tests + TODO: Use config for graceful shutdown of all services and add HTTP / TiDB server tests See - https://github.com/gin-gonic/gin/blob/dfe37ea6f1b9127be4cff4822a1308b4349444e0/examples/graceful-shutdown/graceful-shutdown/server.go diff --git a/internal/context/capture.go b/internal/util/capture.go similarity index 96% rename from internal/context/capture.go rename to internal/util/capture.go index 64947f1ec..57b9cef84 100644 --- a/internal/context/capture.go +++ b/internal/util/capture.go @@ -1,4 +1,4 @@ -package context +package util import ( "bytes" diff --git a/internal/context/capture_test.go b/internal/util/capture_test.go similarity index 94% rename from internal/context/capture_test.go rename to internal/util/capture_test.go index b646a4fbd..4cd167959 100644 --- a/internal/context/capture_test.go +++ b/internal/util/capture_test.go @@ -1,4 +1,4 @@ -package context +package util import ( "fmt" diff --git a/internal/fsutil/doc.go b/internal/util/doc.go similarity index 59% rename from internal/fsutil/doc.go rename to internal/util/doc.go index fb8ac43be..65673360e 100644 --- a/internal/fsutil/doc.go +++ b/internal/util/doc.go @@ -1,8 +1,8 @@ /* -Package context contains filesystem related utility functions. +Package config contains filesystem related utility functions. Additional information can be found in our Developer Guide: https://github.com/photoprism/photoprism/wiki */ -package fsutil +package util diff --git a/internal/fsutil/file.go b/internal/util/file.go similarity index 99% rename from internal/fsutil/file.go rename to internal/util/file.go index 688837629..c1db36f34 100644 --- a/internal/fsutil/file.go +++ b/internal/util/file.go @@ -1,4 +1,4 @@ -package fsutil +package util import ( "archive/zip" diff --git a/internal/fsutil/file_test.go b/internal/util/file_test.go similarity index 95% rename from internal/fsutil/file_test.go rename to internal/util/file_test.go index f1fde3b4e..1cdc75f55 100644 --- a/internal/fsutil/file_test.go +++ b/internal/util/file_test.go @@ -1,4 +1,4 @@ -package fsutil +package util import ( "testing" diff --git a/internal/fsutil/hash.go b/internal/util/hash.go similarity index 96% rename from internal/fsutil/hash.go rename to internal/util/hash.go index 9864ad840..64d061ffc 100644 --- a/internal/fsutil/hash.go +++ b/internal/util/hash.go @@ -1,4 +1,4 @@ -package fsutil +package util import ( "crypto/sha1" diff --git a/internal/fsutil/hash_test.go b/internal/util/hash_test.go similarity index 92% rename from internal/fsutil/hash_test.go rename to internal/util/hash_test.go index 5cc63bd62..ec4ccefcc 100644 --- a/internal/fsutil/hash_test.go +++ b/internal/util/hash_test.go @@ -1,4 +1,4 @@ -package fsutil +package util import ( "testing" diff --git a/internal/fsutil/testdata/test.jpg b/internal/util/testdata/test.jpg similarity index 100% rename from internal/fsutil/testdata/test.jpg rename to internal/util/testdata/test.jpg