From 3a7d70c9083a99307ffcff67643a2cef72ffdd7b Mon Sep 17 00:00:00 2001
From: Deluan <deluan@thoughtworks.com>
Date: Thu, 2 Jul 2020 20:08:41 -0400
Subject: [PATCH] Add `scan` command

---
 cmd/root.go           | 17 +++++++++++++----
 cmd/scan.go           | 36 ++++++++++++++++++++++++++++++++++++
 cmd/wire_gen.go       |  6 ++++++
 cmd/wire_injectors.go |  6 ++++++
 4 files changed, 61 insertions(+), 4 deletions(-)
 create mode 100644 cmd/scan.go

diff --git a/cmd/root.go b/cmd/root.go
index 977cf7068..ace6100d7 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -12,13 +12,17 @@ import (
 )
 
 var (
-	cfgFile string
+	cfgFile  string
+	noBanner bool
 
 	rootCmd = &cobra.Command{
 		Use:   "navidrome",
 		Short: "Navidrome is a self-hosted music server and streamer",
 		Long: `Navidrome is a self-hosted music server and streamer.
 Complete documentation is available at https://www.navidrome.org/docs`,
+		PersistentPreRun: func(cmd *cobra.Command, args []string) {
+			preRun()
+		},
 		Run: func(cmd *cobra.Command, args []string) {
 			startServer()
 		},
@@ -34,10 +38,14 @@ func Execute() {
 	}
 }
 
-func startServer() {
-	println(consts.Banner())
-
+func preRun() {
+	if !noBanner {
+		println(consts.Banner())
+	}
 	conf.Load()
+}
+
+func startServer() {
 	db.EnsureLatestVersion()
 
 	subsonic, err := CreateSubsonicAPIRouter()
@@ -57,6 +65,7 @@ func init() {
 	})
 
 	rootCmd.PersistentFlags().StringVarP(&cfgFile, "configfile", "c", "", `config file (default "./navidrome.toml")`)
+	rootCmd.PersistentFlags().BoolVarP(&noBanner, "nobanner", "n", false, `don't show banner`)
 	rootCmd.PersistentFlags().String("musicfolder", viper.GetString("musicfolder"), "folder where your music is stored")
 	rootCmd.PersistentFlags().String("datafolder", viper.GetString("datafolder"), "folder to store application data (DB, cache...), needs write access")
 	rootCmd.PersistentFlags().StringP("loglevel", "l", viper.GetString("loglevel"), "log level, possible values: error, info, debug, trace")
diff --git a/cmd/scan.go b/cmd/scan.go
new file mode 100644
index 000000000..034ea333e
--- /dev/null
+++ b/cmd/scan.go
@@ -0,0 +1,36 @@
+package cmd
+
+import (
+	"github.com/deluan/navidrome/conf"
+	"github.com/deluan/navidrome/log"
+	"github.com/spf13/cobra"
+)
+
+var fullRescan bool
+
+func init() {
+	scanCmd.Flags().BoolVarP(&fullRescan, "full", "f", false, "check all subfolders, ignoring timestamps")
+	rootCmd.AddCommand(scanCmd)
+}
+
+var scanCmd = &cobra.Command{
+	Use:   "scan",
+	Short: "Scan music folder",
+	Long:  "Scan music folder for updates",
+	Run: func(cmd *cobra.Command, args []string) {
+		runScanner()
+	},
+}
+
+func runScanner() {
+	scanner := CreateScanner(conf.Server.MusicFolder)
+	err := scanner.RescanAll(fullRescan)
+	if err != nil {
+		log.Error("Error scanning media folder", "folder", conf.Server.MusicFolder, err)
+	}
+	if fullRescan {
+		log.Info("Finished full rescan")
+	} else {
+		log.Info("Finished rescan")
+	}
+}
diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go
index b66ab69ce..8348d09ad 100644
--- a/cmd/wire_gen.go
+++ b/cmd/wire_gen.go
@@ -25,6 +25,12 @@ func CreateServer(musicFolder string) *server.Server {
 	return serverServer
 }
 
+func CreateScanner(musicFolder string) *scanner.Scanner {
+	dataStore := persistence.New()
+	scannerScanner := scanner.New(dataStore)
+	return scannerScanner
+}
+
 func CreateAppRouter() *app.Router {
 	dataStore := persistence.New()
 	router := app.New(dataStore)
diff --git a/cmd/wire_injectors.go b/cmd/wire_injectors.go
index 8cd49f622..1c5499afd 100644
--- a/cmd/wire_injectors.go
+++ b/cmd/wire_injectors.go
@@ -27,6 +27,12 @@ func CreateServer(musicFolder string) *server.Server {
 	))
 }
 
+func CreateScanner(musicFolder string) *scanner.Scanner {
+	panic(wire.Build(
+		allProviders,
+	))
+}
+
 func CreateAppRouter() *app.Router {
 	panic(wire.Build(allProviders))
 }