Skip to content

Instantly share code, notes, and snippets.

@lukaskollmer
Created February 3, 2019 12:26
Show Gist options
  • Save lukaskollmer/c231abe2602267bfda13a4ed83b113a8 to your computer and use it in GitHub Desktop.
Save lukaskollmer/c231abe2602267bfda13a4ed83b113a8 to your computer and use it in GitHub Desktop.
OCaml program to count the total amount of space freed up when running `brew cleanup`
(*
OCaml program to count the total amount of space freed up when running `brew cleanup`
Usage:
brew cleanup | ocaml count_homebrew_cleanup.ml
Author: Lukas Kollmer <lukas.kollmer@gmail.com>
Date: 2019-02-03
License: MIT
*)
let read_stdin () =
let rec imp acc =
try imp (input_line stdin :: acc)
with End_of_file -> List.rev acc
in
imp []
type comparison_result = Same | Less | Greater
let compare_len a b =
match String.length a, String.length b with
| x, y when x > y -> Greater
| x, y when x = y -> Same
| _ -> Less
let string_has_prefix pre str =
match compare_len pre str with
| Greater -> false
| Same -> str = pre
| Less -> String.sub str 0 (String.length pre) = pre
let string_has_suffix suf str =
match compare_len suf str with
| Greater -> false
| Same -> str = suf
| Less ->
let suf_len = String.length suf in
String.sub str (String.length str - suf_len) suf_len = suf
let rec get_last = function
| [] -> failwith "get_last"
| x::[] -> x
| x::xs -> get_last xs
let split_last char str =
String.split_on_char char str |> get_last
let split_first char str =
String.split_on_char char str |> List.hd
let parse_byte_string str =
let count = str |> split_first 'B' |> split_first 'K' |> split_first 'M' |> split_first 'G' |> float_of_string in
if string_has_suffix "MB" str then
count *. 1e+6
else if string_has_suffix "KB" str then
count *. 1e+3
else if string_has_suffix "GB" str then
count *. 1e+9
else (* bytes, probably *)
count
(* basic idea inspired by https://stackoverflow.com/a/1094933/2513803 *)
let format_byte_count count =
let rec imp count = function
| [] -> Printf.sprintf "%.2f GB" count
| x::xs -> if Float.abs count < 1024. then Printf.sprintf "%3.1f %s" count x else imp (count /. 1024.) xs
in
imp count [""; "KB"; "MB"]
let () =
read_stdin ()
|> List.filter (string_has_prefix "Removing: ")
|> List.map (fun line -> line |> split_last '(' |> split_last ' ' |> String.split_on_char ')' |> List.hd)
|> List.map parse_byte_string
|> List.fold_left (+.) 0.
|> format_byte_count
|> Printf.sprintf "Total: %s" |> print_endline
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment