.dvmrc is how a project says which Dart SDK it wants. It is the only dvm file that belongs in version control.
The format#
Canonically it is JSON, which leaves room for the format to grow while everything already written keeps parsing:
{ "dart": "3.9.0" }
dvm use always writes that form:
dvm use 3.9.0
{
"dart": "3.9.0"
}
A bare version on a single line is also accepted, the way .nvmrc works, for hand-editing:
3.9.0
dvm reads both. It only ever writes the JSON one, so a hand-written bare pin becomes JSON the next time you run
dvm use in that directory or any directory below it.
What a pin may contain#
The value is a reference. Three kinds are valid:
| Pin | Means |
|---|---|
3.9.0 | Exactly that version. |
work |
An alias you defined with dvm alias work 3.9.0. |
stable |
The version that channel resolved to when you last ran dvm install stable. |
Resolving an alias or a channel name reads ~/.dvm/config.json and stops there: aliases live in that file, and a channel's concrete version was written into it at install time. See
Aliases and Channels for why that matters.
Where dvm looks#
dvm walks up from the current directory to the filesystem root and uses the first .dvmrc
it finds. That is what makes a monorepo work:
my-monorepo/
.dvmrc { "dart": "3.9.0" } <- applies to everything below
packages/
api/
tools/
.dvmrc { "dart": "3.13.2" } <- except here
dart in packages/api gets 3.9.0. dart in packages/tools
gets 3.13.2. Nearest wins.
dvm use writes by that same walk. It updates the .dvmrc
that governs the directory you run it in, so the file it changes is the file dart reads: in
packages/api above, it updates the root pin that was covering it, and it prints the path of the file it wrote.
dvm use 3.13.2 --here is how packages/tools came to have a pin of its own — it creates a
.dvmrc in the directory you are in and names the ancestor pin it now shadows.
The other file: .dvm/dart_sdk#
In the directory that holds the .dvmrc, dvm use creates a link:
.dvm/dart_sdk -> ~/.dvm/versions/3.9.0
This is for IDEs and editors that want to be handed an SDK directory rather than a dart on
PATH. Point your analyzer or plugin at .dvm/dart_sdk and it follows the pin along with everything else. On Windows it is a symbolic link where the account can make one and a directory junction where it cannot; both resolve to the same SDK.
Keep it out of version control. It is an absolute path into your own home directory, so it means something on this machine and nowhere else. Ignore it:
dvm use 3.9.0 --gitignore
which appends:
# dvm's per-project SDK symlink; .dvmrc is the part you commit.
.dvm/
dvm edits .gitignore when you pass --gitignore, and otherwise names the rule it would add and leaves the file to you. The repository is yours, so the edit is yours to ask for.
A pin dvm cannot resolve is an error#
If .dvmrc cannot be parsed, or names something dvm cannot resolve, resolution fails
with a message rather than quietly falling through to your global default:
dvm: Dart 3.9.0 is pinned by /Users/you/code/api/.dvmrc, but it is not installed. Run: dvm install 3.9.0
So you always get the SDK the pin names, or a message naming the pin. A typo is reported where you made it, rather than turning up much later as a build that behaved oddly.
Checking what applies#
dvm which
names both the SDK and the .dvmrc that chose it. See Resolution Order
for the full set of rules that surround this one.