fileprogress

package module
v0.0.0-...-a126fea Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2026 License: BSD-3-Clause Imports: 1 Imported by: 0

README

fileprogress

CI Go Reference Go Report Card

Pure-Go (CGO_ENABLED=0) publishing of a file's download progress to macOS, so the Finder draws on the file's icon the pie it draws for a browser's downloads. Reached through ebitengine/purego and go-macos/objcdlopen + objc_msgSend — so it links with no cgo.

p, err := fileprogress.Publish(path, total)
if err != nil {
    // Worth logging, never worth failing a download over: a file that
    // arrives without a pie has still arrived.
}
defer p.Done()

for n := range bytesArriving {
    p.Set(n)
}

The mechanism, and the one that looks like it should work

macOS infers nothing from a file growing on disk. The pie has to be published, and the system hears it exactly one way: an NSProgress whose kind is NSProgressKindFile, carrying the file's URL and a file-operation kind of downloading, handed to -publish.

There is a second mechanism widely described as equivalent — setting the extended attribute com.apple.progress.fractionCompleted on the file. It does not work. Both were tried on the same machine against a real Finder, one at a time, with a person looking: the attribute is written perfectly and draws nothing; the published progress draws the pie. That measurement is why this package exists, and it is worth repeating rather than trusting, because the failure is silent — the attribute approach has tests that pass and a feature that does nothing.

Confirmed a second time, end to end: a downloader wired to this package draws the pie on a real download of a real file, watched in a real Finder. The tests here cannot show that, and never could — they prove the object is made, kept, updated and taken back, which is exactly what the attribute version also proved about itself.

Notes

  • The published object is retained. What a class method hands back is autoreleased, and a published progress freed with the current pool stops being published silently and intermittently.
  • Done is safe to call twice, so a caller can defer it and also call it where the work really ends.
  • The four Foundation constants are read from the framework with dlsym, not written down: a name wrong by one character is not an error, it is a publication nobody subscribes to.
  • Away from macOS every call is a no-op returning ErrUnavailable once.

Documentation

Overview

Package fileprogress tells macOS that a file is being downloaded, so the Finder draws the pie it draws for a browser's downloads.

The pie is not something the system works out by watching a file grow: nothing about writing a file announces anything. It has to be published, and the system has exactly one way of hearing it — an NSProgress, published to whoever subscribes. An extended attribute on the file looks like it ought to work, is documented in various corners of the internet, and does nothing: that was measured against a real Finder before this package was written.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnavailable = errors.New("fileprogress: only macOS publishes a file's progress")

ErrUnavailable means the system will not publish a file's progress. Away from macOS that is every system, which is not a fault worth reporting twice.

Functions

This section is empty.

Types

type Progress

type Progress struct{}

Progress is a download nobody was told about.

func Publish

func Publish(string, int64) (*Progress, error)

Publish does nothing away from macOS, and says so once.

func (*Progress) Done

func (p *Progress) Done()

Done does nothing.

func (*Progress) Set

func (p *Progress) Set(int64)

Set does nothing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL