libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 50099d49212c21a0af866e589068be993938b7a0
parent 891dba51dde9e49716038ffc54a44e7ec6620f64
Author: Florian Dold <dold@taler.net>
Date:   Fri,  4 Sep 2026 21:26:11 +0200

libeufin: replace build-common with local build scripts

Diffstat:
M.gitmodules | 3---
MMakefile | 6+++---
Mbootstrap | 7+------
Abuild-system/archive.py | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dbuild-system/configure.py | 9---------
Abuild-system/configure.sh | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dbuild-system/taler-build-scripts | 1-
7 files changed, 227 insertions(+), 22 deletions(-)

diff --git a/.gitmodules b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "build-system/taler-build-scripts"] - path = build-system/taler-build-scripts - url = ../build-common.git [submodule "doc/prebuilt"] path = doc/prebuilt url = ../taler-docs.git diff --git a/Makefile b/Makefile @@ -1,12 +1,12 @@ # This Makefile has been placed under the public domain --include build-system/config.mk +-include .config.mk # Default target, must be at the top. # Should be changed with care to not break (Debian) packaging. all: build -git-archive-all = ./build-system/taler-build-scripts/archive-with-submodules/git_archive_all.py +archive = ./build-system/archive.py git_tag=$(shell git describe --tags) gradle_version=$(shell ./gradlew -q libeufinVersion) @@ -35,7 +35,7 @@ build: dist: $(call versions_check) mkdir -p build/distributions - $(git-archive-all) --include ./configure build/distributions/libeufin-$(gradle_version)-sources.tar.gz + $(archive) --include ./configure build/distributions/libeufin-$(gradle_version)-sources.tar.gz .PHONY: deb deb: diff --git a/bootstrap b/bootstrap @@ -10,11 +10,6 @@ if ! git --version >/dev/null; then exit 1 fi -if ! python3 --version >/dev/null; then - echo "python3 not installed" - exit 1 -fi - # Make sure that "git pull" et al. also update # submodules to avoid accidental rollbacks. git config --local submodule.recurse true @@ -22,4 +17,4 @@ git config --local submodule.recurse true git submodule sync git submodule update --init rm -f ./configure -cp build-system/taler-build-scripts/configure ./configure +cp build-system/configure.sh ./configure diff --git a/build-system/archive.py b/build-system/archive.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 + +# This file has been placed in the public domain. + +"""Create a source archive containing this repository and its submodules.""" + +from __future__ import annotations + +import argparse +import os +from pathlib import Path +import subprocess +import sys +import tarfile + + +def run_git(repo: Path, *args: str, input_data: bytes | None = None) -> bytes: + try: + return subprocess.run( + ["git", *args], + cwd=repo, + input=input_data, + check=True, + stdout=subprocess.PIPE, + ).stdout + except subprocess.CalledProcessError as exc: + command = " ".join(("git", *args)) + raise RuntimeError(f"'{command}' failed in {repo}") from exc + + +def tracked_paths(repo: Path) -> list[Path]: + output = run_git(repo, "ls-files", "-z", "--cached") + return [ + Path(os.fsdecode(item)) for item in output.rstrip(b"\0").split(b"\0") if item + ] + + +def submodule_paths(repo: Path) -> set[Path]: + gitmodules = repo / ".gitmodules" + if not gitmodules.exists(): + return set() + result = subprocess.run( + [ + "git", + "config", + "-f", + ".gitmodules", + "--get-regexp", + r"^submodule\..*\.path$", + ], + cwd=repo, + check=False, + stdout=subprocess.PIPE, + text=True, + ) + if result.returncode not in (0, 1): + raise RuntimeError(f"could not read submodules from {gitmodules}") + return {Path(line.split(maxsplit=1)[1]) for line in result.stdout.splitlines()} + + +def export_ignored(repo: Path, paths: list[Path]) -> set[Path]: + if not paths: + return set() + query = b"\0".join(os.fsencode(path) for path in paths) + b"\0" + output = run_git( + repo, "check-attr", "-z", "--stdin", "export-ignore", input_data=query + ) + fields = output.rstrip(b"\0").split(b"\0") + ignored: set[Path] = set() + for index in range(0, len(fields), 3): + if fields[index + 2] == b"set": + ignored.add(Path(os.fsdecode(fields[index]))) + return ignored + + +def repository_entries(repo: Path) -> list[tuple[Path, Path]]: + """Return (filesystem path, archive-relative path) pairs for one repository.""" + submodules = submodule_paths(repo) + candidates: list[tuple[Path, Path]] = [] + + for relative in tracked_paths(repo): + if relative not in submodules: + candidates.append((repo / relative, relative)) + + for submodule in sorted(submodules): + submodule_dir = repo / submodule + if not (submodule_dir / ".git").exists(): + raise RuntimeError( + f"submodule '{submodule}' is not initialized; run './bootstrap' first" + ) + for source, relative in repository_entries(submodule_dir): + candidates.append((source, submodule / relative)) + + ignored = export_ignored(repo, [relative for _, relative in candidates]) + return [ + (source, relative) for source, relative in candidates if relative not in ignored + ] + + +def archive_prefix(output: Path) -> Path: + name = output.name + for suffix in (".tar.gz", ".tgz"): + if name.endswith(suffix): + prefix = name[: -len(suffix)] + if prefix: + return Path(prefix) + break + raise ValueError("output file must end in .tar.gz or .tgz") + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--include", + action="append", + default=[], + metavar="FILE", + help="include an untracked or export-ignored file (may be repeated)", + ) + parser.add_argument("output", type=Path, help="output .tar.gz file") + return parser.parse_args() + + +def main() -> int: + args = parse_args() + root = Path(run_git(Path.cwd(), "rev-parse", "--show-toplevel").decode().strip()) + output = args.output.resolve() + prefix = archive_prefix(output) + entries = repository_entries(root) + + included: list[tuple[Path, Path]] = [] + for name in args.include: + relative = Path(name) + if relative.is_absolute() or ".." in relative.parts: + raise ValueError( + f"included path must be relative to the repository: {name}" + ) + source = (root / relative).absolute() + if not source.is_file(): + raise FileNotFoundError(f"included file does not exist: {name}") + included.append((source, relative)) + + with tarfile.open(output, "w:gz") as archive: + for source, relative in [*included, *entries]: + archive.add(source, arcname=prefix / relative, recursive=False) + + print(f"created {output}") + return 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except (OSError, RuntimeError, ValueError) as exc: + print(f"archive: {exc}", file=sys.stderr) + sys.exit(1) diff --git a/build-system/configure.py b/build-system/configure.py @@ -1,9 +0,0 @@ -# This configure.py.template file is in the public domain. - -from talerbuildconfig import * - -b = BuildConfig() -b.enable_prefix() -b.enable_configmk() -b.add_tool(PosixTool("find")) -b.run() diff --git a/build-system/configure.sh b/build-system/configure.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# This file has been placed in the public domain. + +set -eu + +prefix=/usr/local + +usage() { + cat <<EOF +Usage: ./configure [--prefix=DIR] [VARIABLE=VALUE]... + +Configure the installation prefix (default: /usr/local). +Unsupported build variables are ignored with a warning. +EOF +} + +while test $# -gt 0; do + case $1 in + --prefix=*) + prefix=${1#*=} + ;; + --prefix) + if test $# -lt 2; then + echo "configure: option '--prefix' requires an argument" >&2 + exit 2 + fi + prefix=$2 + shift + ;; + -h|--help) + usage + exit 0 + ;; + *=*) + variable=${1%%=*} + case $variable in + ""|[!A-Za-z_]*|*[!A-Za-z0-9_]*) + echo "configure: unrecognized option '$1'" >&2 + echo "Try './configure --help' for more information." >&2 + exit 2 + ;; + *) + echo "configure: WARNING: unsupported variable '$variable' is ignored" >&2 + ;; + esac + ;; + *) + echo "configure: unrecognized option '$1'" >&2 + echo "Try './configure --help' for more information." >&2 + exit 2 + ;; + esac + shift +done + +if test -z "$prefix"; then + echo "configure: installation prefix must not be empty" >&2 + exit 2 +fi + +cat >.config.mk <<EOF +# This makefile fragment is generated by configure. +prefix = $prefix +EOF + +echo "configured installation prefix: $prefix" diff --git a/build-system/taler-build-scripts b/build-system/taler-build-scripts @@ -1 +0,0 @@ -Subproject commit 884e13fe65b584f63d4cf92348fab1136af4bd69