This repository has no description
3.4 kB
127 lines
1{ lib, pkgs, ... }:
2{
3 /**
4 Create a wrapped application that preserves all original outputs (man pages, completions, etc.)
5
6 # Arguments
7
8 - `package`: The package to wrap
9 - `runtimeInputs`: List of packages to add to PATH (optional)
10 - `env`: Attribute set of environment variables to export (optional)
11 - `flags`: Attribute set of command-line flags to add (optional)
12 - `preHook`: Shell script to run before executing the command (optional)
13 - `wrapper`: Custom wrapper function (optional, defaults to exec'ing the original binary with flags)
14 - Called with { env, flags, envString, flagsString, exePath, preHook }
15
16 # Example
17
18 ```nix
19 makeWrapper pkgs.curl {
20 runtimeInputs = [ pkgs.jq ];
21 env = {
22 CURL_CA_BUNDLE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
23 };
24 flags = {
25 "--silent" = { }; # becomes --silent
26 "--connect-timeout" = "30"; # becomes --connect-timeout 30
27 };
28 preHook = ''
29 echo "Making request..." >&2
30 '';
31 }
32
33 # Or with custom wrapper:
34 makeWrapper pkgs.someProgram {
35 wrapper = { exePath, flagsString, envString, preHook, ... }: ''
36 ${envString}
37 ${preHook}
38 echo "Custom logic here"
39 exec ${exePath} ${flagsString} "$@"
40 '';
41 }
42 ```
43 */
44 makeWrapper =
45 package:
46 {
47 runtimeInputs ? [ ],
48 env ? { },
49 flags ? { },
50 flagSeparator ? " ", # " " for "--flag value" or "=" for "--flag=value"
51 preHook ? "",
52 wrapper ? (
53 {
54 exePath,
55 flagsString,
56 envString,
57 preHook,
58 ...
59 }:
60 ''
61 ${envString}
62 ${preHook}
63 exec ${exePath}${flagsString} "$@"
64 ''
65 ),
66 }:
67 let
68 # Extract binary name from the exe path
69 exePath = lib.getExe package;
70 binName = baseNameOf exePath;
71
72 # Generate environment variable exports
73 envString =
74 if env == { } then
75 ""
76 else
77 lib.concatStringsSep "\n" (
78 lib.mapAttrsToList (name: value: ''export ${name}="${toString value}"'') env
79 )
80 + "\n";
81
82 # Generate flag arguments with proper line breaks and indentation
83 flagsString =
84 if flags == { } then
85 ""
86 else
87 " \\\n "
88 + lib.concatStringsSep " \\\n " (
89 lib.mapAttrsToList (
90 name: value: if value == { } then "${name}" else "${name}${flagSeparator}${lib.escapeShellArg (toString value)}"
91 ) flags
92 );
93
94 finalWrapper = wrapper {
95 inherit
96 env
97 flags
98 envString
99 flagsString
100 exePath
101 preHook
102 ;
103 };
104 in
105 pkgs.symlinkJoin {
106 name = package.pname or package.name;
107 paths = [
108 (pkgs.writeShellApplication {
109 name = binName;
110 runtimeInputs = runtimeInputs;
111 text = finalWrapper;
112 })
113 package
114 ];
115 passthru = (package.passthru or { }) // {
116 inherit env flags preHook;
117 };
118 # Pass through original attributes
119 inherit (package) meta;
120 }
121 // lib.optionalAttrs (package ? version) {
122 inherit (package) version;
123 }
124 // lib.optionalAttrs (package ? pname) {
125 inherit (package) pname;
126 };
127}