This post describes my experience for MAC0470 on packaging the Nushell for Debian, a new concept of a shell for Linux distros, programmed on Rust.
What is Nushell?
Nushell is a new type of shell. Compared to other common shells like bash, zsh, nu has a more light and safe design by using Rust as your main programming language. Besides that, nu has much more functions compared to other shells, like the auto completion, which is way more developed as common autocompletions, like the one used by zsh.
Besides that, Nushell has a great potential for contribution, as it has one repository destined only to scripts that can be used by anyone, for example, the completions said before, that aren’t only command completions, but input ones. For example, if you type and press TAB:
git checkout <TAB>
All the branches and commits from that repository will appear, so you don’t have to type that many letters and numbers just to checkout to that commit ou branch.
How to start packaging
We followed the tutorias from Joenio, in two parts: Part 1 and Part 2. Besides Joenio uses perl as a demonstration of packaging, as my group and I decided to move on contributing to Nushell in the Second Phase of MAC0470, we are going to package Nushell to Debian, which is one of some distros that doesn’t have native support in your main package manager.
To do this, there is a dh-cargo
, very next to dh-make-perl
, which is used by Joenio. It takes a Rust project that is ready and transforms it in a package, using Rust crates as the dependencies.
Part 1
In the first part, the class had some problems with virtualization and recommended versions, as Joenio said to use debian-testing, and not debian-stable. So, the class needed to re-download and reinstall the VM. The result? The internet connection didn’t cooperate and we had to finish it at home.
After getting home, the tutorial went all. The first dependencies to install and buildings took a while, but nothing to worry about. Some people had problems when using a container instead of a virtual machine. As I used QEMU all the time, I didn’t had any problem at all and could build without problems.
Part 2
Besides having the Debian QEMU already up and running, different from Joenio’s suggestion, it was possible to follow the Nushell packaging in our main system, in my case, Ubuntu. We are going to test the building in the Debian, of course, but we didn’t need any special dependencies that were only available in Debian. So, we started searching how to package a Rust.
Rust crates
In Rust, a crate is a fundamental unit of code organization and compilation. Crates serve as the building blocks of Rust programs and libraries, and they can contain various modules, functions, types, constants, and more. In this way, they can be used as a base for dependencies in a package, making the packaging easier.
The copyright “problem”
When we install packages in our distro, we have to install their dependencies together. A small package can have many dependencies. In a project like Nushell, which is a shell that is used to access basically all the functions a distro can execute, there are MANY dependencies.
In this way, besides dh-cargo
joining those dependencies, they need to be well documented, principally the Copyright part. If any dependency is proprietary software, we need to inform it. If any project is developed based on Nushell, we have to inform it. There any many licenses that can pass its attributes “recursively”, like “GNU 3.0”. It is very difficult to check each dependency license and apply it to the copyright files inside the package.
The most difficult part of Rust packaging isn’t the package itself, but the documentation (the most boring part for any software project).
The dependencies problem
After checking every file necessary to a Debian package, we made it to a package build, using a build.sh
file in a debcargo-conf
, a repository recommended by the Rust Debian Team to prepare packages. We generated a .dsc
file, that we used to generate a .deb
file, but, after executing the last command necessary to generate it, we encountered a very common problem between our class: dependencies.
dpkg-checkbuilddeps: error: Unmet build dependencies: rustc:native (>= 1.77.2) librust-crossterm-0.27+default-dev librust-ctrlc-3+default-dev (>= 3.4-~~) librust-log-0.4+default-dev librust-miette-7+default-dev (>= 7.2-~~) librust-miette-7+fancy-dev (>= 7.2-~~) librust-miette-7+fancy-no-backtrace-dev (>= 7.2-~~) librust-mimalloc-0.1-dev (>= 0.1.42-~~) librust-nix-0.28+fs-dev librust-nix-0.28+process-dev librust-nix-0.28+signal-dev librust-nix-0.28+term-dev librust-nu-cli-0.94+default-dev (>= 0.94.2-~~) librust-nu-cli-0.94+plugin-dev (>= 0.94.2-~~) librust-nu-cli-0.94+system-clipboard-dev (>= 0.94.2-~~) librust-nu-cmd-base-0.94+default-dev (>= 0.94.2-~~) librust-nu-cmd-extra-0.94+default-dev (>= 0.94.2-~~) librust-nu-cmd-lang-0.94+default-dev (>= 0.94.2-~~) librust-nu-cmd-lang-0.94+mimalloc-dev (>= 0.94.2-~~) librust-nu-cmd-lang-0.94+sqlite-dev (>= 0.94.2-~~) librust-nu-cmd-lang-0.94+system-clipboard-dev (>= 0.94.2-~~) librust-nu-cmd-lang-0.94+trash-support-dev (>= 0.94.2-~~) librust-nu-cmd-lang-0.94+which-support-dev (>= 0.94.2-~~) librust-nu-cmd-plugin-0.94+default-dev (>= 0.94.2-~~) librust-nu-command-0.94+default-dev (>= 0.94.2-~~) librust-nu-command-0.94+plugin-dev (>= 0.94.2-~~) librust-nu-command-0.94+sqlite-dev (>= 0.94.2-~~) librust-nu-command-0.94+trash-support-dev (>= 0.94.2-~~) librust-nu-command-0.94+which-support-dev (>= 0.94.2-~~) librust-nu-engine-0.94+default-dev (>= 0.94.2-~~) librust-nu-engine-0.94+plugin-dev (>= 0.94.2-~~) librust-nu-explore-0.94+default-dev (>= 0.94.2-~~) librust-nu-lsp-0.94+default-dev (>= 0.94.2-~~) librust-nu-parser-0.94+default-dev (>= 0.94.2-~~) librust-nu-parser-0.94+plugin-dev (>= 0.94.2-~~) librust-nu-path-0.94+default-dev (>= 0.94.2-~~) librust-nu-plugin-engine-0.94+default-dev (>= 0.94.2-~~) librust-nu-protocol-0.94+default-dev (>= 0.94.2-~~) librust-nu-protocol-0.94+plugin-dev (>= 0.94.2-~~) librust-nu-std-0.94+default-dev (>= 0.94.2-~~) librust-nu-system-0.94+default-dev (>= 0.94.2-~~) librust-nu-utils-0.94+default-dev (>= 0.94.2-~~) librust-reedline-0.32+bashisms-dev librust-reedline-0.32+default-dev librust-reedline-0.32+sqlite-dev librust-reedline-0.32+system-clipboard-dev librust-serde-json-1+default-dev librust-simplelog-0.12+default-dev librust-time-0.3+default-dev librust-winresource-0.1+default-dev
As you can see, those are a lot of dependencies, necessary for running and installing the Nushell. It is a very complicated task to accomplish, as we didn’t have time necessary, we choice to not continue this journey.
Conclusions about the experience
It was a very interesting experience to see how the packaging of a program works, principally in a well-known system like Debian. Besides being a difficult task, as there are many files and documentation to write (an dependencies) it was very nice to know how packaging were done, in a way we will give more value to packages already written in apt.
And remember that we were responsible for this to happen, which will make Nu much more known to the community.