Skip to content

Commit 1fec6ed

Browse files
NanoClaw Researchclaude
andcommitted
fix(check-schema): check ALL schema IDs for settings-schema match
When gschema.xml contains multiple <schema> elements (e.g. a main schema plus a .keybindings sub-schema), the previous code extracted only the first <schema id=...> attribute. If a sub-schema appeared first (as in PaperWM, where org.gnome.shell.extensions.paperwm.keybindings precedes the main org.gnome.shell.extensions.paperwm schema), schema/id-matches and schema/filename-convention both produced false-positive FAILs even though the correct schema was present. Changes: - Extract all schema IDs via new extract_all_schema_ids() helper - Refactor extract_schema_id() to use it (single-schema case unchanged) - Add schema_id_in_file() to test membership across all <schema> elements - schema/id-matches: pass if settings-schema is found in ANY schema element - schema/filename-convention: use settings-schema as the reference ID when settings-schema is defined in metadata.json (not the first schema found) - Add multi-schema@test fixture reproducing the PaperWM layout - Add 4 assertions to run-tests.sh covering the new behaviour Fixes false-positive FAILs on PaperWM and any extension that uses sub-schemas (keybindings, overrides, etc.) in a single gschema.xml. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent dad1e72 commit 1fec6ed

File tree

5 files changed

+80
-15
lines changed

5 files changed

+80
-15
lines changed

skills/ego-lint/scripts/check-schema.sh

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,27 @@ set -euo pipefail
99

1010
EXT_DIR="$(cd "${1:-.}" && pwd)"
1111

12-
# Extract the schema id from a .gschema.xml file.
13-
# Uses a <schema>-specific grep to avoid picking up <enum id=> or other
14-
# elements that appear before <schema id=> in files with multiple top-level
15-
# elements (e.g. caffeine's schema has three <enum> elements first).
12+
# Extract ALL schema ids from a .gschema.xml file.
13+
# Filters to <schema\b lines to avoid matching <enum id=> or other elements.
14+
extract_all_schema_ids() {
15+
local file="$1"
16+
grep -P '<schema\b' "$file" | grep -oP 'id="[^"]*"' | sed 's/id="//;s/"//'
17+
}
18+
19+
# Extract the first schema id from a .gschema.xml file.
20+
# For single-schema files this is the only schema. For multi-schema files
21+
# (e.g. a main schema + .keybindings sub-schema), prefer using
22+
# extract_all_schema_ids() + targeted matching instead.
1623
extract_schema_id() {
1724
local file="$1"
18-
grep -P '<schema\b' "$file" | grep -oP 'id="[^"]*"' | head -1 | sed 's/id="//;s/"//'
25+
extract_all_schema_ids "$file" | head -1
26+
}
27+
28+
# Return true (0) if a specific schema ID exists anywhere in a .gschema.xml file.
29+
schema_id_in_file() {
30+
local file="$1"
31+
local target_id="$2"
32+
extract_all_schema_ids "$file" | grep -qxF "$target_id"
1933
}
2034

2135
METADATA="$EXT_DIR/metadata.json"
@@ -63,24 +77,33 @@ echo "PASS|schema/exists|Found ${#schema_files[@]} schema file(s)"
6377
# Validate schema IDs match metadata
6478
if [[ "$has_settings_schema" == true ]]; then
6579
for schema_file in "${schema_files[@]}"; do
66-
# Extract schema id from XML (use extract_schema_id to avoid matching <enum id=> etc.)
67-
schema_id="$(extract_schema_id "$schema_file")"
68-
if [[ "$schema_id" == "$settings_schema" ]]; then
69-
echo "PASS|schema/id-matches|Schema ID '$schema_id' matches metadata.json settings-schema"
80+
# Check whether settings-schema appears as ANY <schema id=> in the file.
81+
# Multi-schema XML (e.g. main schema + .keybindings sub-schema) must not
82+
# fail just because a sub-schema appears first.
83+
if schema_id_in_file "$schema_file" "$settings_schema"; then
84+
echo "PASS|schema/id-matches|Schema ID '$settings_schema' found in $(basename "$schema_file")"
7085
else
71-
echo "FAIL|schema/id-matches|Schema ID '$schema_id' does not match metadata.json settings-schema '$settings_schema'"
86+
all_ids="$(extract_all_schema_ids "$schema_file" | paste -sd ' ')"
87+
echo "FAIL|schema/id-matches|settings-schema '$settings_schema' not found in $(basename "$schema_file") (found: ${all_ids})"
7288
fi
7389
done
7490
fi
7591

