From 0214fee6509cd4347ea523364860e5219c7ebf33 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 8 Jul 2026 21:15:32 +0100 Subject: [PATCH 1/2] Preserve a consumer's copyright default profile on migrate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `migrate` copies config's `.idea/` over the consumer's on every `./config/pull`, preserving only `.idea/misc.xml` and `module.gradle.kts`. That clobbers `.idea/copyright/profiles_settings.xml`, which selects the default copyright profile — and that choice is project-specific: proprietary repositories use `TeamDev Proprietary` while the open-source SDK repositories use `TeamDev Open-Source`. Overwriting it silently re-licenses the consumer's headers, and the `update-copyright` hook then applies the wrong notice on the next edit. Preserve an existing `profiles_settings.xml` across the `.idea` overlay, mirroring the `misc.xml` handling: config still seeds a consumer that has none, but an existing project-local copy wins. Co-Authored-By: Claude Opus 4.8 --- migrate | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/migrate b/migrate index c66229a6..1b28f0e5 100644 --- a/migrate +++ b/migrate @@ -87,6 +87,21 @@ if [ -f "$DEST_MISC" ]; then cp -a "$DEST_MISC" "$MISC_PRESERVE_TMP" fi +# Preserve a project's `.idea/copyright/profiles_settings.xml` (do not overwrite it). +# It selects the default copyright profile, which is project-specific: proprietary +# repositories keep `TeamDev Proprietary`, while the open-source SDK repositories keep +# `TeamDev Open-Source`. Letting config's copy clobber it silently re-licenses the +# consumer's headers (the `update-copyright` hook then applies the wrong notice on the +# next edit). Config's copy still seeds a consumer that has none yet; an existing +# project-local copy wins. Same approach as `.idea/misc.xml` above. +DEST_COPYRIGHT="../.idea/copyright/profiles_settings.xml" +COPYRIGHT_PRESERVE_TMP="" +if [ -f "$DEST_COPYRIGHT" ]; then + echo "Preserving existing \`.idea/copyright/profiles_settings.xml\`" + COPYRIGHT_PRESERVE_TMP=$(mktemp -t copyright.XXXXXX) + cp -a "$DEST_COPYRIGHT" "$COPYRIGHT_PRESERVE_TMP" +fi + cp -R .idea .. # Restore preserved `.idea/misc.xml`, if any. @@ -96,6 +111,13 @@ if [ -n "$MISC_PRESERVE_TMP" ] && [ -f "$MISC_PRESERVE_TMP" ]; then rm -f "$MISC_PRESERVE_TMP" fi +# Restore preserved `.idea/copyright/profiles_settings.xml`, if any. +if [ -n "$COPYRIGHT_PRESERVE_TMP" ] && [ -f "$COPYRIGHT_PRESERVE_TMP" ]; then + echo "Restoring existing \`.idea/copyright/profiles_settings.xml\`" + cp -a "$COPYRIGHT_PRESERVE_TMP" "$DEST_COPYRIGHT" + rm -f "$COPYRIGHT_PRESERVE_TMP" +fi + echo "Updating Contributor's Guide" # CONTRIBUTING.md is identical org-wide and static; copy it only if the repo # does not already have one (don't clobber a deliberately customized copy). From 3bfca36e4495e2aa55198bf6f3b901940e499456 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 8 Jul 2026 21:40:16 +0100 Subject: [PATCH 2/2] Fail closed when preserving the copyright profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address review: the `profiles_settings.xml` preserve/restore was fail-open — a failed `cp` would let config's `.idea` overlay silently switch the consumer's default copyright profile, re-licensing its source headers. Abort on failure in both the preserve and restore steps (matching the `.gitignore` merge), and create the destination directory explicitly before restoring. Co-Authored-By: Claude Opus 4.8 --- migrate | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/migrate b/migrate index 1b28f0e5..b395ef5a 100644 --- a/migrate +++ b/migrate @@ -93,13 +93,16 @@ fi # `TeamDev Open-Source`. Letting config's copy clobber it silently re-licenses the # consumer's headers (the `update-copyright` hook then applies the wrong notice on the # next edit). Config's copy still seeds a consumer that has none yet; an existing -# project-local copy wins. Same approach as `.idea/misc.xml` above. +# project-local copy wins. Unlike `.idea/misc.xml`, this preservation fails closed +# (aborts on a copy error): a silently switched default copyright profile re-licenses +# the consumer's source headers, so we must never continue past a failure here. DEST_COPYRIGHT="../.idea/copyright/profiles_settings.xml" COPYRIGHT_PRESERVE_TMP="" if [ -f "$DEST_COPYRIGHT" ]; then echo "Preserving existing \`.idea/copyright/profiles_settings.xml\`" COPYRIGHT_PRESERVE_TMP=$(mktemp -t copyright.XXXXXX) - cp -a "$DEST_COPYRIGHT" "$COPYRIGHT_PRESERVE_TMP" + cp -a "$DEST_COPYRIGHT" "$COPYRIGHT_PRESERVE_TMP" \ + || { echo "ERROR: failed to back up '$DEST_COPYRIGHT' — aborting so the consumer's default copyright profile is not silently switched." >&2; exit 1; } fi cp -R .idea .. @@ -111,10 +114,14 @@ if [ -n "$MISC_PRESERVE_TMP" ] && [ -f "$MISC_PRESERVE_TMP" ]; then rm -f "$MISC_PRESERVE_TMP" fi -# Restore preserved `.idea/copyright/profiles_settings.xml`, if any. +# Restore preserved `.idea/copyright/profiles_settings.xml`, if any. Fails closed for +# the same reason as the preservation above — ensure the parent dir exists and abort +# if the restore copy fails, so the pull never silently changes the default profile. if [ -n "$COPYRIGHT_PRESERVE_TMP" ] && [ -f "$COPYRIGHT_PRESERVE_TMP" ]; then echo "Restoring existing \`.idea/copyright/profiles_settings.xml\`" - cp -a "$COPYRIGHT_PRESERVE_TMP" "$DEST_COPYRIGHT" + mkdir -p "$(dirname "$DEST_COPYRIGHT")" + cp -a "$COPYRIGHT_PRESERVE_TMP" "$DEST_COPYRIGHT" \ + || { echo "ERROR: failed to restore '$DEST_COPYRIGHT' — aborting so the pull does not silently change the default copyright profile." >&2; exit 1; } rm -f "$COPYRIGHT_PRESERVE_TMP" fi