clean both flake and non-flake API

This commit is contained in:
Clément DOUIN
2024-11-27 10:04:12 +01:00
parent 7806de626e
commit 6dc448b062
11 changed files with 154 additions and 302 deletions

View File

@@ -46,6 +46,7 @@ jobs:
with:
nix_path: nixpkgs=channel:nixos-24.05
enable_kvm: true
extra_nix_config: "experimental-features = nix-command flakes"
- name: Cache Nix store
uses: cachix/cachix-action@v15
with:
@@ -54,7 +55,8 @@ jobs:
extraPullNames: nix-community
- name: Build release
run: |
nix-build --argstr target ${{ matrix.target }} --arg isStatic true
nix build .#cross-${{ matrix.target }}
nix run .#cross-${{ matrix.target }} -- --version
- name: Upload release artifacts
uses: actions/upload-artifact@v4
with:

View File

@@ -21,11 +21,11 @@ default = [
"maildir",
#"notmuch",
"smtp",
#"sendmail",
#"keyring",
#"oauth2",
"sendmail",
"keyring",
"oauth2",
"wizard",
#"pgp-commands",
"pgp-commands",
#"pgp-gpg",
#"pgp-native",
]
@@ -40,10 +40,9 @@ keyring = ["email-lib/keyring", "pimalaya-tui/keyring", "secret-lib/keyring"]
oauth2 = ["email-lib/oauth2", "pimalaya-tui/oauth2", "keyring"]
wizard = ["email-lib/autoconfig", "pimalaya-tui/wizard"]
pgp = []
pgp-commands = ["email-lib/pgp-commands", "mml-lib/pgp-commands", "pimalaya-tui/pgp-commands", "pgp"]
pgp-gpg = ["email-lib/pgp-gpg", "mml-lib/pgp-gpg", "pimalaya-tui/pgp-gpg", "pgp"]
pgp-native = ["email-lib/pgp-native", "mml-lib/pgp-native", "pimalaya-tui/pgp-native", "pgp"]
pgp-commands = ["email-lib/pgp-commands", "mml-lib/pgp-commands", "pimalaya-tui/pgp-commands"]
pgp-gpg = ["email-lib/pgp-gpg", "mml-lib/pgp-gpg", "pimalaya-tui/pgp-gpg"]
pgp-native = ["email-lib/pgp-native", "mml-lib/pgp-native", "pimalaya-tui/pgp-native"]
[build-dependencies]
git2 = { version = "0.19", default-features = false }

View File

