Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions exec/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Package exec provides simplified command execution utilities for running
// shell commands with enhanced error handling and output management.
//
// The package wraps Go's os/exec with convenience functions that handle
// common patterns like forwarding output to console, capturing combined
// output, and ignoring errors for optional operations.
//
// Key Features:
// - Execute commands with automatic stdout/stderr forwarding
// - Safe execution that never panics on errors
// - Environment variable support
// - Printf-style argument formatting
// - Combined output capture
//
// Basic Execution:
//
// // Execute a command and forward output to console
// err := exec.Exec("ls -la")
//
// // Execute with formatted arguments
// err := exec.Execf("echo 'Hello %s'", "World")
//
// // Execute with custom environment variables
// env := map[string]string{
// "DEBUG": "true",
// "CONFIG_PATH": "/etc/app",
// }
// err := exec.ExecfWithEnv("./script.sh", env)
//
// Safe Execution:
//
// SafeExec executes commands and returns success status instead of errors,
// useful for optional operations or when you want to continue on failure:
//
// // Try to get git branch, continue if git isn't available
// branch, ok := exec.SafeExec("git rev-parse --abbrev-ref HEAD")
// if ok {
// fmt.Printf("Current branch: %s\n", branch)
// }
//
// // Check if a command exists
// _, exists := exec.SafeExec("which docker")
// if exists {
// // Docker is installed
// }
//
// Output Handling:
//
// // Exec forwards both stdout and stderr to console
// err := exec.Exec("make build")
// // User sees all output in real-time
//
// // SafeExec captures output and returns it
// output, ok := exec.SafeExec("cat /etc/hostname")
// if ok {
// fmt.Println("Hostname:", output)
// }
//
// Environment Variables:
//
// // Set environment for command execution
// env := map[string]string{
// "PATH": "/usr/local/bin:/usr/bin",
// "DATABASE_URL": "postgres://localhost/mydb",
// }
// err := exec.ExecfWithEnv("migrate up", env)
//
// Error Handling:
//
// // Exec returns error with command output on failure
// if err := exec.Exec("./deploy.sh"); err != nil {
// // err contains both error and stderr output
// log.Fatal(err)
// }
//
// // SafeExec returns false on any error
// output, ok := exec.SafeExec("risky-command")
// if !ok {
// // Command failed, output is empty string
// log.Warn("Command failed, using default")
// }
//
// Formatted Commands:
//
// // Use printf-style formatting for dynamic commands
// filename := "data.json"
// err := exec.Execf("cat %s | jq .", filename)
//
// // Multiple arguments
// src := "/source"
// dst := "/dest"
// err := exec.Execf("rsync -av %s %s", src, dst)
//
// Common Use Cases:
//
// // Run build commands
// exec.Exec("go build -o app ./cmd/server")
//
// // Check tool availability
// if _, ok := exec.SafeExec("which kubectl"); !ok {
// log.Fatal("kubectl not found in PATH")
// }
//
// // Get version information
// version, ok := exec.SafeExec("app --version")
//
// // Run tests with environment
// env := map[string]string{"TEST_ENV": "integration"}
// exec.ExecfWithEnv("go test ./...", env)
//
// Note: All commands are executed through bash -c, providing full shell
// functionality including pipes, redirects, and variable expansion.
package exec
104 changes: 104 additions & 0 deletions files/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Package files provides utilities for file operations, archive handling,
// and path manipulation.
//
// The package offers comprehensive support for working with various archive
// formats (tar, zip, gzip, xz), file path validation, glob pattern matching,
// and common file operations.
//
// Key Features:
// - Archive extraction with detailed results and statistics
// - Support for tar, tar.gz, tar.xz, and zip formats
// - Path traversal vulnerability protection
// - Glob pattern matching with doublestar support
// - File compression and decompression
// - Safe file operations with validation
//
// Archive Extraction:
//
// // Simple extraction
// err := files.UnarchiveSimple("package.tar.gz", "/dest")
//
// // Extraction with detailed results
// result, err := files.Unarchive("package.tar.gz", "/dest")
// fmt.Printf("Extracted %d files (%s)\n", len(result.Files), result.String())
//
// // Extraction with options
// result, err := files.Unarchive("archive.zip", "/dest",
// files.WithOverwrite(true))
//
// // Extract only executables
// err := files.UnarchiveExecutables("binaries.tar.gz", "/usr/local/bin")
//
// Compression:
//
// // Gzip a file
// data, err := files.GzipFile("document.txt")
//
// // Create a zip archive
// err := files.Zip("/source/dir", "archive.zip")
//
// // Decompress xz
// err := files.Unxz("file.xz", "file.txt")
//
// // Decompress gzip
// err := files.Ungzip("file.gz", "file.txt")
//
// Path Operations:
//
// // Validate path (check for traversal attacks)
// err := files.ValidatePath("../../etc/passwd") // Returns error
//
// // Check file type by extension
// if files.IsValidPathType("config.yaml", ".yaml", ".yml") {
// // Process YAML file
// }
//
// // Get base name without extension
// name := files.GetBaseName("config.yaml") // "config"
//
// Glob Matching:
//
// // Expand glob patterns
// matches, err := files.UnfoldGlobs("**/*.go", "**/*.yaml")
//
// // Match with doublestar patterns
// files, err := files.DoubleStarGlob("/project", []string{"**/*.go"})
//
// File Operations:
//
// // Check if file exists
// if files.Exists("/path/to/file") {
// // File exists
// }
//
// // Safe read (returns empty string on error)
// content := files.SafeRead("/path/to/file")
//
// // Copy file
// err := files.Copy("/source/file", "/dest/file")
//
// // Copy from reader with permissions
// n, err := files.CopyFromReader(reader, "/dest/file", 0644)
//
// // Create temp file with custom name
// tmpFile := files.TempFileName("prefix-", ".txt")
//
// Archive Results:
//
// The Archive type provides detailed information about extraction operations:
//
// result, _ := files.Unarchive("package.tar.gz", "/dest")
// fmt.Printf("Files: %d\n", len(result.Files))
// fmt.Printf("Directories: %d\n", len(result.Directories))
// fmt.Printf("Symlinks: %d\n", len(result.Symlinks))
// fmt.Printf("Size: %s -> %s (%.1f%% compression)\n",
// formatSize(result.CompressedSize),
// formatSize(result.ExtractedSize),
// result.CompressionRatio*100)
//
// Security:
//
// The package includes protection against path traversal vulnerabilities
// when extracting archives. All paths are validated to ensure they don't
// escape the destination directory.
package files
92 changes: 92 additions & 0 deletions is/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Package is provides simple type checking and environment detection utilities.
//
// The package offers concise boolean functions for common type checks and
// runtime environment detection. All functions follow the pattern is.X()
// for readable, natural-language code.
//
// Key Features:
// - Type checking with reflection
// - File and archive detection
// - Terminal/TTY detection
// - Simple, readable API
//
// Type Checking:
//
// // Check if value is a slice
// data := []string{"a", "b", "c"}
// if is.Slice(data) {
// // data is a slice
// }
//
// // Works with any type
// numbers := []int{1, 2, 3}
// is.Slice(numbers) // true
//
// str := "hello"
// is.Slice(str) // false
//
// File Detection:
//
// // Check if file exists
// if is.File("/etc/hosts") {
// // File exists
// }
//
// // Check if file is an archive
// if is.Archive("package.tar.gz") {
// // Extract the archive
// }
//
// // Supported archive formats
// is.Archive("file.zip") // true
// is.Archive("file.tar.gz") // true
// is.Archive("file.gz") // true
// is.Archive("file.xz") // true
// is.Archive("file.txz") // true
// is.Archive("file.txt") // false
//
// Terminal Detection:
//
// // Check if running in an interactive terminal
// if is.TTY() {
// // Enable colored output, progress bars, etc.
// fmt.Println("\033[32mGreen text\033[0m")
// } else {
// // Plain output for logs, pipes, redirects
// fmt.Println("Plain text")
// }
//
// Common Use Cases:
//
// // Conditional output formatting
// if is.TTY() {
// showProgressBar()
// } else {
// logToFile()
// }
//
// // File processing
// if is.File(configPath) {
// loadConfig(configPath)
// }
//
// // Archive handling
// if is.Archive(input) {
// extractArchive(input)
// } else {
// processFile(input)
// }
//
// // Generic type checking
// if is.Slice(value) {
// processSlice(value)
// }
//
// Limitations:
//
// The Slice function uses reflection and only checks if a value is a slice type.
// It doesn't validate slice element types or other slice properties.
//
// The Archive function only checks file extensions, not actual file content.
// For robust archive detection, consider inspecting file headers/magic numbers.
package is
84 changes: 84 additions & 0 deletions text/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Package text provides utilities for text processing, formatting, and
// manipulation.
//
// The package includes functions for humanizing numbers and durations,
// indenting text, parsing extended duration formats, and safe I/O operations.
//
// Key Features:
// - Human-readable formatting for bytes, numbers, and durations
// - Text indentation for hierarchical output
// - Extended duration parsing (days, weeks, years)
// - Safe I/O operations that never panic
//
// Byte and Number Formatting:
//
// // Format bytes in human-readable form
// text.HumanizeBytes(1536) // "1.5 KB"
// text.HumanizeBytes(1048576) // "1.0 MB"
// text.HumanizeBytes(5368709120) // "5.0 GB"
//
// // Format large numbers with thousand separators
// text.HumanizeInt(1000000) // "1,000,000"
// text.HumanizeInt(42) // "42"
//
// Duration Formatting:
//
// // Format durations in human-readable form
// text.HumanizeDuration(90 * time.Minute) // "1h30m"
// text.HumanizeDuration(25 * time.Hour) // "1d1h"
// text.HumanizeDuration(8 * 24 * time.Hour) // "1w1d"
//
// // Calculate age since a time
// created := time.Now().Add(-48 * time.Hour)
// text.Age(created) // "2d"
//
// Duration Parsing:
//
// Parse durations with extended units beyond the standard Go time.Duration:
//
// d, err := text.ParseDuration("3d") // 72 hours
// d, err := text.ParseDuration("1w") // 168 hours
// d, err := text.ParseDuration("2y") // ~17520 hours
// d, err := text.ParseDuration("1d12h30m") // 36.5 hours
//
// Supported units: ns, us/µs, ms, s, m, h, d (days), w (weeks), y (years)
//
// Text Indentation:
//
// // Indent a string
// indented := text.String(" ", "line1\nline2\nline3")
// // " line1\n line2\n line3"
//
// // Indent bytes
// data := []byte("line1\nline2")
// indented := text.Bytes(" ", data)
//
// // Create an indenting writer
// writer := text.NewWriter(os.Stdout, " ")
// fmt.Fprintln(writer, "This will be indented")
// fmt.Fprintln(writer, "So will this")
//
// Safe I/O:
//
// // Read from reader without error handling
// resp, _ := http.Get("https://example.com")
// defer resp.Body.Close()
// content := text.SafeRead(resp.Body) // Empty string on error
//
// Formatting Examples:
//
// // Display file sizes
// fmt.Printf("Size: %s\n", text.HumanizeBytes(fileSize))
//
// // Display request counts
// fmt.Printf("Requests: %s\n", text.HumanizeInt(requestCount))
//
// // Display uptime
// fmt.Printf("Uptime: %s\n", text.HumanizeDuration(time.Since(startTime)))
//
// // Display last updated
// fmt.Printf("Updated: %s ago\n", text.Age(lastModified))
//
// Related Packages:
// - duration: Extended duration parsing (used internally)
package text
Loading