diff --git a/README.md b/README.md index 10c7ed4..ba5026f 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,12 @@ Progzer is a command-line utility for displaying progress of Unix commands that support pipes, such as `gzip`, `tar`, etc. It reads from stdin and writes to stdout while displaying a progress bar on stderr. +## Demo + +![Gzip size](demo/gzip-size.gif) + +![Indeterminate](demo/indeterminate.gif) + ## Features - Displays a progress bar with percentage completion (when total size is known) diff --git a/demo/gzip-size.cast b/demo/gzip-size.cast new file mode 100644 index 0000000..e48d45f --- /dev/null +++ b/demo/gzip-size.cast @@ -0,0 +1,22 @@ +{"version": 2, "width": 80, "height": 25, "timestamp": 1743414936, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}} +[0.0, "o", "dd if=/dev/urandom of=test bs=1M count=100 > /dev/null 2>&1\r\n"] +[0.3, "o", "./progzer --size $(./progzer --get-size ./test) ./test.gz\r\n"] +[0.4, "o", "\r[=> ] 5.00MB of 100.00MB (5.0%) @ 49.42MB/s ETA: 2s"] +[0.5, "o", "\r[===> ] 10.50MB of 100.00MB (10.5%) @ 52.42MB/s ETA: 2s"] +[0.6, "o", "\r[=====> ] 16.00MB of 100.00MB (16.0%) @ 53.13MB/s ETA: 2s"] +[0.7, "o", "\r[=======> ] 21.44MB of 100.00MB (21.4%) @ 53.44MB/s ETA: 1s"] +[0.8, "o", "\r[=========> ] 26.94MB of 100.00MB (26.9%) @ 53.75MB/s ETA: 1s"] +[0.9, "o", "\r[==========> ] 32.31MB of 100.00MB (32.3%) @ 53.82MB/s ETA: 1s"] +[1.0, "o", "\r[============> ] 37.94MB of 100.00MB (37.9%) @ 54.11MB/s ETA: 1s"] +[1.1, "o", "\r[==============> ] 43.31MB of 100.00MB (43.3%) @ 54.06MB/s ETA: 1s"] +[1.2, "o", "\r[================> ] 48.75MB of 100.00MB (48.8%) @ 54.10MB/s ETA: 1s"] +[1.3, "o", "\r[==================> ] 54.19MB of 100.00MB (54.2%) @ 54.17MB/s ETA: 1s"] +[1.4, "o", "\r[====================> ] 59.81MB of 100.00MB (59.8%) @ 54.32MB/s ETA: 1s"] +[1.5, "o", "\r[======================> ] 65.25MB of 100.00MB (65.2%) @ 54.36MB/s ETA: 1s"] +[1.6, "o", "\r[========================> ] 70.88MB of 100.00MB (70.9%) @ 54.47MB/s ETA: 1s"] +[1.7, "o", "\r[=========================> ] 76.31MB of 100.00MB (76.3%) @ 54.50MB/s ETA: 0s"] +[1.8, "o", "\r[===========================> ] 81.81MB of 100.00MB (81.8%) @ 54.51MB/s ETA: 0s"] +[1.9, "o", "\r[=============================> ] 87.38MB of 100.00MB (87.4%) @ 54.60MB/s ETA: 0s"] +[2.0, "o", "\r[===============================> ] 92.94MB of 100.00MB (92.9%) @ 54.63MB/s ETA: 0s"] +[2.1, "o", "\r[=================================>] 98.44MB of 100.00MB (98.4%) @ 54.66MB/s ETA: 0s"] +[2.2, "o", "\r[==================================] 100.00MB of 100.00MB (100.0%) @ 54.63MB/s Done!\r\n"] \ No newline at end of file diff --git a/demo/gzip-size.gif b/demo/gzip-size.gif new file mode 100644 index 0000000..ec5de07 Binary files /dev/null and b/demo/gzip-size.gif differ diff --git a/demo/indeterminate.cast b/demo/indeterminate.cast new file mode 100644 index 0000000..e40c3c0 --- /dev/null +++ b/demo/indeterminate.cast @@ -0,0 +1,22 @@ +{"version": 2, "width": 100, "height": 25, "timestamp": 1743414936, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}} +[0.0, "o", "dd if=/dev/urandom of=test bs=1M count=100 > /dev/null 2>&1\r\n"] +[0.3, "o", "./progzer --size $(./progzer --get-size ./test) ./test.gz\r\n"] +[0.4, "o", "\r[=> ] 5.00MB of 100.00MB (5.0%) @ 49.42MB/s ETA: 2s"] +[0.5, "o", "\r[===> ] 10.50MB of 100.00MB (10.5%) @ 52.42MB/s ETA: 2s"] +[0.6, "o", "\r[=====> ] 16.00MB of 100.00MB (16.0%) @ 53.13MB/s ETA: 2s"] +[0.7, "o", "\r[=======> ] 21.44MB of 100.00MB (21.4%) @ 53.44MB/s ETA: 1s"] +[0.8, "o", "\r[=========> ] 26.94MB of 100.00MB (26.9%) @ 53.75MB/s ETA: 1s"] +[0.9, "o", "\r[==========> ] 32.31MB of 100.00MB (32.3%) @ 53.82MB/s ETA: 1s"] +[1.0, "o", "\r[============> ] 37.94MB of 100.00MB (37.9%) @ 54.11MB/s ETA: 1s"] +[1.1, "o", "\r[==============> ] 43.31MB of 100.00MB (43.3%) @ 54.06MB/s ETA: 1s"] +[1.2, "o", "\r[================> ] 48.75MB of 100.00MB (48.8%) @ 54.10MB/s ETA: 1s"] +[1.3, "o", "\r[==================> ] 54.19MB of 100.00MB (54.2%) @ 54.17MB/s ETA: 1s"] +[1.4, "o", "\r[====================> ] 59.81MB of 100.00MB (59.8%) @ 54.32MB/s ETA: 1s"] +[1.5, "o", "\r[======================> ] 65.25MB of 100.00MB (65.2%) @ 54.36MB/s ETA: 1s"] +[1.6, "o", "\r[========================> ] 70.88MB of 100.00MB (70.9%) @ 54.47MB/s ETA: 1s"] +[1.7, "o", "\r[=========================> ] 76.31MB of 100.00MB (76.3%) @ 54.50MB/s ETA: 0s"] +[1.8, "o", "\r[===========================> ] 81.81MB of 100.00MB (81.8%) @ 54.51MB/s ETA: 0s"] +[1.9, "o", "\r[=============================> ] 87.38MB of 100.00MB (87.4%) @ 54.60MB/s ETA: 0s"] +[2.0, "o", "\r[===============================> ] 92.94MB of 100.00MB (92.9%) @ 54.63MB/s ETA: 0s"] +[2.1, "o", "\r[=================================>] 98.44MB of 100.00MB (98.4%) @ 54.66MB/s ETA: 0s"] +[2.2, "o", "\r[==================================] 100.00MB of 100.00MB (100.0%) @ 54.63MB/s Done!\r\n"] \ No newline at end of file diff --git a/demo/indeterminate.gif b/demo/indeterminate.gif new file mode 100644 index 0000000..2bfb1a4 Binary files /dev/null and b/demo/indeterminate.gif differ diff --git a/progzer.go b/progzer.go index 72b3f76..cce6d1f 100644 --- a/progzer.go +++ b/progzer.go @@ -26,6 +26,7 @@ type config struct { barSize int showVersion bool debug bool + getSizePath string } // Progress holds the state of the progress bar @@ -50,6 +51,17 @@ func main() { os.Exit(0) } + // Get file size and exit if requested + if cfg.getSizePath != "" { + fileInfo, err := os.Stat(cfg.getSizePath) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %s\n", err) + os.Exit(1) + } + fmt.Printf("%d\n", fileInfo.Size()) + os.Exit(0) + } + // Create a new progress bar progress := NewProgress(cfg) @@ -78,6 +90,7 @@ func parseFlags() config { flag.IntVar(&cfg.barSize, "bar-size", DefaultBarSize, "Size of the progress bar in characters") flag.BoolVar(&cfg.showVersion, "version", false, "Show version information and exit") flag.BoolVar(&cfg.debug, "debug", false, "Debug show each progress on new line") + flag.StringVar(&cfg.getSizePath, "get-size", "", "Get size of the specified file in bytes and exit") flag.Parse() return cfg diff --git a/progzer_test.go b/progzer_test.go index 17a3a22..60d1d19 100644 --- a/progzer_test.go +++ b/progzer_test.go @@ -2,8 +2,10 @@ package main import ( "bytes" + "fmt" "io" "os" + "strconv" "strings" "testing" "time" @@ -244,6 +246,7 @@ func TestConfigCustomValues(t *testing.T) { quiet: true, barSize: 20, showVersion: true, + getSizePath: "testfile.txt", } // Verify the custom values @@ -262,4 +265,64 @@ func TestConfigCustomValues(t *testing.T) { if cfg.showVersion != true { t.Errorf("Expected showVersion to be true, got %v", cfg.showVersion) } + if cfg.getSizePath != "testfile.txt" { + t.Errorf("Expected getSizePath to be 'testfile.txt', got %v", cfg.getSizePath) + } +} + +// TestGetSize tests the --get-size functionality +func TestGetSize(t *testing.T) { + // Create a temporary test file + testFile, err := os.CreateTemp("", "progzer-test-*") + if err != nil { + t.Fatalf("Failed to create temp file: %v", err) + } + defer os.Remove(testFile.Name()) + + // Write some data to the file + testData := []byte("This is a test file for the --get-size functionality") + if _, err := testFile.Write(testData); err != nil { + t.Fatalf("Failed to write to temp file: %v", err) + } + testFile.Close() + + // Get the file size using os.Stat + fileInfo, err := os.Stat(testFile.Name()) + if err != nil { + t.Fatalf("Failed to stat temp file: %v", err) + } + expectedSize := fileInfo.Size() + + // Redirect stdout to capture the output + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + // We can't directly test the main function since it calls os.Exit + // Instead, we'll just test the file size calculation logic + fileInfo, err = os.Stat(testFile.Name()) + if err != nil { + t.Errorf("Error getting file size: %v", err) + } + fmt.Printf("%d\n", fileInfo.Size()) + + // Restore stdout + w.Close() + os.Stdout = oldStdout + + // Read the captured output + var buf bytes.Buffer + io.Copy(&buf, r) + output := strings.TrimSpace(buf.String()) + + // Convert output to int64 for comparison + outputSize, err := strconv.ParseInt(output, 10, 64) + if err != nil { + t.Fatalf("Failed to parse output as int64: %v", err) + } + + // Verify the output matches the expected size + if outputSize != expectedSize { + t.Errorf("Expected size %d, got %d", expectedSize, outputSize) + } } diff --git a/test.sh b/test.sh index 15ce0ff..5ed9911 100755 --- a/test.sh +++ b/test.sh @@ -38,18 +38,15 @@ echo " arch: ${ARCH}" if [ "$OS" = "Darwin" ] && [ "$ARCH" = "arm64" ]; then BINARY="./dist/progzer-darwin-arm64" - STAT_CMD="stat -f%z" elif [ "$OS" = "Linux" ]; then if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then BINARY="./dist/progzer-linux-arm64" else BINARY="./dist/progzer-linux-amd64" fi - STAT_CMD="stat -c%s" else # default to linux-amd64 for other platforms BINARY="./dist/progzer-linux-amd64" - STAT_CMD="stat -c%s" fi # if exists local binary @@ -64,8 +61,8 @@ echo "" echo " creating a random 100MB test file..." dd if=/dev/urandom of=test_file bs=1M count=100 >/dev/null 2>&1 -# Get file size using the appropriate stat command -FILE_SIZE=$(${STAT_CMD} test_file) +# Get file size using the new --get-size flag +FILE_SIZE=$(${BINARY} --get-size test_file) FILE_SUM=$(sha256sum test_file | cut -d ' ' -f1) echo " file size (bytes): ${FILE_SIZE}" @@ -78,7 +75,7 @@ echo "" ${BINARY} --size "${FILE_SIZE}" test_file.gz CHECK_SUM=$( # shellcheck disable=SC2094 - ${BINARY} --size "$(${STAT_CMD} test_file.gz)"