diff --git a/method-core.lock.json b/method-core.lock.json index 3cbb17c..801e3b7 100644 --- a/method-core.lock.json +++ b/method-core.lock.json @@ -83,7 +83,7 @@ { "mode": "100644", "path": "scripts/method_core.py", - "sha256": "72ed9894391ee836611d1dde1c89db8c00ac7c7b68fae648253be84add3a552f" + "sha256": "70a0532c5179916e6433edc47f504d77ce82b2d4573ad41686f3bcf3a23a80be" }, { "mode": "100644", @@ -288,7 +288,7 @@ { "mode": "100644", "path": "tests/test_core_sync.py", - "sha256": "7ba34142488b9fb812e34196f6a272fdabaab0b72077f9bcdc8abcd6c7a9a6d4" + "sha256": "aec5541e99ad09524a533a2e81a5a70f6c1582c1881c4a6a812ac764b31405ea" }, { "mode": "100644", @@ -347,7 +347,7 @@ } ], "repository": "https://github.com/phense/method-core.git", - "revision": "b202d7af3626e95f92e93255d62b79718e0198b1", + "revision": "ca9f5d16aeb54bc0081f6b33b809c3aab64c8861", "schema_version": 1, "version": "0.1.0" } diff --git a/scripts/method_core.py b/scripts/method_core.py index 4037344..4b2577c 100644 --- a/scripts/method_core.py +++ b/scripts/method_core.py @@ -75,7 +75,8 @@ def check(root, *, allow_transaction=False): path = contained(root,item['path']) if not path.is_file() or hashlib.sha256(path.read_bytes()).hexdigest() != item['sha256']: raise ValueError(f'core drift: {item["path"]}') - if path.stat().st_mode & 0o777 != int(item['mode'],8) & 0o777: + # Git records only the executable bit; group/other bits follow the installing umask. + if bool(path.stat().st_mode & 0o100) != (item['mode'] == '100755'): raise ValueError(f'core mode drift: {item["path"]}') return lock diff --git a/tests/test_core_sync.py b/tests/test_core_sync.py index 41f6fb7..1b09ba1 100644 --- a/tests/test_core_sync.py +++ b/tests/test_core_sync.py @@ -67,6 +67,13 @@ def test_malformed_lock_and_mode_drift_are_not_overwritten(self): self.assertNotEqual(0,self.sync('--source-root',str(self.source)).returncode) (self.target/'method-core.lock.json').write_text('{"files": []}') self.assertNotEqual(0,self.sync('--check').returncode) + def test_umask_dependent_permission_bits_are_not_mode_drift(self): + # A host umask of 0002 installs 664/775 copies; only the executable bit is recorded by Git. + self.install() + (self.target/'shared/platform/codex.md').chmod(0o664);(self.target/'scripts/project-state').chmod(0o775) + r=self.sync('--check');self.assertEqual(0,r.returncode,r.stdout+r.stderr) + (self.target/'shared/platform/codex.md').chmod(0o755) + self.assertNotEqual(0,self.sync('--check').returncode) def test_update_adds_and_removes_only_owned_exports(self): self.install();self.put('new.txt',b'new');self.manifest(['new.txt','scripts/project-state']);self.commit();self.install() self.assertFalse((self.target/'shared/platform/codex.md').exists());self.assertEqual(b'new',(self.target/'new.txt').read_bytes())