Andrey Listopadov

deps.fnl

~2 minutes read

A Fennel dependency manager inspired by deps.edn.

Dependencies and Fennel

  • Luarocks
  • Git
  • Vendoring

Why not Luarocks

  • Unsure if it can provide non-lua files
  • Cumbersome
  • Outdated

Why not Git

  • Git submodules are a pain
  • Git subtree is an arcane art that no one understands
  • A lot of unnecessary files in the project
  • PATH problems

Why not vendoring

  • Vendoring is pretty cool actually
  • Still PATH problems
  • Updating a library requires manual work
  • A lot of manual work to build a project

deps.fnl

  • A file at the root of the project
  • Understands how to download dependencies
  • Knows how to build dependencies
  • Automatically generates PATH for Lua, Fennel, and macros

deps.fnl file format

{:deps
 {:async.fnl {:type "git"
              :url "https://gitlab.com/andreyorst/async.fnl"
              :tag "deps"}
  :json.fnl {:type "git"
             :url "https://gitlab.com/andreyorst/json.fnl"
             :tag "deps"}
  :reader.fnl {:type "git"
               :url "https://gitlab.com/andreyorst/reader.fnl"
               :tag "deps"}
  :luasocket {:type "rock"}}
 :paths {:fennel ["src/?.fnl" "src/?/init.fnl"]}}

.deps directory

.deps
├── git
│   ├── async.fnl # name from deps.fnl file
│   │   └── deps # branch name
│   │       ├── deps.fnl # inner deps file
│   │       ├── lib
│   │       │   └── fennel-test.fnl
│   │       └── src
│   │           └── io
│   │               └── gitlab
│   │                   └── andreyorst
│   │                       └── async.fnl
│   └ ...
└── rocks
    ├── lib
    │   ├── lua
    │   │   └── 5.4
    │   │       └── socket
    │   └── luarocks
    │       └── rocks-5.4
    │           ├── luasocket
    │           │   └── 3.1.0-1
    │           └── manifest
    └── share
        └── lua
            └── 5.4
                ├── ltn12.lua
                ├── mime.lua
                ├── socket
                │   └── ...
                └── socket.lua

62 directories, 137 files

PATH generation

$ deps --path
LUA_PATH="~/Projects/Fennel/fnl-http/.deps/rocks/share/lua/5.4/?.lua;~/Projects/Fennel/fnl-http/.deps/rocks/share/lua/5.4/?/init.lua;~/.luarocks/share/lua/5.4/?.lua;~/.luarocks/share/lua/5.4/?/init.lua;~/.local/share/lua/5.4/?.lua;~/.local/share/lua/5.4/?/init.lua;/usr/share/lua/5.4/?.lua;/usr/share/lua/5.4/?/init.lua;/usr/lib64/lua/5.4/?.lua;/usr/lib64/lua/5.4/?/init.lua;./?.lua;./?/init.lua"
FENNEL_PATH="~/Projects/Fennel/fnl-http/src/?.fnl;~/Projects/Fennel/fnl-http/src/?/init.fnl;~/Projects/Fennel/fnl-http/.deps/git/reader.fnl/deps/src/?.fnl;~/Projects/Fennel/fnl-http/.deps/git/async.fnl/deps/src/?.fnl;~/Projects/Fennel/fnl-http/.deps/git/json.fnl/deps/src/?.fnl"
LUA_CPATH="~/Projects/Fennel/fnl-http/.deps/rocks/lib/lua/5.4/?.so;~/.luarocks/lib/lua/5.4/?.so;~/.local/lib/lua/5.4/?.so;/usr/lib64/lua/5.4/?.so;/usr/lib64/lua/5.4/loadall.so;./?.so"
$ deps
Welcome to Fennel 1.5.1-dev on PUC Lua 5.4!
Use ,help to see available commands.
>> (local client (require :io.gitlab.andreyorst.fnl-http.client))
nil
>> client.get
#<function: 0x5636ba3823a0>
>>

Conflicts

  • If two libraries are of the same origin but of different version deps will signal an error
  • Conflicts can be allowed with the --allow-conflicts flag
  • If conflicts are allowed, project dependencies take priority

Pros

  • Small source code ~300 LOC
  • Doesn’t depend on anything but fennel itself
  • Handles both Git and Luarocks dependencies
  • If Git dependency has deps.fnl, processes its dependencies recursively
  • Automatically sets up PATH
  • A drop-in replecement for fennel launcher script
  • Can be potentially included in the launcher.fnl

Cons

  • There are no cons cells in Fennel
  • Happy path all the way
    • Potentially will grow beyond ~300 LOC
    • Windows OS is supported but completely untested
  • Not purely functional, I guess

You can try it yourself!

  • Install deps from https://gitlab.com/andreyorst/deps.fnl
      $ git clone https://gitlab.com/andreyorst/deps.fnl && cd deps.fnl
      $ ln -sf deps ~/.local/bin/deps # or other location in your system PATH
    
  • Checkout fnl-http on the deps branch
      $ git clone --depth 1 https://gitlab.com/andreyorst/fnl-http --branch deps
    
  • Run deps at project root
      $ cd fnl-http
      $ deps
    
  • Enjoy REPL with all of the paths set up!

Thanks!

Questions?