aboutsummaryrefslogtreecommitdiff
path: root/scripts/disk_usage.py
diff options
context:
space:
mode:
authormosimchah <mosimchah@gmail.com>2025-12-02 09:27:38 -0500
committermosimchah <mosimchah@gmail.com>2025-12-02 09:27:38 -0500
commitc7bade461dc55726f62997d13a48582f7c4b4655 (patch)
treeea0588da76060a2038f54f67efd046ca77634b10 /scripts/disk_usage.py
parent0f5414d19317805e8bbbe7c4db5f0fd78769bad5 (diff)
parent89d78cff8b00d3b20a90074635c3fe5a2ee49474 (diff)
Merge branch 'lineage-23.1' of https://github.com/LineageOS/android_build_soong into HEADw16.1
* 'lineage-23.1' of https://github.com/LineageOS/android_build_soong: (528 commits) Revert "install_symlink: Make symlink target configurable" Reapply "Clear as much of cc.Module as possible after GenerateBuildActions" Revert "rust: config: Fix missing CPU variant LD flags in Rust" Rename build-flag in outdir Revert^4 "cipd: Default CIPD proxy server to on, add opt-out" Convert check-vintf-all to phony with actions Create a partial implementation of check-vintf-all for soong-only Configure RBE rust pool based on build variant Revert^3 "Add sdk version check to arr" Add jdk.internal.invoke to the allowlist Make droid always depend on symbols zip Import Device and Odm skus Don't install gob_gen in Soong Remove bazel reference from run_integration_tests.sh Fix bootstrap_test.sh Don't panic in aconfig libraries when AllowMissingDependencies is set Avoid returning nil paths from PathForModuleSrc Revert "Flag controled clang version" Rework module target dependencies on required deps Revert^2 "Add sdk version check to arr" ... Change-Id: I6e9a63fa14fda917a42e426e5dcebbad7f67e1de
Diffstat (limited to 'scripts/disk_usage.py')
-rw-r--r--scripts/disk_usage.py86
1 files changed, 86 insertions, 0 deletions
diff --git a/scripts/disk_usage.py b/scripts/disk_usage.py
new file mode 100644
index 000000000..940cea73a
--- /dev/null
+++ b/scripts/disk_usage.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+"""Calculates the disk size of each repository managed by 'repo'.
+
+This script invokes 'repo forall ...' to get the disk usage
+for each project repository and prints the combined output as a CSV.
+"""
+
+import os
+import re
+import subprocess
+import sys
+
+
+def get_repo_disk_usage() -> dict[str, int]:
+ """Invokes 'repo forall -p -c du -s .' and parses the output into a dictionary.
+
+ Returns:
+ A dictionary mapping project paths (str) to their disk size in bytes (int).
+ Returns an empty dictionary if the input is empty or malformed.
+
+ Raises:
+ subprocess.CalledProcessError: If the command returns a non-zero exit
+ code.
+ FileNotFoundError: If the 'repo' command is not found.
+ """
+ output = subprocess.check_output(
+ ["repo", "forall", "-p", "-c", "du", "-s", "-b", "."],
+ text=True,
+ )
+
+ project_sizes: dict[str, int] = {}
+ lines = output.strip().split("\n")
+ current_project_name = None
+
+ for line in lines:
+ line = line.strip()
+ if not line:
+ continue # Skip empty lines
+
+ if line.startswith("project "):
+ # Extract project name: remove "project " prefix and trailing "/"
+ current_project_name = line.removeprefix("project ").removesuffix("/")
+ elif current_project_name is not None:
+ match = re.match(r"^(\d+)\s+\.$", line)
+ if not match:
+ continue
+ size_str = match.group(1)
+ project_sizes[current_project_name] = int(size_str)
+ current_project_name = None # Reset for the next project
+
+ return project_sizes
+
+
+def get_dot_repo_size() -> int:
+ """Gets the disk usage of the '.repo' directory in bytes.
+
+ Returns:
+ The size of the '.repo' directory in bytes. Returns 0 if the command
+ fails or the directory doesn't exist (du returns 0).
+
+ Raises:
+ FileNotFoundError: If the 'du' command is not found.
+ # Note: subprocess.CalledProcessError is not explicitly raised on failure
+ # because we want to return 0 in that case.
+ """
+
+ result = subprocess.check_output(["du", "-s", "-b", ".repo"], text=True)
+ size_str = result.split()[0]
+ return int(size_str)
+
+
+def main():
+ if not os.path.isdir(".repo"):
+ sys.exit("Error: .repo directory not found, run inside a repo root.")
+
+ project_sizes = get_repo_disk_usage()
+ dot_repo_size = get_dot_repo_size()
+
+ print("project_name,size_bytes")
+ print(f".repo,{dot_repo_size}")
+ for name, size_bytes in sorted(project_sizes.items()):
+ print(f"{name},{size_bytes}")
+
+
+if __name__ == "__main__":
+ main()