mirror of
https://github.com/nix-community/dream2nix.git
synced 2024-11-26 22:31:39 +03:00
Merge pull request #212 from a-kenji/init/debian-binary-builder
init: debian-binary builder
This commit is contained in:
commit
da45122814
20
examples/debian-binary/flake.nix
Normal file
20
examples/debian-binary/flake.nix
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
inputs = {
|
||||
dream2nix.url = "github:nix-community/dream2nix";
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
dream2nix,
|
||||
} @ inp: (dream2nix.lib.makeFlakeOutputs {
|
||||
systems = ["x86_64-linux"];
|
||||
config.projectRoot = ./.;
|
||||
source = ./.;
|
||||
projects = {
|
||||
htop = {
|
||||
name = "htop";
|
||||
translator = "debian-binary";
|
||||
};
|
||||
};
|
||||
});
|
||||
}
|
114
src/subsystems/debian/builders/default/default.nix
Normal file
114
src/subsystems/debian/builders/default/default.nix
Normal file
@ -0,0 +1,114 @@
|
||||
{...}: {
|
||||
type = "pure";
|
||||
|
||||
build = {
|
||||
lib,
|
||||
pkgs,
|
||||
stdenv,
|
||||
# dream2nix inputs
|
||||
externals,
|
||||
...
|
||||
}: {
|
||||
### FUNCTIONS
|
||||
# AttrSet -> Bool) -> AttrSet -> [x]
|
||||
getCyclicDependencies, # name: version: -> [ {name=; version=; } ]
|
||||
getDependencies, # name: version: -> [ {name=; version=; } ]
|
||||
getSource, # name: version: -> store-path
|
||||
# to get information about the original source spec
|
||||
getSourceSpec, # name: version: -> {type="git"; url=""; hash="";}
|
||||
### ATTRIBUTES
|
||||
subsystemAttrs, # attrset
|
||||
defaultPackageName, # string
|
||||
defaultPackageVersion, # string
|
||||
# all exported (top-level) package names and versions
|
||||
# attrset of pname -> version,
|
||||
packages,
|
||||
# all existing package names and versions
|
||||
# attrset of pname -> versions,
|
||||
# where versions is a list of version strings
|
||||
packageVersions,
|
||||
# function which applies overrides to a package
|
||||
# It must be applied by the builder to each individual derivation
|
||||
# Example:
|
||||
# produceDerivation name (mkDerivation {...})
|
||||
produceDerivation,
|
||||
...
|
||||
} @ args: let
|
||||
l = lib // builtins;
|
||||
|
||||
allDependencySources' =
|
||||
l.flatten
|
||||
(l.mapAttrsToList
|
||||
(name: versions:
|
||||
if
|
||||
l.elem name [
|
||||
defaultPackageName
|
||||
"libc6"
|
||||
]
|
||||
then []
|
||||
else l.map (ver: getSource name ver) versions)
|
||||
packageVersions);
|
||||
|
||||
allDependencySources =
|
||||
l.map
|
||||
(src: src.original or src)
|
||||
allDependencySources';
|
||||
|
||||
package = produceDerivation defaultPackageName (stdenv.mkDerivation {
|
||||
name = defaultPackageName;
|
||||
src = ":";
|
||||
dontUnpack = true;
|
||||
buildInputs = [pkgs.unzip];
|
||||
nativeBuildInputs = [pkgs.autoPatchelfHook];
|
||||
doCheck = false;
|
||||
dontStrip = true;
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
mkdir -p $out/bin
|
||||
mkdir -p $out/share
|
||||
mkdir -p $out/lib
|
||||
mkdir -p $out/etc
|
||||
|
||||
for file in ${toString allDependencySources};do
|
||||
mkdir -p $TMP/unpack
|
||||
# unzip -d $TMP/unpack $file
|
||||
cd $TMP/unpack
|
||||
ar vx $file
|
||||
tar xvf $TMP/unpack/data.tar.xz
|
||||
|
||||
echo $file
|
||||
|
||||
for variant in "bin" "sbin" "games"; do
|
||||
if [[ -d $TMP/unpack/usr/$variant && -n "$(ls -A $TMP/unpack/usr/$variant)" ]]; then
|
||||
echo "Copying usr/$variant"
|
||||
cp -r $TMP/unpack/usr/$variant/* $out/bin
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Copying usr/share"
|
||||
if [ -d $TMP/unpack/usr/share ]; then
|
||||
cp -r $TMP/unpack/usr/share/* $out/share
|
||||
fi
|
||||
|
||||
|
||||
for variant in "/usr/lib" "/usr/lib64" "/lib" "/lib64"; do
|
||||
for file in $(find $TMP/unpack/$variant -type f -or -type l);do
|
||||
cp -r $file $out/lib
|
||||
done
|
||||
done
|
||||
|
||||
mkdir -p $TMP/unpack/etc
|
||||
cp -r $TMP/unpack/etc $out
|
||||
rm -rf $TMP/unpack
|
||||
done
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
installPhase = ":";
|
||||
# autoPatchelfIgnoreMissingDeps = true;
|
||||
});
|
||||
in {
|
||||
packages.${defaultPackageName}.${defaultPackageVersion} = package;
|
||||
};
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc
|
||||
index c9c6a7e..0c7fb03 100644
|
||||
--- a/apt-pkg/deb/debsystem.cc
|
||||
+++ b/apt-pkg/deb/debsystem.cc
|
||||
@@ -320,7 +320,7 @@ APT_PURE bool debSystem::ArchiveSupported(const char *Type)
|
||||
System.. */
|
||||
signed debSystem::Score(Configuration const &Cnf)
|
||||
{
|
||||
- signed Score = 0;
|
||||
+ signed Score = 10;
|
||||
if (FileExists(Cnf.FindFile("Dir::State::status",getDpkgStatusLocation(Cnf).c_str())) == true)
|
||||
Score += 10;
|
||||
if (FileExists(Cnf.Find("Dir::Bin::dpkg",BIN_DIR"/dpkg")) == true)
|
@ -0,0 +1,7 @@
|
||||
/*
|
||||
This apt is patched so it can run inside the nix build sandbox.
|
||||
By default apt refuses to execute if it does not detect a debian-like system.
|
||||
The patch is a one-liner bypassing that check.
|
||||
*/
|
||||
{pkgs, ...}:
|
||||
pkgs.apt.overrideDerivation (oldAttrs: {patches = [./apt.patch];})
|
72
src/subsystems/debian/translators/debian-binary/default.nix
Normal file
72
src/subsystems/debian/translators/debian-binary/default.nix
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
dlib,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
l = lib // builtins;
|
||||
in {
|
||||
type = "impure";
|
||||
|
||||
# A derivation which outputs a single executable at `$out`.
|
||||
# The executable will be called by dream2nix for translation
|
||||
# The input format is specified in /specifications/translator-call-example.json.
|
||||
# The first arg `$1` will be a json file containing the input parameters
|
||||
# like defined in /src/specifications/translator-call-example.json and the
|
||||
# additional arguments required according to extraArgs
|
||||
#
|
||||
# The program is expected to create a file at the location specified
|
||||
# by the input parameter `outFile`.
|
||||
# The output file must contain the dream lock data encoded as json.
|
||||
# See /src/specifications/dream-lock-example.json
|
||||
translateBin = {
|
||||
# dream2nix utils
|
||||
utils,
|
||||
# nixpkgs dependenies
|
||||
bash,
|
||||
coreutils,
|
||||
jq,
|
||||
writeScriptBin,
|
||||
nix,
|
||||
callPackage,
|
||||
python3,
|
||||
...
|
||||
}:
|
||||
utils.writePureShellScript
|
||||
[
|
||||
bash
|
||||
coreutils
|
||||
jq
|
||||
nix
|
||||
(callPackage ./aptdream {})
|
||||
python3
|
||||
]
|
||||
''
|
||||
# accroding to the spec, the translator reads the input from a json file
|
||||
jsonInput=$1
|
||||
|
||||
# read the json input
|
||||
export outputFile=$(realpath -m $(jq '.outputFile' -c -r $jsonInput))
|
||||
|
||||
pkgsName=$(jq '.project.name' -c -r $jsonInput)
|
||||
|
||||
cd $TMPDIR
|
||||
|
||||
mkdir ./state
|
||||
touch ./status
|
||||
mkdir ./download
|
||||
|
||||
mkdir -p ./etc/apt
|
||||
echo "deb http://deb.debian.org/debian bullseye main" >> ./etc/apt/sources.list
|
||||
|
||||
export NAME=$pkgsName
|
||||
python3 ${./generate_dream_lock.py}
|
||||
'';
|
||||
|
||||
# If the translator requires additional arguments, specify them here.
|
||||
# When users run the CLI, they will be asked to specify these arguments.
|
||||
# There are only two types of arguments:
|
||||
# - string argument (type = "argument")
|
||||
# - boolean flag (type = "flag")
|
||||
# String arguments contain a default value and examples. Flags do not.
|
||||
extraArgs = {};
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import subprocess
|
||||
|
||||
# for initialization
|
||||
def update_apt():
|
||||
subprocess.run(
|
||||
["apt",
|
||||
"-o", "Acquire::AllowInsecureRepositories=1",
|
||||
"-o", "Dir::State::status=./status",
|
||||
"-o", "Dir::Etc=./etc/apt",
|
||||
"-o" ,"Dir::State=./state",
|
||||
"update"
|
||||
])
|
||||
|
||||
def get_package_info_apt(name):
|
||||
result = subprocess.run(
|
||||
["apt",
|
||||
"-o Acquire::AllowInsecureRepositories=1",
|
||||
"-o", "Dir::State::status=./status",
|
||||
"-o", "Dir::Etc=./etc/apt",
|
||||
"-o" "Dir::State=./state",
|
||||
"install", f"{name}", "--print-uris",
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
print(f"result {result.stdout}")
|
||||
with open('./deb-uris', 'w') as f:
|
||||
f.write(result.stdout)
|
||||
|
||||
subprocess.run(
|
||||
["apt",
|
||||
"-o", "Acquire::AllowInsecureRepositories=1",
|
||||
"-o", "Dir::State::status=./status",
|
||||
"-o", "Dir::Etc=./etc/apt",
|
||||
"-o", "Dir::Cache=./download",
|
||||
"-o", "Dir::State=./state",
|
||||
"install", f"{name}", "--download-only", "-y" ,"--allow-unauthenticated",
|
||||
])
|
||||
|
||||
def main():
|
||||
update_apt()
|
||||
get_package_info_apt(os.environ.get("NAME"))
|
||||
|
||||
default_package_src_name = f"{os.environ.get('NAME')}-binary"
|
||||
|
||||
with open("./deb-uris") as f:
|
||||
uris = f.readlines()
|
||||
|
||||
dream_lock = dict(
|
||||
sources={},
|
||||
_generic={
|
||||
"subsystem": "debian",
|
||||
"defaultPackage": os.environ.get("NAME"),
|
||||
"packages": {
|
||||
os.environ.get("NAME"): os.environ.get("VERSION"),
|
||||
},
|
||||
"sourcesAggregatedHash": None,
|
||||
"location": "",
|
||||
},
|
||||
_subsystem={},
|
||||
)
|
||||
|
||||
for line in uris:
|
||||
# print(line)
|
||||
split_lines = line.split(" ")
|
||||
if len(split_lines) == 4:
|
||||
(uri, deb, _, _) = split_lines
|
||||
with open(f"./download/archives/{deb}", "rb") as f:
|
||||
bin = f.read()
|
||||
hash = hashlib.sha256(bin)
|
||||
digest = hash.digest()
|
||||
base = base64.b64encode(digest)
|
||||
decode = base.decode()
|
||||
sha256 = f"sha256-{decode}"
|
||||
print(f"uri {uri}, deb: {deb}")
|
||||
(name, version, _) = deb.split("_")
|
||||
|
||||
if name == os.environ.get("NAME"):
|
||||
name = default_package_src_name
|
||||
dream_lock["sources"][name] = {
|
||||
version: dict(
|
||||
type="http",
|
||||
url=uri.replace("http:", "https:").replace("'", ""),
|
||||
hash=sha256,
|
||||
)
|
||||
}
|
||||
|
||||
# add the version of the root package
|
||||
dream_lock["_generic"]["packages"][os.environ.get("NAME")] = list(
|
||||
dream_lock["sources"][default_package_src_name].keys()
|
||||
)[0]
|
||||
|
||||
# dump dream lock to $outputFile
|
||||
outputFile = (os.environ.get("outputFile"))
|
||||
dirPath = pathlib.Path(os.path.dirname(outputFile))
|
||||
dirPath.mkdir(parents=True, exist_ok=True)
|
||||
with open(outputFile, "w") as lock:
|
||||
json.dump(dream_lock, lock, indent=2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user