From c0fa734e0e3fbb034ff28899b0a1088450093fba Mon Sep 17 00:00:00 2001 From: Rakshit Gondwal Date: Sat, 25 May 2024 00:28:00 +0530 Subject: [PATCH 1/4] remove bubbletea from init Signed-off-by: Rakshit Gondwal --- cmd/init/init.go | 74 +++++++++++++++++++-- cmd/init/model.go | 159 ---------------------------------------------- 2 files changed, 69 insertions(+), 164 deletions(-) delete mode 100644 cmd/init/model.go diff --git a/cmd/init/init.go b/cmd/init/init.go index c66b7966..2bc19451 100644 --- a/cmd/init/init.go +++ b/cmd/init/init.go @@ -4,7 +4,6 @@ import ( "fmt" "os" - tea "github.com/charmbracelet/bubbletea" "github.com/spf13/cobra" bsfv1 "github.com/buildsafedev/bsf-apis/go/buildsafe/v1" @@ -12,7 +11,11 @@ import ( "github.com/buildsafedev/bsf/cmd/precheck" "github.com/buildsafedev/bsf/cmd/styles" "github.com/buildsafedev/bsf/pkg/clients/search" + "github.com/buildsafedev/bsf/pkg/generate" + bgit "github.com/buildsafedev/bsf/pkg/git" "github.com/buildsafedev/bsf/pkg/hcl2nix" + "github.com/buildsafedev/bsf/pkg/langdetect" + "github.com/buildsafedev/bsf/pkg/nix/cmd" ) // InitCmd represents the init command @@ -35,17 +38,78 @@ var InitCmd = &cobra.Command{ sc, err := search.NewClientWithAddr(conf.BuildSafeAPI, conf.BuildSafeAPITLS) if err != nil { + fmt.Println(styles.ErrorStyle.Render("error:", err.Error())) os.Exit(1) } - m := model{sc: sc} - m.resetSpinner() - if _, err := tea.NewProgram(m).Run(); err != nil { + err = initializeProject(sc) + if err != nil { + fmt.Println(styles.ErrorStyle.Render("error:", err.Error())) + cleanUp() os.Exit(1) } + + fmt.Println(styles.SucessStyle.Render("Initialized successfully!")) }, } +func initializeProject(sc bsfv1.SearchServiceClient) error { + fmt.Println(styles.TextStyle.Render("Initializing project, detecting project language...")) + + pt, pd, err := langdetect.FindProjectType() + if err != nil { + return err + } + + fmt.Println(styles.TextStyle.Render("Detected language as " + string(pt))) + if pt == langdetect.Unknown { + return fmt.Errorf("project language isn't currently supported, some features might not work") + } + + fmt.Println(styles.TextStyle.Render("Resolving dependencies...")) + + fh, err := hcl2nix.NewFileHandlers(false) + if err != nil { + return err + } + defer fh.ModFile.Close() + defer fh.LockFile.Close() + defer fh.FlakeFile.Close() + defer fh.DefFlakeFile.Close() + + conf, err := generatehcl2NixConf(pt, pd) + if err != nil { + return err + } + + err = hcl2nix.WriteConfig(conf, fh.ModFile) + if err != nil { + return err + } + + err = generate.Generate(fh, sc) + if err != nil { + return err + } + + err = cmd.Lock() + if err != nil { + return err + } + + err = bgit.Add("bsf/") + if err != nil { + return err + } + + err = bgit.Ignore("bsf-result/") + if err != nil { + return err + } + + return nil +} + // GetBSFInitializers generates the nix files func GetBSFInitializers() (bsfv1.SearchServiceClient, *hcl2nix.FileHandlers, error) { if _, err := os.Stat("bsf.hcl"); err != nil { @@ -72,7 +136,7 @@ func GetBSFInitializers() (bsfv1.SearchServiceClient, *hcl2nix.FileHandlers, err } // CleanUp removes the bsf config if any error occurs in init process (ctrl+c or any init process stage) -func cleanUp(){ +func cleanUp() { configs := []string{"bsf", "bsf.hcl", "bsf.lock"} for _, f := range configs { diff --git a/cmd/init/model.go b/cmd/init/model.go deleted file mode 100644 index ddc1c7dd..00000000 --- a/cmd/init/model.go +++ /dev/null @@ -1,159 +0,0 @@ -package init - -import ( - "fmt" - "time" - - "github.com/charmbracelet/bubbles/spinner" - tea "github.com/charmbracelet/bubbletea" - - buildsafev1 "github.com/buildsafedev/bsf-apis/go/buildsafe/v1" - "github.com/buildsafedev/bsf/cmd/styles" - "github.com/buildsafedev/bsf/pkg/generate" - bgit "github.com/buildsafedev/bsf/pkg/git" - "github.com/buildsafedev/bsf/pkg/hcl2nix" - "github.com/buildsafedev/bsf/pkg/langdetect" - "github.com/buildsafedev/bsf/pkg/nix/cmd" -) - -var ( - // ANSI codes reference- https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 - textStyle = styles.TextStyle.Render - sucessStyle = styles.SucessStyle.Render - spinnerStyle = styles.SpinnerStyle - helpStyle = styles.HelpStyle.Render - errorStyle = styles.ErrorStyle.Render - stages = 4 -) - -type model struct { - spinner spinner.Model - sc buildsafev1.SearchServiceClient - stageMsg string - permMsg string - stage int - pt langdetect.ProjectType - pd *langdetect.ProjectDetails -} - -func (m model) Init() tea.Cmd { - return tea.Tick(time.Second, func(t time.Time) tea.Msg { - return spinner.TickMsg(spinner.TickMsg{Time: t}) - }) -} - -func (m *model) resetSpinner() { - m.spinner = spinner.New() - m.spinner.Style = spinnerStyle - m.spinner.Spinner = spinner.Points -} - -func (m model) View() (s string) { - s += fmt.Sprintf("\n %s%s%s\n\n", m.spinner.View(), " ", m.stageMsg) - if m.permMsg != "" { - s += fmt.Sprintf("\n %s\n", m.permMsg) - } - return s -} - -func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "q", "esc": - cleanUp() - return m, tea.Quit - } - } - - var err error - if m.stage >= stages { - m.stageMsg = sucessStyle("Initialised sucessfully!") - return m, tea.Quit - } - err = m.processStages(m.stage) - if err != nil { - cleanUp() - return m, tea.Quit - } - m.stage++ - - var cmd tea.Cmd - m.spinner, cmd = m.spinner.Update(spinner.TickMsg(spinner.TickMsg{Time: time.Now()})) - return m, cmd -} - -func (m *model) processStages(stage int) error { - switch stage { - case 0: - m.stageMsg = textStyle("Initializing project, detecting project language.. ") - return nil - case 1: - // var err error - pt, pd, err := langdetect.FindProjectType() - if err != nil { - m.stageMsg = errorStyle(err.Error()) - return err - } - m.stageMsg = textStyle("Detected language as " + string(pt)) - if m.pt == langdetect.Unknown { - m.permMsg = errorStyle("Project language isn't currently supported. Some features might not work.") - } - m.pt = pt - m.pd = pd - return nil - case 2: - m.stageMsg = textStyle("Resolving dependencies... ") - return nil - - case 3: - fh, err := hcl2nix.NewFileHandlers(false) - if err != nil { - m.stageMsg = errorStyle(err.Error()) - return err - } - defer fh.ModFile.Close() - defer fh.LockFile.Close() - defer fh.FlakeFile.Close() - defer fh.DefFlakeFile.Close() - - conf, err := generatehcl2NixConf(m.pt, m.pd) - if err != nil { - m.stageMsg = errorStyle(err.Error()) - return err - } - err = hcl2nix.WriteConfig(conf, fh.ModFile) - if err != nil { - m.stageMsg = errorStyle(err.Error()) - return err - } - - err = generate.Generate(fh, m.sc) - if err != nil { - m.stageMsg = errorStyle(err.Error()) - return err - } - - err = cmd.Lock() - if err != nil { - m.stageMsg = errorStyle(err.Error()) - return err - } - - err = bgit.Add("bsf/") - if err != nil { - m.stageMsg = errorStyle(err.Error()) - return err - } - - err = bgit.Ignore("bsf-result/") - if err != nil { - m.stageMsg = errorStyle(err.Error()) - return err - } - - return nil - } - - return nil -} From 96051adf4ee2c3c19740f736d7ace24ddf3e90c1 Mon Sep 17 00:00:00 2001 From: Rakshit Gondwal Date: Sun, 26 May 2024 21:30:57 +0530 Subject: [PATCH 2/4] add tracker Signed-off-by: Rakshit Gondwal --- cmd/init/init.go | 65 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/cmd/init/init.go b/cmd/init/init.go index 2bc19451..900cb354 100644 --- a/cmd/init/init.go +++ b/cmd/init/init.go @@ -3,7 +3,9 @@ package init import ( "fmt" "os" + "time" + "github.com/jedib0t/go-pretty/v6/progress" "github.com/spf13/cobra" bsfv1 "github.com/buildsafedev/bsf-apis/go/buildsafe/v1" @@ -54,20 +56,33 @@ var InitCmd = &cobra.Command{ } func initializeProject(sc bsfv1.SearchServiceClient) error { - fmt.Println(styles.TextStyle.Render("Initializing project, detecting project language...")) + // Set up the progress writer + pw, steps := setupProgressTracker() - pt, pd, err := langdetect.FindProjectType() - if err != nil { - return err + trackers := make([]*progress.Tracker, len(steps)) + for i, step := range steps { + trackers[i] = &progress.Tracker{Message: step, Total: 100} + pw.AppendTracker(trackers[i]) } - fmt.Println(styles.TextStyle.Render("Detected language as " + string(pt))) - if pt == langdetect.Unknown { - return fmt.Errorf("project language isn't currently supported, some features might not work") + go pw.Render() + + // Initialize progress tracking + updateProgress := func(tracker *progress.Tracker, progress int64) { + tracker.SetValue(progress) + if progress >= 100 { + tracker.MarkAsDone() + } } - fmt.Println(styles.TextStyle.Render("Resolving dependencies...")) + // Detect project language + pt, pd, err := langdetect.FindProjectType() + if err != nil { + return err + } + updateProgress(trackers[0], 100) + // Resolve dependencies fh, err := hcl2nix.NewFileHandlers(false) if err != nil { return err @@ -76,32 +91,40 @@ func initializeProject(sc bsfv1.SearchServiceClient) error { defer fh.LockFile.Close() defer fh.FlakeFile.Close() defer fh.DefFlakeFile.Close() + updateProgress(trackers[1], 100) + // Write configuration conf, err := generatehcl2NixConf(pt, pd) if err != nil { return err } - err = hcl2nix.WriteConfig(conf, fh.ModFile) if err != nil { return err } + updateProgress(trackers[2], 100) + // Generate files err = generate.Generate(fh, sc) if err != nil { return err } + updateProgress(trackers[3], 100) + // Lock dependencies err = cmd.Lock() if err != nil { return err } + updateProgress(trackers[4], 100) + // Add to git err = bgit.Add("bsf/") if err != nil { return err } + // Set up git ignore err = bgit.Ignore("bsf-result/") if err != nil { return err @@ -143,3 +166,27 @@ func cleanUp() { os.RemoveAll(f) } } + +func setupProgressTracker() (progress.Writer, []string) { + pw := progress.NewWriter() + pw.SetAutoStop(true) + pw.SetTrackerLength(25) + pw.SetMessageLength(50) + pw.SetUpdateFrequency(time.Millisecond * 100) + pw.Style().Colors = progress.StyleColorsExample + pw.Style().Options.PercentFormat = "%4.1f%%" + pw.Style().Visibility.ETA = true + pw.Style().Visibility.Percentage = true + pw.Style().Visibility.Time = true + + // Define the steps and create trackers for each + steps := []string{ + "Detecting project language...", + "Resolving dependencies...", + "Writing configuration...", + "Generating files...", + "Locking dependencies...", + } + + return pw, steps +} From 5fef660414333b89477ae72bc74d9a87f5797ce2 Mon Sep 17 00:00:00 2001 From: Rakshit Gondwal Date: Wed, 5 Jun 2024 14:13:19 +0530 Subject: [PATCH 3/4] add time tracker Signed-off-by: Rakshit Gondwal --- cmd/init/init.go | 7 ++++--- pkg/nix/cmd/closure.go | 1 - pkg/nix/cmd/lock.go | 9 ++++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/cmd/init/init.go b/cmd/init/init.go index 900cb354..75e0b55a 100644 --- a/cmd/init/init.go +++ b/cmd/init/init.go @@ -112,11 +112,12 @@ func initializeProject(sc bsfv1.SearchServiceClient) error { updateProgress(trackers[3], 100) // Lock dependencies - err = cmd.Lock() + err = cmd.Lock(func(progress int) { + updateProgress(trackers[4], int64(progress)) + }) if err != nil { return err } - updateProgress(trackers[4], 100) // Add to git err = bgit.Add("bsf/") @@ -187,6 +188,6 @@ func setupProgressTracker() (progress.Writer, []string) { "Generating files...", "Locking dependencies...", } - + return pw, steps } diff --git a/pkg/nix/cmd/closure.go b/pkg/nix/cmd/closure.go index 8fe3c644..b613e8cd 100644 --- a/pkg/nix/cmd/closure.go +++ b/pkg/nix/cmd/closure.go @@ -137,7 +137,6 @@ func addNarHashToGraph(graph *gographviz.Graph) { } wg.Wait() - return } // GetNarHashFromPath returns the sha256 hash of the nar diff --git a/pkg/nix/cmd/lock.go b/pkg/nix/cmd/lock.go index 815549bc..d7287d48 100644 --- a/pkg/nix/cmd/lock.go +++ b/pkg/nix/cmd/lock.go @@ -4,10 +4,11 @@ import ( "fmt" "os" "os/exec" + "time" ) // Lock generates the Nix flake lock file -func Lock() error { +func Lock(reportProgress func(int)) error { dir, err := os.Getwd() if err != nil { return err @@ -24,6 +25,12 @@ func Lock() error { return fmt.Errorf("failed with %s", err) } + // Simulate incremental progress + for i := 0; i <= 100; i += 10 { + time.Sleep(100 * time.Millisecond) + reportProgress(i) + } + err = cmd.Wait() if err != nil { if exitError, ok := err.(*exec.ExitError); ok { From 8c900d3b9dc66acc5e2ca60693b63817f306f603 Mon Sep 17 00:00:00 2001 From: Rakshit Gondwal Date: Wed, 5 Jun 2024 15:37:38 +0530 Subject: [PATCH 4/4] modify cleanup Signed-off-by: Rakshit Gondwal --- cmd/init/init.go | 7 +++++-- pkg/hcl2nix/file.go | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/init/init.go b/cmd/init/init.go index 75e0b55a..d7467714 100644 --- a/cmd/init/init.go +++ b/cmd/init/init.go @@ -46,8 +46,11 @@ var InitCmd = &cobra.Command{ err = initializeProject(sc) if err != nil { - fmt.Println(styles.ErrorStyle.Render("error:", err.Error())) - cleanUp() + errorMessage := err.Error() + fmt.Println(styles.ErrorStyle.Render("Error:", errorMessage)) + if errorMessage != "project already initialised. bsf.hcl found" { + cleanUp() + } os.Exit(1) } diff --git a/pkg/hcl2nix/file.go b/pkg/hcl2nix/file.go index 336c3393..423546bd 100644 --- a/pkg/hcl2nix/file.go +++ b/pkg/hcl2nix/file.go @@ -42,7 +42,7 @@ func NewFileHandlers(expectInit bool) (*FileHandlers, error) { } if exists != expectInit { - return nil, fmt.Errorf("Project already initialised. bsf.hcl found") + return nil, fmt.Errorf("project already initialised. bsf.hcl found") } lockFile, err := os.Create("bsf.lock")