mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-22 06:53:01 +00:00
update-script-combinators: experimental init
The sequence combinator will be useful for updating packages consisting of multiple sources.
This commit is contained in:
parent
d4b1bbb7d3
commit
7d6b5d171a
128
pkgs/common-updater/combinators.nix
Normal file
128
pkgs/common-updater/combinators.nix
Normal file
@ -0,0 +1,128 @@
|
||||
{ lib
|
||||
}:
|
||||
|
||||
/*
|
||||
This is a set of tools to manipulate update scripts as recognized by update.nix.
|
||||
It is still very experimental with **instability** almost guaranteed so any use
|
||||
outside Nixpkgs is discouraged.
|
||||
|
||||
update.nix currently accepts the following type:
|
||||
|
||||
type UpdateScript
|
||||
// Simple path to script to execute script
|
||||
= FilePath
|
||||
// Path to execute plus arguments to pass it
|
||||
| [ (FilePath | String) ]
|
||||
// Advanced attribue set (experimental)
|
||||
| {
|
||||
// Script to execute (same as basic update script above)
|
||||
command : (FilePath | [ (FilePath | String) ])
|
||||
// Features that the script supports
|
||||
// - commit: (experimental) returns commit message in stdout
|
||||
supportedFeatures : ?[ "commit" ]
|
||||
// Override attribute path detected by update.nix
|
||||
attrPath : ?String
|
||||
}
|
||||
*/
|
||||
|
||||
let
|
||||
/*
|
||||
type ShellArg = String | { __rawShell : String }
|
||||
*/
|
||||
|
||||
/*
|
||||
Quotes all arguments to be safely passed to the Bourne shell.
|
||||
|
||||
escapeShellArgs' : [ShellArg] -> String
|
||||
*/
|
||||
escapeShellArgs' = lib.concatMapStringsSep " " (arg: if arg ? __rawShell then arg.__rawShell else lib.escapeShellArg arg);
|
||||
|
||||
/*
|
||||
processArg : { maxArgIndex : Int, args : [ShellArg], paths : [FilePath] } → (String|FilePath) → { maxArgIndex : Int, args : [ShellArg], paths : [FilePath] }
|
||||
Helper reducer function for building a command arguments where file paths are replaced with argv[x] reference.
|
||||
*/
|
||||
processArg =
|
||||
{ maxArgIndex, args, paths }:
|
||||
arg:
|
||||
if builtins.isPath arg then {
|
||||
args = args ++ [ { __rawShell = "\"\$${builtins.toString maxArgIndex}\""; } ];
|
||||
maxArgIndex = maxArgIndex + 1;
|
||||
paths = paths ++ [ arg ];
|
||||
} else {
|
||||
args = args ++ [ arg ];
|
||||
inherit maxArgIndex paths;
|
||||
};
|
||||
/*
|
||||
extractPaths : Int → [ (String|FilePath) ] → { maxArgIndex : Int, args : [ShellArg], paths : [FilePath] }
|
||||
Helper function that extracts file paths from command arguments and replaces them with argv[x] references.
|
||||
*/
|
||||
extractPaths = maxArgIndex: command: builtins.foldl' processArg { inherit maxArgIndex; args = [ ]; paths = [ ]; } command;
|
||||
/*
|
||||
processCommand : { maxArgIndex : Int, commands : [[ShellArg]], paths : [FilePath] } → [ (String|FilePath) ] → { maxArgIndex : Int, commands : [[ShellArg]], paths : [FilePath] }
|
||||
Helper reducer function for extracting file paths from individual commands.
|
||||
*/
|
||||
processCommand =
|
||||
{ maxArgIndex, commands, paths }:
|
||||
command:
|
||||
let
|
||||
new = extractPaths maxArgIndex command;
|
||||
in
|
||||
{
|
||||
commands = commands ++ [ new.args ];
|
||||
paths = paths ++ new.paths;
|
||||
maxArgIndex = new.maxArgIndex;
|
||||
};
|
||||
/*
|
||||
extractCommands : Int → [[ (String|FilePath) ]] → { maxArgIndex : Int, commands : [[ShellArg]], paths : [FilePath] }
|
||||
Helper function for extracting file paths from a list of commands and replacing them with argv[x] references.
|
||||
*/
|
||||
extractCommands = maxArgIndex: commands: builtins.foldl' processCommand { inherit maxArgIndex; commands = [ ]; paths = [ ]; } commands;
|
||||
|
||||
/*
|
||||
commandsToShellInvocation : [[ (String|FilePath) ]] → [ (String|FilePath) ]
|
||||
Converts a list of commands into a single command by turning them into a shell script and passing them to `sh -c`.
|
||||
*/
|
||||
commandsToShellInvocation = commands:
|
||||
let
|
||||
extracted = extractCommands 0 commands;
|
||||
in
|
||||
[
|
||||
"sh"
|
||||
"-c"
|
||||
(lib.concatMapStringsSep ";" escapeShellArgs' extracted.commands)
|
||||
# We need paths as separate arguments so that update.nix can ensure they refer to the local directory
|
||||
# rather than a store path.
|
||||
] ++ extracted.paths;
|
||||
in
|
||||
rec {
|
||||
/*
|
||||
normalize : UpdateScript → UpdateScript
|
||||
EXPERIMENTAL! Converts a basic update script to the experimental attribute set form.
|
||||
*/
|
||||
normalize = updateScript: {
|
||||
command = lib.toList (updateScript.command or updateScript);
|
||||
supportedFeatures = updateScript.supportedFeatures or [ ];
|
||||
} // lib.optionalAttrs (updateScript ? attrPath) {
|
||||
inherit (updateScript) attrPath;
|
||||
};
|
||||
|
||||
/*
|
||||
sequence : [UpdateScript] → UpdateScript
|
||||
EXPERIMENTAL! Combines multiple update scripts to run in sequence.
|
||||
*/
|
||||
sequence =
|
||||
scripts:
|
||||
|
||||
let
|
||||
scriptsNormalized = builtins.map normalize scripts;
|
||||
in
|
||||
let
|
||||
scripts = scriptsNormalized;
|
||||
validateFeatures = ({ supportedFeatures, ... }: supportedFeatures == [ ]);
|
||||
in
|
||||
|
||||
assert lib.assertMsg (lib.all validateFeatures scripts) "Combining update scripts with features enabled is currently unsupported.";
|
||||
assert lib.assertMsg (builtins.length (lib.unique (builtins.map ({ attrPath ? null, ... }: attrPath) scripts)) == 1) "Combining update scripts with different attr paths is currently unsupported.";
|
||||
|
||||
commandsToShellInvocation (builtins.map ({ command, ... }: command) scripts);
|
||||
}
|
@ -124,6 +124,8 @@ with pkgs;
|
||||
|
||||
genericUpdater = callPackage ../common-updater/generic-updater.nix { };
|
||||
|
||||
update-script-combinators = callPackage ../common-updater/combinators.nix { };
|
||||
|
||||
gitUpdater = callPackage ../common-updater/git-updater.nix { };
|
||||
|
||||
httpTwoLevelsUpdater = callPackage ../common-updater/http-two-levels-updater.nix { };
|
||||
|
Loading…
Reference in New Issue
Block a user