Skip to content

Commit

Permalink
Merge pull request #1 from brokenpip3/add-nix-shell
Browse files Browse the repository at this point in the history
feat: run directly a shell with all the tools
  • Loading branch information
brokenpip3 authored Mar 24, 2024
2 parents 5b44530 + 9a7598f commit e8c35da
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 17 deletions.
75 changes: 73 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,90 @@
# asdf2nix

**asdf2nix** is a tool that converts an [asdf](https://asdf-vm.com/) `.tool-versions` file into a Nix flake, simplifying the process of transitioning from asdf to Nix.
**asdf2nix** is a tool that converts an [asdf](https://asdf-vm.com/) `.tool-versions` file into a Nix flake or run a nix shell, simplifying the process of transitioning from asdf to Nix.

## Usage

To use **asdf2nix**, run the following command in your project root where the `.tool-versions` file is located:

```bash
nix run github:brokenpip3/asdf2nix -- flake
nix run github:brokenpip3/asdf2nix -- <command>
```

You can also specify the file location as an argument if it's in a different directory.

**Note:** Make sure Nix is installed on your system and that flakes are enabled before using this tool.

## Commands

### Flake

```bash
nix run github:brokenpip3/asdf2nix -- flake
```

This command generates a flake based on the packages listed in the `.tool-versions` file:

```bash
$ cat .tool-versions
terraform 1.5.2
nodejs 16.15.0

$ nix run github:brokenpip3/asdf2nix -- flake

{
description = "A flake with devshell generated from .tools-version";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
terraform_1_5_2.url = github:NixOS/nixpkgs/0b9be173860cd1d107169df87f1c7af0d5fac4aa;
nodejs_16_15_0.url = github:NixOS/nixpkgs/7b7fe29819c714bb2209c971452506e78e1d1bbd;

};

outputs = { self, nixpkgs, flake-utils, ... }@inputs:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
terraform = inputs.terraform_1_5_2.legacyPackages.${system}.terraform;
nodejs = inputs.nodejs_16_15_0.legacyPackages.${system}.nodejs;

in
{
devShells.default = pkgs.mkShell {
packages = [
terraform
nodejs

];
};
}
);
}
```
### Shell
```bash
nix run github:brokenpip3/asdf2nix -- shell
```
This command generates and executes a Nix shell based on the packages specified in the `.tool-versions` file.
```bash
$ cat .tool-versions
terraform 1.5.2
nodejs 16.15.0

$ nix run github:brokenpip3/asdf2nix -- shell
Generating shell from .tool-versions: nix shell nixpkgs/0b9be173860cd1d107169df87f1c7af0d5fac4aa#terraform nixpkgs/7b7fe29819c714bb2209c971452506e78e1d1bbd#nodejs

$ terraform version
Terraform v1.5.2
on linux_amd64
...
```
## Credits
* Special thanks to `RikudouSage` for the versions [database](https://github.com/RikudouSage/NixPackageHistoryBackend).
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tool.poetry]
name = "asdf2nix"
version = "0.1.0"
description = "Generate Flake from an asdf .tool-versions file"
version = "0.2.0"
description = "Generate Flake or run a shell from an asdf .tool-versions file"
authors = ["Brokenpip3 <[email protected]>"]
license = "MIT"
readme = "README.md"
Expand Down
1 change: 1 addition & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "0.1.0"
68 changes: 55 additions & 13 deletions src/asdf2nix.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
import subprocess
import warnings
from dataclasses import dataclass
from pathlib import Path
Expand Down Expand Up @@ -69,6 +70,17 @@ def compare_versions(version1: str, version2: str) -> tuple[bool, str]:
return False, ""


def generate_shell_from_tools_version(tools: List[Tool]) -> str:
"""
Generate a nix shell command
like "nix shell nixpkgs/revision1#tool1 nixpkgs/revision2#tool2"
"""
shell_command = "nix shell"
for tool in tools:
shell_command += f" nixpkgs/{tool.revision}#{tool.name}"
return shell_command


def generate_flake_from_tools_version(tools: List[Tool]) -> str:
system = "${system}"
flake_content = """
Expand Down Expand Up @@ -120,39 +132,69 @@ def generate_flake_from_tools_version(tools: List[Tool]) -> str:
return flake_content


@app.command()
def flake(
file: Annotated[Optional[str], typer.Argument(help=".tool-versions file")] = None
) -> str:
def read_tool_versions_file(file_path: Path) -> List[str]:
"""
Generate a flake from .tool-versions file.
You can optional pass an argument to specify the path to the .tool-versions file.
Read the .tool-versions file and return the lines.
"""
if file is None:
file = Path.cwd() / ".tool-versions"
try:
with open(file, "r") as file:
tools_lines = file.readlines()
with open(file_path, "r") as file:
return file.readlines()
except FileNotFoundError:
typer.echo(f"File {file} not found.")
typer.echo(f"File {file_path} not found.")
raise typer.Exit(code=1)


def get_revised_tools(tools_lines: List[str]) -> List[Tool]:
"""
Fetch the revised tool information for each tool in the .tool-versions file.
"""
tools = []
for line in tools_lines:
name, version = line.strip("").split()
name, version = line.strip().split()
tool = Tool(name=name, version=version)
try:
revised_tool = get_revision(tool)
if revised_tool:
tools.append(revised_tool)
except ValueError as err:
typer.echo(err)
return tools


@app.command()
def flake(
file: Annotated[Optional[str], typer.Argument(help=".tool-versions file")] = None
) -> str:
"""
Generate a flake from .tool-versions file.
"""
if file is None:
file = Path.cwd() / ".tool-versions"
tools_lines = read_tool_versions_file(file)
tools = get_revised_tools(tools_lines)
flake_content = generate_flake_from_tools_version(tools)
typer.echo(flake_content)


@app.command()
def shell(
file: Annotated[Optional[str], typer.Argument(help=".tool-versions file")] = None
) -> str:
"""
Run a nix shell from .tool-versions file.
"""
if file is None:
file = Path.cwd() / ".tool-versions"
tools_lines = read_tool_versions_file(file)
tools = get_revised_tools(tools_lines)
shell_command = generate_shell_from_tools_version(tools)
try:
typer.echo(f"Generating shell from .tool-versions: {shell_command}")
subprocess.run(shell_command, shell=True)
except subprocess.CalledProcessError as err:
typer.echo(err)


@app.command()
def version() -> str:
"""
Expand Down
6 changes: 6 additions & 0 deletions test/test_asdf2nix.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,9 @@ def test_flake_generation_minor(capsys):
"terraform = inputs.terraform_1_6_4.legacyPackages.${system}.terraform;"
in result.output
)


def test_shell_file_not_found(capsys):
result = runner.invoke(app, ["shell", "nonexistent_file.txt"])
assert result.exit_code == 1
assert "nonexistent_file.txt not found." in result.output

0 comments on commit e8c35da

Please sign in to comment.