Files
dingtalk-workspace-cli/internal/upgrade/skill_publication_identity_linux.go
玉澜 fdcaa61587 test(skills): cover child-move edges for the 100% changed-code gates
The platform coverage gates execute only TestCrossPlatformCoverage-named
tests, so the child-move error and dispatch branches that the full local
suite covered incidentally were reported as uncovered changed code on
Windows (96.78% vs the 100% target). Adds a seam-driven edge suite for
the child-move fallback — source/claim/child stat and read failures,
per-child link and symlink collisions and publish failures, rollback
rename failure, foreign-entry abort, mode-restore failure, source shell
removal failure, nested-directory and simulated-symlink children, and
post-rename content drift — plus the retained-destination notice for a
dependent uncertain target in skill setup. The POSIX file identity impl
now consults the lstat seam so its degradation branches are coverable
the same way. Verified against the gate's own changed-line computation:
zero uncovered changed statements in internal/upgrade.
2026-08-19 18:54:04 +08:00

50 lines
1.6 KiB
Go

//go:build linux
package upgrade
import (
"fmt"
"os"
"syscall"
)
func skillPathFileIncarnationImpl(info os.FileInfo) string {
stat, ok := info.Sys().(*syscall.Stat_t)
if !ok {
return fmt.Sprintf("unknown:%T", info.Sys())
}
return fmt.Sprintf("%d:%d:%d:%d", stat.Dev, stat.Ino, stat.Ctim.Sec, stat.Ctim.Nsec)
}
func skillPathSameFileIdentityImpl(left, right os.FileInfo) bool {
return os.SameFile(left, right)
}
// skillPathFileIdentityImpl reports the device/inode pair from lstat. POSIX
// has no open-by-ID handle, but dev:ino identifies the object for its
// lifetime and is the same witness os.SameFile compares. It anchors the
// mkdir-claim identity of the child-move fallback: a wholesale replacement
// of the claimed destination reports a different identity, except in the
// classic inode-reuse race on recycled-inode filesystems (notably tmpfs),
// which the publication fingerprint backstop still catches. An unreadable
// or unrecognizable path reports "" and callers treat that as "no witness".
func skillPathFileIdentityImpl(path string) string {
info, err := skillPathLstat(path)
if err != nil {
return ""
}
stat, ok := info.Sys().(*syscall.Stat_t)
if !ok {
return ""
}
return fmt.Sprintf("%d:%d", stat.Dev, stat.Ino)
}
// skillPathIdentityProven stays SameFile-based on POSIX: the file ID above is
// the same dev:ino witness, so preferring it would add no strength while
// making the proof refuse publishes whose staged lstat (and therefore staged
// identity) could not be read.
func skillPathIdentityProven(staged, published os.FileInfo, _, _ string) bool {
return skillPathSameFileIdentity(staged, published)
}