76-
# Validate schema filename convention: <schema-id>.gschema.xml
92+
# Validate schema filename convention: <settings-schema>.gschema.xml
93+
# When settings-schema is defined in metadata.json, the file MUST be named
94+
# after that ID (the primary schema). For extensions without settings-schema,
95+
# fall back to the first schema ID found in the file.
7796
for schema_file in "${schema_files[@]}"; do
78-
schema_id="$(extract_schema_id "$schema_file")"
79-
if [[ -n "$schema_id" ]]; then
80-
expected_filename="${schema_id}.gschema.xml"
97+
if [[ "$has_settings_schema" == true ]]; then
98+
ref_id="$settings_schema"
99+
else
100+
ref_id="$(extract_schema_id "$schema_file")"
101+
fi
102+
if [[ -n "$ref_id" ]]; then
103+
expected_filename="${ref_id}.gschema.xml"
81104
actual_filename="$(basename "$schema_file")"
82105
if [[ "$actual_filename" == "$expected_filename" ]]; then
83-
echo "PASS|schema/filename-convention|Schema filename matches ID: $actual_filename"
106+
echo "PASS|schema/filename-convention|Schema filename matches settings-schema: $actual_filename"
84107
else
85108
echo "FAIL|schema/filename-convention|Schema filename '$actual_filename' MUST be '$expected_filename'"
86109
fi
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js';
2+
3+
export default class MultiSchemaExtension extends Extension {
4+
enable() {}
5+
disable() {}
6+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"uuid": "multi-schema@test",
3+
"name": "Multi-Schema Test",
4+
"description": "Tests that schema/id-matches passes when settings-schema appears after a sub-schema (e.g. .keybindings) in gschema.xml",
5+
"shell-version": ["48"],
6+
"settings-schema": "org.gnome.shell.extensions.multi-schema",
7+
"url": "https://github.com/test/multi-schema"
8+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<schemalist>
3+
<!-- Sub-schema appears FIRST — this is what caused the PaperWM FP -->
4+
<schema id="org.gnome.shell.extensions.multi-schema.keybindings"
5+
path="/org/gnome/shell/extensions/multi-schema/keybindings/">
6+
<key name="move-left" type="as">
7+
<default>["&lt;Super&gt;Left"]</default>
8+
<summary>Move left keybinding</summary>
9+
</key>
10+
</schema>
11+
<!-- Main schema appears SECOND — must match settings-schema in metadata.json -->
12+
<schema id="org.gnome.shell.extensions.multi-schema"
13+
path="/org/gnome/shell/extensions/multi-schema/">
14+
<key name="enable-feature" type="b">
15+
<default>true</default>
16+
<summary>Enable feature</summary>
17+
</key>
18+
</schema>
19+
</schemalist>

tests/run-tests.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,15 @@ assert_exit_code "exits with 1 (has failures)" 1
466466
assert_output_contains "fails on schema filename" "\[FAIL\].*schema/filename-convention"
467467
echo ""
468468

469+
# --- multi-schema (sub-schema appears before main schema in XML) ---
470+
echo "=== multi-schema ==="
471+
run_lint "multi-schema@test"
472+
assert_output_not_contains "no schema/id-matches FAIL for multi-schema XML" "\[FAIL\].*schema/id-matches"
473+
assert_output_not_contains "no schema/filename-convention FAIL for multi-schema XML" "\[FAIL\].*schema/filename-convention"
474+
assert_output_contains "id-matches passes for multi-schema XML" "\[PASS\].*schema/id-matches"
475+
assert_output_contains "filename-convention passes for multi-schema XML" "\[PASS\].*schema/filename-convention"
476+
echo ""
477+
469478
# --- gnome46-compat ---
470479
echo "=== gnome46-compat ==="
471480
run_lint "gnome46-compat@test"

0 commit comments

Comments
 (0)