From ed172f2805046a9d44914828421f6f5afb00cc73 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Sun, 26 Oct 2025 20:06:55 +0200 Subject: [PATCH] Add progress bars --- src/bpm/go.mod | 9 ++++++--- src/bpm/go.sum | 20 ++++++++++++++++++++ src/bpmlib/compilation.go | 4 ++-- src/bpmlib/databases.go | 29 +++++++++++++++++++++++++---- src/bpmlib/go.mod | 10 +++++++++- src/bpmlib/go.sum | 20 ++++++++++++++++++++ src/bpmlib/net.go | 29 +++++++++++++---------------- src/bpmlib/operations.go | 18 +++++++++++------- src/bpmlib/packages.go | 18 +++++++++++++++++- src/bpmlib/utils.go | 28 ++++++++++++++++++++++++++++ 10 files changed, 151 insertions(+), 34 deletions(-) diff --git a/src/bpm/go.mod b/src/bpm/go.mod index 29cbb80..337f54e 100644 --- a/src/bpm/go.mod +++ b/src/bpm/go.mod @@ -1,8 +1,6 @@ module git.enumerated.dev/bubble-package-manager/bpm/src/bpm -go 1.23 - -toolchain go1.23.7 +go 1.24.0 require ( git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib v0.5.0 @@ -15,6 +13,11 @@ replace git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib => ../bpmlib require ( github.com/drone/envsubst v1.0.3 // indirect github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f // indirect + github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/schollz/progressbar/v3 v3.18.0 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/term v0.36.0 // indirect golang.org/x/text v0.9.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/src/bpm/go.sum b/src/bpm/go.sum index 968b419..22ad960 100644 --- a/src/bpm/go.sum +++ b/src/bpm/go.sum @@ -1,3 +1,7 @@ +github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= +github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g= github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= @@ -6,8 +10,20 @@ github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f h1:xt29M2T github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f/go.mod h1:i4sF0l1fFnY1aiw08QQSwVAFxHEm311Me3WsU/X7nL0= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA= +github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -26,9 +42,13 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/src/bpmlib/compilation.go b/src/bpmlib/compilation.go index 84de1d2..fe21fbf 100644 --- a/src/bpmlib/compilation.go +++ b/src/bpmlib/compilation.go @@ -343,7 +343,7 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks, k } func downloadPackageFiles(pkgInfo *PackageInfo, tempDirectory string, verbose bool) error { - for _, download := range pkgInfo.Downloads { + for i, download := range pkgInfo.Downloads { // Replace variables replaceVars := func(s string) string { switch s { @@ -387,7 +387,7 @@ func downloadPackageFiles(pkgInfo *PackageInfo, tempDirectory string, verbose bo filepath = path.Join(tempDirectory, download.Filepath) } - err := downloadFile(downloadUrl, filepath, 0644) + err := downloadFile("Downloading file "+strconv.Itoa(i+1), downloadUrl, filepath, 0644) if err != nil { return err } diff --git a/src/bpmlib/databases.go b/src/bpmlib/databases.go index fd0726a..cb71490 100644 --- a/src/bpmlib/databases.go +++ b/src/bpmlib/databases.go @@ -1,9 +1,13 @@ package bpmlib import ( + "bufio" + "bytes" "errors" "fmt" + "io" "maps" + "net/http" "net/url" "os" "path" @@ -135,13 +139,30 @@ func (db *configDatabase) SyncLocalDatabaseFile() error { } // Retrieve data from URL - buffer, err := retrieveUrlData(u) + req, err := http.NewRequest("GET", u, nil) + if err != nil { + return err + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + // Create progress bar + bar := createProgressBar(resp.ContentLength, "Syncing "+db.Name, false) + + // Copy data + var buffer bytes.Buffer + bufferWriter := bufio.NewWriter(&buffer) + _, err = io.Copy(io.MultiWriter(bufferWriter, bar), resp.Body) if err != nil { return err } // Unmarshal data to ensure it is a valid BPM database - err = yaml.Unmarshal(buffer, &BPMDatabase{}) + err = yaml.Unmarshal(buffer.Bytes(), &BPMDatabase{}) if err != nil { return fmt.Errorf("could not decode database: %s", err) } @@ -159,7 +180,7 @@ func (db *configDatabase) SyncLocalDatabaseFile() error { } defer out.Close() - _, err = out.Write(buffer) + _, err = out.Write(buffer.Bytes()) return nil } @@ -244,7 +265,7 @@ func (db *BPMDatabase) FetchPackage(pkg string) (string, error) { } // Download package from url - err = downloadFile(u, path.Join("/var/cache/bpm/fetched/", path.Base(entry.Filepath)), 0644) + err = downloadFile("Downloading "+entry.Info.Name, u, path.Join("/var/cache/bpm/fetched/", path.Base(entry.Filepath)), 0644) if err != nil { return "", err } diff --git a/src/bpmlib/go.mod b/src/bpmlib/go.mod index 46b4404..96d6ca3 100644 --- a/src/bpmlib/go.mod +++ b/src/bpmlib/go.mod @@ -1,9 +1,17 @@ module git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib -go 1.23 +go 1.24.0 require ( github.com/drone/envsubst v1.0.3 github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f + github.com/schollz/progressbar/v3 v3.18.0 gopkg.in/yaml.v3 v3.0.1 ) + +require ( + github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect + github.com/rivo/uniseg v0.4.7 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/term v0.36.0 // indirect +) diff --git a/src/bpmlib/go.sum b/src/bpmlib/go.sum index b639e84..ae8731f 100644 --- a/src/bpmlib/go.sum +++ b/src/bpmlib/go.sum @@ -1,9 +1,29 @@ +github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= +github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g= github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f h1:xt29M2T6STgldg+WEP51gGePQCsQvklmP2eIhPIBK3g= github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f/go.mod h1:i4sF0l1fFnY1aiw08QQSwVAFxHEm311Me3WsU/X7nL0= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA= +github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/src/bpmlib/net.go b/src/bpmlib/net.go index 60c01e5..420a96b 100644 --- a/src/bpmlib/net.go +++ b/src/bpmlib/net.go @@ -9,29 +9,22 @@ import ( "strings" ) -func retrieveUrlData(u string) ([]byte, error) { - resp, err := http.Get(u) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - // Load data into byte buffer - buffer, err := io.ReadAll(resp.Body) - - return buffer, nil -} - -func downloadFile(u, filepath string, perm os.FileMode) error { +func downloadFile(barText, u, filepath string, perm os.FileMode) error { if strings.HasSuffix(filepath, "/") { return fmt.Errorf("Filepath must not end in '/'") } - data, err := retrieveUrlData(u) + req, err := http.NewRequest("GET", u, nil) if err != nil { return err } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + // Create parent directories err = os.MkdirAll(path.Dir(filepath), 0755) if err != nil { @@ -45,8 +38,12 @@ func downloadFile(u, filepath string, perm os.FileMode) error { } defer file.Close() + // Create progress bar + bar := createProgressBar(resp.ContentLength, barText, false) + defer bar.Close() + // Copy data - _, err = file.Write(data) + _, err = io.Copy(io.MultiWriter(file, bar), resp.Body) if err != nil { return err } diff --git a/src/bpmlib/operations.go b/src/bpmlib/operations.go index 7f1e22c..848f087 100644 --- a/src/bpmlib/operations.go +++ b/src/bpmlib/operations.go @@ -478,7 +478,7 @@ func (operation *BPMOperation) FetchPackages() (err error) { var bpmpkg *BPMPackage // Check if package has already been fetched from download link - if _, ok := fetchedPackages[entry.Filepath]; !ok { + if fetchedFilepath, ok := fetchedPackages[entry.Filepath]; !ok { // Fetch package from database fetchedPackage, err := entry.Database.FetchPackage(entry.Info.Name) if err != nil { @@ -493,16 +493,22 @@ func (operation *BPMOperation) FetchPackages() (err error) { // Add fetched package to map fetchedPackages[entry.Filepath] = fetchedPackage - - fmt.Printf("Package (%s) was successfully fetched!\n", entry.Info.Name) } else { // Read fetched package - bpmpkg, err = ReadPackage(fetchedPackages[entry.Filepath]) + bpmpkg, err = ReadPackage(fetchedFilepath) if err != nil { return fmt.Errorf("could not read package (%s): %s\n", entry.Info.Name, err) } - fmt.Printf("Package (%s) was successfully fetched!\n", entry.Info.Name) + // Get size of fetched archive + stat, err := os.Stat(fetchedFilepath) + if err != nil { + return err + } + + bar := createProgressBar(stat.Size(), "Downloading "+entry.Info.Name, false) + bar.Set64(stat.Size()) + bar.Close() } if bpmpkg.PkgInfo.IsSplitPackage() { @@ -622,8 +628,6 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) { if err != nil { return fmt.Errorf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err) } - - fmt.Printf("Package (%s) was successfully installed\n", bpmpkg.PkgInfo.Name) } } fmt.Println("Operation complete!") diff --git a/src/bpmlib/packages.go b/src/bpmlib/packages.go index 005cd2d..82be0ff 100644 --- a/src/bpmlib/packages.go +++ b/src/bpmlib/packages.go @@ -601,6 +601,10 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) return err } + // Initialize progress bar + bar := createProgressBar(int64(bpmpkg.GetInstalledSize()), "Installing "+bpmpkg.PkgInfo.Name, verbose) + defer bar.Close() + tarballFile, err := readTarballFile(filename, "files.tar.gz") if err != nil { return err @@ -612,6 +616,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) return err } packageFilesReader := tar.NewReader(archive) + for { header, err := packageFilesReader.Next() if err == io.EOF { @@ -648,6 +653,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) if verbose { fmt.Printf("Created directory %s (%o)\n", extractFilename, header.Mode) } + bar.Add64(header.Size) case tar.TypeReg: skip := false if _, err := os.Stat(extractFilename); err == nil { @@ -704,6 +710,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) if verbose { fmt.Printf("Created File: %s (%o)\n", extractFilename, header.Mode) } + bar.Add64(header.Size) case tar.TypeSymlink: err := os.Remove(extractFilename) if err != nil && !os.IsNotExist(err) { @@ -718,6 +725,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) if verbose { fmt.Println("Created Symlink: " + extractFilename + " -> " + header.Linkname) } + bar.Add64(header.Size) case tar.TypeLink: if verbose { fmt.Println("Detected Hard Link: " + extractFilename + " -> " + path.Join(rootDir, strings.TrimPrefix(header.Linkname, "files/"))) @@ -727,6 +735,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) if err != nil && !os.IsNotExist(err) { return err } + bar.Add64(header.Size) default: return errors.New("unknown type (" + strconv.Itoa(int(header.Typeflag)) + ") in " + extractFilename) } @@ -979,8 +988,11 @@ func removePackage(pkg string, verbose bool, rootDir string) error { log.Printf("Warning: %s\n", err) } + // Get BPM package + bpmpkg := GetPackage(pkg, rootDir) + // Fetching and reversing package file entry list - fileEntries := GetPackage(pkg, rootDir).PkgFiles + fileEntries := bpmpkg.PkgFiles sort.Slice(fileEntries, func(i, j int) bool { return fileEntries[i].Path < fileEntries[j].Path }) @@ -990,8 +1002,12 @@ func removePackage(pkg string, verbose bool, rootDir string) error { return err } + bar := createProgressBar(int64(bpmpkg.GetInstalledSize()), "Removing "+bpmpkg.PkgInfo.Name, verbose) + defer bar.Close() + // Removing package files for _, entry := range fileEntries { + bar.Add64(int64(entry.SizeInBytes)) file := path.Join(rootDir, entry.Path) lstat, err := os.Lstat(file) if os.IsNotExist(err) { diff --git a/src/bpmlib/utils.go b/src/bpmlib/utils.go index a259245..270bd8d 100644 --- a/src/bpmlib/utils.go +++ b/src/bpmlib/utils.go @@ -2,10 +2,14 @@ package bpmlib import ( "fmt" + "io" "math" "os" "path" "syscall" + "time" + + "github.com/schollz/progressbar/v3" ) type BPMLock struct { @@ -64,6 +68,30 @@ func GetArch() string { return string(byteString[:indexLength]) } +func createProgressBar(max int64, description string, hideBar bool) *progressbar.ProgressBar { + var output io.Writer + if hideBar { + output = io.Discard + } else { + output = os.Stderr + } + + return progressbar.NewOptions64(max, + progressbar.OptionSetDescription(description), + progressbar.OptionSetWriter(output), + progressbar.OptionShowBytes(true), + progressbar.OptionShowTotalBytes(true), + progressbar.OptionSetWidth(20), + progressbar.OptionThrottle(65*time.Millisecond), + progressbar.OptionShowCount(), + progressbar.OptionOnCompletion(func() { + fmt.Fprint(output, "\n") + }), + progressbar.OptionSpinnerType(14), + progressbar.OptionSetRenderBlankState(true), + progressbar.OptionSetTheme(progressbar.ThemeASCII)) +} + func stringSliceRemove(s []string, r string) []string { for i, v := range s { if v == r {