Documentation
¶
Overview ¶
Package uninstall backs `moltnet uninstall` (PLAN.md phase 5): the non-CLI mechanics of enumerating every network a `moltnet init` (or `moltnet service install`) may have left behind, scanning $PATH for other installed copies of the binary, and deleting the running executable itself. Flag parsing, prompting, and printing stay in cmd/moltnet.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DanglingSymlinks ¶
DanglingSymlinks scans pathEnv for a "moltnet" symlink that no longer resolves, most commonly a PATH entry such as ~/.local/bin/moltnet that pointed at removedBinary, the moltnet binary `moltnet uninstall` just deleted. Call this AFTER removing the binary, not before: OtherCopies resolves through os.Stat, which fails on a now-dangling symlink exactly like it fails on "nothing here", so a symlink to the deleted binary silently disappears from OtherCopies' results instead of being reported, this function exists to catch that case and warn about it explicitly. A candidate counts as dangling when EvalSymlinks fails to resolve it (the usual case: the target file is simply gone) or, defensively, when it still resolves but lands back on removedBinary itself.
func NetworkIDs ¶
NetworkIDs returns every network id `moltnet uninstall` should stop and remove the service for: the union of network directories under ~/.moltnet/ (internal/app.ListNetworkIDs) and installed unit/plist files for manager's GOOS (service.Manager.InstalledNetworkIDs). The union matters because either half of that pairing can go missing independently of the other: a network directory removed by hand while its service is still loaded, or a service uninstalled by hand while ~/.moltnet/<id>/ still holds data. The result is sorted and deduplicated.
A manager for an unsupported OS (anything but darwin/linux) is treated as "no installed services" rather than a hard error, so `moltnet uninstall` still enumerates and can `--purge` network directories on a host internal/service does not manage services on.
func OtherCopies ¶
OtherCopies scans each directory in pathEnv (a $PATH-style, os.PathListSeparator-joined string) for an executable file named "moltnet" that is not currentBinary, and returns their paths in PATH order, deduplicated. Both currentBinary and each candidate are symlink-resolved before comparison, so a PATH entry that is just a symlink to the binary actually running is not reported as "another copy".
OtherCopies tolerates being called after currentBinary has already been removed from disk: a candidate that resolves back to that now-deleted path simply fails os.Stat and is silently skipped, the same as any other nonexistent PATH entry; see DanglingSymlinks for the complementary scan that catches that specific case instead of dropping it.
func RemoveBinary ¶
RemoveBinary deletes the file at path: the running moltnet executable, resolved by the caller via os.Executable + filepath.EvalSymlinks. Removing an executable's own backing file while the process is still running is safe on macOS and Linux: the kernel keeps the inode alive until the last open file descriptor/mapping closes, so only the directory entry disappears, immediately.
os.Remove's *PathError already names path, so its error is returned as-is rather than re-wrapped; errors.Is(err, fs.ErrPermission) still matches through it, which callers use to print a `sudo rm` fallback (a root-owned install directory such as /usr/local/bin) instead of crashing.
Types ¶
type HomeState ¶
type HomeState struct {
// Existed is true when there was something at root to act on. False
// means root was already gone.
Existed bool
// IsSymlink is true when root itself is a symlink rather than a real
// directory.
IsSymlink bool
// SymlinkTarget is the resolved target when IsSymlink is true and the
// target still exists; empty when IsSymlink is true but the symlink is
// itself dangling (its target no longer exists).
SymlinkTarget string
}
HomeState describes what root (typically ~/.moltnet, or a MOLTNET_HOME override) actually is on disk before anything is removed: a real directory holding data, a symlink (and what it resolves to, if anything), or nothing at all. InspectHomeDir and PurgeHomeDir share this so the CLI layer can describe an accurate --purge confirmation prompt before asking, and an accurate outcome after acting, from the same underlying check.
func InspectHomeDir ¶
InspectHomeDir reports root's HomeState without removing anything, so callers can build an accurate --purge confirmation prompt (PLAN.md phase 5 item 2: name what --purge is really about to do, before asking) ahead of calling PurgeHomeDir.
type PurgeResult ¶
type PurgeResult struct {
HomeState
}
PurgeResult reports what PurgeHomeDir actually did, built from the same HomeState InspectHomeDir would have reported beforehand.
func PurgeHomeDir ¶
func PurgeHomeDir(root string) (PurgeResult, error)
PurgeHomeDir removes root (the ~/.moltnet home directory, or a MOLTNET_HOME install-state override) entirely, deleting every network's config, message history, and credentials, unless root is itself a symlink. In that case only the link is removed; the resolved target is left untouched, since following an operator-controlled symlink to delete whatever it happens to point at is too dangerous to do unconditionally. Callers must have already confirmed this with the operator; PLAN.md phase 5 item 2 requires --purge to always be confirmed, always listing the networks that will be destroyed, before this runs. A missing root is not an error: the returned PurgeResult.Existed is simply false.
Before touching anything, PurgeHomeDir refuses to run at all when root resolves to something far broader than a moltnet install directory: the user's actual $HOME, an ancestor of $HOME (such as / or /Users), or the filesystem root, since a misresolved MOLTNET_HOME (e.g. accidentally set to $HOME or /) combined with --purge --yes would otherwise silently os.RemoveAll the operator's entire home directory. This check lives here rather than in the CLI layer so every caller of PurgeHomeDir, present and future, gets it for free.