Routing
It is not uncommon for the same config file to be placed in different places
depending on the environment. For example, the config file for psql
,
a client of PostgreSQL, has the following different paths depending
on the environment, according to documentation:
- POSIX: If the
PSQLRC
environment variable is present, use its value as the path; if not, use ~/.psqlrc. - Windows: If the
PSQLRC
environment variable is present, use its value as the path; otherwise, use %APPDATA%\postgresql\psqlrc.conf.
Dojang utilizes a concept called routing to deal with such complex cases.
Directory Routing
Many programs store their config files in $XDG_CONFIG_HOME
on Linux,
~/Library/Application Support on macOS, and %AppData%
or %LocalAppData%
on Windows.1 So if you want to use the same config file in multiple
environments, it's convenient to route those paths together.
The declaration below shows an example of this.
[dirs.app_config]
linux = "$XDG_CONFIG_HOME"
mac = "$HOME/Library/Application Support"
win = "$AppData"
[monikers.linux]
os = "linux"
[monikers.mac]
os = "macos"
[monikers.win]
os = "windows"
Here, the routing name, app_config
, is also the name of a directory within
the repository. If we say that the files in the repository are as follows:
- dojang.toml
- app_config/
- alacritty/
- alacritty.toml
- ghc/
- ghci.conf
- nvim/ init.vim
- alacritty/
On Linux, you will have files in the following paths:
- /home/$USER/.config/alacritty/
- /home/$USER/.config/alacritty/alacritty.toml
- /home/$USER/.config/ghc/
- /home/$USER/.config/ghc/ghci.conf
- /home/$USER/.config/nvim/
- /home/$USER/.config/nvim/init.vim
However, what if the XDG_CONFIG_HOME
environment variable is not defined?
The app_config
routing on Linux would be an empty path, i.e. the current
working directory (CWD) at the time you run Dojang. If you want to prevent
this, you can tweak the routing a bit, as shown below.
linux = "${XDG_CONFIG_HOME:-$HOME/.config}"
The syntax above means that if the XDG_CONFIG_HOME
environment variable
exists, take its value, but otherwise take the path ~/.config.
For more advanced features like this, see the file path
expressions documentation.
Ignoring irrelevant files
In some cases, like your home directory, where you might have a lot of stuff
besides your config file, the results of dojang status
can be overwhelming
and difficult to see. In addition, too many files can make it slow.
To avoid this, you can specify which files to ignore in the ignores
section.
For example, suppose you added a home
route like below:
[dirs.home]
linux = "$HOME"
mac = "$HOME"
win = "$UserProfile"
Now, any files inside the directory that the home
routes to will appear in
the results of dojang status
. However, you may want to ignore the Documents
directory among them. In this case, you can specify the files you want to
ignore in the ignores
section, as shown below:
[ignores]
home = [
"Documents",
]
In practice, there are much more files in the home directory to ignore than not, so it's usually more convenient to just ignore everything:
[ignores]
home = ["*"]
Even if we ignore all the files like this, we can still reflect them by
specifying them one by one with the dojang reflect -f
command.
Once added to the repository, files are managed even if they are on
the ignore list.
In case of overlapping routing
Let's say you have routed app_config
to XDG_CONFIG_HOME
on Linux,
which is ~/.config, as in the example above, and you want to add a route to
your home directory:
[dirs.home]
linux = "$HOME"
mac = "$HOME"
win = "$UserProfile"
In most cases, the directory where home
is routed will also contain
the directory where app_config
is routed. It's easy to make mistakes
when dealing with overlapping directories in two or more routes like this,
so you should have one side ignore the other, like below:
[ignores].
home = [
".config",
"AppData/Roaming",
"Library/Application Support"
]
Per-file routing
For some config files, not only the directory but also the filename
itself can vary depending on the environment, and it can be simpler to route
them on a per-file basis. For example, the psql
config file,
which we used as an example at the beginning of this document,
could be routed on a per-file basis, as shown below:
[files.".psqlrc"]
posix = "${PSQLRC:-$HOME/.psqlrc}"
win = "${PSQLRC:-${AppData:-$UserProfile/AppData/Roaming}/postgresql/psqlrc.conf}"
[monikers.posix]
os = ["linux", "macos"]
[monikers.win]
os = "windows"
Null routing
Some config files may not exist or be needed in some environments. In these cases, you can choose not to route them at all, which is called null routing. For example, if you have a config file that is only needed on Windows, you can route it like below:
[files."Microsoft.WindowsTerminal.json"]
win = "$LocalAppData/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json"
The above config file is only required on Windows, so you won't have it at all on Linux or macOS.
-
For example, in the cross-platform app framework Electron, the
app.getPath("appData")
API returns different paths depending on the environment. In the same manner, GLib'sget_user_config_dir()
API behaves similarly. ↩