A Survey of other XDG-y packages

The entire point of this package is to handle locations in a fairly standardised way. With this in mind, it seems fairly sensible to survey other notable XDG-y packages and see how them behave. Specifically, we will be looking at the following:

Base directories

Linux

Common NameEnvVarXDG specQStandardPathsGo XDGRust directories-rsPython platform-dirs
User dataXDG_DATA_HOME~/.local/shareXDG specXDG specXDG specXDG spec
System dataXDG_DATA_DIRS/usr/local/share, /usr/shareXDG specXDG spec~/.local/shareXDG spec
User configXDG_CONFIG_HOME~/.configXDG specXDG specXDG specXDG spec
System configXDG_CONFIG_DIRS/etc/xdgXDG specXDG spec-XDG spec
StateXDG_STATE_HOME~/.local/state-XDG specXDG specXDG spec
User executablesXDG_BIN_HOME [binhome]~/.local/bin--XDG spec-
CacheXDG_CACHE_HOME~/.cacheXDG specXDG specXDG specXDG spec
RuntimeXDG_RUNTIME_DIR/run/user/$UIDXDG specXDG spec-XDG spec

MacOS

Common NameEnvVarQStandardPathsGo XDGRust directories-rsPython platform-dirs
User dataXDG_DATA_HOME~/Library/Application SupportQtQtQt
System dataXDG_DATA_DIRS/Library/Application SupportQt~/Library/Application SupportQt
User configXDG_CONFIG_HOME~/Library/Preferences~/Library/Application SupportGo XDGQt
System configXDG_CONFIG_DIRS~/Library/Preferences~/Library/Preferences, /Library/Application Support, /Library/Preferences--
StateXDG_STATE_HOME-~/Library/Application Support-Go XDG
User executablesXDG_BIN_HOME [binhome]----
CacheXDG_CACHE_HOME~/Library/Caches/ , /Library/CachesQtQtQt
RuntimeXDG_RUNTIME_DIR~/Library/Application SupportQt-~/Library/Caches/TemporaryItems

Windows

Here folder names not beginning with ~ or / refer to Known Folders.

Common NameEnvVarQStandardPathsGo XDGRust directories-rsPython platform-dirs
User dataXDG_DATA_HOMELocalAppDataQtQtLocalAppData or RoamingAppData
System dataXDG_DATA_DIRSProgramDataRoamingAppData, ProgramDataRoamingAppDataProgramData
User configXDG_CONFIG_HOMELocalAppDataLocalAppDataRoamingAppDataLocalAppData or RoamingAppData
System configXDG_CONFIG_DIRSProgramDataProgramData, RoamingAppData-ProgramData
StateXDG_STATE_HOME-LocalAppData-LocalAppData
User executablesXDG_BIN_HOME [binhome]---
CacheXDG_CACHE_HOMELocalAppData\cacheLocalAppData\cacheLocalAppDataLocalAppData\Cache
RuntimeXDG_RUNTIME_DIR~LocalAppDataGo XDGLocalAppData\Temp

User directories

Linux

Common NameEnvVarXDG specQStandardPathsGo XDGRust directories-rsPython platform-dirs
DesktopXDG_DESKTOP_DIR~/DesktopXDG specXDG spec--
DownloadXDG_DOWNLOAD_DIR~/DownloadsXDG specXDG spec--
DocumentsXDG_DOCUMENTS_DIR~/DocumentsXDG specXDG spec-XDG spec
MusicXDG_MUSIC_DIR~/MusicXDG specXDG spec--
PicturesXDG_PICTURES_DIR~/PicturesXDG specXDG spec--
VideosXDG_VIDEOS_DIR~/VideosXDG specXDG spec--
TemplatesXDG_TEMPLATES_DIR~/Templates-XDG spec--
PublicXDG_PUBLICSHARE_DIR~/Public-XDG spec--

MacOS

Common NameEnvVarQStandardPathsGo XDGRust directories-rsPython platform-dirs
DesktopXDG_DESKTOP_DIR~/DesktopQtQt-
DownloadXDG_DOWNLOAD_DIR~/DownloadsQtQt-
DocumentsXDG_DOCUMENTS_DIR~/DocumentQtQtQt
MusicXDG_MUSIC_DIR~/MusicQtQt-
PicturesXDG_PICTURES_DIR~/PicturesQtQt-
VideosXDG_VIDEOS_DIR~/MoviesQtQt-
TemplatesXDG_TEMPLATES_DIR-~/TemplateGo XDG-
PublicXDG_PUBLICSHARE_DIR-~/PublicGo XDG-

Windows

Common NameEnvVarGo XDGRust directories-rsPython platform-dirs
DesktopXDG_DESKTOP_DIRDesktopGo XDG-
DownloadXDG_DOWNLOAD_DIRDownloadsGo XDG-
DocumentsXDG_DOCUMENTS_DIRDocumentsGo XDGGo XDG
MusicXDG_MUSIC_DIRMusicGo XDG-
PicturesXDG_PICTURES_DIRPicturesGo XDG-
VideosXDG_VIDEOS_DIRVideosGo XDG-
TemplatesXDG_TEMPLATES_DIRTemplatesGo XDG-
PublicXDG_PUBLICSHARE_DIRPublicGo XDG-

Project directories

