Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at release-18.03 110 lines 4.2 kB view raw
1#!/usr/bin/env escript 2%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- 3%%! -smp enable 4%%% --------------------------------------------------------------------------- 5%%% @doc 6%%% The purpose of this command is to prepare a mix project so that mix 7%%% understands that the dependencies are all already installed. If you want a 8%%% hygienic build on nix then you must run this command before running mix. I 9%%% suggest that you add a `Makefile` to your project and have the bootstrap 10%%% command be a dependency of the build commands. See the nix documentation for 11%%% more information. 12%%% 13%%% This command designed to have as few dependencies as possible so that it can 14%%% be a dependency of root level packages like mix. To that end it does many 15%%% things in a fairly simplistic way. That is by design. 16%%% 17%%% ### Assumptions 18%%% 19%%% This command makes the following assumptions: 20%%% 21%%% * It is run in a nix-shell or nix-build environment 22%%% * that all dependencies have been added to the ERL_LIBS 23%%% Environment Variable 24 25-record(data, {version 26 , erl_libs 27 , root 28 , name 29 , registry_snapshot}). 30-define(LOCAL_HEX_REGISTRY, "registry.ets"). 31 32main(Args) -> 33 {ok, RequiredData} = gather_required_data_from_the_environment(Args), 34 ok = bootstrap_libs(RequiredData). 35 36%% @doc 37%% This takes an app name in the standard OTP <name>-<version> format 38%% and returns just the app name. Why? Because rebar doesn't 39%% respect OTP conventions in some cases. 40-spec fixup_app_name(file:name()) -> string(). 41fixup_app_name(Path) -> 42 BaseName = filename:basename(Path), 43 case string:tokens(BaseName, "-") of 44 [Name, _Version] -> Name; 45 Name -> Name 46 end. 47 48 49-spec gather_required_data_from_the_environment([string()]) -> {ok, #data{}}. 50gather_required_data_from_the_environment(_) -> 51 {ok, #data{ version = guard_env("version") 52 , erl_libs = os:getenv("ERL_LIBS", []) 53 , root = code:root_dir() 54 , name = guard_env("name") 55 , registry_snapshot = guard_env("HEX_REGISTRY_SNAPSHOT")}}. 56 57-spec guard_env(string()) -> string(). 58guard_env(Name) -> 59 case os:getenv(Name) of 60 false -> 61 stderr("Expected Environment variable ~s! Are you sure you are " 62 "running in a Nix environment? Either a nix-build, " 63 "nix-shell, etc?~n", [Name]), 64 erlang:halt(1); 65 Variable -> 66 Variable 67 end. 68 69-spec bootstrap_libs(#data{}) -> ok. 70bootstrap_libs(#data{erl_libs = ErlLibs}) -> 71 io:format("Bootstrapping dependent libraries~n"), 72 Target = "_build/prod/lib/", 73 Paths = string:tokens(ErlLibs, ":"), 74 CopiableFiles = 75 lists:foldl(fun(Path, Acc) -> 76 gather_directory_contents(Path) ++ Acc 77 end, [], Paths), 78 lists:foreach(fun (Path) -> 79 ok = link_app(Path, Target) 80 end, CopiableFiles). 81 82-spec gather_directory_contents(string()) -> [{string(), string()}]. 83gather_directory_contents(Path) -> 84 {ok, Names} = file:list_dir(Path), 85 lists:map(fun(AppName) -> 86 {filename:join(Path, AppName), fixup_app_name(AppName)} 87 end, Names). 88 89%% @doc 90%% Makes a symlink from the directory pointed at by Path to a 91%% directory of the same name in Target. So if we had a Path of 92%% {`foo/bar/baz/bash`, `baz`} and a Target of `faz/foo/foos`, the symlink 93%% would be `faz/foo/foos/baz`. 94-spec link_app({string(), string()}, string()) -> ok. 95link_app({Path, TargetFile}, TargetDir) -> 96 Target = filename:join(TargetDir, TargetFile), 97 ok = make_symlink(Path, Target). 98 99-spec make_symlink(string(), string()) -> ok. 100make_symlink(Path, TargetFile) -> 101 file:delete(TargetFile), 102 ok = filelib:ensure_dir(TargetFile), 103 io:format("Making symlink from ~s to ~s~n", [Path, TargetFile]), 104 ok = file:make_symlink(Path, TargetFile). 105 106%% @doc 107%% Write the result of the format string out to stderr. 108-spec stderr(string(), [term()]) -> ok. 109stderr(FormatStr, Args) -> 110 io:put_chars(standard_error, io_lib:format(FormatStr, Args)).