@@ -71,32 +71,35 @@ fn target_envs() {
/// variables. In case of failure, it tries to build them using
/// [`git2`].
fn git_envs() {
// skip the process if the current directory is not a git
// repository (for example, from a nix build root jail)
let Ok(git) = Repository::open(".") else {
println!("cargo::rustc-env=GIT_DESCRIBE=unknown");
println!("cargo::rustc-env=GIT_REV=unknown");
return;
};
let git = Repository::open(".").ok();
if try_forward_env("GIT_DESCRIBE").is_err() {
let mut opts = DescribeOptions::new();
opts.describe_all();
opts.show_commit_oid_as_fallback(true);
let description = match &git {
None => String::from("unknown"),
Some(git) => {
let mut opts = DescribeOptions::new();
opts.describe_all();
opts.show_commit_oid_as_fallback(true);
let description = git
.describe(&opts)
.expect("should describe git object")
.format(None)
.expect("should format git object description");
git.describe(&opts)
.expect("should describe git object")
.format(None)
.expect("should format git object description")
}
};
println!("cargo::rustc-env=GIT_DESCRIBE={description}");
};
if try_forward_env("GIT_REV").is_err() {
let head = git.head().expect("should get git HEAD");
let commit = head.peel_to_commit().expect("should get git HEAD commit");
let rev = commit.id().to_string();
let rev = match &git {
None => String::from("unknown"),
Some(git) => {
let head = git.head().expect("should get git HEAD");
let commit = head.peel_to_commit().expect("should get git HEAD commit");
commit.id().to_string()
}
};
println!("cargo::rustc-env=GIT_REV={rev}");
};

View File

@@ -1,28 +1,18 @@
{ target ? null
, isStatic ? false
{ pkgs ? import <nixpkgs> { }
, crossPkgs ? pkgs
, fenix ? import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { }
, defaultFeatures ? true
, features ? ""
}:
let
buildPackages = import (fetchTarball "https://github.com/soywod/nixpkgs/archive/master.tar.gz") { };
inherit (buildPackages) stdenv binutils mktemp gnutar zip;
inherit (pkgs) binutils gnutar lib mktemp stdenv zip;
inherit (crossPkgs) buildPlatform hostPlatform;
pkgs = import (fetchTarball "https://github.com/soywod/nixpkgs/archive/master.tar.gz") (
if isNull target then { } else {
crossSystem = {
inherit isStatic;
config = target;
};
}
);
inherit (pkgs) lib hostPlatform;
fenix = import (fetchTarball "https://github.com/soywod/fenix/archive/main.tar.gz") { };
mkToolchain = import ./rust-toolchain.nix { inherit lib fenix; };
rustTarget = if isNull target then null else hostPlatform.rust.rustcTarget;
rustTarget = if buildPlatform == hostPlatform then null else hostPlatform.rust.rustcTarget;
rustToolchain = mkToolchain.fromTarget rustTarget;
rustPlatform = pkgs.makeRustPlatform {
rustPlatform = crossPkgs.makeRustPlatform {
rustc = rustToolchain;
cargo = rustToolchain;
};
@@ -40,19 +30,19 @@ let
himalayaExe =
let ext = lib.optionalString hostPlatform.isWindows ".exe";
in "${hostPlatform.emulator buildPackages} ./himalaya${ext}";
in "${hostPlatform.emulator pkgs} ./himalaya${ext}";
himalaya = import ./package.nix {
inherit lib rustPlatform;
fetchFromGitHub = pkgs.fetchFromGitHub;
stdenv = pkgs.stdenv;
apple-sdk = if pkgs.stdenv.hostPlatform.isx86_64 then pkgs.apple-sdk_13 else pkgs.apple-sdk_14;
fetchFromGitHub = crossPkgs.fetchFromGitHub;
stdenv = crossPkgs.stdenv;
apple-sdk = if hostPlatform.isx86_64 then crossPkgs.apple-sdk_13 else crossPkgs.apple-sdk_14;
installShellFiles = false;
installShellCompletions = false;
installManPages = false;
notmuch = pkgs.notmuch;
gpgme = pkgs.gpgme;
pkg-config = pkgs.pkg-config;
notmuch = crossPkgs.notmuch;
gpgme = crossPkgs.gpgme;
pkg-config = crossPkgs.pkg-config;
buildNoDefaultFeatures = !defaultFeatures;
buildFeatures = lib.strings.splitString "," features;
};
@@ -86,7 +76,7 @@ himalaya.overrideAttrs (drv: {
mv himalaya.zip ../
'';
src = pkgs.nix-gitignore.gitignoreSource [ ] ./.;
src = crossPkgs.nix-gitignore.gitignoreSource [ ] ./.;
cargoDeps = rustPlatform.importCargoLock {
lockFile = ./Cargo.lock;

74
flake.lock generated
View File

@@ -1,20 +1,5 @@
{
"nodes": {
"crane": {
"locked": {
"lastModified": 1731974733,
"narHash": "sha256-enYSSZVVl15FI5p+0Y5/Ckf5DZAvXe6fBrHxyhA/njc=",
"owner": "ipetkov",
"repo": "crane",
"rev": "3cb338ce81076ce5e461cf77f7824476addb0e1c",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"fenix": {
"inputs": {
"nixpkgs": [
@@ -23,11 +8,11 @@
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1713081044,
"narHash": "sha256-ZwbJDrizU+nzU7wTgokYuu5yK71wLPmOLukiunm5B6Y=",
"lastModified": 1732405626,
"narHash": "sha256-uDbQrdOyqa2679kKPzoztMxesOV7DG2+FuX/TZdpxD0=",
"owner": "soywod",
"repo": "fenix",
"rev": "af99e7e9c87389c0a5aaf953478664d7126c2b14",
"rev": "c7af381484169a78fb79a11652321ae80b0f92a6",
"type": "github"
},
"original": {
@@ -36,75 +21,36 @@
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1731797254,
"narHash": "sha256-df3dJApLPhd11AlueuoN0Q4fHo/hagP75LlM5K1sz9g=",
"lastModified": 1732014248,
"narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "e8c38b73aeb218e27163376a2d617e61a2ad9b59",
"rev": "23e89b7da85c3640bbc2173fe04f4bd114342367",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-24.05",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"crane": "crane",
"fenix": "fenix",
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": "nixpkgs"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1712818880,
"narHash": "sha256-VDxsvgj/bNypHq48tQWtc3VRbWvzlFjzKf9ZZIVO10Y=",
"lastModified": 1732050317,
"narHash": "sha256-G5LUEOC4kvB/Xbkglv0Noi04HnCfryur7dVjzlHkgpI=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "657b33b0cb9bd49085202e91ad5b4676532c9140",
"rev": "c0bbbb3e5d7d1d1d60308c8270bfd5b250032bb4",
"type": "github"
},
"original": {

229
flake.nix
View File

@@ -2,199 +2,94 @@
description = "CLI to manage emails";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
gitignore = {
url = "github:hercules-ci/gitignore.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
fenix = {
# https://github.com/nix-community/fenix/pull/145
# url = "github:nix-community/fenix";
url = "github:soywod/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
crane.url = "github:ipetkov/crane";
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
};
outputs = { self, nixpkgs, gitignore, fenix, crane, ... }:
outputs = { self, nixpkgs, fenix }:
let
inherit (nixpkgs) lib;
inherit (gitignore.lib) gitignoreSource;
crossSystems = {
x86_64-linux = {
x86_64-linux = {
rustTarget = "x86_64-unknown-linux-musl";
};
aarch64-apple = [ ];
aarch64-linux = [
"aarch64-unknown-linux-musl"
];
x86_64-apple = [ ];
x86_64-linux = [
"aarch64-unknown-linux-musl"
"armv6l-unknown-linux-musleabihf"
"armv7l-unknown-linux-musleabihf"
"i686-unknown-linux-musl"
"x86_64-unknown-linux-musl"
"x86_64-w64-mingw32"
];
};
aarch64-linux = rec {
rustTarget = "aarch64-unknown-linux-musl";
runner = { pkgs, himalaya }: "${pkgs.qemu}/bin/qemu-aarch64 ${himalaya}";
mkPackage = { system, ... }: package:
let
inherit (mkPkgsCross system rustTarget) stdenv;
cc = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
in
package // {
TARGET_CC = cc;
CARGO_BUILD_RUSTFLAGS = package.CARGO_BUILD_RUSTFLAGS ++ [ "-Clinker=${cc}" ];
};
};
# Dev shells
x86_64-windows = {
rustTarget = "x86_64-pc-windows-gnu";
runner = { pkgs, himalaya }:
let wine = pkgs.wine.override { wineBuild = "wine64"; };
in "${wine}/bin/wine64 ${himalaya}.exe";
mkPackage = { pkgs, ... }: package:
let
inherit (pkgs.pkgsCross.mingwW64) stdenv windows;
cc = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
in
package // {
depsBuildBuild = [ stdenv.cc windows.pthreads ];
TARGET_CC = cc;
CARGO_BUILD_RUSTFLAGS = package.CARGO_BUILD_RUSTFLAGS ++ [ "-Clinker=${cc}" ];
};
};
};
aarch64-linux.aarch64-linux = {
rustTarget = "aarch64-unknown-linux-musl";
};
x86_64-darwin.x86_64-darwin = {
rustTarget = "x86_64-apple-darwin";
};
aarch64-darwin.aarch64-darwin = {
rustTarget = "aarch64-apple-darwin";
mkDevShell = system: {
default = import ./shell.nix {
pkgs = import nixpkgs { inherit system; };
fenix = fenix.packages.${system};
};
};
eachBuildSystem = lib.genAttrs (builtins.attrNames crossSystems);
# Packages
mkPkgsCross = buildSystem: crossSystem: import nixpkgs {
system = buildSystem;
crossSystem.config = crossSystem;
mkPackages = system: mkCrossPackages system // {
default = withGitEnvs (import ./default.nix ({
pkgs = import nixpkgs { inherit system; };
fenix = fenix.packages.${system};
}));
};
mkToolchain = import ./rust-toolchain.nix fenix;
withGitEnvs = package: package.overrideAttrs (drv: {
GIT_REV = drv.GIT_REV or self.rev or self.dirtyRev or "dirty";
GIT_DESCRIBE = drv.GIT_DESCRIBE or "flake-" + self.shortRev or self.dirtyShortRev or "dirty";
});
mkApp = { pkgs, buildSystem, targetSystem ? buildSystem }:
mkCrossPackages = system:
lib.attrsets.mergeAttrsList (map (mkCrossPackage system) crossSystems.${system});
mkCrossPackage = system: crossConfig:
let
himalaya = lib.getExe self.packages.${buildSystem}.${targetSystem};
wrapper = crossSystems.${buildSystem}.${targetSystem}.runner or (_: himalaya) { inherit pkgs himalaya; };
program = lib.getExe (pkgs.writeShellScriptBin "himalaya" "${wrapper} $@");
app = { inherit program; type = "app"; };
pkgs = import nixpkgs { inherit system; };
crossSystem = { config = crossConfig; isStatic = true; };
crossPkgs = import nixpkgs { inherit system crossSystem; };
crossPkg = import ./default.nix { inherit pkgs crossPkgs; fenix = fenix.packages.${system}; };
in
app;
{ "cross-${crossPkgs.hostPlatform.system}" = withGitEnvs crossPkg; };
mkApps = buildSystem:
# Apps
mkApps = system: mkCrossApps system // {
default = { type = "app"; program = lib.getExe self.packages.${system}.default; };
};
mkCrossApps = system:
lib.attrsets.mergeAttrsList (map (mkCrossApp system) crossSystems.${system});
mkCrossApp = system: crossConfig:
let
pkgs = import nixpkgs { system = buildSystem; };
mkApp' = targetSystem: _: mkApp { inherit pkgs buildSystem targetSystem; };
defaultApp = mkApp { inherit pkgs buildSystem; };
apps = builtins.mapAttrs mkApp' crossSystems.${buildSystem};
pkgs = import nixpkgs { inherit system; };
emulator = crossPkgs.hostPlatform.emulator pkgs;
crossSystem = { config = crossConfig; isStatic = true; };
crossPkgs = import nixpkgs { inherit system crossSystem; };
crossPkgName = "cross-${crossPkgs.hostPlatform.system}";
crossPkgExe = lib.getExe self.packages.${system}.${crossPkgName};
program = lib.getExe (pkgs.writeShellScriptBin "himalaya" "${emulator} ${crossPkgExe} $@");
in
apps // { default = defaultApp; };
mkPackage = { pkgs, buildSystem, targetSystem ? buildSystem }:
let
targetConfig = crossSystems.${buildSystem}.${targetSystem};
toolchain = mkToolchain.fromTarget {
inherit pkgs buildSystem;
targetSystem = targetConfig.rustTarget;
};
rust = (crane.mkLib pkgs).overrideToolchain toolchain;
mkPackage' = targetConfig.mkPackage or (_: p: p);
himalaya = "./himalaya";
runner = targetConfig.runner or (_: himalaya) { inherit pkgs himalaya; };
package = mkPackage' { inherit pkgs; system = buildSystem; } {
name = "himalaya";
src = gitignoreSource ./.;
strictDeps = true;
doCheck = false;
auditable = false;
buildInputs = lib.optionals pkgs.stdenv.isDarwin [
pkgs.libiconv
pkgs.darwin.apple_sdk_11_0.frameworks.Security
];
nativeBuildInputs = with pkgs; [ pkg-config ];
CARGO_BUILD_TARGET = targetConfig.rustTarget;
CARGO_BUILD_RUSTFLAGS = [ "-Ctarget-feature=+crt-static" ];
GIT_REV = self.rev or self.dirtyRev or "dirty";
GIT_DESCRIBE = "flake-" + self.shortRev or self.dirtyShortRev or "dirty";
postInstall = ''
export WINEPREFIX="$(mktemp -d)"
mkdir -p $out/bin/share/{applications,completions,man,services}
cp assets/himalaya.desktop $out/bin/share/applications/
cp assets/himalaya-watch@.service $out/bin/share/services/
cd $out/bin
${runner} man ./share/man
${runner} completion bash > ./share/completions/himalaya.bash
${runner} completion elvish > ./share/completions/himalaya.elvish
${runner} completion fish > ./share/completions/himalaya.fish
${runner} completion powershell > ./share/completions/himalaya.powershell
${runner} completion zsh > ./share/completions/himalaya.zsh
tar -czf himalaya.tgz himalaya* share
mv himalaya.tgz ../
${pkgs.zip}/bin/zip -r himalaya.zip himalaya* share
mv himalaya.zip ../
'';
meta.mainProgram = "himalaya";
};
in
rust.buildPackage package;
mkPackages = buildSystem:
let
pkgs = import nixpkgs { system = buildSystem; };
mkPackage' = targetSystem: _: mkPackage { inherit pkgs buildSystem targetSystem; };
defaultPackage = mkPackage { inherit pkgs buildSystem; };
packages = builtins.mapAttrs mkPackage' crossSystems.${buildSystem};
in
packages // { default = defaultPackage; };
mkDevShells = buildSystem:
let
pkgs = import nixpkgs { system = buildSystem; };
rust-toolchain = mkToolchain.fromFile { inherit buildSystem; };
defaultShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [ pkg-config ];
buildInputs = with pkgs; [
# Nix
nixd
nixpkgs-fmt
# Rust
rust-toolchain
cargo-watch
# Email env
gnupg
gpgme
msmtp
notmuch
openssl.dev
];
};
in
{ default = defaultShell; };
{ "${crossPkgName}" = { inherit program; type = "app"; }; };
in
{
apps = eachBuildSystem mkApps;
packages = eachBuildSystem mkPackages;
devShells = eachBuildSystem mkDevShells;
devShells = lib.genAttrs (lib.attrNames crossSystems) mkDevShell;
packages = lib.genAttrs (lib.attrNames crossSystems) mkPackages;
apps = lib.genAttrs (lib.attrNames crossSystems) mkApps;
};
}

View File

@@ -6,14 +6,16 @@ let
in
{
fromFile = fenix.fromToolchainFile { inherit file sha256; };
fromFile =
let spec = { inherit file sha256; };
in fenix.fromToolchainFile spec;
fromTarget = target:
let
name = (lib.importTOML file).toolchain.channel;
specs = { inherit name sha256; };
toolchain = fenix.fromToolchainName specs;
crossToolchain = fenix.targets.${target}.fromToolchainName specs;
spec = { inherit name sha256; };
toolchain = fenix.fromToolchainName spec;
crossToolchain = fenix.targets.${target}.fromToolchainName spec;
components = [ toolchain.rustc toolchain.cargo ]
++ lib.optional (!isNull target) crossToolchain.rust-std;
in

View File

@@ -1,17 +1,26 @@
{ pkgs ? import <nixpkgs> { } }:
{ pkgs ? import <nixpkgs> { }
, fenix ? import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { }
, withNotmuch ? false
, withGpg ? false
, withOpenSsl ? false
}:
let
inherit (pkgs) lib;
fenix = import (fetchTarball "https://github.com/soywod/fenix/archive/main.tar.gz") { };
mkToolchain = import ./rust-toolchain.nix { inherit lib fenix; };
rust = mkToolchain.fromFile;
mkRustToolchain = import ./rust-toolchain.nix { inherit lib fenix; };
rust = mkRustToolchain.fromFile;
in
pkgs.mkShell {
buildInputs = with pkgs; [
nixd
nixpkgs-fmt
rust
];
buildInputs = [ ]
# Nix language
++ [ pkgs.nixd pkgs.nixpkgs-fmt ]
# Rust
++ [ rust ]
# Cargo features
++ lib.optional withNotmuch pkgs.notmuch
++ lib.optional withGpg pkgs.gpgme
++ lib.optional withOpenSsl pkgs.openssl;
}

View File

@@ -4,7 +4,13 @@ use color_eyre::Result;
use email::imap::config::ImapAuthConfig;
#[cfg(feature = "smtp")]
use email::smtp::config::SmtpAuthConfig;
#[cfg(any(feature = "imap", feature = "smtp", feature = "pgp"))]
#[cfg(any(
feature = "imap",
feature = "smtp",
feature = "pgp-gpg",
feature = "pgp-commands",
feature = "pgp-native",
))]
use pimalaya_tui::terminal::prompt;
use pimalaya_tui::terminal::{cli::printer::Printer, config::TomlConfig as _};
use tracing::info;
@@ -69,7 +75,7 @@ impl AccountConfigureCommand {
}
}
#[cfg(feature = "pgp")]
#[cfg(any(feature = "pgp-gpg", feature = "pgp-commands", feature = "pgp-native"))]
if let Some(config) = &toml_account_config.pgp {
config.reset().await?;
}
@@ -107,7 +113,7 @@ impl AccountConfigureCommand {
_ => Ok(()),
}?;
#[cfg(feature = "pgp")]
#[cfg(any(feature = "pgp-gpg", feature = "pgp-commands", feature = "pgp-native"))]
if let Some(config) = &toml_account_config.pgp {
config
.configure(&toml_account_config.email, || {

View File

@@ -78,7 +78,7 @@ impl TemplateSaveCommand {
#[allow(unused_mut)]
let mut compiler = MmlCompilerBuilder::new();
#[cfg(feature = "pgp")]
#[cfg(any(feature = "pgp-gpg", feature = "pgp-commands", feature = "pgp-native"))]
compiler.set_some_pgp(account_config.pgp.clone());
let msg = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;

View File

@@ -71,7 +71,7 @@ impl TemplateSendCommand {
#[allow(unused_mut)]
let mut compiler = MmlCompilerBuilder::new();
#[cfg(feature = "pgp")]
#[cfg(any(feature = "pgp-gpg", feature = "pgp-commands", feature = "pgp-native"))]
compiler.set_some_pgp(account_config.pgp.clone());
let msg = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;