diff --git a/README.md b/README.md index f1812cb6..255cd4f7 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,10 @@ Fleek is a user-friendly wrapper around Nix and Nix Home Manager, but the friend You need `nix`. We love the [Determinate Systems Installer](https://zero-to-nix.com/), but any `nix` is good. If you're on Fedora Silverblue [this script](https://github.com/dnkmmr69420/nix-with-selinux/blob/main/silverblue-installer.sh) is the good stuff. Next you'll need `fleek`. Download from the releases link. + + +## Shoulders + +Standing on the shoulders of giants: + +- [flake template](https://github.com/Misterio77/nix-starter-configs) \ No newline at end of file diff --git a/build.sh b/build.sh index 77cdd823..f819da26 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,3 @@ #!/bin/sh CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags '-w -extldflags "-static"' -rm -f fleek.1 -rm -f fleek.1.gz -./fleek man > fleek.1 -gzip fleek.1 + diff --git a/clean.sh b/clean.sh index 7989f5d6..b1e6159a 100755 --- a/clean.sh +++ b/clean.sh @@ -1,5 +1,5 @@ #!/bin/sh -rm ~/.fleek.yml +rm -f ~/.fleek.yml rm -rf ~/.config/home-manager rm -rf dist \ No newline at end of file diff --git a/cmd/add.go b/cmd/add.go index 7993f235..126ccb65 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -10,21 +10,21 @@ import ( func NewAddCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("add.use"), - fleek.Trans("add.long"), - fleek.Trans("add.short"), + app.Trans("add.use"), + app.Trans("add.long"), + app.Trans("add.short"), add, ).WithBoolFlag( cmdr.NewBoolFlag( "program", "p", - fleek.Trans("add.program"), + app.Trans("add.program"), false, )).WithBoolFlag( cmdr.NewBoolFlag( "apply", "a", - fleek.Trans("add.apply"), + app.Trans("add.apply"), false, )) cmd.Args = cobra.MinimumNArgs(1) @@ -43,25 +43,30 @@ func add(cmd *cobra.Command, args []string) { apply = true } if verbose { - cmdr.Info.Println(fleek.Trans("add.applying")) + cmdr.Info.Println(app.Trans("add.applying")) } var err error for _, p := range args { if cmd.Flag("program").Changed { - err = config.AddProgram(p) + err = f.config.AddProgram(p) cobra.CheckErr(err) } else { - err = config.AddPackage(p) + err = f.config.AddPackage(p) cobra.CheckErr(err) } - + repo, err := f.Repo() + cobra.CheckErr(err) + err = repo.Commit() + cobra.CheckErr(err) } if apply { + flake, err := f.Flake() + cobra.CheckErr(err) err = flake.Apply() cobra.CheckErr(err) } - cmdr.Info.Println(fleek.Trans("add.done")) + cmdr.Info.Println(app.Trans("add.done")) } diff --git a/cmd/apply.go b/cmd/apply.go index 840116e7..94e6dab2 100644 --- a/cmd/apply.go +++ b/cmd/apply.go @@ -10,21 +10,21 @@ import ( func NewApplyCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("apply.use"), - fleek.Trans("apply.long"), - fleek.Trans("apply.short"), + app.Trans("apply.use"), + app.Trans("apply.long"), + app.Trans("apply.short"), apply, ).WithBoolFlag( cmdr.NewBoolFlag( "dry-run", "d", - fleek.Trans("apply.dryRun"), + app.Trans("apply.dryRun"), false, )).WithBoolFlag( cmdr.NewBoolFlag( "push", "p", - fleek.Trans("apply.push"), + app.Trans("apply.push"), false, )) return cmd @@ -41,24 +41,28 @@ func apply(cmd *cobra.Command, args []string) { if cmd.Flag("push").Changed { push = true } - if behind { - cmdr.Error.Println(fleek.Trans("apply.behind")) + if f.flakeStatus == FlakeBehind { + cmdr.Error.Println(app.Trans("apply.behind")) return } if verbose { - cmdr.Info.Println(fleek.Trans("apply.writingConfig")) + cmdr.Info.Println(app.Trans("apply.writingConfig")) } // only re-apply the templates if not `ejected` - if !config.Ejected { + if !f.config.Ejected { if verbose { - cmdr.Info.Println(fleek.Trans("apply.writingFlake")) + cmdr.Info.Println(app.Trans("apply.writingFlake")) } - err := flake.Write() + flake, err := f.Flake() + cobra.CheckErr(err) + err = flake.Write(false) + cobra.CheckErr(err) + repo, err := f.Repo() cobra.CheckErr(err) err = repo.Commit() if err != nil { - cmdr.Error.Println(fleek.Trans("apply.commitError"), err) + cmdr.Error.Println(app.Trans("apply.commitError"), err) } cobra.CheckErr(err) @@ -69,24 +73,32 @@ func apply(cmd *cobra.Command, args []string) { dry = true } if !dry { - cmdr.Info.Println(fleek.Trans("apply.applyingConfig")) - err := flake.Apply() + cmdr.Info.Println(app.Trans("apply.applyingConfig")) + flake, err := f.Flake() cobra.CheckErr(err) - err = repo.Commit() + err = flake.Apply() + cobra.CheckErr(err) + r, err := f.Repo() + cobra.CheckErr(err) + err = r.Commit() if err != nil { - cmdr.Error.Println(fleek.Trans("apply.commitError"), err) + cmdr.Error.Println(app.Trans("apply.commitError"), err) } } else { - cmdr.Info.Println(fleek.Trans("apply.dryApplyingConfig")) - err := flake.Check() + cmdr.Info.Println(app.Trans("apply.dryApplyingConfig")) + flake, err := f.Flake() + cobra.CheckErr(err) + err = flake.Check() cobra.CheckErr(err) } if push { - cmdr.Info.Println(fleek.Trans("apply.pushing")) - err := repo.Push() + cmdr.Info.Println(app.Trans("apply.pushing")) + repo, err := f.Repo() + cobra.CheckErr(err) + err = repo.Push() cobra.CheckErr(err) } - cmdr.Success.Println(fleek.Trans("apply.done")) + cmdr.Success.Println(app.Trans("apply.done")) } diff --git a/cmd/eject.go b/cmd/eject.go index 9d4c3062..e3e71601 100644 --- a/cmd/eject.go +++ b/cmd/eject.go @@ -5,15 +5,14 @@ package cmd import ( "github.com/spf13/cobra" - "github.com/ublue-os/fleek/core" "github.com/vanilla-os/orchid/cmdr" ) func NewEjectCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("eject.use"), - fleek.Trans("eject.long"), - fleek.Trans("eject.short"), + app.Trans("eject.use"), + app.Trans("eject.long"), + app.Trans("eject.short"), eject, ) return cmd @@ -22,16 +21,18 @@ func NewEjectCommand() *cmdr.Command { // initCmd represents the init command func eject(cmd *cobra.Command, args []string) { - ok, err := cmdr.Confirm.Show(fleek.Trans("eject.confirm")) + ok, err := cmdr.Confirm.Show(app.Trans("eject.confirm")) cobra.CheckErr(err) if ok { - cmdr.Info.Println(fleek.Trans("eject.start")) - err := flake.Write() + cmdr.Info.Println(app.Trans("eject.start")) + flake, err := f.Flake() cobra.CheckErr(err) - err = core.WriteEjectConfig() + err = flake.Write(true) cobra.CheckErr(err) - cmdr.Info.Println(fleek.Trans("eject.complete")) + err = f.config.Eject() + cobra.CheckErr(err) + cmdr.Info.Println(app.Trans("eject.complete")) } } diff --git a/cmd/fleek.go b/cmd/fleek.go new file mode 100644 index 00000000..ca947e0f --- /dev/null +++ b/cmd/fleek.go @@ -0,0 +1,188 @@ +package cmd + +import ( + "errors" + "fmt" + "path/filepath" + + "io/fs" + "os" + + "github.com/ublue-os/fleek/core" + "github.com/ublue-os/fleek/git" + "github.com/ublue-os/fleek/nix" + "github.com/vanilla-os/orchid/cmdr" +) + +type FlakeStatus int + +const ( + FlakeNone FlakeStatus = iota + FlakeExists + FlakeDirty + FlakeBehind + FlakeAhead +) + +func (f FlakeStatus) String() string { + return [...]string{"None", "Dirty", "Behind", "Ahead"}[f] +} + +type ConfigStatus int + +const ( + ConfigNone ConfigStatus = iota + ConfigExists +) + +func (c ConfigStatus) String() string { + return [...]string{"None", "Exists"}[c] +} + +type GitStatus int + +const ( + GitNone GitStatus = iota + GitExists + GitHasRemote +) + +func (g GitStatus) String() string { + return [...]string{"Repository Not Initialized", "Repository Exists", "Repository Has Remote"}[g] +} + +// Fleek is the controller for the command +// line experience and holds state for all +// the commands. +type fleek struct { + flake *nix.Flake + config *core.Config + repo *git.FlakeRepo + configStatus ConfigStatus + flakeStatus FlakeStatus + gitStatus GitStatus + flakeLocation string +} + +func initFleek() (*fleek, error) { + f := &fleek{} + // set up config + var err error + config, err := core.ReadConfig() + + if err != nil { + if errors.Is(err, os.ErrNotExist) { + f.configStatus = ConfigNone + } else { + return f, err + } + } else { + f.configStatus = ConfigExists + } + f.flakeStatus = FlakeNone + f.gitStatus = GitNone + if f.configStatus != ConfigNone { + if config != nil { + err = config.Validate() + if err != nil { + if errors.Is(err, core.ErrMissingFlakeDir) { + cmdr.Info.Println("Migrating .fleek.yml to current version") + // get previous default flake location + home, hErr := os.UserHomeDir() + if hErr != nil { + return f, hErr + } + defaultFlakeDir := filepath.Join(home, ".config", "home-manager") + config.FlakeDir = defaultFlakeDir + // now save the config + err2 := config.Save() + if err2 != nil { + return f, err2 + } + cmdr.Success.Println("Migrated .fleek.yml ") + + } else { + return f, err + } + } + f.config = config + f.flakeLocation = f.config.FlakeDir + + // setup flake + flake, err := nix.NewFlake(f.flakeLocation, f.config) + if err != nil { + return f, err + } + exists, err := flake.Exists() + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + f.flakeStatus = FlakeNone + } + } + if exists { + f.flakeStatus = FlakeExists + } + f.flake = flake + + // setup repo + f.repo = git.NewFlakeRepo(f.flakeLocation) + exists = f.repo.IsValid() + if exists { + f.gitStatus = GitExists + } + ahead, behind, err := f.repo.AheadBehind() + if err != nil { + fmt.Println(err) + return f, err + } + if ahead { + f.flakeStatus = FlakeAhead + } + if behind { + f.flakeStatus = FlakeBehind + } + } + } + + return f, nil +} + +func (f *fleek) Flake() (*nix.Flake, error) { + if f.flake != nil { + return f.flake, nil + } + // setup flake + flake, err := nix.NewFlake(f.flakeLocation, f.config) + if err != nil { + return nil, err + } + exists, err := flake.Exists() + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + f.flakeStatus = FlakeNone + } + } + if exists { + f.flakeStatus = FlakeExists + } + + f.flake = flake + return f.flake, nil +} +func (f *fleek) Repo() (*git.FlakeRepo, error) { + if f.repo != nil { + return f.repo, nil + } + f.repo = git.NewFlakeRepo(f.flakeLocation) + exists := f.repo.IsValid() + if exists { + f.gitStatus = GitExists + } + return f.repo, nil +} + +func (f *fleek) Sanity() ([]string, error) { + // check nix + // check flakes + return []string{}, nil +} diff --git a/cmd/fleek_test.go b/cmd/fleek_test.go new file mode 100644 index 00000000..f74e00f2 --- /dev/null +++ b/cmd/fleek_test.go @@ -0,0 +1,7 @@ +package cmd + +import "testing" + +func TestRepoStatu(t *testing.T) { + t.Skip("not implemented") +} diff --git a/cmd/init.go b/cmd/init.go index 5fb7744b..c2fd6cf3 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -4,40 +4,51 @@ Copyright © 2023 NAME HERE package cmd import ( + "os" + "path/filepath" "strings" "github.com/spf13/cobra" "github.com/ublue-os/fleek/core" - "github.com/ublue-os/fleek/git" "github.com/ublue-os/fleek/nix" "github.com/vanilla-os/orchid/cmdr" ) +var ( + locationFlag string = "location" +) + func NewInitCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("init.use"), - fleek.Trans("init.long"), - fleek.Trans("init.short"), + app.Trans("init.use"), + app.Trans("init.long"), + app.Trans("init.short"), initialize, ).WithBoolFlag( cmdr.NewBoolFlag( "force", "f", - fleek.Trans("init.force"), + app.Trans("init.force"), false, )).WithStringFlag( cmdr.NewStringFlag( "clone", "c", - fleek.Trans("init.clone"), + app.Trans("init.clone"), "", )).WithBoolFlag( cmdr.NewBoolFlag( "apply", "a", - fleek.Trans("init.apply"), + app.Trans("init.apply"), false, - )) + )). + WithStringFlag( + cmdr.NewStringFlag( + locationFlag, + "l", + app.Trans("init.locationFlag"), + ".config/home-manager")) return cmd } @@ -48,33 +59,43 @@ func initialize(cmd *cobra.Command, args []string) { verbose = true } var upstream string + loc := cmd.Flag(locationFlag).Value.String() + home, err := os.UserHomeDir() + cobra.CheckErr(err) + // hack! + floc := filepath.Join(home, loc) + f.config = &core.Config{ + FlakeDir: floc, + } + f.flakeLocation = f.config.FlakeDir + if cmd.Flag("clone").Changed { upstream = cmd.Flag("clone").Value.String() // clone it - err := core.Clone(upstream) + err := f.config.Clone(upstream) cobra.CheckErr(err) if cmd.Flag("apply").Changed { // load the new config - config, err = core.ReadConfig() + f.config, err = core.ReadConfig() cobra.CheckErr(err) - flakeLocation, err = core.FlakeLocation() + _, err := f.Flake() cobra.CheckErr(err) - - flake, err = nix.NewFlake(flakeLocation, config) + _, err = f.Repo() cobra.CheckErr(err) - repo = git.NewFlakeRepo(flakeLocation) + // only re-apply the templates if not `ejected` - if !config.Ejected { + if !f.config.Ejected { if verbose { - cmdr.Info.Println(fleek.Trans("apply.checkingSystem")) + cmdr.Info.Println(app.Trans("apply.checkingSystem")) } + var includeSystems bool // check to see if the current machine (system) is in the existing // configs. If not, create a new one and add it. _, err := core.CurrentSystem() if err != nil { if strings.Contains(err.Error(), "not") { - cmdr.Info.Println(fleek.Trans("apply.newSystem")) + cmdr.Info.Println(app.Trans("apply.newSystem")) // make a new system @@ -90,39 +111,39 @@ func initialize(cmd *cobra.Command, args []string) { cobra.CheckErr(err) cmdr.Info.Printfln("New System: %s@%s", sys.Username, sys.Hostname) // get current config - conf, err := core.ReadConfig() - cobra.CheckErr(err) - + includeSystems = true // append new(current) system - conf.Systems = append(conf.Systems, *sys) + f.config.Systems = append(f.config.Systems, *sys) // save it - err = conf.Save() + err = f.config.Save() cobra.CheckErr(err) } } if verbose { - cmdr.Info.Println(fleek.Trans("apply.writingFlake")) + cmdr.Info.Println(app.Trans("apply.writingFlake")) } - err = flake.Write() + err = f.flake.Write(includeSystems) cobra.CheckErr(err) } - cmdr.Info.Println(fleek.Trans("apply.applyingConfig")) - err := flake.Apply() + cmdr.Info.Println(app.Trans("apply.applyingConfig")) + err = f.flake.Apply() cobra.CheckErr(err) - cmdr.Success.Println(fleek.Trans("apply.done")) + cmdr.Success.Println(app.Trans("apply.done")) return } + cmdr.Info.Println(app.Trans("init.cloned")) + return } - cmdr.Info.Println(fleek.Trans("init.start")) + cmdr.Info.Println(app.Trans("init.start")) var force bool if cmd.Flag("force").Changed { force = true } if verbose { - cmdr.Info.Println(fleek.Trans("init.checkNix")) + cmdr.Info.Println(app.Trans("init.checkNix")) } ok := nix.CheckNix() @@ -133,21 +154,29 @@ func initialize(cmd *cobra.Command, args []string) { name, err := cmdr.Prompt.Show("Git Config - enter your full name") cobra.CheckErr(err) if verbose { - cmdr.Info.Println(fleek.Trans("init.writingConfigs")) + cmdr.Info.Println(app.Trans("init.writingConfigs")) } - err = core.MakeFlakeDir() - cobra.CheckErr(err) - err = core.WriteSampleConfig(email, name, force) + err = f.config.MakeFlakeDir() cobra.CheckErr(err) + err = core.WriteSampleConfig(floc, email, name, force) + cobra.CheckErr(err) + f.config, err = core.ReadConfig() + cobra.CheckErr(err) + flake, err := f.Flake() + cobra.CheckErr(err) err = flake.Init(force) cobra.CheckErr(err) + repo, err := f.Repo() + cobra.CheckErr(err) err = repo.CreateRepo() cobra.CheckErr(err) + err = repo.LocalConfig(name, email) + cobra.CheckErr(err) err = repo.Commit() cobra.CheckErr(err) } else { - cmdr.Error.Println(fleek.Trans("init.nixNotFound")) + cmdr.Error.Println(app.Trans("init.nixNotFound")) } - cmdr.Info.Println(fleek.Trans("init.complete")) + cmdr.Info.Println(app.Trans("init.complete")) } diff --git a/cmd/list.go b/cmd/list.go index f7c10a82..45f575ff 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -10,9 +10,9 @@ import ( func NewListCommand() *cmdr.Command { cmd := &cobra.Command{ - Use: fleek.Trans("list.use"), - Long: fleek.Trans("list.long"), - Short: fleek.Trans("list.short"), + Use: app.Trans("list.use"), + Long: app.Trans("list.long"), + Short: app.Trans("list.short"), } cmdrcmd := &cmdr.Command{Command: cmd} return cmdrcmd diff --git a/cmd/list_packages.go b/cmd/list_packages.go index e6818cf0..c14c6914 100644 --- a/cmd/list_packages.go +++ b/cmd/list_packages.go @@ -14,9 +14,9 @@ import ( func NewListPackagesCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("listPackages.use"), - fleek.Trans("listPackages.long"), - fleek.Trans("listPackages.short"), + app.Trans("listPackages.use"), + app.Trans("listPackages.long"), + app.Trans("listPackages.short"), list, ) return cmd @@ -25,25 +25,22 @@ func NewListPackagesCommand() *cmdr.Command { // initCmd represents the init command func list(cmd *cobra.Command, args []string) { - conf, err := core.ReadConfig() - cobra.CheckErr(err) - - cmdr.Info.Println(fleek.Trans("listPackages.userBling"), strings.ToUpper(conf.Bling)) - switch conf.Bling { + cmdr.Info.Println(app.Trans("listPackages.userBling"), strings.ToUpper(f.config.Bling)) + switch f.config.Bling { case "high": - cmdr.Info.Println(fleek.Trans("listPackages.highBling")) + cmdr.Info.Println(app.Trans("listPackages.highBling")) case "default": - cmdr.Info.Println(fleek.Trans("listPackages.defaultBling")) + cmdr.Info.Println(app.Trans("listPackages.defaultBling")) case "low": - cmdr.Info.Println(fleek.Trans("listPackages.lowBling")) + cmdr.Info.Println(app.Trans("listPackages.lowBling")) } - if conf.Bling == "high" { + if f.config.Bling == "high" { for _, pkg := range core.HighPackages { fmt.Printf("\t%s\n", pkg) } } - if conf.Bling == "default" || conf.Bling == "high" { + if f.config.Bling == "default" || f.config.Bling == "high" { for _, pkg := range core.DefaultPackages { fmt.Printf("\t%s\n", pkg) @@ -53,9 +50,9 @@ func list(cmd *cobra.Command, args []string) { fmt.Printf("\t%s\n", pkg) } - cmdr.Info.Println(fleek.Trans("listPackages.userInstalled")) + cmdr.Info.Println(app.Trans("listPackages.userInstalled")) - for _, pkg := range conf.Packages { + for _, pkg := range f.config.Packages { fmt.Printf("\t%s\n", pkg) } diff --git a/cmd/list_programs.go b/cmd/list_programs.go index 096b534c..02f3984b 100644 --- a/cmd/list_programs.go +++ b/cmd/list_programs.go @@ -14,9 +14,9 @@ import ( func NewListProgramsCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("listPrograms.use"), - fleek.Trans("listPrograms.long"), - fleek.Trans("listPrograms.short"), + app.Trans("listPrograms.use"), + app.Trans("listPrograms.long"), + app.Trans("listPrograms.short"), listPrograms, ) return cmd @@ -24,26 +24,22 @@ func NewListProgramsCommand() *cmdr.Command { // initCmd represents the init command func listPrograms(cmd *cobra.Command, args []string) { - - conf, err := core.ReadConfig() - cobra.CheckErr(err) - - cmdr.Info.Println(fleek.Trans("listPrograms.userBling"), strings.ToUpper(conf.Bling)) - switch conf.Bling { + cmdr.Info.Println(app.Trans("listPrograms.userBling"), strings.ToUpper(f.config.Bling)) + switch f.config.Bling { case "high": - cmdr.Info.Println(fleek.Trans("listPrograms.highBling")) + cmdr.Info.Println(app.Trans("listPrograms.highBling")) case "default": - cmdr.Info.Println(fleek.Trans("listPrograms.defaultBling")) + cmdr.Info.Println(app.Trans("listPrograms.defaultBling")) case "low": - cmdr.Info.Println(fleek.Trans("listPrograms.lowBling")) + cmdr.Info.Println(app.Trans("listPrograms.lowBling")) } - if conf.Bling == "high" { + if f.config.Bling == "high" { for _, pkg := range core.HighPrograms { fmt.Printf("\t%s\n", pkg) } } - if conf.Bling == "default" || conf.Bling == "high" { + if f.config.Bling == "default" || f.config.Bling == "high" { for _, pkg := range core.DefaultPrograms { fmt.Printf("\t%s\n", pkg) @@ -53,9 +49,9 @@ func listPrograms(cmd *cobra.Command, args []string) { fmt.Printf("\t%s\n", pkg) } - cmdr.Info.Println(fleek.Trans("listPrograms.userInstalled")) + cmdr.Info.Println(app.Trans("listPrograms.userInstalled")) - for _, pkg := range conf.Programs { + for _, pkg := range f.config.Programs { fmt.Printf("\t%s\n", pkg) } diff --git a/cmd/remove.go b/cmd/remove.go index 86624385..49c3d5fc 100644 --- a/cmd/remove.go +++ b/cmd/remove.go @@ -10,21 +10,21 @@ import ( func NewRemoveCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("remove.use"), - fleek.Trans("remove.long"), - fleek.Trans("remove.short"), + app.Trans("remove.use"), + app.Trans("remove.long"), + app.Trans("remove.short"), remove, ).WithBoolFlag( cmdr.NewBoolFlag( "program", "p", - fleek.Trans("remove.program"), + app.Trans("remove.program"), false, )).WithBoolFlag( cmdr.NewBoolFlag( "apply", "a", - fleek.Trans("remove.apply"), + app.Trans("remove.apply"), false, )) cmd.Args = cobra.MinimumNArgs(1) @@ -43,25 +43,31 @@ func remove(cmd *cobra.Command, args []string) { apply = true } if verbose { - cmdr.Info.Println(fleek.Trans("remove.applying")) + cmdr.Info.Println(app.Trans("remove.applying")) } var err error for _, p := range args { if cmd.Flag("program").Changed { - err = config.RemoveProgram(p) + err = f.config.RemoveProgram(p) cobra.CheckErr(err) } else { - err = config.RemovePackage(p) + err = f.config.RemovePackage(p) cobra.CheckErr(err) } + repo, err := f.Repo() + cobra.CheckErr(err) + err = repo.Commit() + cobra.CheckErr(err) } if apply { + flake, err := f.Flake() + cobra.CheckErr(err) err = flake.Apply() cobra.CheckErr(err) } - cmdr.Info.Println(fleek.Trans("remove.done")) + cmdr.Info.Println(app.Trans("remove.done")) } diff --git a/cmd/repo.go b/cmd/repo.go index a9dcedf4..f9fb5f6f 100644 --- a/cmd/repo.go +++ b/cmd/repo.go @@ -10,9 +10,9 @@ import ( func NewRepoCommand() *cmdr.Command { cmd := &cobra.Command{ - Use: fleek.Trans("repo.use"), - Long: fleek.Trans("repo.long"), - Short: fleek.Trans("repo.short"), + Use: app.Trans("repo.use"), + Long: app.Trans("repo.long"), + Short: app.Trans("repo.short"), } cmdrcmd := &cmdr.Command{Command: cmd} return cmdrcmd diff --git a/cmd/repo_add.go b/cmd/repo_add.go index f474bb54..06432182 100644 --- a/cmd/repo_add.go +++ b/cmd/repo_add.go @@ -10,14 +10,14 @@ import ( func NewRepoAddCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("repoadd.use"), - fleek.Trans("repoadd.long"), - fleek.Trans("repoadd.short"), + app.Trans("repoadd.use"), + app.Trans("repoadd.long"), + app.Trans("repoadd.short"), remoteadd, ).WithStringFlag(cmdr.NewStringFlag( "name", "n", - fleek.Trans("repoadd.name"), + app.Trans("repoadd.name"), "origin", )) cmd.Args = cobra.ExactArgs(1) @@ -27,14 +27,16 @@ func NewRepoAddCommand() *cmdr.Command { // initCmd represents the init command func remoteadd(cmd *cobra.Command, args []string) { - config.Repository = args[0] - err := config.Save() + f.config.Repository = args[0] + err := f.config.Save() cobra.CheckErr(err) // now actually add the remote name := cmd.Flag("name").Value.String() + repo, err := f.Repo() + cobra.CheckErr(err) repo.RemoteAdd(args[0], name) err = repo.Commit() cobra.CheckErr(err) - cmdr.Info.Println(config.Repository) + cmdr.Info.Println(f.config.Repository) } diff --git a/cmd/repo_show.go b/cmd/repo_show.go index 9239ce3f..87c2c5b7 100644 --- a/cmd/repo_show.go +++ b/cmd/repo_show.go @@ -10,9 +10,9 @@ import ( func NewRepoShowCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("reposhow.use"), - fleek.Trans("reposhow.long"), - fleek.Trans("reposhow.short"), + app.Trans("reposhow.use"), + app.Trans("reposhow.long"), + app.Trans("reposhow.short"), show, ) return cmd @@ -21,9 +21,11 @@ func NewRepoShowCommand() *cmdr.Command { // initCmd represents the init command func show(cmd *cobra.Command, args []string) { + repo, err := f.Repo() + cobra.CheckErr(err) urls, err := repo.Remote() cobra.CheckErr(err) - cmdr.Info.Println("configured:", config.Repository) + cmdr.Info.Println("configured:", f.config.Repository) cmdr.Info.Println("actual:", urls) } diff --git a/cmd/root.go b/cmd/root.go index 9823392f..92be18ac 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,125 +2,154 @@ package cmd import ( "embed" - "errors" "os" "github.com/spf13/cobra" - "github.com/ublue-os/fleek/core" - "github.com/ublue-os/fleek/git" "github.com/ublue-os/fleek/nix" "github.com/vanilla-os/orchid/cmdr" ) -var fleek *cmdr.App -var flake *nix.Flake -var config *core.Config -var repo *git.FlakeRepo -var firstrun bool -var flakeLocation string -var ahead bool -var behind bool +var app *cmdr.App +var f *fleek const ( verboseFlag string = "verbose" syncFlag string = "sync" + nixGC string = "garbage-collect" ) func New(version string, fs embed.FS) *cmdr.App { - fleek = cmdr.NewApp("fleek", version, fs) - return fleek + app = cmdr.NewApp("fleek", version, fs) + return app } func NewRootCommand(version string) *cmdr.Command { root := cmdr.NewCommand( - fleek.Trans("fleek.use"), - fleek.Trans("fleek.long"), - fleek.Trans("fleek.short"), + app.Trans("fleek.use"), + app.Trans("fleek.long"), + app.Trans("fleek.short"), nil). WithPersistentBoolFlag( cmdr.NewBoolFlag( verboseFlag, "v", - fleek.Trans("fleek.verboseFlag"), + app.Trans("fleek.verboseFlag"), false)). WithPersistentBoolFlag( cmdr.NewBoolFlag( syncFlag, "s", - fleek.Trans("fleek.syncFlag"), + app.Trans("fleek.syncFlag"), + false)). + WithPersistentBoolFlag( + cmdr.NewBoolFlag( + nixGC, + "g", + app.Trans("fleek.nixGarbage"), false)) root.Version = version root.PersistentPreRun = func(cmd *cobra.Command, args []string) { ok := nix.CheckNix() if !ok { - cmdr.Error.Println(fleek.Trans("fleek.installNix")) + cmdr.Error.Println(app.Trans("fleek.installNix")) os.Exit(1) } - // set up config and flake before each command var err error - config, err = core.ReadConfig() - if errors.Is(err, os.ErrNotExist) { - firstrun = true - return - } - - flakeLocation, err = core.FlakeLocation() + f, err = initFleek() cobra.CheckErr(err) - flake, err = nix.NewFlake(flakeLocation, config) - cobra.CheckErr(err) - - repo = git.NewFlakeRepo(flakeLocation) - - cmdr.Info.Println(fleek.Trans("fleek.gitStatus")) - - dirty, err := repo.Dirty() - cobra.CheckErr(err) - if dirty { - cmdr.Warning.Println(fleek.Trans("fleek.dirty")) - } - ahead, behind, err = repo.AheadBehind() - cobra.CheckErr(err) - if ahead { - cmdr.Warning.Println(fleek.Trans("fleek.ahead")) - } - if behind { - cmdr.Warning.Println(fleek.Trans("fleek.behind")) - } - if cmd.Flag("sync").Changed && behind { - cmdr.Info.Println(fleek.Trans("fleek.pull")) - err = repo.Pull() + /* + dirty, err := repo.Dirty() cobra.CheckErr(err) - behind = false + if dirty { + cmdr.Warning.Println(app.Trans("fleek.dirty")) + } + ahead, behind, err = repo.AheadBehind() + cobra.CheckErr(err) + if ahead { + cmdr.Warning.Println(app.Trans("fleek.ahead")) + } + if behind { + cmdr.Warning.Println(app.Trans("fleek.behind")) + } + + */ + if cmd.Flag(syncFlag).Changed && f.flakeStatus == FlakeBehind { + cmdr.Info.Println(app.Trans("fleek.pull")) + r, err := f.Repo() + cobra.CheckErr(err) + r.Pull() + cobra.CheckErr(err) + f.flakeStatus = FlakeExists + } } root.PersistentPostRun = func(cmd *cobra.Command, args []string) { - - repo = git.NewFlakeRepo(flakeLocation) - - cmdr.Info.Println(fleek.Trans("fleek.gitStatus")) - + repo, err := f.Repo() + cobra.CheckErr(err) dirty, err := repo.Dirty() cobra.CheckErr(err) if dirty { - cmdr.Warning.Println(fleek.Trans("fleek.dirty")) + f.flakeStatus = FlakeDirty + cmdr.Warning.Println(app.Trans("fleek.dirty")) } - ahead, behind, err = repo.AheadBehind() + + ahead, behind, err := f.repo.AheadBehind() cobra.CheckErr(err) if ahead { - cmdr.Warning.Println(fleek.Trans("fleek.ahead")) + f.flakeStatus = FlakeAhead + // only show the warning if we're not already + // planning to sync + if !cmd.Flag("sync").Changed { + cmdr.Warning.Println(app.Trans("fleek.ahead")) + } } if behind { - cmdr.Warning.Println(fleek.Trans("fleek.behind")) + f.flakeStatus = FlakeBehind + cmdr.Warning.Println(app.Trans("fleek.behind")) } - if cmd.Flag("sync").Changed && ahead { - cmdr.Info.Println(fleek.Trans("fleek.push")) + if cmd.Flag(nixGC).Changed { + f, err := f.Flake() + cobra.CheckErr(err) + err = f.GC() + cobra.CheckErr(err) + + } + if cmd.Flag("sync").Changed && f.flakeStatus == FlakeAhead { + cmdr.Info.Println(app.Trans("fleek.push")) + repo, err := f.Repo() + cobra.CheckErr(err) err = repo.Push() cobra.CheckErr(err) } + /* + repo = git.NewFlakeRepo(flakeLocation) + + cmdr.Info.Println(app.Trans("fleek.gitStatus")) + + dirty, err := repo.Dirty() + cobra.CheckErr(err) + if dirty { + cmdr.Warning.Println(app.Trans("fleek.dirty")) + } + ahead, behind, err = repo.AheadBehind() + cobra.CheckErr(err) + if ahead { + cmdr.Warning.Println(app.Trans("fleek.ahead")) + } + if behind { + cmdr.Warning.Println(app.Trans("fleek.behind")) + } + if cmd.Flag("sync").Changed && ahead { + cmdr.Info.Println(app.Trans("fleek.push")) + err = repo.Push() + cobra.CheckErr(err) + + } + */ } return root diff --git a/cmd/update.go b/cmd/update.go index 359552c9..89710db9 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -10,15 +10,15 @@ import ( func NewUpdateCommand() *cmdr.Command { cmd := cmdr.NewCommandRun( - fleek.Trans("update.use"), - fleek.Trans("update.long"), - fleek.Trans("update.short"), + app.Trans("update.use"), + app.Trans("update.long"), + app.Trans("update.short"), update, ).WithBoolFlag( cmdr.NewBoolFlag( "apply", "a", - fleek.Trans("update.apply"), + app.Trans("update.apply"), false, )) return cmd @@ -26,18 +26,19 @@ func NewUpdateCommand() *cmdr.Command { // initCmd represents the init command func update(cmd *cobra.Command, args []string) { - cmdr.Info.Println(fleek.Trans("update.start")) + cmdr.Info.Println(app.Trans("update.start")) - err := flake.Update() + flake, err := f.Flake() cobra.CheckErr(err) + flake.Update() if cmd.Flag("apply").Changed { - cmdr.Info.Println(fleek.Trans("update.apply")) + cmdr.Info.Println(app.Trans("update.apply")) err = flake.Apply() cobra.CheckErr(err) } else { - cmdr.Info.Println(fleek.Trans("update.needApply")) + cmdr.Info.Println(app.Trans("update.needApply")) } - cmdr.Success.Println(fleek.Trans("update.done")) + cmdr.Success.Println(app.Trans("update.done")) } diff --git a/core/config.go b/core/config.go index 219d2504..8ee50bcb 100644 --- a/core/config.go +++ b/core/config.go @@ -2,6 +2,8 @@ package core import ( "errors" + "fmt" + "io/fs" "os" "os/exec" "path/filepath" @@ -27,7 +29,8 @@ var ( // Config holds the options that will be // merged into the home-manager flake. type Config struct { - Unfree bool `yaml:"unfree"` + FlakeDir string `yaml:"flakedir"` + Unfree bool `yaml:"unfree"` // bash or zsh Shell string `yaml:"shell"` // low, default, high @@ -83,20 +86,33 @@ func NewSystem(name, email string) (*System, error) { }, nil } -func (c Config) Validate() error { +var ( + ErrMissingFlakeDir = errors.New("fleek.yml: missing `flakedir`") + ErrInvalidShell = errors.New("fleek.yml: invalid shell, valid shells are: " + strings.Join(shells, ", ")) + ErrInvalidBling = errors.New("fleek.yml: invalid bling level, valid levels are: " + strings.Join(blingLevels, ", ")) + ErrorInvalidArch = errors.New("fleek.yml: invalid architecture, valid architectures are: " + strings.Join(architectures, ", ")) + ErrInvalidOperatingSystem = errors.New("fleek.yml: invalid OS, valid operating systems are: " + strings.Join(operatingSystems, ", ")) + ErrPackageNotFound = errors.New("package not found in configuration file") + ErrProgramNotFound = errors.New("program not found in configuration file") +) + +func (c *Config) Validate() error { + if c.FlakeDir == "" { + return ErrMissingFlakeDir + } if !isValueInList(c.Shell, shells) { - return errors.New("fleek.yml: invalid shell, valid shells are: " + strings.Join(shells, ", ")) + return ErrInvalidShell } if !isValueInList(c.Bling, blingLevels) { - return errors.New("fleek.yml: invalid bling level, valid levels are: " + strings.Join(blingLevels, ", ")) + return ErrInvalidBling } for _, sys := range c.Systems { if !isValueInList(sys.Arch, architectures) { - return errors.New("fleek.yml: invalid architecture, valid architectures are: " + strings.Join(architectures, ", ")) + return ErrorInvalidArch } if !isValueInList(sys.OS, operatingSystems) { - return errors.New("fleek.yml: invalid OS, valid operating systems are: " + strings.Join(operatingSystems, ", ")) + return ErrInvalidOperatingSystem } } return nil @@ -132,7 +148,7 @@ func (c *Config) RemovePackage(pack string) error { if found { c.Packages = append(c.Packages[:index], c.Packages[index+1:]...) } else { - return errors.New("not found") + return ErrPackageNotFound } err := c.Validate() if err != nil { @@ -153,7 +169,7 @@ func (c *Config) RemoveProgram(prog string) error { if found { c.Programs = append(c.Programs[:index], c.Programs[index+1:]...) } else { - return errors.New("not found") + return ErrProgramNotFound } err := c.Validate() if err != nil { @@ -171,7 +187,7 @@ func (c *Config) AddProgram(prog string) error { } func (c *Config) Save() error { - cfile, err := ConfigLocation() + cfile, err := c.Location() if err != nil { return err } @@ -205,12 +221,12 @@ func (c *Config) Save() error { // stored in $HOME/.fleek.yml func ReadConfig() (*Config, error) { c := &Config{} - cfile, err := ConfigLocation() + home, err := os.UserHomeDir() if err != nil { return c, err } - - bb, err := os.ReadFile(cfile) + csym := filepath.Join(home, ".fleek.yml") + bb, err := os.ReadFile(csym) if err != nil { return c, err } @@ -221,19 +237,15 @@ func ReadConfig() (*Config, error) { return c, nil } -func Clone(repo string) error { - location, err := FlakeLocation() - if err != nil { - return err - } +func (c *Config) Clone(repo string) error { - clone := exec.Command("git", "clone", repo, location) + clone := exec.Command("git", "clone", repo, c.FlakeDir) clone.Stderr = os.Stderr clone.Stdin = os.Stdin clone.Stdout = os.Stdout clone.Env = os.Environ() - err = clone.Run() + err := clone.Run() if err != nil { return err } @@ -241,7 +253,7 @@ func Clone(repo string) error { if err != nil { return err } - yamlPath := filepath.Join(location, ".fleek.yml") + yamlPath := filepath.Join(c.FlakeDir, ".fleek.yml") csym := filepath.Join(home, ".fleek.yml") return os.Symlink(yamlPath, csym) @@ -249,19 +261,19 @@ func Clone(repo string) error { // WriteSampleConfig creates the first fleek // configuration file -func WriteSampleConfig(email, name string, force bool) error { - +func WriteSampleConfig(location, email, name string, force bool) error { aliases := make(map[string]string) aliases["cdfleek"] = "cd ~/.config/home-manager" sys, err := NewSystem(name, email) if err != nil { return err } - c := Config{ - Unfree: true, - Shell: "bash", - Bling: "default", - Name: "My Fleek Configuration", + c := &Config{ + FlakeDir: location, + Unfree: true, + Shell: "bash", + Bling: "default", + Name: "My Fleek Configuration", Packages: []string{ "helix", }, @@ -275,13 +287,17 @@ func WriteSampleConfig(email, name string, force bool) error { }, Systems: []System{*sys}, } - cfile, err := ConfigLocation() + cfile, err := c.Location() if err != nil { return err } + err = c.MakeFlakeDir() + if err != nil { + return fmt.Errorf("making flake dir: %s", err) + } _, err = os.Stat(cfile) - if force || os.IsNotExist(err) { + if force || errors.Is(err, fs.ErrNotExist) { cfg, err := os.Create(cfile) if err != nil { @@ -323,12 +339,11 @@ func WriteSampleConfig(email, name string, force bool) error { // WriteEjectConfig updates the .fleek.yml file // to indicated ejected status -func WriteEjectConfig() error { +func (c *Config) Eject() error { - c := Config{ - Ejected: true, - } - cfile, err := ConfigLocation() + c.Ejected = true + + cfile, err := c.Location() if err != nil { return err } diff --git a/core/fleek.go b/core/fleek.go index 138c8610..ba9e6544 100644 --- a/core/fleek.go +++ b/core/fleek.go @@ -7,30 +7,13 @@ import ( // ConfigLocation returns the path for the // fleek configuration file. -func ConfigLocation() (string, error) { - hm, err := FlakeLocation() - if err != nil { - return "", err - } - return filepath.Join(hm, ".fleek.yml"), nil -} - -// FlakeLocation returns the path where the -// interpolated flake will be created. -func FlakeLocation() (string, error) { - home, err := os.UserHomeDir() - if err != nil { - return "", err - } - return filepath.Join(home, ".config", "home-manager"), nil +func (c *Config) Location() (string, error) { + return filepath.Join(c.FlakeDir, ".fleek.yml"), nil } // MakeFlakeDir creates the directory that holds // the interpolated flake. -func MakeFlakeDir() error { - f, err := FlakeLocation() - if err != nil { - return err - } - return os.MkdirAll(f, 0755) +func (c *Config) MakeFlakeDir() error { + + return os.MkdirAll(c.FlakeDir, 0755) } diff --git a/core/system.go b/core/system.go index 7a54eeb7..a88572e0 100644 --- a/core/system.go +++ b/core/system.go @@ -72,5 +72,5 @@ func CurrentSystem() (*System, error) { } } } - return nil, fmt.Errorf("system not found") + return nil, ErrSysNotFound } diff --git a/git/git.go b/git/git.go index 0db7b6b6..2c92931f 100644 --- a/git/git.go +++ b/git/git.go @@ -1,6 +1,7 @@ package git import ( + "errors" "fmt" "os" "os/exec" @@ -31,6 +32,17 @@ func NewFlakeRepo(root string) *FlakeRepo { return frepo } +func (fr *FlakeRepo) IsValid() bool { + var err error + _, err = git.PlainOpen(fr.RootDir) + if err != nil { + if errors.Is(err, git.ErrRepositoryNotExists) { + return false + } + } + return true +} + func (fr *FlakeRepo) runGit(cmd string, cmdLine []string) ([]byte, error) { command := exec.Command(cmd, cmdLine...) command.Stdin = os.Stdin @@ -59,14 +71,36 @@ func (fr *FlakeRepo) Commit() error { } func (fr *FlakeRepo) Pull() error { + remote, err := fr.Remote() + if err != nil { + return err + } + // if no remote, no need to push + if remote == "" { + return nil + } pullCmdline := []string{"pull", "origin", "main"} - _, err := fr.runGit(gitbin, pullCmdline) + _, err = fr.runGit(gitbin, pullCmdline) if err != nil { return fmt.Errorf("git add: %s", err) } return nil } +func (fr *FlakeRepo) LocalConfig(user, email string) error { + userCmdline := []string{"config", "user.name", user} + _, err := fr.runGit(gitbin, userCmdline) + if err != nil { + return fmt.Errorf("git config: %s", err) + } + emailCmdline := []string{"config", "user.email", email} + _, err = fr.runGit(gitbin, emailCmdline) + if err != nil { + return fmt.Errorf("git config: %s", err) + } + return nil +} + func (fr *FlakeRepo) CreateRepo() error { initCmdLine := []string{"init"} _, err := fr.runGit(gitbin, initCmdLine) @@ -83,8 +117,16 @@ func (fr *FlakeRepo) CreateRepo() error { return err } func (fr *FlakeRepo) Push() error { + remote, err := fr.Remote() + if err != nil { + return err + } + // if no remote, no need to push + if remote == "" { + return nil + } pushCmdline := []string{"push", "origin", "main"} - _, err := fr.runGit(gitbin, pushCmdline) + _, err = fr.runGit(gitbin, pushCmdline) if err != nil { return fmt.Errorf("git push: %s", err) } @@ -107,7 +149,6 @@ func (fr *FlakeRepo) Dirty() (bool, error) { outString := string(out) if len(outString) > 0 { - fmt.Println("debug: ", outString) lines := strings.Split(outString, "\n") for _, line := range lines { cleanLine := strings.TrimSpace(line) @@ -121,7 +162,7 @@ func (fr *FlakeRepo) Dirty() (bool, error) { if len(parts[0]) == 2 { remote = parts[0][:1] } - fmt.Printf("file: %s\n", parts[1]) + fmt.Printf("git status: %s\n", parts[1]) fmt.Printf("\tlocal: %s\n", local) if len(remote) > 0 { @@ -137,6 +178,14 @@ func (fr *FlakeRepo) Dirty() (bool, error) { } func (fr *FlakeRepo) AheadBehind() (bool, bool, error) { + remote, err := fr.Remote() + if err != nil { + return false, false, err + } + // if no remote, not ahead or behind + if remote == "" { + return false, false, nil + } var ahead bool var behind bool diff --git a/locales/en.yml b/locales/en.yml index d6d7b986..093edb49 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -3,12 +3,13 @@ fleek: long: "Fleek installs and manages packages in your nix installation with a \nfriendly and approachable config file." short: "Fleek makes nix friendly" gitStatus: "Checking status of fleek repository" - dirty: "fleek repository has uncreconciled changes" - ahead: "local fleek repository has unpushed changes" + dirty: "fleek repository has uncreconciled changes, run `fleek apply --push` to push changes" + ahead: "local fleek repository has unpushed changes, run `fleek apply --push` to push changes" behind: "remote fleek repository has changes to be pulled" pull: "Pulling remote changes" push: "Synchronizing local changes with remote" verboseFlag: "show more detailed output" + nixGarbage: "run garbage collection to remove unused items" syncFlag: "synchronize git repository before and after command" installNix: "No nix installation found! We recommend starting at https://zero-to-nix.com/" @@ -22,8 +23,8 @@ eject: confirm: "Are you sure you want to manage your home configuration files directly?" apply: use: "apply" - long: "Apply fleek profile by reading the ~/.fleek.yml file and updating \nthe flake templates." - short: "Apply fleek profile" + long: "Apply fleek configuration by reading the ~/.fleek.yml file and updating \nthe flake templates." + short: "Apply fleek configuration" behind: "Can't apply with unmerged remote changes. Use `--sync` flag to pull remote changes." dryRun: "dry run - don't apply configuration" push: "push modified configuration to git remote" @@ -45,16 +46,18 @@ init: start: "initializing fleek" apply: "apply configuration immediately after cloning" clone: "address of existing fleek repository" + cloned: "repository cloned" checkNix: "checking for nix installation" writingConfigs: "writing configuration files" nixNotFound: "can't find `nix` binary - is nix installed?" complete: "Done. \n\nEdit ~/.fleek.yml to your taste and run `fleek apply`" + locationFlag: "location of fleek repository, relative to home" add: use: "add [package] [package] ..." long: "Add a new package or program to your configuration.\n Use the `--program` flag to specify a program which can also be configured by nix." short: "Add a new package or program to your configuration" program: "add a program instead of package" - apply: "apply configs after adding" + apply: "apply configuration after adding" applying: "Adding package and applying configuration" done: "Complete!" diff --git a/move.sh b/move.sh new file mode 100755 index 00000000..02151a46 --- /dev/null +++ b/move.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +mv ~/.fleek.yml ~/.fleek.yml.save +mv ~/.config/home-manager ~/.config/hm-save diff --git a/nix/flake.go b/nix/flake.go index a2231209..745b072a 100644 --- a/nix/flake.go +++ b/nix/flake.go @@ -44,6 +44,15 @@ func NewFlake(root string, config *core.Config) (*Flake, error) { } +// Exist verifies that the Flake directory exists +func (f *Flake) Exists() (bool, error) { + _, err := os.Stat(f.RootDir) + if err != nil { + return true, nil + } + return false, err +} + // Init writes the first flake configuration func (f *Flake) Init(force bool) error { @@ -98,7 +107,7 @@ func (f *Flake) Init(force bool) error { } // Write writes the applied flake configuration -func (f *Flake) Write() error { +func (f *Flake) Write(includeSystems bool) error { data := Data{ Config: f.Config, @@ -129,10 +138,12 @@ func (f *Flake) Write() error { if err != nil { return err } - for _, sys := range data.Config.Systems { - err = f.writeSystem(sys, true) - if err != nil { - return err + if includeSystems { + for _, sys := range data.Config.Systems { + err = f.writeSystem(sys, true) + if err != nil { + return err + } } } return f.writeFile("shell.nix", data, true) @@ -141,10 +152,6 @@ func (f *Flake) Write() error { func (f *Flake) Apply() error { - workdir, err := core.FlakeLocation() - if err != nil { - return err - } user, err := core.Username() if err != nil { return err @@ -157,7 +164,7 @@ func (f *Flake) Apply() error { apply.Stderr = os.Stderr apply.Stdin = os.Stdin apply.Stdout = os.Stdout - apply.Dir = workdir + apply.Dir = f.RootDir apply.Env = os.Environ() if f.Config.Unfree { @@ -170,53 +177,61 @@ func (f *Flake) Apply() error { } return nil } -func (f *Flake) Check() error { +func (f *Flake) GC() error { + + gc := exec.Command("nix-collect-garbage", "-d") + gc.Stderr = os.Stderr + gc.Stdin = os.Stdin + gc.Stdout = os.Stdout + gc.Dir = f.RootDir + gc.Env = os.Environ() + if f.Config.Unfree { + gc.Env = append(gc.Env, "NIXPKGS_ALLOW_UNFREE=1") + } - workdir, err := core.FlakeLocation() + err := gc.Run() if err != nil { return err } + return nil +} +func (f *Flake) Check() error { + apply := exec.Command("nix", "run", "--impure", "home-manager/master", "build", "--impure", "--", "--flake", ".") apply.Stderr = os.Stderr apply.Stdin = os.Stdin apply.Stdout = os.Stdout - apply.Dir = workdir + apply.Dir = f.RootDir apply.Env = os.Environ() if f.Config.Unfree { apply.Env = append(apply.Env, "NIXPKGS_ALLOW_UNFREE=1") } - err = apply.Run() + err := apply.Run() if err != nil { return err } return nil } func (f *Flake) Update() error { - workdir, err := core.FlakeLocation() - if err != nil { - return err - } + apply := exec.Command("nix", "flake", "update") apply.Stderr = os.Stderr apply.Stdin = os.Stdin apply.Stdout = os.Stdout - apply.Dir = workdir + apply.Dir = f.RootDir apply.Env = os.Environ() - err = apply.Run() + err := apply.Run() if err != nil { return err } return nil } func (f *Flake) writeFile(fname string, d Data, force bool) error { - fleekPath, err := core.FlakeLocation() - if err != nil { - return err - } - fpath := filepath.Join(fleekPath, fname) - _, err = os.Stat(fpath) + + fpath := filepath.Join(f.RootDir, fname) + _, err := os.Stat(fpath) if force || os.IsNotExist(err) { file, err := os.Create(fpath) @@ -234,12 +249,9 @@ func (f *Flake) writeFile(fname string, d Data, force bool) error { return nil } func (f *Flake) writeSystem(sys core.System, force bool) error { - fleekPath, err := core.FlakeLocation() - if err != nil { - return err - } - hostPath := filepath.Join(fleekPath, sys.Hostname) - err = os.MkdirAll(hostPath, 0755) + + hostPath := filepath.Join(f.RootDir, sys.Hostname) + err := os.MkdirAll(hostPath, 0755) if err != nil { return err } diff --git a/prep.sh b/prep.sh new file mode 100755 index 00000000..77cdd823 --- /dev/null +++ b/prep.sh @@ -0,0 +1,6 @@ +#!/bin/sh +CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags '-w -extldflags "-static"' +rm -f fleek.1 +rm -f fleek.1.gz +./fleek man > fleek.1 +gzip fleek.1 diff --git a/restore.sh b/restore.sh new file mode 100755 index 00000000..42ba1d6d --- /dev/null +++ b/restore.sh @@ -0,0 +1,6 @@ +#!/bin/sh +rm -f ~/.fleek.yml +rm -rf ~/.config/home-manager + +mv ~/.fleek.yml.save ~/.fleek.yml +mv ~/.config/hm-save ~/.config/home-manager