build out cli and add size and gather functionality
This commit is contained in:
@ -1,31 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/urfave/cli/v2"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
commands := []*cli.Command{
|
||||
&cli.Command{
|
||||
Name: "start",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Start the application service",
|
||||
Action: func(c *cli.Context) error {
|
||||
//d := daemon.NewDaemon()
|
||||
//d.Start()
|
||||
return nil
|
||||
},
|
||||
},
|
||||
gather(),
|
||||
plan(),
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Name: "ForeverFiles",
|
||||
Name: "forever",
|
||||
Usage: "Create backups designed to last forever",
|
||||
Version: "v1.0.0",
|
||||
Description: "ForeverFiles is a system for storing files forever.",
|
||||
@ -37,7 +26,7 @@ func main() {
|
||||
Email: "mason@masonitestudios.com",
|
||||
},
|
||||
},
|
||||
Copyright: fmt.Sprintf("%v Masonite Studios LLC", time.Now().Year()),
|
||||
Copyright: "2024 Masonite Studios LLC",
|
||||
UseShortOptionHandling: true,
|
||||
}
|
||||
err := app.Run(os.Args)
|
||||
@ -46,16 +35,3 @@ func main() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func getConn(dialAddr string) (*grpc.ClientConn, error) {
|
||||
conn, err := grpc.DialContext(
|
||||
context.Background(),
|
||||
dialAddr,
|
||||
//grpc.WithBlock(),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
)
|
||||
if err != nil {
|
||||
return &grpc.ClientConn{}, fmt.Errorf("failed to dial server: %w", err)
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
12
cmd/cli/flags.go
Normal file
12
cmd/cli/flags.go
Normal file
@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
func baseDirFlag() *cli.StringFlag {
|
||||
return &cli.StringFlag{
|
||||
Name: "baseDir",
|
||||
Usage: "The base directory to gather info from",
|
||||
Aliases: []string{"b"},
|
||||
Value: ".",
|
||||
}
|
||||
}
|
69
cmd/cli/gather.go
Normal file
69
cmd/cli/gather.go
Normal file
@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dustin/go-humanize"
|
||||
|
||||
"forever-files/db"
|
||||
"forever-files/source"
|
||||
"forever-files/types"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func gather() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "gather",
|
||||
Aliases: []string{"g"},
|
||||
Usage: "Collects the files to be backed up and stores their info in the database",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "reset",
|
||||
Usage: "Reset the database before gathering info",
|
||||
Aliases: []string{"r"},
|
||||
Action: func(c *cli.Context, reset bool) error {
|
||||
if reset {
|
||||
err := db.DeleteDB(types.AppName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting db: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
baseDirFlag(),
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
|
||||
store, err := db.NewDB(types.AppName)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error creating db: %w", err))
|
||||
}
|
||||
defer store.Close()
|
||||
|
||||
err = store.Migrate()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error migrating db: %w", err))
|
||||
}
|
||||
|
||||
baseDir := c.String("baseDir")
|
||||
|
||||
err = source.GatherInfo(baseDir, store)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error gathering info: %w", err)
|
||||
}
|
||||
|
||||
fileCount, err := store.GetFileCount()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting file count: %w", err)
|
||||
}
|
||||
totalSize, err := store.GetTotalSize()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting total size: %w", err)
|
||||
}
|
||||
fmt.Printf("Total Files: %v\n", fileCount)
|
||||
fmt.Printf("Total Size: %v\n", humanize.Bytes(uint64(totalSize)))
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
107
cmd/cli/plan.go
Normal file
107
cmd/cli/plan.go
Normal file
@ -0,0 +1,107 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"forever-files/db"
|
||||
"forever-files/partitioner"
|
||||
"forever-files/types"
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/urfave/cli/v2"
|
||||
"math"
|
||||
)
|
||||
|
||||
func plan() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "plan",
|
||||
Aliases: []string{"p"},
|
||||
Usage: "Reads the database and plans the partitions for the backup, stores the partitions in the database",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "targetSize",
|
||||
Usage: "The target size for each partition, valid options are DVD-SL, DVD-DL, BD-SL, BD-DL, BD-TL, BD-QL\nor you can provide any specific size e.g. 4.6GB, 8.1GB, 25GB, 50GB, 100GB, 128GB or 5MB!",
|
||||
Aliases: []string{"s"},
|
||||
Value: "DVD-SL",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Usage: "Print the files in each partition",
|
||||
Aliases: []string{"v"},
|
||||
Value: false,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
|
||||
store, err := db.NewDB(types.AppName)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error creating db: %w", err))
|
||||
}
|
||||
defer store.Close()
|
||||
|
||||
err = store.Migrate()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error migrating db: %w", err))
|
||||
}
|
||||
|
||||
size := int64(4600000000) // size of a single layer DVD
|
||||
targetSize := c.String("targetSize")
|
||||
switch targetSize {
|
||||
case "DVD-SL":
|
||||
size = 4600000000
|
||||
case "DVD-DL":
|
||||
size = 8100000000
|
||||
case "BD-SL":
|
||||
size = 25000000000
|
||||
case "BD-DL":
|
||||
size = 50000000000
|
||||
case "BD-TL":
|
||||
size = 100000000000
|
||||
case "BD-QL":
|
||||
size = 128000000000
|
||||
default:
|
||||
// try to parse the size from human-readable format
|
||||
usize, err := humanize.ParseBytes(targetSize)
|
||||
if err != nil {
|
||||
fmt.Printf("invalid target size: %v\n", err)
|
||||
fmt.Println("valid options are DVD-SL, DVD-DL, BD-SL, BD-DL, BD-TL, BD-QL")
|
||||
fmt.Println("or you can provide any specific size e.g. 4.6GB, 8.1GB, 25GB, 50GB, 100GB, 128GB or 5MB!")
|
||||
size = 4600000000
|
||||
}
|
||||
if usize > math.MaxInt64 {
|
||||
fmt.Println("size is too large")
|
||||
size = 4600000000
|
||||
}
|
||||
size = int64(usize)
|
||||
}
|
||||
|
||||
fmt.Printf("Target Size: %v\n", humanize.Bytes(uint64(size)))
|
||||
fmt.Println("Calculating partitions...")
|
||||
|
||||
partitions, err := partitioner.CalculatePartitions(store, size)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error calculating partitions: %w", err)
|
||||
}
|
||||
|
||||
for i, partition := range partitions {
|
||||
partSize := int64(0)
|
||||
if c.Bool("verbose") {
|
||||
fmt.Printf("Partition %v:\n", i)
|
||||
}
|
||||
for _, file := range partition {
|
||||
if c.Bool("verbose") {
|
||||
fmt.Printf("%v/%v %v\n", file.Path, file.Name, humanize.Bytes(uint64(file.Size)))
|
||||
}
|
||||
partSize += file.Size
|
||||
// save the planned partitions
|
||||
file.PartitionId = fmt.Sprintf("%d", i)
|
||||
err = store.StoreFilePartition(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error storing file's partition: %w", err)
|
||||
}
|
||||
}
|
||||
fmt.Printf("Partition %v Size: %v files %v\n", i, len(partition), humanize.Bytes(uint64(partSize)))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user