script/install: do not stop on a missing closing comment
check / check (push) Successful in 55s

A .gitignore or .dockerignore lacking the canonical last line no longer
stops the script: each line the canonical file has never held goes
below the fetched content. An .editorconfig lacking it is replaced,
unless it has such a line, which stops the script.

The stub curl now writes files with no execute bit, as a real download
does, so the tests exercise the mode the script sets.

Model: opus-5-5
This commit is contained in:
clawbot committed 2026-11-09 21:34:29 +00:00
1 parent 9f83f3c1b1
commit 8a25e502f4
3 files changed
+62 -15

No files matched your search

+12 -9
View File
@@ -214,15 +214,18 @@ with your task.
- [ ] `script/install` and `script/update-policy` exist, identical to the model
scripts, and `make update-policy` shims to `script/update-policy`.
`make update-policy` commits without pushing, so a person reviews and
pushes the commit. Before its first use, the repo's own entries in
`.gitignore`, `.editorconfig` and `.dockerignore` go below the comment
that ends each canonical file. An entry above that comment which the
canonical file has never held makes the script stop before it writes
anything, naming the file and the entry. It stops the same way on a line
in `.golangci.yml` that the canonical file has never held, apart from
comments and the repo's entries in the `deny` list of the `test-support`
rule. It also stops on a repo's own `script/install` or
`script/update-policy`.
pushes the commit. A `.gitignore` or `.dockerignore` without the comment
that ends the canonical file needs no preparation. The script moves each
line the canonical file has never held to below the canonical content.
Blank lines and comments are dropped. Before its first use, add that
comment to an `.editorconfig` that has lines of its own, and put those
lines below it. Otherwise the script stops before it writes anything,
naming the file and each line. In a file that has the comment, an entry
above it which the canonical file has never held also stops the script. It
stops the same way on a line in `.golangci.yml` that the canonical file
has never held, apart from comments and the repo's entries in the `deny`
list of the `test-support` rule. It also stops on a repo's own
`script/install` or `script/update-policy`.
- [ ] README has an **Entrypoints** section documenting the `script/`
entrypoints and linking the standard
- [ ] `script/lint` and `script/test` each run
+19 -2
View File
@@ -15,6 +15,12 @@
# - .gitignore, .editorconfig, .dockerignore: the lines below the
# canonical file's last line. An entry above that line which the
# canonical file has never held stops the script.
# - .gitignore, .dockerignore lacking that last line: each line the
# canonical file has never held, unless it is blank or a comment,
# goes below the canonical content.
# - .editorconfig lacking that last line: it is replaced if it has no
# such line. Otherwise the script stops, because a setting means
# nothing away from its section.
# - .golangci.yml: the entries the repo added to the deny list of the
# test-support rule. Any other line the canonical file has never
# held stops the script, unless it is blank or a comment.
@@ -117,12 +123,23 @@ local_only_lines() {
# keep_lines_below_last <fetched> <local>: append to the fetched file
# whatever follows its last line in the local file. Stop if the canonical
# file has never held a line above that one, unless it is blank or a
# comment: replacing the file would delete it.
# comment: replacing the file would delete it. If the local file lacks
# that last line, append each line the canonical file has never held,
# unless it is blank or a comment. An .editorconfig with such a line
# stops the script instead, because a setting means nothing away from
# its section.
keep_lines_below_last() {
last="$(tail -n 1 "$1")"
number="$(grep -n -F -x -- "$last" "$2" | head -n 1 | cut -d: -f1)"
if [ -z "$last" ] || [ -z "$number" ]; then
die "$2 lacks this line; add it and put the repo's own entries below it: $last"
own="$(local_only_lines "$1" "$2")"
[ -n "$own" ] || return 0
if [ "$2" = .editorconfig ]; then
die "$2 lacks this line and has lines the canonical file has never held; add it and put those lines below it: $last
$own"
fi
printf '%s\n' "$own" >> "$1"
return 0
fi
own="$(local_only_lines "$1" "$2" "$number")"
if [ -n "$own" ]; then
+31 -4
View File
@@ -45,7 +45,7 @@ not_found() {
serve_file() {
[ -f "$canonical/$1" ] || not_found
cp "$canonical/$1" "$output"
cat "$canonical/$1" > "$output"
}
case "$url" in
@@ -703,12 +703,37 @@ test_own_script_stops() {
}
test_gitignore_lacks_canonical_last_line() {
start_scenario ".gitignore lacking the canonical last line stops"
printf '*.log\n/myapp\n' > "$dir/repo/.gitignore"
start_scenario ".gitignore lacking the canonical last line keeps the repo's own line below the canonical content"
printf '*.log\n\n# A comment of our own.\n/myapp\n' > "$dir/repo/.gitignore"
commit_and_push_fixture .gitignore .prettierrc
run_update_policy
expect_success
expect_file .gitignore << 'EOF'
*.log
*.tmp
# Own entries go below this comment.
/myapp
EOF
expect_new_commit_not_pushed
}
test_dockerignore_lacks_canonical_last_line() {
start_scenario ".dockerignore lacking the canonical last line drops a line an earlier canonical commit held"
echo "**/*.log" > "$dir/repo/.dockerignore"
expect_former_canonical_line_replaced .dockerignore ".git"
expect_same_as_canonical .dockerignore
}
test_editorconfig_lacks_canonical_last_line() {
start_scenario ".editorconfig lacking the canonical last line with a line of its own stops"
printf 'root = true\n[*.py]\nindent_size = 2\n' > "$dir/repo/.editorconfig"
commit_and_push_fixture .editorconfig .prettierrc
run_update_policy
expect_failure
expect_output ".gitignore lacks this line"
expect_output ".editorconfig lacks this line"
expect_output "[*.py]"
expect_output "indent_size = 2"
expect_nothing_written
}
@@ -861,6 +886,8 @@ main() {
test_ignored_file_stops
test_own_script_stops
test_gitignore_lacks_canonical_last_line
test_dockerignore_lacks_canonical_last_line
test_editorconfig_lacks_canonical_last_line
test_fetched_golangci_without_deny_list
test_own_golangci_setting_stops
test_source_repo_stops