Skip to content

Commit

Permalink
feat: Add support for legacy files (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
sestrella authored Nov 25, 2023
1 parent 5b49c46 commit 2ac381d
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 95 deletions.
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"; };
}
]

0 comments on commit 2ac381d

Please sign in to comment.