-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclean
More file actions
executable file
·184 lines (159 loc) · 6.4 KB
/
clean
File metadata and controls
executable file
·184 lines (159 loc) · 6.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/bin/sh
# UTF cleanup script — remove Zig build artifacts and root build logs.
#
# Usage:
# sh clean.sh # list candidates, prompt y/N, remove on confirm
# sh clean.sh --dry-run # list candidates, do not remove
# sh clean.sh --force # remove without prompting (for CI / scripts)
# sh clean.sh --help # show this help
#
# Removes:
# - every .zig-cache/ directory under the UTF root
# - every zig-out/ directory under the UTF root
# - root-level build logs: build-*.log and the build-latest.log symlink
#
# Does NOT touch:
# - anything under .git/
# - /usr/src, /boot, /usr/obj or anything outside the UTF checkout
# - .config, configure.sh output, or any source file
# - the drawfs kernel-module build (that's under /usr/src — use
# `drawfs/build.sh` for that if you need to clean it)
#
# The script refuses to run if it cannot verify it is inside a
# UTF-shaped tree (presence of build.zig + shared/ + drawfs/).
set -eu
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
DRY_RUN=0
FORCE=0
# ============================================================================
# Argument parsing
# ============================================================================
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=1 ;;
--force) FORCE=1 ;;
--help|-h)
sed -n '2,20p' "$0" | sed 's/^# \?//'
exit 0 ;;
*)
echo "unknown argument: $arg" >&2
echo "try: sh clean.sh --help" >&2
exit 2 ;;
esac
done
# ============================================================================
# Sanity check: are we inside a UTF checkout?
#
# This guards against a configuration accident (e.g. SCRIPT_DIR resolving to
# somewhere surprising) wiping things we shouldn't touch. All three markers
# must be present before we do anything.
# ============================================================================
if [ ! -f "$SCRIPT_DIR/build.zig" ] \
|| [ ! -d "$SCRIPT_DIR/shared" ] \
|| [ ! -d "$SCRIPT_DIR/drawfs" ]; then
echo "ERROR: $SCRIPT_DIR does not look like a UTF checkout." >&2
echo " Refusing to clean anything." >&2
exit 1
fi
cd "$SCRIPT_DIR"
# ============================================================================
# Discover candidates.
#
# -prune keeps find(1) from descending into .git or into an already-matched
# cache directory (cheaper, and avoids listing nested zig-out/.zig-cache/).
# ============================================================================
# Use a tmpfile rather than a shell variable so we preserve newlines cleanly
# across /bin/sh implementations and so the listing can be re-read twice
# (once for display, once for deletion).
TMPLIST=$(mktemp -t utf-clean.XXXXXX)
trap 'rm -f "$TMPLIST"' EXIT
find . \
-name .git -type d -prune -o \
\( -name .zig-cache -o -name zig-out \) -type d -print -prune \
> "$TMPLIST"
# Root-level build artifacts. Symlinks are matched by -maxdepth 1 and the
# explicit -name pattern; both regular files and the dangling/live
# build-latest.log symlink are captured.
find . -maxdepth 1 \( -name 'build-*.log' -o -name 'build-latest.log' \) \
\( -type f -o -type l \) -print >> "$TMPLIST"
# Sort and de-dup for stable output. Also strip leading "./" for readability.
sort -u "$TMPLIST" | sed 's|^\./||' > "$TMPLIST.sorted"
mv "$TMPLIST.sorted" "$TMPLIST"
if [ ! -s "$TMPLIST" ]; then
echo "Nothing to clean. The tree is already pristine."
exit 0
fi
# ============================================================================
# Report, with a size total. du is best-effort — failures are silent because
# some platforms complain about vanished files or symlinks mid-walk.
# ============================================================================
COUNT=$(wc -l < "$TMPLIST" | tr -d ' ')
TOTAL=$(xargs du -sch < "$TMPLIST" 2>/dev/null | awk 'END{print $1}')
TOTAL=${TOTAL:-unknown}
echo "UTF cleanup — $COUNT item(s), approximately $TOTAL:"
echo ""
# Prefix each line with a marker for visual clarity.
sed 's/^/ /' "$TMPLIST"
echo ""
# ============================================================================
# Dry run: list only, exit success without touching anything.
# ============================================================================
if [ "$DRY_RUN" -eq 1 ]; then
echo "(dry run — nothing removed)"
exit 0
fi
# ============================================================================
# Confirm unless --force. Read from /dev/tty so piped input can't silently
# auto-confirm; if there is no tty (e.g. running under a supervisor without
# --force), refuse rather than guess.
# ============================================================================
if [ "$FORCE" -ne 1 ]; then
# Choose a source for the answer. We actually attempt to open /dev/tty
# rather than trusting [ -r /dev/tty ], because on some systems (notably
# containers without a controlling terminal) the test reports readable
# but the open at read(1) time fails. Attempting to read a single
# throwaway byte is the only reliable probe.
TTY_OK=0
if (: < /dev/tty) 2>/dev/null; then
TTY_OK=1
fi
if [ "$TTY_OK" -eq 0 ] && [ ! -t 0 ] && [ ! -p /dev/stdin ]; then
echo "ERROR: no tty or stdin available for confirmation." >&2
echo " Re-run with --force if this is intentional." >&2
exit 1
fi
printf "Remove these? [y/N]: "
if [ "$TTY_OK" -eq 1 ]; then
read -r ANSWER < /dev/tty
else
read -r ANSWER
fi
case "$ANSWER" in
y|Y|yes|YES) ;;
*) echo "Aborted."; exit 0 ;;
esac
fi
# ============================================================================
# Do the work. rm -rf for directories, rm -f for files/symlinks. xargs -0
# would be tidier but we don't have NUL-delimited output from find here;
# these paths never contain whitespace in a UTF checkout (build-YYYYMMDD-…).
# ============================================================================
REMOVED=0
FAILED=0
while IFS= read -r path; do
[ -z "$path" ] && continue
if rm -rf -- "$path" 2>/dev/null; then
echo " removed $path"
REMOVED=$((REMOVED + 1))
else
echo " FAILED $path" >&2
FAILED=$((FAILED + 1))
fi
done < "$TMPLIST"
echo ""
echo "Done. Removed $REMOVED item(s)."
if [ "$FAILED" -gt 0 ]; then
echo "$FAILED item(s) could not be removed (see errors above)." >&2
exit 1
fi
exit 0