Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for legacy files #13

Merged
merged 4 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
workflow_run:
workflows: [Build]
types: [completed]
branches: [main]

concurrency:
group: release
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ devShells.default = pkgs.mkShell {
`packagesFromVersionsFile` is of the form `{ “<plugin-1>” = <package-1>;
"<plugin-2>" = <package-2>; ... }`.

## Version Files

As of version `2.1.0`, asdf2nix now supports legacy version files in the same
way that
[asdf](https://asdf-vm.com/manage/configuration.html#legacy-version-file) does.
Check the version files [test suite](tests/version_files_test.nix) for more
information on how this feature works.

## Plugins

In an asdf2nix context, a plugin’s primary goal is to determine whether a
Expand Down
60 changes: 46 additions & 14 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
in
{
lib.packagesFromVersionsFile =
{ versionsFile
{ versionsFile ? null
, legacyVersionFiles ? { }
, system ? builtins.currentSystem
, plugins ? { }
, skipMissingPlugins ? false
Expand All @@ -22,10 +23,46 @@
in
{
name = builtins.elemAt pluginAndVersion 0;
version = builtins.elemAt pluginAndVersion 1;
value = builtins.elemAt pluginAndVersion 1;
});
filterPlugins = builtins.filter
({ name, ... }:
toolVersions =
if versionsFile == null
then { }
else
builtins.listToAttrs
(parseVersions
(removeComments
(fileLines versionsFile)));
legacyVersions =
builtins.mapAttrs
(_: file: lib.fileContents file)
legacyVersionFiles;
versions =
lib.throwIf (versionsFile == null && legacyVersionFiles == { })
''
No version files provided. Try with `versionsFile`:

```
packagesFromVersionsFile {
versionsFile = ./.tool-versions;
...
}
```

Or `legacyVersionFiles`:

```
packagesFromVersionsFile {
legacyVersionFiles = {
python = ./.python-version;
};
...
}
```
''
toolVersions // legacyVersions;
filterPlugins = lib.filterAttrs
(name: _:
let
hasPlugin = builtins.hasAttr name plugins;
in
Expand Down Expand Up @@ -56,8 +93,8 @@
lib.warnIf
(!hasPlugin) "Skipping \"${name}\" plugin"
hasPlugin);
findPackages = builtins.map
({ name, version }:
findPackages = builtins.mapAttrs
(name: version:
let
plugin = plugins.${name};
in
Expand All @@ -70,18 +107,13 @@
> nix flake lock --update-input <asdf2nix-${name}>
```
''
plugin.packageFromVersion
{
inherit name;
value = plugin.packageFromVersion { inherit system version; };
inherit system version;
}
);
in
builtins.listToAttrs
(findPackages
(filterPlugins
(parseVersions
(removeComments
(fileLines versionsFile)))));
findPackages (filterPlugins versions);

templates = {
default = {
Expand Down
111 changes: 30 additions & 81 deletions tests/lib_test.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,12 @@ let
lib = (builtins.getFlake (builtins.toString ./..)).lib;
in
[
# comments
{
name = "Ignores comment lines";
actual = lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
# This is a comment
python 3.12.0
# This is another comment
terraform 1.6.3
'';
plugins = {
python = {
hasVersion = _: true;
packageFromVersion = { version, ... }: version;
};
terraform = {
hasVersion = _: true;
packageFromVersion = { version, ... }: version;
};
};
};
expected = { python = "3.12.0"; terraform = "1.6.3"; };
}
{
name = "Ignores inline comments";
name = ''
When versionsFile contain comments, then it ignores those during the
parsing
'';
actual = lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
# This is a comment
Expand All @@ -48,14 +30,8 @@ in
# skipMissingPlugins = false
{
name = ''
Given:
- A versions file referencing some plugins
- A set of plugins matching only one of them
- A feature flag to skip missing plugins
When:
- The matching plugin provides a package for the requested version
Then:
- Returns a set with the retrieved package
When skipMissingPlugins is enabled and some plugins are missing, then
returns packages only for the ones matching
'';
actual = lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
Expand All @@ -74,15 +50,8 @@ in
}
{
name = ''
Given:
- A versions file referencing some plugins
- A set of plugins matching only one of them
- A feature flag to skip missing plugins
When:
- The matching plugin does not provide a package for the requested
version
Then:
- Throws an error
When skipMissingPlugins is enabled and all plugins are provided, then it
returns all the packages
'';
actual = builtins.tryEval (
(lib.packagesFromVersionsFile {
Expand All @@ -96,20 +65,14 @@ in
};
};
skipMissingPlugins = true;
})
}).python
);
expected = { success = false; value = false; };
}
{
name = ''
Given:
- A versions file referencing some plugins
- A set of empty plugins
- A feature flag to skip missing plugins
When:
- There are no plugins available
Then:
- Returns an empty set
When skipMissingPlugins is enabled and no plugins are provided, then
returns an empty set
'';
actual = lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
Expand All @@ -123,13 +86,8 @@ in
# skipMissingPlugins = false
{
name = ''
Given:
- A versions file referencing some plugins
- A set of plugins matching all of them
When:
- The matching plugins provide packages for the requested versions
Then:
- Returns a set with the retrieved packages
When skipMissingPlugins is disabled and all plugins are provided, then
returns all packages
'';
actual = lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
Expand All @@ -149,39 +107,30 @@ in
};
expected = { python = "3.12.0"; terraform = "1.6.3"; };
}
# hasVersions
{
name = ''
Given:
- A versions file referencing some plugins
- A set of plugins matching all of them
When:
- The matching plugin does not provide a package for the requested
version
Then:
- Throws an error
When the provided plugin does not contain the requested version, then
throws an error
'';
actual = builtins.tryEval (lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
python 3.12.0
'';
plugins = {
python = {
hasVersion = _: false;
packageFromVersion = { version, ... }: version;
actual = builtins.tryEval (
(lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
python 3.12.0
'';
plugins = {
python = {
hasVersion = _: false;
packageFromVersion = { version, ... }: version;
};
};
};
});
}).python
);
expected = { success = false; value = false; };
}
{
name = ''
Given:
- A versions file referencing some plugins
- A set of empty plugins
When:
- There are no plugins available
Then:
- Throws an error
When no plugins are provided, then throws an error
'';
actual = builtins.tryEval (lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
Expand Down
89 changes: 89 additions & 0 deletions tests/version_files_test.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
let
lib = (builtins.getFlake (builtins.toString ./..)).lib;
in
[
{
name = ''
When neither versionsFile nor legacyVersionFiles are provided, then
throws an error
'';
actual = builtins.tryEval (lib.packagesFromVersionsFile { });
expected = { success = false; value = false; };
}
{
name = ''
When only legacyVersionFiles is provided, then returns the package
matching the requested version
'';
actual = lib.packagesFromVersionsFile {
legacyVersionFiles = {
python = builtins.toFile ".python-version" ''
3.12.0
'';
};
plugins = {
python = {
hasVersion = _: true;
packageFromVersion = { version, ... }: version;
};
};
};
expected = { python = "3.12.0"; };
}
{
name = ''
When both versionsFile and legacyVersionFiles are provided and the
plugins does not overlap, then returns packages specified in both files
'';
actual = lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
terraform 1.6.3
'';
legacyVersionFiles = {
python = builtins.toFile ".python-version" ''
3.12.0
'';
};
plugins = {
python = {
hasVersion = _: true;
packageFromVersion = { version, ... }: version;
};
terraform = {
hasVersion = _: true;
packageFromVersion = { version, ... }: version;
};
};
};
expected = { python = "3.12.0"; terraform = "1.6.3"; };
}
{
name = ''
When both versionsFile and legacyVersionFiles are provided and the
plugins overlap, then the version of the tool coming from the legacy file
takes more precedence
'';
actual = lib.packagesFromVersionsFile {
versionsFile = builtins.toFile ".tool-versions" ''
python 2.7.6
terraform 1.6.3
'';
legacyVersionFiles = {
python = builtins.toFile ".python-version" ''
3.12.0
'';
};
plugins = {
python = {
hasVersion = _: true;
packageFromVersion = { version, ... }: version;
};
terraform = {
hasVersion = _: true;
packageFromVersion = { version, ... }: version;
};
};
};
expected = { python = "3.12.0"; terraform = "1.6.3"; };
}
]