diff options
| author | mo khan <mo@mokhan.ca> | 2026-01-30 18:16:31 -0700 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2026-01-30 18:16:31 -0700 |
| commit | feee7d43ef63ae607c6fd4cca88a356a93553ebe (patch) | |
| tree | 2969055a894dc4e72d8d79a9ac74cc30d78aff64 /internal/git/utils.go | |
| parent | e0db8f82e96acadf6968e0cf9c805a7b22d835db (diff) | |
refactor: move packages to internal/
Diffstat (limited to 'internal/git/utils.go')
| -rw-r--r-- | internal/git/utils.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/internal/git/utils.go b/internal/git/utils.go new file mode 100644 index 0000000..68e4497 --- /dev/null +++ b/internal/git/utils.go @@ -0,0 +1,91 @@ +package git + +import ( + "fmt" + "strconv" + "strings" +) + +// ParseFileMode converts a git-style file mode (e.g. "100644") +// into a human-readable string like "rw-r--r--". +func ParseFileMode(modeStr string) (string, error) { + // Git modes are typically 6 digits. The last 3 represent permissions. + // e.g. 100644 → 644 + if len(modeStr) < 3 { + return "", fmt.Errorf("invalid mode: %s", modeStr) + } + + permStr := modeStr[len(modeStr)-3:] + permVal, err := strconv.Atoi(permStr) + if err != nil { + return "", err + } + + return numericPermToLetters(permVal), nil +} + +func numericPermToLetters(perm int) string { + // Map each octal digit to rwx letters + lookup := map[int]string{ + 0: "---", + 1: "--x", + 2: "-w-", + 3: "-wx", + 4: "r--", + 5: "r-x", + 6: "rw-", + 7: "rwx", + } + + u := perm / 100 // user + g := (perm / 10) % 10 // group + o := perm % 10 // others + + return lookup[u] + lookup[g] + lookup[o] +} + +// IsBinary performs a heuristic check to determine if data is binary. +// Rules: +// - Any NUL byte => binary +// - Consider only a sample (up to 8 KiB). If >30% of bytes are control characters +// outside the common whitespace/newline range, treat as binary. +func IsBinary(b []byte) bool { + n := len(b) + if n == 0 { + return false + } + if n > 8192 { + n = 8192 + } + sample := b[:n] + bad := 0 + for _, c := range sample { + if c == 0x00 { + return true + } + // Allow common whitespace and control: tab(9), LF(10), CR(13) + if c == 9 || c == 10 || c == 13 { + continue + } + // Count other control chars and DEL as non-text + if c < 32 || c == 127 { + bad++ + } + } + // If more than 30% of sampled bytes are non-text, consider binary + return bad*100 > n*30 +} + +func RefToFileName(ref string) string { + var result strings.Builder + for _, c := range ref { + if (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '.' { + result.WriteByte(byte(c)) + } else if c >= 'A' && c <= 'Z' { + result.WriteByte(byte(c - 'A' + 'a')) + } else { + result.WriteByte('-') + } + } + return result.String() +} |
