@@ -623,6 +623,51 @@ def test_status_treats_dangling_symlink_as_missing(self, copilot_project):
623623 assert first_rel in payload ["manifests" ]["copilot" ]["missing_files" ]
624624 assert first_rel not in payload ["manifests" ]["copilot" ]["modified_files" ]
625625
626+ def test_status_treats_windows_style_dangling_symlink_as_missing (self , tmp_path , monkeypatch ):
627+ from specify_cli .integration_status import _manifest_file_status
628+ from specify_cli .integrations .manifest import IntegrationManifest
629+
630+ project = tmp_path / "proj"
631+ project .mkdir ()
632+ tracked = project / "tracked.md"
633+ tracked .write_text ("content\n " , encoding = "utf-8" )
634+ regular_stat = tracked .lstat ()
635+
636+ manifest = IntegrationManifest ("test" , project , version = "test" )
637+ manifest .record_existing ("tracked.md" )
638+
639+ tracked .unlink ()
640+ try :
641+ tracked .symlink_to (project / "missing-target" )
642+ except OSError as exc :
643+ pytest .skip (f"symlinks unavailable: { exc } " )
644+
645+ original_lstat = Path .lstat
646+ original_is_symlink = Path .is_symlink
647+
648+ def windows_style_lstat (self ):
649+ if self == tracked :
650+ return regular_stat
651+ return original_lstat (self )
652+
653+ def windows_style_is_symlink (self ):
654+ if self == tracked :
655+ return True
656+ return original_is_symlink (self )
657+
658+ monkeypatch .setattr (Path , "lstat" , windows_style_lstat )
659+ monkeypatch .setattr (Path , "is_symlink" , windows_style_is_symlink )
660+
661+ missing , modified , invalid , valid = _manifest_file_status (
662+ manifest ,
663+ project .resolve (),
664+ )
665+
666+ assert missing == ["tracked.md" ]
667+ assert modified == []
668+ assert invalid == []
669+ assert valid == ["tracked.md" ]
670+
626671 def test_status_reports_unsafe_manifest_paths_without_hashing_them (self , tmp_path , copilot_project ):
627672 outside = tmp_path / "outside"
628673 outside .mkdir ()
0 commit comments