何を見つけたか
devbase snapshot rotate で、削除の対象になった世代がすべて場所の検証(_safe_snap_dir)で拒否されたとき(snapshot.yml の名前が backups/ の外を指す、または世代がシンボリックリンク)、SnapshotManager.rotate() はエントリを一覧から外して警告を出すが、戻り値は 0 になる。CLI の _snapshot_rotate は戻り値 0 を見て続けて「ローテーション不要です」と出す。
再現の形: backups/old を backups/ の外を指すシンボリックリンクにし、old が保持数を超えて削除の対象になる状態で devbase snapshot rotate を実行する。出力は「警告(一覧から外した)」の直後に「ローテーション不要です」となり、一覧は実際には変わっている。
どこで見つけたか
lib/devbase/snapshot/manager.py の rotate()(removed_ids と deleted_ids を分けて持ち、戻り値は実際に消した数)
lib/devbase/commands/snapshot.py の _snapshot_rotate(deleted == 0 で「ローテーション不要です」)
PR feat(PLAN68): スナップショットの世代をアカウントグループごとの系列で持つ (#248) #263 の確定仕様化(docs/specifications/snapshot-series.md を書くときの実装との照合)で見つけた
なぜこの変更の範囲外なのか
PLAN68 の受け入れ条件 25〜28 は「backups/ の外やリンク先を消さない」「エントリは一覧から外れ、警告が 1 行出る」までで、rotate() の戻り値と CLI の後続の文言は条件に無い。条件はすべて満たしており、危険な削除は起きない。
直さないと何が起きるか
警告の直後に「ローテーション不要です」と出るため、利用者は一覧が変わったこと(エントリが外れたこと)を見落としうる。削除やデータの損失は起きない。対象は危険な名前・リンクの世代を持つ端末に限られる。
由来
PR #263 (issue #248 )
何を見つけたか
devbase snapshot rotateで、削除の対象になった世代がすべて場所の検証(_safe_snap_dir)で拒否されたとき(snapshot.ymlの名前がbackups/の外を指す、または世代がシンボリックリンク)、SnapshotManager.rotate()はエントリを一覧から外して警告を出すが、戻り値は 0 になる。CLI の_snapshot_rotateは戻り値 0 を見て続けて「ローテーション不要です」と出す。再現の形:
backups/oldをbackups/の外を指すシンボリックリンクにし、oldが保持数を超えて削除の対象になる状態でdevbase snapshot rotateを実行する。出力は「警告(一覧から外した)」の直後に「ローテーション不要です」となり、一覧は実際には変わっている。どこで見つけたか
lib/devbase/snapshot/manager.pyのrotate()(removed_idsとdeleted_idsを分けて持ち、戻り値は実際に消した数)lib/devbase/commands/snapshot.pyの_snapshot_rotate(deleted == 0で「ローテーション不要です」)docs/specifications/snapshot-series.mdを書くときの実装との照合)で見つけたなぜこの変更の範囲外なのか
PLAN68 の受け入れ条件 25〜28 は「
backups/の外やリンク先を消さない」「エントリは一覧から外れ、警告が 1 行出る」までで、rotate()の戻り値と CLI の後続の文言は条件に無い。条件はすべて満たしており、危険な削除は起きない。直さないと何が起きるか
警告の直後に「ローテーション不要です」と出るため、利用者は一覧が変わったこと(エントリが外れたこと)を見落としうる。削除やデータの損失は起きない。対象は危険な名前・リンクの世代を持つ端末に限られる。
由来
PR #263(issue #248)