Here $PP will be a stand-in for the project path, according to the conventions of the OS.

Linux

Common NameQStandardPathsRust directories-rs
User data$(User data)/$PP$(User data)/$PP
System data$(System data)/$PP$(User data)/$PP
User config$(User config)/$PP$(User config)/$PP
System config$(System config)/$PP-
Cache$(Cache)/$PP$(Cache)/$PP
State-$(State)/$PP

MacOS

Common NameQStandardPathsRust directories-rs
User data$(User data)/$PP$(User data)/$PP
System data$(System data)/$PP$(User data)/$PP
User config$(User config)/$PP$(User config)/$PP
System config--
Cache$(Cache)/$PP$(Cache)/$PP
State--

Windows

Common NameQStandardPathsRust directories-rs
User data$(User data)\$PP$(User data)\$PP\data
System data$(System data)\$PP$(User data)\$PP\data
User config$(User config)\$PP$(User config)\$PP\config
System config$(System config)\$PP-
Cache$(Cache)\$PP$(Cache)\$PP\cache
State--

Extra directories

Linux

Common NameQStandardPathsGo XDGRust directories-rsPython platform-dirs
Fonts~/.fonts, $(User/System data)/fontsQt~/.local/share/fonts-
Applications$(User/System data)/applicationsQt--

MacOS

Common NameQStandardPathsGo XDGRust directories-rsPython platform-dirs
Fonts/System/Library/Fonts~/Library/Fonts, /Library/Fonts, /System/Library/Fonts, /Network/Library/Fonts~/Library/Fonts-
Applications/ApplicationsQt--

Windows

Common NameQStandardPathsGo XDGRust directories-rsPython platform-dirs
FontsFontsQt--
ApplicationsRoamingAppData, ProgramsPrograms, CommonPrograms--

Discrepancies

Base directories

MacOS

User configuration
The conflict

directories-rs uses ~/Library/Preferences while all the other implementations use ~/Library/Application support.

Resolution

Looking at Table 1.3 of Apple's Standard Directory Guidelines, it says of ~/Library/Preferences that "You should not create files in this directory yourself. Instead, use the NSUserDefaults class or CFPreferences API to get and set preference values for your app." (wnich I interpret as "don't touch directly"), and of ~/Library/Application Support that "Use this directory to store all app data files except those associated with the user’s documents". Given the intended use of this package is to procure the correct locations to read/write files to, ~/Library/Application Support is thus the more appropriate choice.

System configuration
The conflict

Qt uses ~/Library/Preferences, while Go XDG uses ~/Library/Preferences, /Library/Application Support, and /Library/Preferences. The other implementations do not declare a MacOS system configuration directory.

Resolution

For the aforementioned reasons with User configuration on MacOS, the Preferences folder does not seem appropriate, which leaves /Library/Application Support.

User executables
The conflict

MacOS does not have a standard directory for user executables.

Resolution

Look for the common manually specified "local executable folder" paths (~/.local/bin/, /opt/local/bin) on the path, and if none of them are found fall back on the system executable folder /usr/local/bin.

Runtime
The conflict

MacOS simply has no direct equivalent of the XDG runtime directory. Thus, we must choose which aspect of the runtime directory we think is more important: the transient-ness, or the association with the application. Qt and Go XDG pick the lattter, but Python's platform-dirs picks the latter.

Resolution

Since in the XDG spec the runtime directory is a collection of all application's runtime files which is held in-memory, a temporary directory seems to make the most sense in this regard. However, while the runtime directory's contents are transient, then might not be able to be safely deleted on a whim, which is one of the usual assumptions made about the contents of a temporary directory.

There is no clear option here, but I will prioritise avoiding putting fragile files in a temporary directory, and so we will go with ~/Library/Application Support.

Windows

Roaming vs Local app data
The conflict

Across the data and configuration folders, there is general contention around whether RoamingAppData or AppData should be used. The difference seems to relate to DomainController and ActiveDirectory — simply put data in RoamingAppData will follow the user around, while AppData won't. The idea is that "less essential but potentially large" information goes in AppData.

Resolution

I think configuration should follow the user around, and if data can be stored locally because it's not essential, then that's what the cache is for. So, RoamingAppData will be used for everything but State, Cache, and Runtime.

In there is demand in the future, a local::Bool keyword argument could be added to support both modes of operaton.

Executable files
The conflict

Windows doesn't have anywhere that user executable files are supposed to go.

Resolution

Like with MacOS, check for locations that users seem to use for this purpose which are also on the path, namely ~\bin, RoamingAppData\bin, and AppData\bin. If none of these exist, use the current working directory as at least that way the provided path will be callable in the state at the time.

User directories

No conflicts 🎉.

Project directories

Windows AppData project suffixes

The conflict

Some projects just use AppData\$Project for the data, config, and cache folders, however directories-rs adds suffixes after the project.

Resolution

There's no formally specified structure, and conventions in usage are loose, so we may as well decide on a more structured approach, and use suffix directories.

Extra directories

A collection of different directories

The conflict

Some packages only have one or two Application/Font directories, other have many.

Resolution

Since these will primarily be used for searching, it makes sense to include all valid paths.

  • binhomeWhile XDG_BIN_HOME is not yet standard, it seems like the most likely name to be given to ~/.local/bin (see this issue), and I think it is worth having something rather than nothing.