Add portable mode

This commit is contained in:
Radhi Fadlillah 2019-08-09 10:19:43 +07:00
parent 20e89216f0
commit ad502c6749
13 changed files with 106 additions and 86 deletions

View file

@ -63,7 +63,7 @@ func addHandler(cmd *cobra.Command, args []string) {
}
// Create bookmark ID
book.ID, err = DB.CreateNewID("bookmark")
book.ID, err = db.CreateNewID("bookmark")
if err != nil {
cError.Printf("Failed to create ID: %v\n", err)
return
@ -150,7 +150,7 @@ func addHandler(cmd *cobra.Command, args []string) {
// If needed, create offline archive as well
if !noArchival {
archivePath := fp.Join(DataDir, "archive", fmt.Sprintf("%d", book.ID))
archivePath := fp.Join(dataDir, "archive", fmt.Sprintf("%d", book.ID))
archivalRequest := warc.ArchivalRequest{
URL: url,
Reader: archivalInput,
@ -173,14 +173,14 @@ func addHandler(cmd *cobra.Command, args []string) {
}
// Save bookmark to database
_, err = DB.SaveBookmarks(book)
_, err = db.SaveBookmarks(book)
if err != nil {
cError.Printf("Failed to save bookmark: %v\n", err)
return
}
// Save article image to local disk
imgPath := fp.Join(DataDir, "thumb", fmt.Sprintf("%d", book.ID))
imgPath := fp.Join(dataDir, "thumb", fmt.Sprintf("%d", book.ID))
for _, imageURL := range imageURLs {
err = downloadBookImage(imageURL, imgPath, time.Minute)
if err == nil {

View file

@ -52,7 +52,7 @@ func deleteHandler(cmd *cobra.Command, args []string) {
}
// Delete bookmarks from database
err = DB.DeleteBookmarks(ids...)
err = db.DeleteBookmarks(ids...)
if err != nil {
cError.Printf("Failed to delete bookmarks: %v\n", err)
return
@ -60,15 +60,15 @@ func deleteHandler(cmd *cobra.Command, args []string) {
// Delete thumbnail image and archives from local disk
if len(ids) == 0 {
thumbDir := fp.Join(DataDir, "thumb")
archiveDir := fp.Join(DataDir, "archive")
thumbDir := fp.Join(dataDir, "thumb")
archiveDir := fp.Join(dataDir, "archive")
os.RemoveAll(thumbDir)
os.RemoveAll(archiveDir)
} else {
for _, id := range ids {
strID := strconv.Itoa(id)
imgPath := fp.Join(DataDir, "thumb", strID)
archivePath := fp.Join(DataDir, "archive", strID)
imgPath := fp.Join(dataDir, "thumb", strID)
archivePath := fp.Join(dataDir, "archive", strID)
os.Remove(imgPath)
os.Remove(archivePath)

View file

@ -25,7 +25,7 @@ func exportCmd() *cobra.Command {
func exportHandler(cmd *cobra.Command, args []string) {
// Fetch bookmarks from database
bookmarks, err := DB.GetBookmarks(database.GetBookmarksOptions{})
bookmarks, err := db.GetBookmarks(database.GetBookmarksOptions{})
if err != nil {
cError.Printf("Failed to get bookmarks: %v\n", err)
return

View file

@ -40,7 +40,7 @@ func importHandler(cmd *cobra.Command, args []string) {
}
// Prepare bookmark's ID
bookID, err := DB.CreateNewID("bookmark")
bookID, err := db.CreateNewID("bookmark")
if err != nil {
cError.Printf("Failed to create ID: %v\n", err)
return
@ -96,7 +96,7 @@ func importHandler(cmd *cobra.Command, args []string) {
return
}
if _, exist := DB.GetBookmark(0, url); exist {
if _, exist := db.GetBookmark(0, url); exist {
cError.Printf("Skip %s: URL already exists\n", url)
mapURL[url] = struct{}{}
return
@ -133,7 +133,7 @@ func importHandler(cmd *cobra.Command, args []string) {
})
// Save bookmark to database
bookmarks, err = DB.SaveBookmarks(bookmarks...)
bookmarks, err = db.SaveBookmarks(bookmarks...)
if err != nil {
cError.Printf("Failed to save bookmarks: %v\n", err)
return

View file

@ -72,7 +72,7 @@ func openHandler(cmd *cobra.Command, args []string) {
WithContent: true,
}
bookmarks, err := DB.GetBookmarks(getOptions)
bookmarks, err := db.GetBookmarks(getOptions)
if err != nil {
cError.Printf("Failed to get bookmarks: %v\n", err)
return
@ -123,7 +123,7 @@ func openHandler(cmd *cobra.Command, args []string) {
// Open archive
id := strconv.Itoa(bookmarks[0].ID)
archivePath := fp.Join(DataDir, "archive", id)
archivePath := fp.Join(dataDir, "archive", id)
archive, err := warc.Open(archivePath)
if err != nil {

View file

@ -26,7 +26,7 @@ func pocketCmd() *cobra.Command {
func pocketHandler(cmd *cobra.Command, args []string) {
// Prepare bookmark's ID
bookID, err := DB.CreateNewID("bookmark")
bookID, err := db.CreateNewID("bookmark")
if err != nil {
cError.Printf("Failed to create ID: %v\n", err)
return
@ -77,7 +77,7 @@ func pocketHandler(cmd *cobra.Command, args []string) {
return
}
if _, exist := DB.GetBookmark(0, url); exist {
if _, exist := db.GetBookmark(0, url); exist {
cError.Printf("Skip %s: URL already exists\n", url)
mapURL[url] = struct{}{}
return
@ -106,7 +106,7 @@ func pocketHandler(cmd *cobra.Command, args []string) {
})
// Save bookmark to database
bookmarks, err = DB.SaveBookmarks(bookmarks...)
bookmarks, err = db.SaveBookmarks(bookmarks...)
if err != nil {
cError.Printf("Failed to save bookmarks: %v\n", err)
return

View file

@ -12,7 +12,7 @@ func printCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "print [indices]",
Short: "Print the saved bookmarks",
Long: "Show the saved bookmarks by its DB index. " +
Long: "Show the saved bookmarks by its database index. " +
"Accepts space-separated list of indices (e.g. 5 6 23 4 110 45), " +
"hyphenated range (e.g. 100-200) or both (e.g. 1-3 7 9). " +
"If no arguments, all records with actual index from database are shown.",
@ -57,7 +57,7 @@ func printHandler(cmd *cobra.Command, args []string) {
OrderMethod: orderMethod,
}
bookmarks, err := DB.GetBookmarks(searchOptions)
bookmarks, err := db.GetBookmarks(searchOptions)
if err != nil {
cError.Printf("Failed to get bookmarks: %v\n", err)
return

7
internal/cmd/root-dev.go Normal file
View file

@ -0,0 +1,7 @@
// +build dev
package cmd
func init() {
developmentMode = true
}

View file

@ -4,20 +4,20 @@ import (
"crypto/tls"
"net/http"
"net/http/cookiejar"
"os"
fp "path/filepath"
"time"
"github.com/go-shiori/shiori/internal/database"
apppaths "github.com/muesli/go-app-paths"
"github.com/spf13/cobra"
)
var (
// DB is database that used by cmd
DB database.DB
// DataDir is directory for downloaded data
DataDir string
httpClient *http.Client
db database.DB
dataDir string
httpClient *http.Client
developmentMode bool
)
func init() {
@ -40,6 +40,8 @@ func ShioriCmd() *cobra.Command {
Short: "Simple command-line bookmark manager built with Go",
}
rootCmd.PersistentPreRun = preRunRootHandler
rootCmd.PersistentFlags().Bool("portable", false, "run shiori in portable mode")
rootCmd.AddCommand(
addCmd(),
printCmd(),
@ -54,3 +56,63 @@ func ShioriCmd() *cobra.Command {
return rootCmd
}
func preRunRootHandler(cmd *cobra.Command, args []string) {
// Read flag
var err error
portableMode, _ := cmd.Flags().GetBool("portable")
// Get and create data dir
dataDir, err = getDataDir(portableMode)
if err != nil {
cError.Printf("Failed to get data dir: %v\n", err)
os.Exit(1)
}
err = os.MkdirAll(dataDir, os.ModePerm)
if err != nil {
cError.Printf("Failed to create data dir: %v\n", err)
os.Exit(1)
}
// Open database
dbPath := fp.Join(dataDir, "shiori.db")
db, err = database.OpenSQLiteDatabase(dbPath)
if err != nil {
cError.Printf("Failed to open database: %v\n", err)
os.Exit(1)
}
}
func getDataDir(portableMode bool) (string, error) {
// If in portable mode, uses directory of executable
if portableMode {
exePath, err := os.Executable()
if err != nil {
return "", err
}
exeDir := fp.Dir(exePath)
return fp.Join(exeDir, "shiori-data"), nil
}
if developmentMode {
return "dev-data", nil
}
// Try to look at environment variables
dataDir, found := os.LookupEnv("SHIORI_DIR")
if found {
return dataDir, nil
}
// Try to use platform specific app path
userScope := apppaths.NewScope(apppaths.User, "shiori", "shiori")
dataDir, err := userScope.DataDir()
if err == nil {
return dataDir, nil
}
// When all fail, use current working directory
return ".", nil
}

View file

@ -24,7 +24,7 @@ func serveCmd() *cobra.Command {
func serveHandler(cmd *cobra.Command, args []string) {
port, _ := cmd.Flags().GetInt("port")
err := webserver.ServeApp(DB, DataDir, port)
err := webserver.ServeApp(db, dataDir, port)
if err != nil {
logrus.Fatalf("Server error: %v\n", err)
}

View file

@ -28,7 +28,7 @@ func updateCmd() *cobra.Command {
"Accepts space-separated list of indices (e.g. 5 6 23 4 110 45), " +
"hyphenated range (e.g. 100-200) or both (e.g. 1-3 7 9). " +
"If no arguments, ALL bookmarks will be updated. Update works differently depending on the flags:\n" +
"- If indices are passed without any flags (--url, --title, --tag and --excerpt), read the URLs from DB and update titles from web.\n" +
"- If indices are passed without any flags (--url, --title, --tag and --excerpt), read the URLs from database and update titles from web.\n" +
"- If --url is passed (and --title is omitted), update the title from web using the URL. While using this flag, update only accept EXACTLY one index.\n" +
"While updating bookmark's tags, you can use - to remove tag (e.g. -nature to remove nature tag from this bookmark).",
Run: updateHandler,
@ -106,7 +106,7 @@ func updateHandler(cmd *cobra.Command, args []string) {
IDs: ids,
}
bookmarks, err := DB.GetBookmarks(filterOptions)
bookmarks, err := db.GetBookmarks(filterOptions)
if err != nil {
cError.Printf("Failed to get bookmarks: %v\n", err)
return
@ -230,7 +230,7 @@ func updateHandler(cmd *cobra.Command, args []string) {
imageURLs = append(imageURLs, article.Favicon)
}
imgPath := fp.Join(DataDir, "thumb", fmt.Sprintf("%d", book.ID))
imgPath := fp.Join(dataDir, "thumb", fmt.Sprintf("%d", book.ID))
for _, imageURL := range imageURLs {
err = downloadBookImage(imageURL, imgPath, time.Minute)
if err == nil {
@ -242,7 +242,7 @@ func updateHandler(cmd *cobra.Command, args []string) {
// If needed, update offline archive as well.
// Make sure to delete the old one first.
if !noArchival {
archivePath := fp.Join(DataDir, "archive", fmt.Sprintf("%d", book.ID))
archivePath := fp.Join(dataDir, "archive", fmt.Sprintf("%d", book.ID))
os.Remove(archivePath)
archivalRequest := warc.ArchivalRequest{
@ -360,7 +360,7 @@ func updateHandler(cmd *cobra.Command, args []string) {
}
// Save bookmarks to database
bookmarks, err = DB.SaveBookmarks(bookmarks...)
bookmarks, err = db.SaveBookmarks(bookmarks...)
if err != nil {
cError.Printf("Failed to save bookmark: %v\n", err)
return

22
main.go
View file

@ -3,14 +3,12 @@
package main
import (
"os"
fp "path/filepath"
"github.com/go-shiori/shiori/internal/cmd"
"github.com/go-shiori/shiori/internal/database"
_ "github.com/mattn/go-sqlite3"
"github.com/sirupsen/logrus"
// Database driver
_ "github.com/mattn/go-sqlite3"
// Add this to prevent it removed by go mod tidy
_ "github.com/shurcooL/vfsgen"
)
@ -18,20 +16,8 @@ import (
var dataDir = "dev-data"
func main() {
// Make sure data dir exists
os.MkdirAll(dataDir, os.ModePerm)
// Open database
dbPath := fp.Join(dataDir, "shiori.db")
sqliteDB, err := database.OpenSQLiteDatabase(dbPath)
err := cmd.ShioriCmd().Execute()
if err != nil {
logrus.Fatalln(err)
}
// Execute cmd
cmd.DB = sqliteDB
cmd.DataDir = dataDir
if err := cmd.ShioriCmd().Execute(); err != nil {
logrus.Fatalln(err)
}
}

View file

@ -1,35 +0,0 @@
// +build !dev
package main
import (
"os"
apppaths "github.com/muesli/go-app-paths"
)
func init() {
// Get data directory
dataDir = getDataDirectory()
// Make sure directory exist
os.MkdirAll(dataDir, os.ModePerm)
}
func getDataDirectory() string {
// Try to look at environment variables
dataDir, found := os.LookupEnv("SHIORI_DIR")
if found {
return dataDir
}
// Try to use platform specific app path
userScope := apppaths.NewScope(apppaths.User, "shiori", "shiori")
dataDir, err := userScope.DataDir()
if err == nil {
return dataDir
}
// When all fail, use current working directory
return "."
}