Project import generated by Copybara.
GitOrigin-RevId: e6e19f3d81a982a62e1bba08f0b4f7fdc21b4ea0
This commit is contained in:
parent
ac06d71d66
commit
a291c8690a
8182 changed files with 116586 additions and 1602792 deletions
6
third_party/tvl/.envrc
vendored
6
third_party/tvl/.envrc
vendored
|
@ -1,5 +1,7 @@
|
||||||
# Configure the local PATH to contain tools which are fetched ad-hoc
|
# Configure the local PATH to contain tools which are fetched ad-hoc
|
||||||
# from Nix.
|
# from Nix.
|
||||||
|
|
||||||
export PATH="${PWD}/bin:${PATH}"
|
out=$(nix-build -A tools.depot-deps --no-out-link)
|
||||||
export REPO_ROOT="${PWD}"
|
PATH_add "$out/bin"
|
||||||
|
|
||||||
|
watch_file tools/depot-deps.nix
|
||||||
|
|
3
third_party/tvl/.git-blame-ignore-revs
vendored
3
third_party/tvl/.git-blame-ignore-revs
vendored
|
@ -21,3 +21,6 @@ c758de9d22506eb279c5abe61f621e5c8f61af95
|
||||||
|
|
||||||
# style(3p/nix): Final act in the brace-wrapping saga
|
# style(3p/nix): Final act in the brace-wrapping saga
|
||||||
39087321811e81e26a1a47d6967df1088dcf0e95
|
39087321811e81e26a1a47d6967df1088dcf0e95
|
||||||
|
|
||||||
|
# style: format entire depot with nixpkgs-fmt
|
||||||
|
aa122cbae78ce97d60c0c98ba14df753d97e40b1
|
||||||
|
|
13
third_party/tvl/.nixery/README.md
vendored
Normal file
13
third_party/tvl/.nixery/README.md
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Nixery set
|
||||||
|
==========
|
||||||
|
|
||||||
|
This folder exports a special import of the depot Nix structure that is
|
||||||
|
compatible with Nixery, by extending nixpkgs with a `tvl` attribute containing
|
||||||
|
the depot.
|
||||||
|
|
||||||
|
This is required because Nixery expects its package set to look like nixpkgs at
|
||||||
|
the top-level.
|
||||||
|
|
||||||
|
In the future we might want to patch Nixery to not require this (e.g. make it
|
||||||
|
possible to pass `third_party.nixpkgs` as a key at which to find the nixpkgs
|
||||||
|
structure).
|
6
third_party/tvl/.nixery/default.nix
vendored
Normal file
6
third_party/tvl/.nixery/default.nix
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# See README.md
|
||||||
|
{ depot ? import ../. {}, ... }:
|
||||||
|
|
||||||
|
depot.third_party.nixpkgs.extend(_: _: {
|
||||||
|
tvl = depot;
|
||||||
|
})
|
22
third_party/tvl/.rustfmt.toml
vendored
22
third_party/tvl/.rustfmt.toml
vendored
|
@ -1,22 +0,0 @@
|
||||||
# This configuration file changes some defaults from the ones
|
|
||||||
# documented on https://rust-lang.github.io/rustfmt/
|
|
||||||
#
|
|
||||||
# All other settings are left at the defaults.
|
|
||||||
|
|
||||||
edition = "2018"
|
|
||||||
newline_style = "Unix"
|
|
||||||
use_try_shorthand = true
|
|
||||||
|
|
||||||
# Unstable settings that we want in the future, once they are
|
|
||||||
# available:
|
|
||||||
#
|
|
||||||
# combine_control_expr = false
|
|
||||||
# comment_width = 100
|
|
||||||
# condense_wildcard_suffixes = true
|
|
||||||
# format_code_in_doc_comments = true
|
|
||||||
# inline_attribute_width = 100
|
|
||||||
# match_block_trailing_comma = true
|
|
||||||
# merge_imports = true
|
|
||||||
# normalize_comments = true
|
|
||||||
# overflow_delimited_expr = true
|
|
||||||
# wrap_comments = true
|
|
1
third_party/tvl/LICENSE
vendored
1
third_party/tvl/LICENSE
vendored
|
@ -1,6 +1,7 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2019 Vincent Ambo
|
Copyright (c) 2019 Vincent Ambo
|
||||||
|
Copyright (c) 2020-2021 The TVL Authors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
2
third_party/tvl/OWNERS
vendored
2
third_party/tvl/OWNERS
vendored
|
@ -2,3 +2,5 @@ inherited: false
|
||||||
owners:
|
owners:
|
||||||
- tazjin
|
- tazjin
|
||||||
- lukegb
|
- lukegb
|
||||||
|
- grfn
|
||||||
|
- sterni
|
||||||
|
|
40
third_party/tvl/README.md
vendored
40
third_party/tvl/README.md
vendored
|
@ -1,19 +1,16 @@
|
||||||
depot
|
depot
|
||||||
=====
|
=====
|
||||||
|
|
||||||
[![Build status](https://badge.buildkite.com/016bff4b8ae2704a3bbbb0a250784e6692007c582983b6dea7.svg?branch=canon)](https://buildkite.com/tvl/depot)
|
[![Build status](https://badge.buildkite.com/016bff4b8ae2704a3bbbb0a250784e6692007c582983b6dea7.svg?branch=refs/heads/canon)](https://buildkite.com/tvl/depot)
|
||||||
|
|
||||||
This repository is the [monorepo][] for the community around [tazjin's virus
|
This repository is the [monorepo][] for the community around [The
|
||||||
lounge][tvl], containing our personal tools and infrastructure. Everything in
|
Virus Lounge][tvl], containing our personal tools and infrastructure.
|
||||||
here is built using [Nix][].
|
Everything in here is built using [Nix][].
|
||||||
|
|
||||||
A large portion of the software here is very self-referential, meaning that it
|
A large portion of the software here is very self-referential, meaning that it
|
||||||
exists to sustain the operation of the repository. This is the case because we
|
exists to sustain the operation of the repository. This is the case because we
|
||||||
partially see this as [an experiment][] in tooling for monorepos.
|
partially see this as [an experiment][] in tooling for monorepos.
|
||||||
|
|
||||||
If you've ended up here and have no idea who I am, feel free to follow me [on
|
|
||||||
Twitter][].
|
|
||||||
|
|
||||||
# Highlights
|
# Highlights
|
||||||
|
|
||||||
## Services
|
## Services
|
||||||
|
@ -41,15 +38,20 @@ Twitter][].
|
||||||
dynamically via
|
dynamically via
|
||||||
[`//ops/pipelines`](https://cs.tvl.fyi/depot/-/tree/ops/pipelines).
|
[`//ops/pipelines`](https://cs.tvl.fyi/depot/-/tree/ops/pipelines).
|
||||||
|
|
||||||
|
* A search service that makes TVL services available via textual
|
||||||
|
shortcuts is available: [atward](https://at.tvl.fyi)
|
||||||
|
|
||||||
All services that we host are deployed on NixOS machines that we manage. Their
|
All services that we host are deployed on NixOS machines that we manage. Their
|
||||||
configuration is tracked in `//ops/nixos`.
|
configuration is tracked in `//ops/{modules,machines}`.
|
||||||
|
|
||||||
## Nix
|
## Nix
|
||||||
|
|
||||||
* `//third_party/nix` contains Tvix, [our fork][tvix] of the Nix package manager
|
|
||||||
* [`//nix/readTree`](https://cs.tvl.fyi/depot/-/blob/nix/readTree/README.md)
|
* [`//nix/readTree`](https://cs.tvl.fyi/depot/-/blob/nix/readTree/README.md)
|
||||||
contains the Nix code which automatically registers projects in our Nix
|
contains the Nix code which automatically registers projects in our Nix
|
||||||
attribute hierarchy based on their in-tree location
|
attribute hierarchy based on their in-tree location
|
||||||
|
* [`//tools/nixery`](https://cs.tvl.fyi/depot/-/tree/tools/nixery)
|
||||||
|
contains the source code of [Nixery][], a container registry that
|
||||||
|
can build images ad-hoc from Nix packages
|
||||||
* `//nix/yants` contains **Y**et **A**nother **N**ix **T**ype **S**ystem, which
|
* `//nix/yants` contains **Y**et **A**nother **N**ix **T**ype **S**ystem, which
|
||||||
we use for a variety of things throughout the repository
|
we use for a variety of things throughout the repository
|
||||||
* `//nix/buildGo` implements a Nix library that can build Go software in the
|
* `//nix/buildGo` implements a Nix library that can build Go software in the
|
||||||
|
@ -58,6 +60,10 @@ configuration is tracked in `//ops/nixos`.
|
||||||
* `//nix/buildLisp` implements a Nix library that can build Common Lisp
|
* `//nix/buildLisp` implements a Nix library that can build Common Lisp
|
||||||
software. Currently only SBCL is supported. Lisp programs in this repository
|
software. Currently only SBCL is supported. Lisp programs in this repository
|
||||||
are built using this library.
|
are built using this library.
|
||||||
|
* `//web/bubblegum` contains a CGI-based web framework written in Nix.
|
||||||
|
* `//nix/nint`: A shebang-compatible interpreter wrapper for Nix.
|
||||||
|
* `//tvix` contains initial work towards a modular architecture for Nix.
|
||||||
|
* `//third_party/nix` contains [our fork][tvix] of the Nix package manager.
|
||||||
|
|
||||||
We have a variety of other tools and libraries in the `//nix` folder which may
|
We have a variety of other tools and libraries in the `//nix` folder which may
|
||||||
be of interest.
|
be of interest.
|
||||||
|
@ -84,9 +90,9 @@ Some examples:
|
||||||
* `//users/tazjin/homepage` && `//users/tazjin/blog`: A Nix-based static site
|
* `//users/tazjin/homepage` && `//users/tazjin/blog`: A Nix-based static site
|
||||||
generator which generates the web page and Atom feed for
|
generator which generates the web page and Atom feed for
|
||||||
[tazj.in](https://tazj.in)
|
[tazj.in](https://tazj.in)
|
||||||
* `//users/tazjin/finito`: A persistent finite-state machine library for Rust.
|
* `//users/grfn/xanthous`: A (WIP) TUI RPG, written in Haskell.
|
||||||
* `//users/glittershark/xanthous`: A (WIP) TUI RPG, written in Haskell.
|
|
||||||
* `//users/tazjin/emacs`: tazjin's Emacs & EXWM configuration
|
* `//users/tazjin/emacs`: tazjin's Emacs & EXWM configuration
|
||||||
|
* `//users/tazjin/finito`: A persistent finite-state machine library for Rust.
|
||||||
|
|
||||||
# Licensing
|
# Licensing
|
||||||
|
|
||||||
|
@ -99,11 +105,21 @@ If you'd like to contribute to any of the tools in here, please check out the
|
||||||
[contribution guidelines](./docs/CONTRIBUTING.md) and our [code of
|
[contribution guidelines](./docs/CONTRIBUTING.md) and our [code of
|
||||||
conduct](./docs/CODE_OF_CONDUCT.md).
|
conduct](./docs/CODE_OF_CONDUCT.md).
|
||||||
|
|
||||||
|
IRC users can find us in [`#tvl`][tvl-irc] on [hackint][], which is also
|
||||||
|
reachable [via XMPP][hackint-xmpp] at [`#tvl@irc.hackint.org`][tvl-xmpp] (sic!).
|
||||||
|
|
||||||
|
Hackint also provide a [web chat][tvl-webchat].
|
||||||
|
|
||||||
[monorepo]: https://en.wikipedia.org/wiki/Monorepo
|
[monorepo]: https://en.wikipedia.org/wiki/Monorepo
|
||||||
[tvl]: https://tvl.fyi
|
[tvl]: https://tvl.fyi
|
||||||
[Nix]: https://nixos.org/nix
|
[Nix]: https://nixos.org/nix
|
||||||
[an experiment]: https://tvl.fyi/monorepo-doc
|
[an experiment]: https://tvl.fyi/monorepo-doc
|
||||||
[on Twitter]: https://twitter.com/tazjin
|
|
||||||
[panettone]: https://cs.tvl.fyi/depot@canon/-/tree/web/panettone
|
[panettone]: https://cs.tvl.fyi/depot@canon/-/tree/web/panettone
|
||||||
[tvix]: https://cs.tvl.fyi/depot/-/blob/third_party/nix/README.md
|
[tvix]: https://cs.tvl.fyi/depot/-/blob/third_party/nix/README.md
|
||||||
[dottime]: https://dotti.me
|
[dottime]: https://dotti.me
|
||||||
|
[tvl-irc]: ircs://irc.hackint.org:6697/#tvl
|
||||||
|
[hackint]: https://hackint.org/
|
||||||
|
[hackint-xmpp]: https://hackint.org/transport/xmpp
|
||||||
|
[tvl-xmpp]: xmpp:#tvl@irc.hackint.org?join
|
||||||
|
[tvl-webchat]: https://webirc.hackint.org/#ircs://irc.hackint.org/#tvl
|
||||||
|
[Nixery]: https://nixery.dev
|
||||||
|
|
2
third_party/tvl/RULES
vendored
2
third_party/tvl/RULES
vendored
|
@ -1 +1 @@
|
||||||
1. Only those who pay the Golden Price may bear The Wheel.
|
1. Only those who pay the Golden Price may bear The Wheel (for the most part).
|
||||||
|
|
70
third_party/tvl/bin/__dispatch.sh
vendored
70
third_party/tvl/bin/__dispatch.sh
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/age
vendored
70
third_party/tvl/bin/age
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/age-keygen
vendored
70
third_party/tvl/bin/age-keygen
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/aoc2019
vendored
70
third_party/tvl/bin/aoc2019
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/depot-build
vendored
70
third_party/tvl/bin/depot-build
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/gerrit
vendored
70
third_party/tvl/bin/gerrit
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/git-bug
vendored
70
third_party/tvl/bin/git-bug
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/hash-password
vendored
70
third_party/tvl/bin/hash-password
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/kontemplate
vendored
70
third_party/tvl/bin/kontemplate
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/meson
vendored
70
third_party/tvl/bin/meson
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/ninja
vendored
70
third_party/tvl/bin/ninja
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/perf-flamegraph
vendored
70
third_party/tvl/bin/perf-flamegraph
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/rebuild-system
vendored
70
third_party/tvl/bin/rebuild-system
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/rebuilder
vendored
70
third_party/tvl/bin/rebuilder
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/rink
vendored
70
third_party/tvl/bin/rink
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/stern
vendored
70
third_party/tvl/bin/stern
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
70
third_party/tvl/bin/terraform
vendored
70
third_party/tvl/bin/terraform
vendored
|
@ -1,70 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# This script dispatches invocations transparently to programs instantiated from
|
|
||||||
# Nix.
|
|
||||||
#
|
|
||||||
# To add a new tool, insert it into the case statement below by setting `attr`
|
|
||||||
# to the key in nixpkgs which represents the program you want to run.
|
|
||||||
set -ueo pipefail
|
|
||||||
|
|
||||||
readonly REPO_ROOT=$(dirname "$0")/..
|
|
||||||
TARGET_TOOL=$(basename "$0")
|
|
||||||
|
|
||||||
case "${TARGET_TOOL}" in
|
|
||||||
age)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
age-keygen)
|
|
||||||
attr="third_party.age"
|
|
||||||
;;
|
|
||||||
aoc2019)
|
|
||||||
attr="fun.aoc2019.${1}"
|
|
||||||
;;
|
|
||||||
depot-build)
|
|
||||||
attr="tools.depot-build"
|
|
||||||
;;
|
|
||||||
git-bug)
|
|
||||||
attr="third_party.git-bug"
|
|
||||||
;;
|
|
||||||
gerrit)
|
|
||||||
attr="tools.gerrit-cli"
|
|
||||||
;;
|
|
||||||
hash-password)
|
|
||||||
attr="tools.hash-password"
|
|
||||||
;;
|
|
||||||
kontemplate)
|
|
||||||
attr="kontemplate"
|
|
||||||
;;
|
|
||||||
meson)
|
|
||||||
attr="third_party.meson"
|
|
||||||
;;
|
|
||||||
ninja)
|
|
||||||
attr="third_party.ninja"
|
|
||||||
;;
|
|
||||||
perf-flamegraph)
|
|
||||||
attr="tools.perf-flamegraph"
|
|
||||||
;;
|
|
||||||
rebuild-system)
|
|
||||||
attr="ops.nixos.rebuild-system"
|
|
||||||
;;
|
|
||||||
rebuilder)
|
|
||||||
attr="users.tazjin.nixos.rebuilder"
|
|
||||||
;;
|
|
||||||
rink)
|
|
||||||
attr="third_party.rink"
|
|
||||||
;;
|
|
||||||
stern)
|
|
||||||
attr="third_party.stern"
|
|
||||||
;;
|
|
||||||
terraform)
|
|
||||||
attr="third_party.terraform-gcp"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
result=$(nix-build --no-out-link --attr "${attr}" "${REPO_ROOT}")
|
|
||||||
PATH="${result}/bin:$PATH"
|
|
||||||
|
|
||||||
exec "${TARGET_TOOL}" "${@}"
|
|
4
third_party/tvl/corp/LICENSE
vendored
Normal file
4
third_party/tvl/corp/LICENSE
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Copyright 2021 ООО ТВЛ
|
||||||
|
|
||||||
|
Code under this folder may be redistributed as part of the TVL depot
|
||||||
|
repository. All other usage rights for this code are reserved.
|
3
third_party/tvl/corp/OWNERS
vendored
Normal file
3
third_party/tvl/corp/OWNERS
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
inherited: false
|
||||||
|
owners:
|
||||||
|
- tvl-employees
|
26
third_party/tvl/corp/website/content.md
vendored
Normal file
26
third_party/tvl/corp/website/content.md
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
The Virus Lounge
|
||||||
|
================
|
||||||
|
|
||||||
|
----------------
|
||||||
|
|
||||||
|
<img class="tvl-logo" src="https://static.tvl.su/latest/logo-animated.svg"
|
||||||
|
alt="Virus with lambda-shaped spike proteins sitting on an armchair">
|
||||||
|
|
||||||
|
Welcome to the corporate face of [The Virus Lounge][tvl-fyi].
|
||||||
|
|
||||||
|
We provide technology consulting around a variety of topics, for
|
||||||
|
example:
|
||||||
|
|
||||||
|
* Advice and setup of organisation-wide monorepos for effective
|
||||||
|
developer workflows, including associated tooling like CI/CD
|
||||||
|
* Assistance with anything related to Nix/NixOS
|
||||||
|
* Software development in various languages (Rust, Common Lisp,
|
||||||
|
Erlang, Java and more)
|
||||||
|
|
||||||
|
We might be able to help you with other things on request.
|
||||||
|
|
||||||
|
Note: We are still in the process of getting started and have limited
|
||||||
|
capacity at the moment. If you would like our help, please reach out
|
||||||
|
at **contact {at} tvl.su** for a discussion.
|
||||||
|
|
||||||
|
[tvl-fyi]: https://tvl.fyi
|
37
third_party/tvl/corp/website/default.nix
vendored
Normal file
37
third_party/tvl/corp/website/default.nix
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
|
|
||||||
|
let
|
||||||
|
# https://developers.google.com/search/docs/advanced/structured-data/logo
|
||||||
|
structuredData = {
|
||||||
|
"@context" = "https://schema.org";
|
||||||
|
"@type" = "Organisation";
|
||||||
|
url = "https://tvl.su";
|
||||||
|
logo = "https://static.tvl.fyi/${depot.web.static.drvHash}/logo-animated.svg";
|
||||||
|
};
|
||||||
|
index = depot.web.tvl.template {
|
||||||
|
title = "TVL (The Virus Lounge) - Software consulting";
|
||||||
|
content = builtins.readFile ./content.md;
|
||||||
|
extraFooter = "\n|\n © ООО ТВЛ";
|
||||||
|
|
||||||
|
# TODO(tazjin): The `.tvl-logo` thing can probably go in the shared CSS.
|
||||||
|
extraHead = ''
|
||||||
|
<meta name="description" content="TVL provides technology consulting for monorepos, Nix, and other SRE/DevOps/Software Engineering topics.">
|
||||||
|
<script type="application/ld+json">
|
||||||
|
${builtins.toJSON structuredData}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.tvl-logo {
|
||||||
|
width: 60%;
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
pkgs.runCommandNoCC "corp-website" { } ''
|
||||||
|
mkdir $out
|
||||||
|
cp ${index} $out/index.html
|
||||||
|
''
|
165
third_party/tvl/default.nix
vendored
165
third_party/tvl/default.nix
vendored
|
@ -1,109 +1,122 @@
|
||||||
# This file sets up the top-level package set by traversing the package tree
|
# This file sets up the top-level package set by traversing the package tree
|
||||||
# (see read-tree.nix for details) and constructing a matching attribute set
|
# (see //nix/readTree for details) and constructing a matching attribute set
|
||||||
# tree.
|
# tree.
|
||||||
#
|
|
||||||
# This makes packages accessible via the Nixery instance that is configured to
|
|
||||||
# use this repository as its nixpkgs source.
|
|
||||||
|
|
||||||
{ ... }@args:
|
{ nixpkgsBisectPath ? null
|
||||||
|
, parentTargetMap ? null
|
||||||
with builtins;
|
, nixpkgsConfig ? { }
|
||||||
|
, ...
|
||||||
|
}@args:
|
||||||
|
|
||||||
let
|
let
|
||||||
# This definition of fix is identical to <nixpkgs>.lib.fix, but the global
|
inherit (builtins)
|
||||||
# package set is not available here.
|
filter
|
||||||
fix = f: let x = f x; in x;
|
;
|
||||||
|
|
||||||
# Global configuration that all packages are called with.
|
readTree = import ./nix/readTree { };
|
||||||
config = depot: {
|
|
||||||
inherit depot;
|
|
||||||
|
|
||||||
# Expose lib & ciBuilds attributes to packages.
|
# Disallow access to //users from other depot parts.
|
||||||
inherit (depot) ciBuilds lib;
|
usersFilter = readTree.restrictFolder {
|
||||||
|
folder = "users";
|
||||||
|
reason = ''
|
||||||
|
Code under //users is not considered stable or dependable in the
|
||||||
|
wider depot context. If a project under //users is required by
|
||||||
|
something else, please move it to a different depot path.
|
||||||
|
'';
|
||||||
|
|
||||||
# Pass third_party as 'pkgs' (for compatibility with external
|
exceptions = [
|
||||||
# imports for certain subdirectories)
|
# whitby is allowed to access //users for several reasons:
|
||||||
pkgs = depot.third_party;
|
#
|
||||||
|
# 1. User SSH keys are set in //users.
|
||||||
|
# 2. Some personal websites or demo projects are served from it.
|
||||||
|
[ "ops" "machines" "whitby" ]
|
||||||
|
|
||||||
|
# Due to evaluation order this also affects these targets.
|
||||||
|
# TODO(tazjin): Can this one be removed somehow?
|
||||||
|
[ "ops" "nixos" ]
|
||||||
|
[ "ops" "machines" "all-systems" ]
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
readTree' = import ./nix/readTree {};
|
# Disallow access to //corp from other depot parts.
|
||||||
|
corpFilter = readTree.restrictFolder {
|
||||||
|
folder = "corp";
|
||||||
|
reason = ''
|
||||||
|
Code under //corp may use incompatible licensing terms with
|
||||||
|
other depot parts and should not be used anywhere else.
|
||||||
|
'';
|
||||||
|
|
||||||
localPkgs = readTree: {
|
exceptions = [
|
||||||
fun = readTree ./fun;
|
# For the same reason as above, whitby is exempt to serve the
|
||||||
lisp = readTree ./lisp;
|
# corp website.
|
||||||
net = readTree ./net;
|
[ "ops" "machines" "whitby" ]
|
||||||
nix = readTree ./nix;
|
[ "ops" "nixos" ]
|
||||||
ops = readTree ./ops;
|
[ "ops" "machines" "all-systems" ]
|
||||||
third_party = readTree ./third_party;
|
];
|
||||||
tools = readTree ./tools;
|
};
|
||||||
users = readTree ./users;
|
|
||||||
web = readTree ./web;
|
readDepot = depotArgs: readTree {
|
||||||
|
args = depotArgs;
|
||||||
|
path = ./.;
|
||||||
|
filter = parts: args: corpFilter parts (usersFilter parts args);
|
||||||
|
scopedArgs = {
|
||||||
|
__findFile = _: _: throw "Do not import from NIX_PATH in the depot!";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# To determine build targets, we walk through the depot tree and
|
# To determine build targets, we walk through the depot tree and
|
||||||
# fetch attributes that were imported by readTree and are buildable.
|
# fetch attributes that were imported by readTree and are buildable.
|
||||||
#
|
#
|
||||||
# Any build target that contains `meta.ci = false` will be skipped.
|
# Any build target that contains `meta.ci.skip = true` will be skipped.
|
||||||
|
|
||||||
# Is this tree node eligible for build inclusion?
|
# Is this tree node eligible for build inclusion?
|
||||||
eligible = node: (node ? outPath) && (node.meta.ci or true);
|
eligible = node: (node ? outPath) && !(node.meta.ci.skip or false);
|
||||||
|
|
||||||
# Walk the tree starting with 'node', recursively extending the list
|
in
|
||||||
# of build targets with anything that looks buildable.
|
readTree.fix (self: (readDepot {
|
||||||
|
depot = self;
|
||||||
|
|
||||||
|
# Pass third_party as 'pkgs' (for compatibility with external
|
||||||
|
# imports for certain subdirectories)
|
||||||
|
pkgs = self.third_party.nixpkgs;
|
||||||
|
|
||||||
|
# Expose lib attribute to packages.
|
||||||
|
lib = self.third_party.nixpkgs.lib;
|
||||||
|
|
||||||
|
# Pass arguments passed to the entire depot through, for packages
|
||||||
|
# that would like to add functionality based on this.
|
||||||
#
|
#
|
||||||
# Any tree node can specify logical targets by exporting a
|
# Note that it is intended for exceptional circumstance, such as
|
||||||
# 'meta.targets' attribute containing a list of keys in itself. This
|
# debugging by bisecting nixpkgs.
|
||||||
# enables target specifications that do not exist on disk directly.
|
externalArgs = args;
|
||||||
gather = node:
|
}) // {
|
||||||
if node ? __readTree then
|
|
||||||
# Include the node itself if it is eligible.
|
|
||||||
(if eligible node then [ node ] else [])
|
|
||||||
# Include eligible children of the node
|
|
||||||
++ concatMap gather (attrValues node)
|
|
||||||
# Include specified sub-targets of the node
|
|
||||||
++ filter eligible (map
|
|
||||||
(k: (node."${k}" or {}) // {
|
|
||||||
# Keep the same tree location, but explicitly mark this
|
|
||||||
# node as a subtarget.
|
|
||||||
__readTree = node.__readTree;
|
|
||||||
__subtarget = k;
|
|
||||||
})
|
|
||||||
(node.meta.targets or []))
|
|
||||||
else [];
|
|
||||||
in fix(self: {
|
|
||||||
config = config self;
|
|
||||||
|
|
||||||
# Elevate 'lib' from nixpkgs
|
|
||||||
lib = import (self.third_party.nixpkgsSrc + "/lib");
|
|
||||||
|
|
||||||
# Expose readTree for downstream repo consumers.
|
|
||||||
readTree = {
|
|
||||||
__functor = x: (readTree' x.config);
|
|
||||||
config = self.config;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Make the path to the depot available for things that might need it
|
# Make the path to the depot available for things that might need it
|
||||||
# (e.g. NixOS module inclusions)
|
# (e.g. NixOS module inclusions)
|
||||||
depotPath = ./.;
|
path = self.third_party.nixpkgs.lib.cleanSourceWith {
|
||||||
|
name = "depot";
|
||||||
|
src = ./.;
|
||||||
|
filter = self.third_party.nixpkgs.lib.cleanSourceFilter;
|
||||||
|
};
|
||||||
|
|
||||||
# List of all buildable targets, for CI purposes.
|
# List of all buildable targets, for CI purposes.
|
||||||
#
|
#
|
||||||
# Note: To prevent infinite recursion, this *must* be a nested
|
# Note: To prevent infinite recursion, this *must* be a nested
|
||||||
# attribute set (which does not have a __readTree attribute).
|
# attribute set (which does not have a __readTree attribute).
|
||||||
ci.targets = gather (self // {
|
ci.targets = readTree.gather eligible (self // {
|
||||||
# remove the pipelines themselves from the set over which to
|
# remove the pipelines themselves from the set over which to
|
||||||
# generate pipelines because that also leads to infinite
|
# generate pipelines because that also leads to infinite
|
||||||
# recursion.
|
# recursion.
|
||||||
ops = self.ops // { pipelines = null; };
|
ops = self.ops // { pipelines = null; };
|
||||||
|
|
||||||
|
# remove nixpkgs from the set, for obvious reasons.
|
||||||
|
third_party = self.third_party // { nixpkgs = null; };
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
# Add local packages as structured by readTree
|
# Derivation that gcroots all depot targets.
|
||||||
// (localPkgs (readTree' self.config))
|
ci.gcroot = with self.third_party.nixpkgs; makeSetupHook
|
||||||
|
{
|
||||||
# Load overrides into the top-level.
|
name = "depot-gcroot";
|
||||||
#
|
deps = self.ci.targets;
|
||||||
# This can be used to move things from third_party into the top-level, too (such
|
}
|
||||||
# as `lib`).
|
emptyFile;
|
||||||
// (readTree' { depot = self; pkgs = self.third_party; }) ./overrides
|
})
|
||||||
)
|
|
||||||
|
|
3
third_party/tvl/docs/CONTRIBUTING.md
vendored
3
third_party/tvl/docs/CONTRIBUTING.md
vendored
|
@ -55,12 +55,13 @@ Where `type` can be one of:
|
||||||
* `refactor`: Hopefully self-explanatory!
|
* `refactor`: Hopefully self-explanatory!
|
||||||
* `test`: Added missing tests / fixed tests
|
* `test`: Added missing tests / fixed tests
|
||||||
* `chore`: Maintenance work
|
* `chore`: Maintenance work
|
||||||
|
* `subtree`: Operations involving `git subtree`
|
||||||
|
|
||||||
And `scope` should refer to some kind of logical grouping inside of the project.
|
And `scope` should refer to some kind of logical grouping inside of the project.
|
||||||
|
|
||||||
It does not make sense to include the full path unless it aids in
|
It does not make sense to include the full path unless it aids in
|
||||||
disambiguating. For example, when changing the configuration of the host
|
disambiguating. For example, when changing the configuration of the host
|
||||||
`camden` at `//ops/nixos/camden` it is enough to write `feat(camden): ...`.
|
`whitby` at `//ops/machines/whitby` it is enough to write `feat(whitby): ...`.
|
||||||
|
|
||||||
Please take a look at the existing commit log for examples.
|
Please take a look at the existing commit log for examples.
|
||||||
|
|
||||||
|
|
9
third_party/tvl/docs/REVIEWS.md
vendored
9
third_party/tvl/docs/REVIEWS.md
vendored
|
@ -111,9 +111,9 @@ themselves**.
|
||||||
If you would like to have an account on the Gerrit instance, follow these
|
If you would like to have an account on the Gerrit instance, follow these
|
||||||
instructions:
|
instructions:
|
||||||
|
|
||||||
1. Be a member of `##tvl`.
|
1. Be a member of `#tvl` on [hackint][].
|
||||||
2. Clone the depot locally (via `git clone "https://cl.tvl.fyi/depot"`).
|
2. Clone the depot locally (via `git clone "https://cl.tvl.fyi/depot"`).
|
||||||
3. Create a user entry in our LDAP server in [tvl-slapd/default.nix][tvl-slapd].
|
3. Create a user entry in our LDAP server in [ops/users][ops-users].
|
||||||
|
|
||||||
We recommend using ARGON2 password hashes, which can be created
|
We recommend using ARGON2 password hashes, which can be created
|
||||||
with the `slappasswd` tool if OpenLDAP was compiled with ARGON2
|
with the `slappasswd` tool if OpenLDAP was compiled with ARGON2
|
||||||
|
@ -128,7 +128,7 @@ instructions:
|
||||||
You can probably create ARGON2 hashes with other tools, but that is
|
You can probably create ARGON2 hashes with other tools, but that is
|
||||||
your job to figure out.
|
your job to figure out.
|
||||||
4. Create a commit adding yourself (see e.g.
|
4. Create a commit adding yourself (see e.g.
|
||||||
[CL/223](https://cl.tvl.fyi/c/depot/+/223)).
|
[CL/2671](https://cl.tvl.fyi/c/depot/+/2671))
|
||||||
5. Submit the commit via email (see below).
|
5. Submit the commit via email (see below).
|
||||||
|
|
||||||
## Submitting changes via email
|
## Submitting changes via email
|
||||||
|
@ -149,5 +149,6 @@ The email address is a [public group][].
|
||||||
[Gerrit walkthrough]: https://gerrit-review.googlesource.com/Documentation/intro-gerrit-walkthrough.html
|
[Gerrit walkthrough]: https://gerrit-review.googlesource.com/Documentation/intro-gerrit-walkthrough.html
|
||||||
[OWNERS]: https://cl.tvl.fyi/plugins/owners/Documentation/config.md
|
[OWNERS]: https://cl.tvl.fyi/plugins/owners/Documentation/config.md
|
||||||
[guidelines]: ./CONTRIBUTING.md#commit-messages
|
[guidelines]: ./CONTRIBUTING.md#commit-messages
|
||||||
[tvl-slapd]: ../ops/nixos/tvl-slapd/default.nix
|
[ops-users]: ../ops/users/default.nix
|
||||||
[public group]: https://groups.google.com/a/tazj.in/forum/?hl=en#!forum/depot
|
[public group]: https://groups.google.com/a/tazj.in/forum/?hl=en#!forum/depot
|
||||||
|
[hackint]: https://hackint.org
|
||||||
|
|
|
@ -9,7 +9,7 @@ Open items:
|
||||||
the closure of a given source directory, using [depot-scan].
|
the closure of a given source directory, using [depot-scan].
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
DEPOT_ROOT="${depot.depotPath}"
|
DEPOT_ROOT="${depot.path}"
|
||||||
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
|
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||||
CLIENT_ROOT="$XDG_DATA_HOME/tvlc/clients"
|
CLIENT_ROOT="$XDG_DATA_HOME/tvlc/clients"
|
||||||
NICE_CHECKOUT_ROOT="$HOME/tvlc"
|
NICE_CHECKOUT_ROOT="$HOME/tvlc"
|
||||||
|
|
13
third_party/tvl/fun/amsterdump/default.nix
vendored
13
third_party/tvl/fun/amsterdump/default.nix
vendored
|
@ -1,13 +0,0 @@
|
||||||
{ depot, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.program {
|
|
||||||
name = "amsterdump";
|
|
||||||
srcs = [
|
|
||||||
./main.go
|
|
||||||
];
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
# gopkgs."golang.org".x.oauth2.google
|
|
||||||
gopkgs."googlemaps.github.io".maps
|
|
||||||
];
|
|
||||||
}
|
|
2326
third_party/tvl/fun/amsterdump/listings-20200105.json
vendored
2326
third_party/tvl/fun/amsterdump/listings-20200105.json
vendored
File diff suppressed because it is too large
Load diff
108
third_party/tvl/fun/amsterdump/main.go
vendored
108
third_party/tvl/fun/amsterdump/main.go
vendored
|
@ -1,108 +0,0 @@
|
||||||
// Amsterdump is a small program that populates a BigQuery table with
|
|
||||||
// a matrix of origin points scattered around Amsterdam and each
|
|
||||||
// respective points travel time to a given destination.
|
|
||||||
//
|
|
||||||
// The two destinations used here are the Schiphol Airport and
|
|
||||||
// Amsterdam Central station.
|
|
||||||
//
|
|
||||||
// To accomplish this the Google Maps Distance Matrix API [1] is
|
|
||||||
// queried with the points. A visualisation is later done using
|
|
||||||
// BigQuery GeoViz[2].
|
|
||||||
//
|
|
||||||
// [1]: https://developers.google.com/maps/documentation/distance-matrix/start#quotas
|
|
||||||
// [2]: https://bigquerygeoviz.appspot.com/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"googlemaps.github.io/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
func failOn(err error, msg string) {
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(msg, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type LocationResult struct {
|
|
||||||
Address string `json:"address"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
Schiphol *maps.DistanceMatrixElement `json:"schiphol"`
|
|
||||||
Centraal *maps.DistanceMatrixElement `json:"centraal"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Listing struct {
|
|
||||||
URL string `json:"url"`
|
|
||||||
Address string `json:"address"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func requestMatrix(ctx context.Context, client *maps.Client, listings []Listing) {
|
|
||||||
origins := make([]string, len(listings))
|
|
||||||
for i, l := range listings {
|
|
||||||
origins[i] = l.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
request := &maps.DistanceMatrixRequest{
|
|
||||||
Mode: maps.TravelModeTransit,
|
|
||||||
Units: maps.UnitsMetric,
|
|
||||||
Origins: origins,
|
|
||||||
|
|
||||||
Destinations: []string{
|
|
||||||
"Schiphol Airport",
|
|
||||||
"Amsterdam Centraal",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := client.DistanceMatrix(ctx, request)
|
|
||||||
failOn(err, "could not retrieve distance matrix:")
|
|
||||||
|
|
||||||
for idx, addr := range response.OriginAddresses {
|
|
||||||
result := LocationResult{
|
|
||||||
Address: addr,
|
|
||||||
URL: listings[idx].URL,
|
|
||||||
Schiphol: response.Rows[idx].Elements[0],
|
|
||||||
Centraal: response.Rows[idx].Elements[1],
|
|
||||||
}
|
|
||||||
|
|
||||||
j, _ := json.Marshal(result)
|
|
||||||
fmt.Println(string(j))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var listings []Listing
|
|
||||||
input, err := ioutil.ReadFile("fun/amsterdump/input.json")
|
|
||||||
failOn(err, "could not read input file:")
|
|
||||||
|
|
||||||
err = json.Unmarshal(input, &listings)
|
|
||||||
failOn(err, "could not deserialise listings:")
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
apiKey := os.Getenv("MAPS_API_KEY")
|
|
||||||
if apiKey == "" {
|
|
||||||
log.Fatalln("API key must be supplied via MAPS_API_KEY")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := maps.NewClient(maps.WithAPIKey(apiKey))
|
|
||||||
failOn(err, "could not create Google Maps API client:")
|
|
||||||
|
|
||||||
var chunk []Listing
|
|
||||||
for _, l := range listings {
|
|
||||||
if len(chunk) == 25 {
|
|
||||||
requestMatrix(ctx, client, chunk)
|
|
||||||
chunk = []Listing{}
|
|
||||||
} else {
|
|
||||||
chunk = append(chunk, l)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(chunk) > 1 {
|
|
||||||
requestMatrix(ctx, client, chunk)
|
|
||||||
}
|
|
||||||
}
|
|
25
third_party/tvl/fun/amsterdump/scrape.el
vendored
25
third_party/tvl/fun/amsterdump/scrape.el
vendored
|
@ -1,25 +0,0 @@
|
||||||
;; Scraping funda.nl (this file is just notes and snippets, not full code)
|
|
||||||
;;
|
|
||||||
;; Begin by copying whole page into buffer (out of inspect element
|
|
||||||
;; because encoding is difficult)
|
|
||||||
|
|
||||||
(beginning-of-buffer)
|
|
||||||
|
|
||||||
;; zap everything that isn't a relevant result
|
|
||||||
(keep-lines "data-object-url-tracking\\|img alt")
|
|
||||||
|
|
||||||
;; mark all spans, move them to the end of the buffer
|
|
||||||
(cl-letf (((symbol-function 'read-regexp)
|
|
||||||
(lambda (&rest _) "</span>")))
|
|
||||||
(mc/mark-all-in-region-regexp (point-min) (point-max)))
|
|
||||||
|
|
||||||
;; mark all images lines (these contain street addresses for things
|
|
||||||
;; with images), clear up and join with previous
|
|
||||||
;;
|
|
||||||
;; mark all: data-image-error-fallback
|
|
||||||
|
|
||||||
;; delete all lines that don't either contain a span or an img tag
|
|
||||||
;; (there are duplicates)
|
|
||||||
(keep-lines "span class\\|img alt")
|
|
||||||
|
|
||||||
;; do some manual cleanup from the hrefs and done
|
|
22
third_party/tvl/fun/aoc2019/default.nix
vendored
22
third_party/tvl/fun/aoc2019/default.nix
vendored
|
@ -1,22 +0,0 @@
|
||||||
# Solutions for Advent of Code 2019, written in Emacs Lisp.
|
|
||||||
#
|
|
||||||
# For each day a new file is created as "solution-day$n.el".
|
|
||||||
{ depot, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (builtins) attrNames filter head listToAttrs match readDir;
|
|
||||||
dir = readDir ./.;
|
|
||||||
matchSolution = match "solution-(.*)\.el";
|
|
||||||
isSolution = f: (matchSolution f) != null;
|
|
||||||
getDay = f: head (matchSolution f);
|
|
||||||
|
|
||||||
solutionFiles = filter (e: dir."${e}" == "regular" && isSolution e) (attrNames dir);
|
|
||||||
solutions = map (f: let day = getDay f; in {
|
|
||||||
name = day;
|
|
||||||
value = depot.writeElispBin { # TODO(tazjin): move writeElispBin to depot.nix
|
|
||||||
name = "aoc2019";
|
|
||||||
deps = p: with p; [ dash s ht ];
|
|
||||||
src = ./. + ("/" + f);
|
|
||||||
};
|
|
||||||
}) solutionFiles;
|
|
||||||
in listToAttrs solutions
|
|
57
third_party/tvl/fun/clbot/clbot.go
vendored
57
third_party/tvl/fun/clbot/clbot.go
vendored
|
@ -6,6 +6,7 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -27,17 +28,20 @@ var (
|
||||||
gerritAuthUsername = flag.String("gerrit_ssh_auth_username", "", "Gerrit SSH username")
|
gerritAuthUsername = flag.String("gerrit_ssh_auth_username", "", "Gerrit SSH username")
|
||||||
gerritAuthKeyPath = flag.String("gerrit_ssh_auth_key", "", "Gerrit SSH private key path")
|
gerritAuthKeyPath = flag.String("gerrit_ssh_auth_key", "", "Gerrit SSH private key path")
|
||||||
|
|
||||||
ircServer = flag.String("irc_server", "chat.freenode.net:7000", "IRC server to connect to")
|
ircServer = flag.String("irc_server", "irc.hackint.org:6697", "IRC server to connect to")
|
||||||
|
ircTls = flag.Bool("irc_tls", false, "Does the server connection need TLS?")
|
||||||
ircNick = flag.String("irc_nick", "clbot", "Nick to use when connecting to IRC")
|
ircNick = flag.String("irc_nick", "clbot", "Nick to use when connecting to IRC")
|
||||||
ircUser = flag.String("irc_user", "clbot", "User string to use for IRC")
|
ircUser = flag.String("irc_user", "clbot", "User string to use for IRC")
|
||||||
ircName = flag.String("irc_name", "clbot", "Name string to use for IRC")
|
ircName = flag.String("irc_name", "clbot", "Name string to use for IRC")
|
||||||
ircChannel = flag.String("irc_channel", "##tvl", "Channel to send messages to")
|
ircChannel = flag.String("irc_channel", "#tvl", "Channel to send messages to")
|
||||||
ircPassword = flag.String("irc_pass", "", "Password to use for IRC")
|
ircPassword = flag.String("irc_pass", "", "Password to use for IRC")
|
||||||
ircSendLimit = flag.Duration("irc_send_limit", 100*time.Millisecond, "Delay between messages")
|
ircSendLimit = flag.Duration("irc_send_limit", 100*time.Millisecond, "Delay between messages")
|
||||||
ircSendBurst = flag.Int("irc_send_burst", 10, "Number of messages which can be sent in a burst")
|
ircSendBurst = flag.Int("irc_send_burst", 10, "Number of messages which can be sent in a burst")
|
||||||
|
|
||||||
notifyRepo = flag.String("notify_repo", "depot", "Repo name to notify about")
|
notifyRepo = flag.String("notify_repo", "depot", "Repo name to notify about")
|
||||||
notifyBranches = stringSetFlag{}
|
notifyBranches = stringSetFlag{}
|
||||||
|
|
||||||
|
neverPing = flag.String("never_ping", "marcus", "Comma-separated terms that should never ping users")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -111,11 +115,21 @@ func runIRC(ctx context.Context, ircCfg irc.ClientConfig, sendMsg <-chan string)
|
||||||
|
|
||||||
(func() {
|
(func() {
|
||||||
connectedStart := time.Now()
|
connectedStart := time.Now()
|
||||||
ircConn, err := tls.Dial("tcp", *ircServer, nil)
|
|
||||||
|
var ircConn net.Conn
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if *ircTls {
|
||||||
|
ircConn, err = tls.Dial("tcp", *ircServer, nil)
|
||||||
|
} else {
|
||||||
|
ircConn, err = net.Dial("tcp", *ircServer)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("connecting to IRC at tcp/%s: %v", *ircServer, err)
|
log.Errorf("connecting to IRC at tcp/%s (tls: %v): %v", *ircServer, *ircTls, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ircClient := irc.NewClient(ircConn, ircCfg)
|
ircClient := irc.NewClient(ircConn, ircCfg)
|
||||||
ircClientCtx, cancel := context.WithCancel(ctx)
|
ircClientCtx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -144,11 +158,11 @@ func runIRC(ctx context.Context, ircCfg irc.ClientConfig, sendMsg <-chan string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func username(p gerritevents.PatchSet) string {
|
func username(a gerritevents.Account) string {
|
||||||
options := []string{
|
options := []string{
|
||||||
p.Uploader.Username,
|
a.Username,
|
||||||
p.Uploader.Name,
|
a.Name,
|
||||||
p.Uploader.Email,
|
a.Email,
|
||||||
}
|
}
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
if opt != "" {
|
if opt != "" {
|
||||||
|
@ -165,6 +179,20 @@ func noping(user string) string {
|
||||||
return string(un[0:1]) + zeroWidthSpace + string(un[1:])
|
return string(un[0:1]) + zeroWidthSpace + string(un[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply noping to each instance of the username in the supplied
|
||||||
|
// message. With this users will not be pinged for their own CLs, but
|
||||||
|
// they will be notified if someone else writes a CL that includes
|
||||||
|
// their username.
|
||||||
|
//
|
||||||
|
// Also applies noping to all instances of the words in `neverPing`.
|
||||||
|
func nopingAll(username, message string) string {
|
||||||
|
for _, word := range strings.Split(*neverPing, ",") {
|
||||||
|
message = strings.ReplaceAll(message, word, noping(word))
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.ReplaceAll(message, username, noping(username))
|
||||||
|
}
|
||||||
|
|
||||||
func patchSetURL(c gerritevents.Change, p gerritevents.PatchSet) string {
|
func patchSetURL(c gerritevents.Change, p gerritevents.PatchSet) string {
|
||||||
return fmt.Sprintf("https://cl.tvl.fyi/%d", c.Number)
|
return fmt.Sprintf("https://cl.tvl.fyi/%d", c.Number)
|
||||||
}
|
}
|
||||||
|
@ -223,12 +251,21 @@ func main() {
|
||||||
if e.Change.Project != *notifyRepo || !notifyBranches[e.Change.Branch] || e.PatchSet.Number != 1 {
|
if e.Change.Project != *notifyRepo || !notifyBranches[e.Change.Branch] || e.PatchSet.Number != 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
parsedMsg = fmt.Sprintf("CL/%d: %q proposed by %s - %s", e.Change.Number, e.Change.Subject, noping(username(e.PatchSet)), patchSetURL(e.Change, e.PatchSet))
|
user := username(e.PatchSet.Uploader)
|
||||||
|
parsedMsg = nopingAll(user, fmt.Sprintf("CL/%d proposed by %s - %s - %s", e.Change.Number, user, e.Change.Subject, patchSetURL(e.Change, e.PatchSet)))
|
||||||
case *gerritevents.ChangeMerged:
|
case *gerritevents.ChangeMerged:
|
||||||
if e.Change.Project != *notifyRepo || !notifyBranches[e.Change.Branch] {
|
if e.Change.Project != *notifyRepo || !notifyBranches[e.Change.Branch] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
parsedMsg = fmt.Sprintf("CL/%d: %q applied by %s - %s", e.Change.Number, e.Change.Subject, noping(username(e.PatchSet)), patchSetURL(e.Change, e.PatchSet))
|
owner := username(e.Change.Owner)
|
||||||
|
submitter := e.Submitter.Username
|
||||||
|
url := patchSetURL(e.Change, e.PatchSet)
|
||||||
|
|
||||||
|
if submitter != owner && submitter == "clbot" {
|
||||||
|
parsedMsg = nopingAll(owner, fmt.Sprintf("CL/%d by %s autosubmitted - %s - %s", e.Change.Number, owner, e.Change.Subject, url))
|
||||||
|
} else {
|
||||||
|
parsedMsg = nopingAll(owner, fmt.Sprintf("CL/%d applied by %s - %s - %s", e.Change.Number, owner, e.Change.Subject, url))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if parsedMsg != "" {
|
if parsedMsg != "" {
|
||||||
sendMsgChan <- parsedMsg
|
sendMsgChan <- parsedMsg
|
||||||
|
|
|
@ -4,17 +4,17 @@ use std::rc::Rc;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
struct Defer<F: Fn()> {
|
struct Defer<F: Fn()> {
|
||||||
f: F
|
f: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <F: Fn()> Drop for Defer<F> {
|
impl<F: Fn()> Drop for Defer<F> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
(self.f)()
|
(self.f)()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only added this for Go-syntax familiarity ;-)
|
// Only added this for Go-syntax familiarity ;-)
|
||||||
fn defer<F: Fn()>(f: F) -> Defer<F> {
|
fn defer<F: Fn()>(f: F) -> Defer<F> {
|
||||||
Defer { f }
|
Defer { f }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@ type ErrorHandle<T> = Rc<RwLock<Option<T>>>;
|
||||||
///////////////////
|
///////////////////
|
||||||
|
|
||||||
#[derive(Debug)] // Debug trait for some default way to print the type.
|
#[derive(Debug)] // Debug trait for some default way to print the type.
|
||||||
enum Error { DropError }
|
enum Error {
|
||||||
|
DropError,
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Create a place to store the error.
|
// Create a place to store the error.
|
||||||
|
@ -60,7 +62,7 @@ fn main() {
|
||||||
|
|
||||||
match *drop_err.read().unwrap() {
|
match *drop_err.read().unwrap() {
|
||||||
Some(ref err) => println!("Oh no, an error occured: {:?}!", err),
|
Some(ref err) => println!("Oh no, an error occured: {:?}!", err),
|
||||||
None => println!("Phew, everything went well.")
|
None => println!("Phew, everything went well."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
// Go's defer in Rust!
|
// Go's defer in Rust!
|
||||||
|
|
||||||
struct Defer<F: Fn()> {
|
struct Defer<F: Fn()> {
|
||||||
f: F
|
f: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <F: Fn()> Drop for Defer<F> {
|
impl<F: Fn()> Drop for Defer<F> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
(self.f)()
|
(self.f)()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only added this for Go-syntax familiarity ;-)
|
// Only added this for Go-syntax familiarity ;-)
|
||||||
fn defer<F: Fn()>(f: F) -> Defer<F> {
|
fn defer<F: Fn()>(f: F) -> Defer<F> {
|
||||||
Defer { f }
|
Defer { f }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// Go's defer in Rust, with a little twist!
|
// Go's defer in Rust, with a little twist!
|
||||||
|
|
||||||
struct Defer<F: Fn()> {
|
struct Defer<F: Fn()> {
|
||||||
f: F
|
f: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <F: Fn()> Drop for Defer<F> {
|
impl<F: Fn()> Drop for Defer<F> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
(self.f)()
|
(self.f)()
|
||||||
}
|
}
|
||||||
|
|
15
third_party/tvl/fun/gemma/default.nix
vendored
15
third_party/tvl/fun/gemma/default.nix
vendored
|
@ -1,8 +1,8 @@
|
||||||
{ depot, ... }:
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (depot) elmPackages;
|
inherit (pkgs) cacert iana-etc libredirect stdenv runCommandNoCC writeText;
|
||||||
inherit (depot.third_party) cacert iana-etc libredirect stdenv runCommandNoCC writeText;
|
elmPackages = depot.third_party.elmPackages_0_18;
|
||||||
|
|
||||||
frontend = stdenv.mkDerivation {
|
frontend = stdenv.mkDerivation {
|
||||||
name = "gemma-frontend.html";
|
name = "gemma-frontend.html";
|
||||||
|
@ -33,7 +33,8 @@ let
|
||||||
cp ${frontend} $out/index.html
|
cp ${frontend} $out/index.html
|
||||||
''}/")
|
''}/")
|
||||||
'';
|
'';
|
||||||
in depot.nix.buildLisp.program {
|
in
|
||||||
|
depot.nix.buildLisp.program {
|
||||||
name = "gemma";
|
name = "gemma";
|
||||||
|
|
||||||
deps = with depot.third_party.lisp; [
|
deps = with depot.third_party.lisp; [
|
||||||
|
@ -47,4 +48,10 @@ in depot.nix.buildLisp.program {
|
||||||
./src/gemma.lisp
|
./src/gemma.lisp
|
||||||
injectFrontend
|
injectFrontend
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# depends on SBCL
|
||||||
|
brokenOn = [
|
||||||
|
"ccl"
|
||||||
|
"ecl"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
17
third_party/tvl/fun/idual/default.nix
vendored
17
third_party/tvl/fun/idual/default.nix
vendored
|
@ -1,22 +1,23 @@
|
||||||
{ pkgs, lib, ... }:
|
{ depot, pkgs, lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (pkgs) python python3 python3Packages;
|
inherit (pkgs) python3 python3Packages;
|
||||||
|
|
||||||
opts = {
|
opts = {
|
||||||
pname = "idualctl";
|
pname = "idualctl";
|
||||||
version = "0.1";
|
version = "0.1";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
|
|
||||||
propagatedBuildInputs = [
|
propagatedBuildInputs = [
|
||||||
python.broadlink
|
depot.third_party.python.broadlink
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
package = python3Packages.buildPythonPackage opts;
|
package = python3Packages.buildPythonPackage opts;
|
||||||
script = python3Packages.buildPythonApplication opts;
|
script = python3Packages.buildPythonApplication opts;
|
||||||
in {
|
in
|
||||||
|
depot.nix.readTree.drvTargets {
|
||||||
inherit script;
|
inherit script;
|
||||||
python = python3.withPackages (_: [ package ]);
|
python = python3.withPackages (_: [ package ]);
|
||||||
setAlarm = pkgs.writeShellScriptBin "set-alarm" ''
|
setAlarm = pkgs.writeShellScriptBin "set-alarm" ''
|
||||||
echo "setting an alarm for ''${1}"
|
echo "setting an alarm for ''${1}"
|
||||||
${pkgs.systemd}/bin/systemd-run --user --on-calendar="''${1} Europe/London" --unit=light-alarm.service
|
${pkgs.systemd}/bin/systemd-run --user --on-calendar="''${1} Europe/London" --unit=light-alarm.service
|
||||||
|
|
BIN
third_party/tvl/fun/logo/depot-logo.png
vendored
BIN
third_party/tvl/fun/logo/depot-logo.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
BIN
third_party/tvl/fun/logo/depot-logo.xcf
vendored
BIN
third_party/tvl/fun/logo/depot-logo.xcf
vendored
Binary file not shown.
13
third_party/tvl/fun/owothia/default.nix
vendored
Normal file
13
third_party/tvl/fun/owothia/default.nix
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{ depot ? (import ../../../. { })
|
||||||
|
, pkgs ? depot.third_party.nixpkgs
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
basePkg = pkgs.haskellPackages.callPackage ./pkg.nix { };
|
||||||
|
in
|
||||||
|
|
||||||
|
pkgs.haskell.lib.overrideSrc basePkg {
|
||||||
|
src = depot.third_party.gitignoreSource ./.;
|
||||||
|
version = "canon";
|
||||||
|
}
|
34
third_party/tvl/fun/owothia/pkg.nix
vendored
Normal file
34
third_party/tvl/fun/owothia/pkg.nix
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{ mkDerivation
|
||||||
|
, base
|
||||||
|
, bytestring
|
||||||
|
, chatter
|
||||||
|
, containers
|
||||||
|
, envy
|
||||||
|
, irc-client
|
||||||
|
, lens
|
||||||
|
, lib
|
||||||
|
, random
|
||||||
|
, relude
|
||||||
|
, text
|
||||||
|
}:
|
||||||
|
mkDerivation {
|
||||||
|
pname = "owothia";
|
||||||
|
version = "0.0.1.0";
|
||||||
|
src = ./.;
|
||||||
|
isLibrary = false;
|
||||||
|
isExecutable = true;
|
||||||
|
executableHaskellDepends = [
|
||||||
|
base
|
||||||
|
bytestring
|
||||||
|
chatter
|
||||||
|
containers
|
||||||
|
envy
|
||||||
|
irc-client
|
||||||
|
lens
|
||||||
|
random
|
||||||
|
relude
|
||||||
|
text
|
||||||
|
];
|
||||||
|
license = "unknown";
|
||||||
|
hydraPlatforms = lib.platforms.none;
|
||||||
|
}
|
22
third_party/tvl/fun/owothia/shell.nix
vendored
Normal file
22
third_party/tvl/fun/owothia/shell.nix
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{ pkgs ? (import ../../../. { }).third_party, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (pkgs)
|
||||||
|
haskellPackages
|
||||||
|
haskell
|
||||||
|
gitignoreSource
|
||||||
|
;
|
||||||
|
in
|
||||||
|
|
||||||
|
(haskellPackages.extend (haskell.lib.packageSourceOverrides {
|
||||||
|
owothia = gitignoreSource ./.;
|
||||||
|
})).shellFor {
|
||||||
|
packages = p: [ p.owothia ];
|
||||||
|
withHoogle = true;
|
||||||
|
doBenchmark = true;
|
||||||
|
buildInputs = with haskellPackages; [
|
||||||
|
cabal-install
|
||||||
|
hlint
|
||||||
|
haskell-language-server
|
||||||
|
];
|
||||||
|
}
|
168
third_party/tvl/fun/owothia/src/Main.hs
vendored
Normal file
168
third_party/tvl/fun/owothia/src/Main.hs
vendored
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import Network.IRC.Client
|
||||||
|
import Control.Lens
|
||||||
|
import NLP.POS
|
||||||
|
import NLP.Types (POSTagger)
|
||||||
|
import qualified NLP.Types.Tags as Tags
|
||||||
|
import NLP.Types.Tree
|
||||||
|
import qualified NLP.Corpora.Conll as Conll
|
||||||
|
import NLP.Corpora.Conll (Tag)
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
import System.Random
|
||||||
|
import System.Envy
|
||||||
|
import System.IO as S
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.Foldable (traverse_)
|
||||||
|
import qualified Data.Text
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
data Config = Config
|
||||||
|
{ _owoChance :: Int
|
||||||
|
, _ircServer :: ByteString
|
||||||
|
, _ircPort :: Int
|
||||||
|
, _ircServerPassword :: Maybe Text
|
||||||
|
, _nickservPassword :: Maybe Text
|
||||||
|
, _ircNick :: Maybe Text
|
||||||
|
, _ircIdent :: Maybe Text
|
||||||
|
, _ircChannels :: [Text]
|
||||||
|
}
|
||||||
|
deriving stock (Show, Eq, Generic)
|
||||||
|
makeLenses ''Config
|
||||||
|
|
||||||
|
instance Var [Text] where
|
||||||
|
toVar ts = show ts
|
||||||
|
fromVar s = readMaybe s >>= (pure . map Data.Text.pack)
|
||||||
|
|
||||||
|
instance FromEnv Config where
|
||||||
|
fromEnv _ =
|
||||||
|
Config <$> env "OWO_CHANCE"
|
||||||
|
<*> env "IRC_SERVER"
|
||||||
|
<*> env "IRC_PORT"
|
||||||
|
<*> envMaybe "IRC_SERVER_PASSWORD"
|
||||||
|
<*> envMaybe "NICKSERV_PASSWORD"
|
||||||
|
<*> envMaybe "IRC_NICK"
|
||||||
|
<*> envMaybe "IRC_IDENT"
|
||||||
|
<*> env "IRC_CHANNELS"
|
||||||
|
|
||||||
|
stopWord :: Text -> Bool
|
||||||
|
stopWord "'s" = True
|
||||||
|
stopWord "\"" = True
|
||||||
|
stopWord "is" = True
|
||||||
|
stopWord "are" = True
|
||||||
|
stopWord "am" = True
|
||||||
|
stopWord "were" = True
|
||||||
|
stopWord "was" = True
|
||||||
|
stopWord "be" = True
|
||||||
|
stopWord _ = False
|
||||||
|
|
||||||
|
pickVerb :: POS Tag -> Maybe Text
|
||||||
|
pickVerb (POS Conll.VB (Token verb)) = Just verb
|
||||||
|
pickVerb (POS Conll.VBD (Token verb)) = Just verb
|
||||||
|
pickVerb (POS Conll.VBG (Token verb)) = Just verb
|
||||||
|
pickVerb (POS Conll.VBN (Token verb)) = Just verb
|
||||||
|
pickVerb (POS Conll.VBZ (Token verb)) = Just verb
|
||||||
|
pickVerb _ = Nothing
|
||||||
|
|
||||||
|
pickNoun :: POS Tag -> Maybe Text
|
||||||
|
pickNoun (POS Conll.NN (Token noun)) = Just noun
|
||||||
|
pickNoun _ = Nothing
|
||||||
|
|
||||||
|
randomPOS
|
||||||
|
:: Tags.Tag tag
|
||||||
|
=> (POS tag -> Maybe Text)
|
||||||
|
-> POSTagger tag
|
||||||
|
-> Text
|
||||||
|
-> IO (Maybe Text)
|
||||||
|
randomPOS pickPOS tagger s = do
|
||||||
|
let candidates
|
||||||
|
= filter (not . stopWord)
|
||||||
|
. mapMaybe pickPOS
|
||||||
|
$ tag tagger s >>= \(TaggedSent ps) -> ps
|
||||||
|
i <- randomRIO (0, length candidates - 1)
|
||||||
|
pure $ candidates ^? ix i
|
||||||
|
|
||||||
|
doOwo :: MonadIO m => Config -> m Bool
|
||||||
|
doOwo conf = do
|
||||||
|
n <- liftIO (randomRIO @Int (0, conf ^. owoChance))
|
||||||
|
pure $ n == 0
|
||||||
|
|
||||||
|
data OwoType = Noun | Verb
|
||||||
|
deriving stock (Show, Eq)
|
||||||
|
|
||||||
|
instance Random OwoType where
|
||||||
|
random = over _1 (bool Noun Verb) . random
|
||||||
|
randomR = const random
|
||||||
|
|
||||||
|
vowels :: [Char]
|
||||||
|
vowels = "aeiou"
|
||||||
|
|
||||||
|
article :: Text -> Text
|
||||||
|
article (x :< _) | x `elem` vowels = "an"
|
||||||
|
article _ = "a"
|
||||||
|
|
||||||
|
owo :: OwoType -> Text -> Text
|
||||||
|
owo Noun n = mconcat
|
||||||
|
[ "I'm "
|
||||||
|
, article n
|
||||||
|
, " "
|
||||||
|
, n
|
||||||
|
, if "o" `Data.Text.isSuffixOf` n
|
||||||
|
then "wo"
|
||||||
|
else " owo"
|
||||||
|
]
|
||||||
|
owo Verb v = v <> " me owo"
|
||||||
|
|
||||||
|
pickOwo :: OwoType -> POS Tag -> Maybe Text
|
||||||
|
pickOwo Verb = pickVerb
|
||||||
|
pickOwo Noun = pickNoun
|
||||||
|
|
||||||
|
randomOwo :: OwoType -> POSTagger Tag -> Text -> IO (Maybe Text)
|
||||||
|
randomOwo = randomPOS . pickOwo
|
||||||
|
|
||||||
|
owothiaHandler :: Config -> Text -> IORef Bool -> POSTagger Tag -> EventHandler s
|
||||||
|
owothiaHandler conf nick state tagger = EventHandler Just $ \src ev -> do
|
||||||
|
hasIdentified <- readIORef state
|
||||||
|
when (not hasIdentified) $ do
|
||||||
|
nickservAuth
|
||||||
|
traverse_ (send . Join) (conf ^. ircChannels)
|
||||||
|
writeIORef state True
|
||||||
|
|
||||||
|
when ("You are now identified" `BS.isInfixOf` (ev ^. raw)) $
|
||||||
|
traverse_ (send . Join) (conf ^. ircChannels)
|
||||||
|
|
||||||
|
case (src, ev ^. message) of
|
||||||
|
(Channel chan nick, Privmsg _ (Right m)) -> do
|
||||||
|
willOwo <- doOwo conf
|
||||||
|
when willOwo $ owoMessage chan m
|
||||||
|
_ -> pure()
|
||||||
|
|
||||||
|
pure ()
|
||||||
|
|
||||||
|
where
|
||||||
|
owoMessage chan m = do
|
||||||
|
owoType <- liftIO randomIO
|
||||||
|
mWord <- liftIO $ randomOwo owoType tagger m
|
||||||
|
for_ mWord $ \word -> send $ Privmsg chan $ Right $ owo owoType word
|
||||||
|
nickservAuthMsg = "IDENTIFY " <> nick <> " " <> fromJust (conf ^. nickservPassword)
|
||||||
|
nickservAuth = send $ Privmsg "NickServ" $ Right nickservAuthMsg
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
conf <- either fail pure =<< decodeEnv
|
||||||
|
tagger <- defaultTagger
|
||||||
|
state <- newIORef $ not . isJust $ (conf ^. nickservPassword)
|
||||||
|
S.hSetBuffering stdout LineBuffering
|
||||||
|
let nick = fromMaybe "owothia" (conf ^. ircNick)
|
||||||
|
conn =
|
||||||
|
plainConnection (conf ^. ircServer) (conf ^. ircPort)
|
||||||
|
& realname .~ "Owothia Revströwö"
|
||||||
|
& password .~ (conf ^. ircServerPassword)
|
||||||
|
& username .~ fromMaybe "owothia" (conf ^. ircIdent)
|
||||||
|
& logfunc .~ stdoutLogger
|
||||||
|
cfg =
|
||||||
|
defaultInstanceConfig nick
|
||||||
|
& channels .~ (conf ^. ircChannels)
|
||||||
|
& handlers %~ (owothiaHandler conf nick state tagger : )
|
||||||
|
runClient conn cfg ()
|
1336
third_party/tvl/fun/paroxysm/Cargo.lock
generated
vendored
1336
third_party/tvl/fun/paroxysm/Cargo.lock
generated
vendored
File diff suppressed because it is too large
Load diff
7
third_party/tvl/fun/paroxysm/default.nix
vendored
7
third_party/tvl/fun/paroxysm/default.nix
vendored
|
@ -1,9 +1,6 @@
|
||||||
{ depot, ... }:
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
let
|
depot.third_party.naersk.buildPackage {
|
||||||
pkgs = depot.third_party;
|
|
||||||
in
|
|
||||||
pkgs.naersk.buildPackage {
|
|
||||||
name = "paroxysm";
|
name = "paroxysm";
|
||||||
version = "0.0.2";
|
version = "0.0.2";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{ depot, ... }:
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
depot.third_party.dockerTools.buildLayeredImage {
|
pkgs.dockerTools.buildLayeredImage {
|
||||||
name = "paroxysm";
|
name = "paroxysm";
|
||||||
contents = [ depot.fun.paroxysm ];
|
contents = [ depot.fun.paroxysm ];
|
||||||
config.Entrypoint = [ "${depot.fun.paroxysm}/bin/paroxysm" ];
|
config.Entrypoint = [ "${depot.fun.paroxysm}/bin/paroxysm" ];
|
||||||
|
|
3
third_party/tvl/fun/paroxysm/src/keyword.rs
vendored
3
third_party/tvl/fun/paroxysm/src/keyword.rs
vendored
|
@ -1,8 +1,7 @@
|
||||||
use crate::models::{Entry, Keyword, NewEntry, NewKeyword};
|
use crate::models::{Entry, Keyword, NewEntry, NewKeyword};
|
||||||
use diesel::pg::PgConnection;
|
use diesel::pg::PgConnection;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use failure::format_err;
|
use failure::{format_err, Error};
|
||||||
use failure::Error;
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
/// Maximum number of times we'll follow a `see: ` pointer.
|
/// Maximum number of times we'll follow a `see: ` pointer.
|
||||||
|
|
20
third_party/tvl/fun/paroxysm/src/main.rs
vendored
20
third_party/tvl/fun/paroxysm/src/main.rs
vendored
|
@ -7,8 +7,7 @@ use crate::cfg::Config;
|
||||||
use crate::keyword::KeywordDetails;
|
use crate::keyword::KeywordDetails;
|
||||||
use diesel::pg::PgConnection;
|
use diesel::pg::PgConnection;
|
||||||
use diesel::r2d2::{ConnectionManager, Pool};
|
use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
use failure::format_err;
|
use failure::{format_err, Error};
|
||||||
use failure::Error;
|
|
||||||
use irc::client::prelude::*;
|
use irc::client::prelude::*;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::{debug, info, warn};
|
use log::{debug, info, warn};
|
||||||
|
@ -153,8 +152,9 @@ impl App {
|
||||||
// Use `nick` here, so things like "grfn: see glittershark" work.
|
// Use `nick` here, so things like "grfn: see glittershark" work.
|
||||||
let val = if let Some(last) = chan_lastmsgs.get(nick_to_grab) {
|
let val = if let Some(last) = chan_lastmsgs.get(nick_to_grab) {
|
||||||
if last.starts_with("\x01ACTION ") {
|
if last.starts_with("\x01ACTION ") {
|
||||||
// Yes, this is inefficient, but it's better than writing some hacky CTCP parsing code
|
// Yes, this is inefficient, but it's better than writing some hacky CTCP parsing
|
||||||
// I guess (also, characters are hard, so just blindly slicing seems like a bad idea)
|
// code I guess (also, characters are hard, so just blindly slicing
|
||||||
|
// seems like a bad idea)
|
||||||
format!(
|
format!(
|
||||||
"* {} {}",
|
"* {} {}",
|
||||||
nick_to_grab,
|
nick_to_grab,
|
||||||
|
@ -208,7 +208,7 @@ impl App {
|
||||||
pub fn handle_query(
|
pub fn handle_query(
|
||||||
&mut self,
|
&mut self,
|
||||||
target: &str,
|
target: &str,
|
||||||
nick: &str,
|
_nick: &str,
|
||||||
chan: &str,
|
chan: &str,
|
||||||
query: Captures,
|
query: Captures,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
@ -239,7 +239,7 @@ impl App {
|
||||||
}
|
}
|
||||||
// step 2: attempt to POST it to eta's pastebin
|
// step 2: attempt to POST it to eta's pastebin
|
||||||
// TODO(eta): make configurable
|
// TODO(eta): make configurable
|
||||||
let response = crimp::Request::put("https://theta.eu.org/lx/upload")
|
let response = crimp::Request::put("https://eta.st/lx/upload")
|
||||||
.user_agent("paroxysm/0.0.2 crimp/0.2")?
|
.user_agent("paroxysm/0.0.2 crimp/0.2")?
|
||||||
.header("Linx-Expiry", "7200")? // 2 hours
|
.header("Linx-Expiry", "7200")? // 2 hours
|
||||||
.body("text/plain", data_to_upload.as_bytes())
|
.body("text/plain", data_to_upload.as_bytes())
|
||||||
|
@ -301,8 +301,12 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.client
|
// If someone just posts "??????????", don't spam the channel with
|
||||||
.send_notice(target, format!("\x02{}\x0f: never heard of it", subj))?;
|
// an error message (but do allow joke entries to appear if set).
|
||||||
|
if !subj.chars().all(|c| c == '?' || c == ' ') {
|
||||||
|
self.client
|
||||||
|
.send_notice(target, format!("\x02{}\x0f: never heard of it", subj))?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
19
third_party/tvl/fun/streamTVL/default.nix
vendored
19
third_party/tvl/fun/streamTVL/default.nix
vendored
|
@ -1,19 +0,0 @@
|
||||||
{ depot, ... }:
|
|
||||||
|
|
||||||
depot.third_party.writeShellScriptBin "start-tvl-stream" ''
|
|
||||||
env LD_LIBRARY_PATH=/run/opengl-driver/lib/ ${depot.third_party.ffmpeg}/bin/ffmpeg \
|
|
||||||
-vsync 0 \
|
|
||||||
-hwaccel cuvid \
|
|
||||||
-init_hw_device cuda=0 -filter_hw_device 0 \
|
|
||||||
-f x11grab \
|
|
||||||
-video_size 1920x1080 \
|
|
||||||
-framerate 60 \
|
|
||||||
-thread_queue_size 256 \
|
|
||||||
-i :0.0+0,0 \
|
|
||||||
-filter:v "format=nv12,hwupload,scale_npp=w=1280:h=720:interp_algo=lanczos" \
|
|
||||||
-c:v h264_nvenc \
|
|
||||||
-preset:v llhq \
|
|
||||||
-rc:v cbr_ld_hq \
|
|
||||||
-an \
|
|
||||||
-f flv rtmp://tazj.in:1935/tvl
|
|
||||||
''
|
|
|
@ -20,7 +20,8 @@ type incomingIRC struct {
|
||||||
User string `json:"User"`
|
User string `json:"User"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var supressionUsernames map[string]bool
|
var suppressionUsernames map[string]bool
|
||||||
|
var noMkov map[string]bool
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
redisc := redis.NewClient(&redis.Options{
|
redisc := redis.NewClient(&redis.Options{
|
||||||
|
@ -30,7 +31,27 @@ func main() {
|
||||||
})
|
})
|
||||||
|
|
||||||
fireaway := make(chan incomingIRC, 10)
|
fireaway := make(chan incomingIRC, 10)
|
||||||
supressionUsernames = make(map[string]bool)
|
suppressionUsernames = make(map[string]bool)
|
||||||
|
|
||||||
|
suppressionList := redisc.HGetAll("suppressionList")
|
||||||
|
suppressionListA, _ := suppressionList.Result()
|
||||||
|
|
||||||
|
suppressionListMap, _ := stringMaptoIntMap(suppressionListA)
|
||||||
|
for v, _ := range suppressionListMap {
|
||||||
|
suppressionUsernames[v] = true
|
||||||
|
suppressionUsernames[strings.ToLower(v)] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
noMkov = make(map[string]bool)
|
||||||
|
|
||||||
|
noMkovRedis := redisc.HGetAll("nomkov")
|
||||||
|
noMkovRedisA, _ := noMkovRedis.Result()
|
||||||
|
|
||||||
|
noMkovMap, _ := stringMaptoIntMap(noMkovRedisA)
|
||||||
|
for v, _ := range noMkovMap {
|
||||||
|
noMkov[v] = true
|
||||||
|
noMkov[strings.ToLower(v)] = true
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
@ -81,8 +102,11 @@ func main() {
|
||||||
func generateMesasge(msg incomingIRC, redisc *redis.Client) string {
|
func generateMesasge(msg incomingIRC, redisc *redis.Client) string {
|
||||||
text := msg.Params[1]
|
text := msg.Params[1]
|
||||||
username := strings.ToLower(msg.Name)
|
username := strings.ToLower(msg.Name)
|
||||||
supressionUsernames[username] = true
|
suppressionUsernames[username] = true
|
||||||
supressionUsernames[username+":"] = true
|
suppressionUsernames[username+":"] = true
|
||||||
|
suppressionUsernames[msg.Name] = true
|
||||||
|
suppressionUsernames[msg.Name+":"] = true
|
||||||
|
redisc.HIncrBy("suppressionList", msg.Name, 1)
|
||||||
|
|
||||||
text = strings.ToLower(text)
|
text = strings.ToLower(text)
|
||||||
text = strings.Replace(text, ",", "", -1)
|
text = strings.Replace(text, ",", "", -1)
|
||||||
|
@ -92,16 +116,19 @@ func generateMesasge(msg incomingIRC, redisc *redis.Client) string {
|
||||||
text = strings.Replace(text, "?", "", -1)
|
text = strings.Replace(text, "?", "", -1)
|
||||||
|
|
||||||
words := strings.Split(text, " ")
|
words := strings.Split(text, " ")
|
||||||
lastWord := propwords(username, words[0], redisc)
|
lastWord := propwords(msg.Name, words[0], redisc)
|
||||||
|
|
||||||
if supressionUsernames[words[0]] {
|
if noMkov[username] {
|
||||||
if len(words[0]) < 2 {
|
lastWord = blockoutWord(lastWord)
|
||||||
words[0] = "vee"
|
words[0] = blockoutWord(words[0])
|
||||||
}
|
|
||||||
words[0] = fmt.Sprintf("%s.%s", string(words[0][0]), words[0][1:])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastWord = filterHighlights(lastWord)
|
||||||
|
|
||||||
if lastWord == "_END_" {
|
if lastWord == "_END_" {
|
||||||
|
if noMkov[username] {
|
||||||
|
return blockoutWord(words[0])
|
||||||
|
}
|
||||||
return words[0]
|
return words[0]
|
||||||
}
|
}
|
||||||
outputMsg := words[0] + " " + lastWord + " "
|
outputMsg := words[0] + " " + lastWord + " "
|
||||||
|
@ -112,13 +139,12 @@ func generateMesasge(msg incomingIRC, redisc *redis.Client) string {
|
||||||
return outputMsg
|
return outputMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
if supressionUsernames[lastWord] {
|
if noMkov[username] {
|
||||||
if len(lastWord) < 2 {
|
lastWord = blockoutWord(lastWord)
|
||||||
lastWord = "vee"
|
|
||||||
}
|
|
||||||
lastWord = fmt.Sprintf("%s.%s", string(lastWord[0]), lastWord[1:])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastWord = filterHighlights(lastWord)
|
||||||
|
|
||||||
outputMsg += lastWord + " "
|
outputMsg += lastWord + " "
|
||||||
if len(outputMsg) > 100 {
|
if len(outputMsg) > 100 {
|
||||||
return outputMsg
|
return outputMsg
|
||||||
|
@ -126,6 +152,28 @@ func generateMesasge(msg incomingIRC, redisc *redis.Client) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filterHighlights: tries to prevent highlights by checking against
|
||||||
|
// a map called suppressionUsernames
|
||||||
|
func filterHighlights(in string) string {
|
||||||
|
for username := range suppressionUsernames {
|
||||||
|
if strings.Contains(in, username) {
|
||||||
|
if len(in) < 2 {
|
||||||
|
in = fmt.Sprintf("%s.%s", string(in[0]), in[1:])
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
|
||||||
|
func blockoutWord(in string) string {
|
||||||
|
block := ""
|
||||||
|
for i := 0; i < len(in); i++ {
|
||||||
|
block += "█"
|
||||||
|
}
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
||||||
func propwords(username string, start string, redisc *redis.Client) string {
|
func propwords(username string, start string, redisc *redis.Client) string {
|
||||||
userHash := redisc.HGetAll(fmt.Sprintf("%s-%s", username, start))
|
userHash := redisc.HGetAll(fmt.Sprintf("%s-%s", username, start))
|
||||||
userHashMap, err := userHash.Result()
|
userHashMap, err := userHash.Result()
|
||||||
|
@ -190,7 +238,9 @@ func learnFromMessage(msg incomingIRC, redisc *redis.Client) {
|
||||||
nextWord = words[k+1]
|
nextWord = words[k+1]
|
||||||
}
|
}
|
||||||
|
|
||||||
redisc.HIncrBy(fmt.Sprintf("%s-%s", username, word), nextWord, 1)
|
if !noMkov[username] {
|
||||||
|
redisc.HIncrBy(fmt.Sprintf("%s-%s", username, word), nextWord, 1)
|
||||||
|
}
|
||||||
redisc.HIncrBy(fmt.Sprintf("generic-%s", word), nextWord, 1)
|
redisc.HIncrBy(fmt.Sprintf("generic-%s", word), nextWord, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
third_party/tvl/fun/uggc/default.nix
vendored
8
third_party/tvl/fun/uggc/default.nix
vendored
|
@ -1,7 +1,8 @@
|
||||||
{ depot, pkgs, ... }@args:
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (pkgs) gopkgs;
|
inherit (depot.third_party) gopkgs;
|
||||||
|
|
||||||
uggc = depot.nix.buildGo.program {
|
uggc = depot.nix.buildGo.program {
|
||||||
name = "uggc";
|
name = "uggc";
|
||||||
srcs = [
|
srcs = [
|
||||||
|
@ -11,7 +12,8 @@ let
|
||||||
gopkgs."github.com".pkg.browser.gopkg
|
gopkgs."github.com".pkg.browser.gopkg
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
in uggc.overrideAttrs(old: {
|
in
|
||||||
|
uggc.overrideAttrs (old: {
|
||||||
buildCommand = old.buildCommand + ''
|
buildCommand = old.buildCommand + ''
|
||||||
install -D ${./uggc.desktop} $out/share/applications/uggc.desktop
|
install -D ${./uggc.desktop} $out/share/applications/uggc.desktop
|
||||||
sed "s|@out@|$out|g" -i $out/share/applications/uggc.desktop
|
sed "s|@out@|$out|g" -i $out/share/applications/uggc.desktop
|
||||||
|
|
3
third_party/tvl/fun/🕰️/OWNERS
vendored
Normal file
3
third_party/tvl/fun/🕰️/OWNERS
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
inherited: true
|
||||||
|
owners:
|
||||||
|
- sterni
|
91
third_party/tvl/fun/🕰️/bin.lisp
vendored
Normal file
91
third_party/tvl/fun/🕰️/bin.lisp
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
(defpackage 🕰️.bin
|
||||||
|
(:shadow :describe)
|
||||||
|
(:use :cl :opts)
|
||||||
|
(:import-from :uiop :quit)
|
||||||
|
(:import-from :local-time
|
||||||
|
:now :timestamp-subtimezone :+utc-zone+
|
||||||
|
:*default-timezone* :define-timezone)
|
||||||
|
(:import-from :klatre :format-dottime-offset)
|
||||||
|
(:import-from :🕰️ :⌚)
|
||||||
|
(:export :🚂))
|
||||||
|
|
||||||
|
(in-package :🕰️.bin)
|
||||||
|
(declaim (optimize (safety 3)))
|
||||||
|
|
||||||
|
(opts:define-opts
|
||||||
|
(:name :help
|
||||||
|
:description "Print this help text"
|
||||||
|
:short #\h
|
||||||
|
:long "help")
|
||||||
|
(:name :dot-time
|
||||||
|
:description "Use pseudo dot-time format (implies -u)"
|
||||||
|
:short #\d
|
||||||
|
:long "dot-time")
|
||||||
|
(:name :utc
|
||||||
|
:description "Display time in UTC instead of local time"
|
||||||
|
:short #\u
|
||||||
|
:long "utc")
|
||||||
|
(:name :no-newline
|
||||||
|
:description "Don't print a trailing newline"
|
||||||
|
:short #\n
|
||||||
|
:long "no-newline"))
|
||||||
|
|
||||||
|
(defun make-slash-terminated (str)
|
||||||
|
(if (eq (char str (1- (length str))) #\/)
|
||||||
|
str
|
||||||
|
(concatenate 'string str "/")))
|
||||||
|
|
||||||
|
; TODO(sterni): upstream this into local-time
|
||||||
|
(defun setup-default-timezone ()
|
||||||
|
(let* ((tz (remove #\: (uiop:getenv "TZ") :count 1))
|
||||||
|
(tz-dir (uiop:getenv "TZDIR"))
|
||||||
|
(tz-file (if (and tz tz-dir)
|
||||||
|
(merge-pathnames
|
||||||
|
(pathname tz)
|
||||||
|
(pathname (make-slash-terminated tz-dir)))
|
||||||
|
(pathname "/etc/localtime"))))
|
||||||
|
(handler-case
|
||||||
|
(define-timezone *default-timezone* tz-file :load t)
|
||||||
|
(t () (setf *default-timezone* +utc-zone+)))))
|
||||||
|
|
||||||
|
|
||||||
|
(defun 🚂 ()
|
||||||
|
(let ((ts (now)))
|
||||||
|
(multiple-value-bind (options free-args)
|
||||||
|
(handler-case (opts:get-opts)
|
||||||
|
; only handle subset of conditions that can happen here
|
||||||
|
(opts:unknown-option (c)
|
||||||
|
(format t "error: unknown option ~s~%" (opts:option c))
|
||||||
|
(quit 100)))
|
||||||
|
|
||||||
|
; check if we have any free args we don't know what to do with
|
||||||
|
(when (> (length free-args) 0)
|
||||||
|
(write-string "error: unexpected command line argument(s): ")
|
||||||
|
(loop for arg in free-args
|
||||||
|
do (progn (write-string arg) (write-char #\space)))
|
||||||
|
(write-char #\newline)
|
||||||
|
(quit 100))
|
||||||
|
|
||||||
|
; print help and exit
|
||||||
|
(when (getf options :help)
|
||||||
|
(opts:describe :usage-of "🕰️")
|
||||||
|
(quit 0))
|
||||||
|
|
||||||
|
; reinit *default-timezone* as it is cached from compilation
|
||||||
|
(setup-default-timezone)
|
||||||
|
; dot-time implies UTC, naturally
|
||||||
|
(when (getf options :dot-time)
|
||||||
|
(setf (getf options :utc) t))
|
||||||
|
; print clock face
|
||||||
|
(format t "~A" (⌚ ts (if (getf options :utc)
|
||||||
|
local-time:+utc-zone+
|
||||||
|
local-time:*default-timezone*)))
|
||||||
|
; render dot-time offset if necessary
|
||||||
|
(when (getf options :dot-time)
|
||||||
|
(multiple-value-bind (offset-secs _dst _name)
|
||||||
|
(timestamp-subtimezone ts local-time:*default-timezone*)
|
||||||
|
(write-string
|
||||||
|
(format-dottime-offset (round (/ offset-secs 3600))))))
|
||||||
|
; write newline if necessary
|
||||||
|
(when (not (getf options :no-newline))
|
||||||
|
(write-char #\newline)))))
|
44
third_party/tvl/fun/🕰️/default.nix
vendored
Normal file
44
third_party/tvl/fun/🕰️/default.nix
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{ depot, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (depot.nix)
|
||||||
|
buildLisp
|
||||||
|
;
|
||||||
|
|
||||||
|
lib = buildLisp.library {
|
||||||
|
name = "lib🕰️";
|
||||||
|
deps = [
|
||||||
|
depot.third_party.lisp.local-time
|
||||||
|
];
|
||||||
|
|
||||||
|
srcs = [
|
||||||
|
./lib.lisp
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
bin = buildLisp.program {
|
||||||
|
name = "🕰️";
|
||||||
|
deps = [
|
||||||
|
depot.third_party.lisp.unix-opts
|
||||||
|
depot.lisp.klatre
|
||||||
|
{
|
||||||
|
default = buildLisp.bundled "asdf";
|
||||||
|
sbcl = buildLisp.bundled "uiop";
|
||||||
|
}
|
||||||
|
lib
|
||||||
|
];
|
||||||
|
|
||||||
|
srcs = [
|
||||||
|
./bin.lisp
|
||||||
|
];
|
||||||
|
|
||||||
|
main = "🕰️.bin:🚂";
|
||||||
|
|
||||||
|
brokenOn = [
|
||||||
|
"ecl" # refuses to create non-ASCII paths even on POSIX…
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
bin // {
|
||||||
|
inherit lib;
|
||||||
|
}
|
32
third_party/tvl/fun/🕰️/lib.lisp
vendored
Normal file
32
third_party/tvl/fun/🕰️/lib.lisp
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
(defpackage 🕰️
|
||||||
|
(:use :cl)
|
||||||
|
(:import-from :local-time
|
||||||
|
:timestamp-subtimezone :*default-timezone* :sec-of)
|
||||||
|
(:export :⌚))
|
||||||
|
|
||||||
|
(in-package :🕰️)
|
||||||
|
(declaim (optimize (safety 3)))
|
||||||
|
|
||||||
|
(defparameter *clock-emojis*
|
||||||
|
(vector #\🕛 #\🕧 ; 00:00 - 00:30
|
||||||
|
#\🕐 #\🕜 ; 01:00 - 01:30
|
||||||
|
#\🕑 #\🕝 ; 00:00 - 00:30
|
||||||
|
#\🕒 #\🕞 ; 00:00 - 00:30
|
||||||
|
#\🕓 #\🕟 ; 00:00 - 00:30
|
||||||
|
#\🕔 #\🕠 ; 00:00 - 00:30
|
||||||
|
#\🕕 #\🕡 ; 00:00 - 00:30
|
||||||
|
#\🕖 #\🕢 ; 00:00 - 00:30
|
||||||
|
#\🕗 #\🕣 ; 00:00 - 00:30
|
||||||
|
#\🕘 #\🕤 ; 00:00 - 00:30
|
||||||
|
#\🕙 #\🕥 ; 00:00 - 00:30
|
||||||
|
#\🕚 #\🕦)) ; 11:00 - 11:30
|
||||||
|
|
||||||
|
(defun ⌚ (timestamp &optional (tz *default-timezone*))
|
||||||
|
"Convert a LOCAL-TIME:TIMESTAMP into the nearest Unicode clock face.
|
||||||
|
Use TZ (which defaults to LOCAL-TIME:*DEFAULT-TIMEZONE*) to determine
|
||||||
|
the UTC offset to factor when determining the local clock face."
|
||||||
|
(let* ((offset (multiple-value-bind (offset-secs _dst _name)
|
||||||
|
(timestamp-subtimezone timestamp tz)
|
||||||
|
offset-secs))
|
||||||
|
(secs (+ (sec-of timestamp) offset)))
|
||||||
|
(elt *clock-emojis* (mod (round (/ secs 1800)) 24))))
|
4
third_party/tvl/lisp/dns/default.nix
vendored
4
third_party/tvl/lisp/dns/default.nix
vendored
|
@ -14,4 +14,8 @@ depot.nix.buildLisp.library {
|
||||||
./message.lisp
|
./message.lisp
|
||||||
./client.lisp
|
./client.lisp
|
||||||
];
|
];
|
||||||
|
|
||||||
|
brokenOn = [
|
||||||
|
"ecl" # dynamic cffi
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
3
third_party/tvl/lisp/klatre/OWNERS
vendored
Normal file
3
third_party/tvl/lisp/klatre/OWNERS
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
inherited: true
|
||||||
|
owners:
|
||||||
|
- grfn
|
33
third_party/tvl/lisp/klatre/klatre.lisp
vendored
33
third_party/tvl/lisp/klatre/klatre.lisp
vendored
|
@ -1,7 +1,8 @@
|
||||||
(in-package #:klatre)
|
(in-package #:klatre)
|
||||||
(declaim (optimize (safety 3)))
|
(declaim (optimize (safety 3)))
|
||||||
|
|
||||||
(defmacro comment (&rest _))
|
(defmacro comment (&rest _)
|
||||||
|
(declare (ignore _)))
|
||||||
|
|
||||||
(defun posp (n) (> n 0))
|
(defun posp (n) (> n 0))
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@
|
||||||
(defun chunk-list (size list &key (start 0) end)
|
(defun chunk-list (size list &key (start 0) end)
|
||||||
"Returns successive chunks of list of size SIZE, starting at START and ending
|
"Returns successive chunks of list of size SIZE, starting at START and ending
|
||||||
at END."
|
at END."
|
||||||
(declare (inline check-list/bounded check-list/simple))
|
(declare (inline chunk-list/bounded chunk-list/unbounded))
|
||||||
(check-type size (integer 1))
|
(check-type size (integer 1))
|
||||||
(let ((list (nthcdr start list)))
|
(let ((list (nthcdr start list)))
|
||||||
(when list
|
(when list
|
||||||
|
@ -76,24 +77,36 @@ separated by SEP."
|
||||||
(defparameter dottime-format
|
(defparameter dottime-format
|
||||||
'((:year 4) #\- (:month 2) #\- (:day 2)
|
'((:year 4) #\- (:month 2) #\- (:day 2)
|
||||||
#\T
|
#\T
|
||||||
(:hour 2) #\· (:min 2) "+00") ; TODO(grfn): Allow passing offset
|
(:hour 2) #\· (:min 2))
|
||||||
"`:LOCAL-TIME' format specifier for dottime")
|
"`:LOCAL-TIME' format specifier for dottime")
|
||||||
|
|
||||||
(defun format-dottime (timestamp)
|
(defun format-dottime (timestamp &optional (offset 0))
|
||||||
"Return TIMESTAMP formatted as dottime, using a +00 offset"
|
"Return TIMESTAMP formatted as dottime, with a specified offset or +00"
|
||||||
(check-type timestamp local-time:timestamp)
|
(check-type timestamp local-time:timestamp)
|
||||||
(local-time:format-timestring nil timestamp
|
(concatenate 'string
|
||||||
:format dottime-format
|
(local-time:format-timestring nil timestamp
|
||||||
:timezone local-time:+utc-zone+))
|
:format dottime-format
|
||||||
|
:timezone local-time:+utc-zone+)
|
||||||
|
(format-dottime-offset offset)))
|
||||||
|
|
||||||
|
(defun format-dottime-offset (offset)
|
||||||
|
"Render OFFSET in hours in the format specified by dottime."
|
||||||
|
(check-type offset integer)
|
||||||
|
(concatenate 'string
|
||||||
|
; render sign manually since format prints it after padding
|
||||||
|
(if (>= offset 0) "+" "-")
|
||||||
|
(format nil "~2,'0D" (abs offset))))
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
(format-dottime (local-time:now)))
|
(format-dottime (local-time:now))
|
||||||
|
(format-dottime (local-time:now) 2))
|
||||||
|
|
||||||
(defun try-parse-integer (str)
|
(defun try-parse-integer (str)
|
||||||
"Attempt to parse STR as an integer, returning nil if it is invalid."
|
"Attempt to parse STR as an integer, returning nil if it is invalid."
|
||||||
(check-type str string)
|
(check-type str string)
|
||||||
(handler-case (parse-integer str)
|
(handler-case (parse-integer str)
|
||||||
(sb-int:simple-parse-error (_) nil)))
|
(#+sbcl sb-int:simple-parse-error
|
||||||
|
#-sbcl parse-error (_) (declare (ignore _)) nil)))
|
||||||
|
|
||||||
;;;
|
;;;
|
||||||
;;; Function utilities
|
;;; Function utilities
|
||||||
|
|
2
third_party/tvl/lisp/klatre/package.lisp
vendored
2
third_party/tvl/lisp/klatre/package.lisp
vendored
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
;; String handling
|
;; String handling
|
||||||
#:+dottime-format+ #:format-dottime
|
#:+dottime-format+ #:format-dottime
|
||||||
#:try-parse-integer
|
#:try-parse-integer #:format-dottime-offset
|
||||||
|
|
||||||
;; Function utilities
|
;; Function utilities
|
||||||
#:partial))
|
#:partial))
|
||||||
|
|
197
third_party/tvl/net/alcoholic_jwt/Cargo.lock
generated
vendored
Normal file
197
third_party/tvl/net/alcoholic_jwt/Cargo.lock
generated
vendored
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alcoholic_jwt"
|
||||||
|
version = "4091.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"openssl",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.125"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"foreign-types",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"openssl-macros",
|
||||||
|
"openssl-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.137"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.137"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.81"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.94"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a07e33e919ebcd69113d5be0e4d70c5707004ff45188910106854f38b960df4a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
9
third_party/tvl/net/alcoholic_jwt/Cargo.toml
vendored
9
third_party/tvl/net/alcoholic_jwt/Cargo.toml
vendored
|
@ -1,15 +1,16 @@
|
||||||
[package]
|
[package]
|
||||||
name = "alcoholic_jwt"
|
name = "alcoholic_jwt"
|
||||||
description = "Library for validation of RS256 JWTs"
|
description = "Library for validation of RS256 JWTs"
|
||||||
version = "1.0.0"
|
version = "4091.0.0"
|
||||||
authors = ["Vincent Ambo <vincent@aprila.no>"]
|
authors = ["Vincent Ambo <tazjin@tvl.su>"]
|
||||||
keywords = ["jwt", "token", "jwks"]
|
keywords = ["jwt", "token", "jwks"]
|
||||||
categories = ["authentication"]
|
categories = ["authentication"]
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
repository = "https://github.com/aprilabank/alcoholic_jwt"
|
homepage = "https://code.tvl.fyi/about/net/alcoholic_jwt"
|
||||||
|
repository = "https://code.tvl.fyi/depot.git:/net/alcoholic_jwt.git"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.10"
|
base64 = "0.13"
|
||||||
openssl = "0.10"
|
openssl = "0.10"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
|
14
third_party/tvl/net/alcoholic_jwt/README.md
vendored
14
third_party/tvl/net/alcoholic_jwt/README.md
vendored
|
@ -1,8 +1,6 @@
|
||||||
alcoholic_jwt
|
alcoholic_jwt
|
||||||
=============
|
=============
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/aprilabank/alcoholic_jwt.svg?branch=master)](https://travis-ci.org/aprilabank/alcoholic_jwt)
|
|
||||||
|
|
||||||
This is a library for **validation** of **RS256** JWTs using keys from
|
This is a library for **validation** of **RS256** JWTs using keys from
|
||||||
a JWKS. Nothing more, nothing less.
|
a JWKS. Nothing more, nothing less.
|
||||||
|
|
||||||
|
@ -56,7 +54,19 @@ This library aims to only use trustworthy off-the-shelf components to
|
||||||
do the work. Cryptographic operations are provided by the `openssl`
|
do the work. Cryptographic operations are provided by the `openssl`
|
||||||
crate, JSON-serialisation is provided by `serde_json`.
|
crate, JSON-serialisation is provided by `serde_json`.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
This project is developed in the [TVL monorepo][depot]. To work on it,
|
||||||
|
you can either use a local clone of the entire repository or clone
|
||||||
|
just the `alcoholic_jwt` subtree:
|
||||||
|
|
||||||
|
https://code.tvl.fyi/depot.git:/net/alcoholic_jwt.git
|
||||||
|
|
||||||
|
Please follow the TVL [contribution guidelines][contributing].
|
||||||
|
|
||||||
[Google]: https://www.google.com/
|
[Google]: https://www.google.com/
|
||||||
[Aprila]: https://www.aprila.no/
|
[Aprila]: https://www.aprila.no/
|
||||||
[JWKS]: https://tools.ietf.org/html/rfc7517
|
[JWKS]: https://tools.ietf.org/html/rfc7517
|
||||||
[`kid` claim]: https://tools.ietf.org/html/rfc7515#section-4.1.4
|
[`kid` claim]: https://tools.ietf.org/html/rfc7515#section-4.1.4
|
||||||
|
[depot]: https://code.tvl.fyi/
|
||||||
|
[contributing]: https://code.tvl.fyi/about/docs/CONTRIBUTING.md
|
||||||
|
|
9
third_party/tvl/net/alcoholic_jwt/default.nix
vendored
Normal file
9
third_party/tvl/net/alcoholic_jwt/default.nix
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
|
depot.third_party.naersk.buildPackage {
|
||||||
|
src = ./.;
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
openssl
|
||||||
|
pkgconfig
|
||||||
|
];
|
||||||
|
}
|
110
third_party/tvl/net/alcoholic_jwt/src/lib.rs
vendored
110
third_party/tvl/net/alcoholic_jwt/src/lib.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (C) 2018 Aprila Bank ASA
|
// Copyright (C) 2019-2022 The TVL Community
|
||||||
//
|
//
|
||||||
// alcoholic_jwt is free software: you can redistribute it and/or
|
// alcoholic_jwt is free software: you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU General Public License as
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
@ -67,23 +67,26 @@
|
||||||
//!
|
//!
|
||||||
//! [JWKS]: https://tools.ietf.org/html/rfc7517
|
//! [JWKS]: https://tools.ietf.org/html/rfc7517
|
||||||
|
|
||||||
#[macro_use] extern crate serde_derive;
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
extern crate base64;
|
extern crate base64;
|
||||||
extern crate openssl;
|
extern crate openssl;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
use base64::{URL_SAFE_NO_PAD, Config, DecodeError};
|
use base64::{Config, DecodeError, URL_SAFE_NO_PAD};
|
||||||
use openssl::bn::BigNum;
|
use openssl::bn::BigNum;
|
||||||
use openssl::error::ErrorStack;
|
use openssl::error::ErrorStack;
|
||||||
use openssl::hash::MessageDigest;
|
use openssl::hash::MessageDigest;
|
||||||
use openssl::pkey::{Public, PKey};
|
use openssl::pkey::{PKey, Public};
|
||||||
use openssl::rsa::Rsa;
|
use openssl::rsa::Rsa;
|
||||||
use openssl::sign::Verifier;
|
use openssl::sign::Verifier;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::time::{UNIX_EPOCH, Duration, SystemTime};
|
use std::error::Error;
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -101,12 +104,16 @@ fn jwt_forgiving() -> Config {
|
||||||
/// JWT algorithm used. The only supported algorithm is currently
|
/// JWT algorithm used. The only supported algorithm is currently
|
||||||
/// RS256.
|
/// RS256.
|
||||||
#[derive(Clone, Deserialize, Debug)]
|
#[derive(Clone, Deserialize, Debug)]
|
||||||
enum KeyAlgorithm { RS256 }
|
enum KeyAlgorithm {
|
||||||
|
RS256,
|
||||||
|
}
|
||||||
|
|
||||||
/// Type of key contained in a JWT. The only supported key type is
|
/// Type of key contained in a JWT. The only supported key type is
|
||||||
/// currently RSA.
|
/// currently RSA.
|
||||||
#[derive(Clone, Deserialize, Debug)]
|
#[derive(Clone, Deserialize, Debug)]
|
||||||
enum KeyType { RSA }
|
enum KeyType {
|
||||||
|
RSA,
|
||||||
|
}
|
||||||
|
|
||||||
/// Representation of a single JSON Web Key. See [RFC
|
/// Representation of a single JSON Web Key. See [RFC
|
||||||
/// 7517](https://tools.ietf.org/html/rfc7517#section-4).
|
/// 7517](https://tools.ietf.org/html/rfc7517#section-4).
|
||||||
|
@ -146,7 +153,7 @@ impl JWKS {
|
||||||
|
|
||||||
/// Representation of an undecoded JSON Web Token. See [RFC
|
/// Representation of an undecoded JSON Web Token. See [RFC
|
||||||
/// 7519](https://tools.ietf.org/html/rfc7519).
|
/// 7519](https://tools.ietf.org/html/rfc7519).
|
||||||
struct JWT<'a> (&'a str);
|
struct JWT<'a>(&'a str);
|
||||||
|
|
||||||
/// Representation of a decoded and validated JSON Web Token.
|
/// Representation of a decoded and validated JSON Web Token.
|
||||||
///
|
///
|
||||||
|
@ -214,18 +221,56 @@ pub enum ValidationError {
|
||||||
InvalidClaims(Vec<&'static str>),
|
InvalidClaims(Vec<&'static str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Error for ValidationError {
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
ValidationError::InvalidBase64(e) => Some(e),
|
||||||
|
ValidationError::OpenSSL(e) => Some(e),
|
||||||
|
ValidationError::JSON(e) => Some(e),
|
||||||
|
ValidationError::InvalidComponents
|
||||||
|
| ValidationError::InvalidJWK
|
||||||
|
| ValidationError::InvalidSignature
|
||||||
|
| ValidationError::InvalidClaims(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ValidationError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
ValidationError::InvalidComponents => {
|
||||||
|
f.write_str("Invalid number of token components in JWT")
|
||||||
|
}
|
||||||
|
ValidationError::InvalidBase64(_) => f.write_str("Invalid Base64 encoding in JWT"),
|
||||||
|
ValidationError::InvalidJWK => f.write_str("JWK decoding failed"),
|
||||||
|
ValidationError::InvalidSignature => f.write_str("JWT signature validation failed"),
|
||||||
|
ValidationError::OpenSSL(e) => write!(f, "SSL error: {}", e),
|
||||||
|
ValidationError::JSON(e) => write!(f, "JSON error: {}", e),
|
||||||
|
ValidationError::InvalidClaims(errs) => {
|
||||||
|
write!(f, "Invalid claims: {}", errs.join(", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type JWTResult<T> = Result<T, ValidationError>;
|
type JWTResult<T> = Result<T, ValidationError>;
|
||||||
|
|
||||||
impl From<ErrorStack> for ValidationError {
|
impl From<ErrorStack> for ValidationError {
|
||||||
fn from(err: ErrorStack) -> Self { ValidationError::OpenSSL(err) }
|
fn from(err: ErrorStack) -> Self {
|
||||||
|
ValidationError::OpenSSL(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<serde_json::Error> for ValidationError {
|
impl From<serde_json::Error> for ValidationError {
|
||||||
fn from(err: serde_json::Error) -> Self { ValidationError::JSON(err) }
|
fn from(err: serde_json::Error) -> Self {
|
||||||
|
ValidationError::JSON(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DecodeError> for ValidationError {
|
impl From<DecodeError> for ValidationError {
|
||||||
fn from(err: DecodeError) -> Self { ValidationError::InvalidBase64(err) }
|
fn from(err: DecodeError) -> Self {
|
||||||
|
ValidationError::InvalidBase64(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to extract the `kid`-claim out of a JWT's header claims.
|
/// Attempt to extract the `kid`-claim out of a JWT's header claims.
|
||||||
|
@ -266,9 +311,7 @@ pub fn token_kid(token: &str) -> JWTResult<Option<String>> {
|
||||||
///
|
///
|
||||||
/// It is the user's task to ensure that the correct JWK is passed in
|
/// It is the user's task to ensure that the correct JWK is passed in
|
||||||
/// for validation.
|
/// for validation.
|
||||||
pub fn validate(token: &str,
|
pub fn validate(token: &str, jwk: &JWK, validations: Vec<Validation>) -> JWTResult<ValidJWT> {
|
||||||
jwk: &JWK,
|
|
||||||
validations: Vec<Validation>) -> JWTResult<ValidJWT> {
|
|
||||||
let jwt = JWT(token);
|
let jwt = JWT(token);
|
||||||
let public_key = public_key_from_jwk(&jwk)?;
|
let public_key = public_key_from_jwk(&jwk)?;
|
||||||
validate_jwt_signature(&jwt, public_key)?;
|
validate_jwt_signature(&jwt, public_key)?;
|
||||||
|
@ -279,7 +322,7 @@ pub fn validate(token: &str,
|
||||||
if parts.len() != 3 {
|
if parts.len() != 3 {
|
||||||
// This is unlikely considering that validation has already
|
// This is unlikely considering that validation has already
|
||||||
// been performed at this point, but better safe than sorry.
|
// been performed at this point, but better safe than sorry.
|
||||||
return Err(ValidationError::InvalidComponents)
|
return Err(ValidationError::InvalidComponents);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform claim validations before constructing the valid token:
|
// Perform claim validations before constructing the valid token:
|
||||||
|
@ -351,7 +394,7 @@ fn validate_jwt_signature(jwt: &JWT, key: Rsa<Public>) -> JWTResult<()> {
|
||||||
verifier.update(data.as_bytes())?;
|
verifier.update(data.as_bytes())?;
|
||||||
|
|
||||||
match verifier.verify(&sig)? {
|
match verifier.verify(&sig)? {
|
||||||
true => Ok(()),
|
true => Ok(()),
|
||||||
false => Err(ValidationError::InvalidSignature),
|
false => Err(ValidationError::InvalidSignature),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -362,7 +405,7 @@ fn validate_jwt_signature(jwt: &JWT, key: Rsa<Public>) -> JWTResult<()> {
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum Audience {
|
enum Audience {
|
||||||
Single(String),
|
Single(String),
|
||||||
Multi(Vec<String>)
|
Multi(Vec<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal helper struct for claims that are relevant for claim
|
/// Internal helper struct for claims that are relevant for claim
|
||||||
|
@ -376,15 +419,14 @@ struct PartialClaims {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply a single validation to the claim set of a token.
|
/// Apply a single validation to the claim set of a token.
|
||||||
fn apply_validation(claims: &PartialClaims,
|
fn apply_validation(claims: &PartialClaims, validation: Validation) -> Result<(), &'static str> {
|
||||||
validation: Validation) -> Result<(), &'static str> {
|
|
||||||
match validation {
|
match validation {
|
||||||
// Validate that an 'iss' claim is present and matches the
|
// Validate that an 'iss' claim is present and matches the
|
||||||
// supplied value.
|
// supplied value.
|
||||||
Validation::Issuer(iss) => {
|
Validation::Issuer(iss) => match claims.iss {
|
||||||
match claims.iss {
|
None => Err("'iss' claim is missing"),
|
||||||
None => Err("'iss' claim is missing"),
|
Some(ref claim) => {
|
||||||
Some(ref claim) => if *claim == iss {
|
if *claim == iss {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("'iss' claim does not match")
|
Err("'iss' claim does not match")
|
||||||
|
@ -394,15 +436,17 @@ fn apply_validation(claims: &PartialClaims,
|
||||||
|
|
||||||
// Validate that an 'aud' claim is present and matches the
|
// Validate that an 'aud' claim is present and matches the
|
||||||
// supplied value.
|
// supplied value.
|
||||||
Validation::Audience(aud) => {
|
Validation::Audience(aud) => match claims.aud {
|
||||||
match claims.aud {
|
None => Err("'aud' claim is missing"),
|
||||||
None => Err("'aud' claim is missing"),
|
Some(Audience::Single(ref claim)) => {
|
||||||
Some(Audience::Single(ref claim)) => if *claim == aud {
|
if *claim == aud {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("'aud' claim does not match")
|
Err("'aud' claim does not match")
|
||||||
},
|
}
|
||||||
Some(Audience::Multi(ref claims)) => if claims.contains(&aud) {
|
}
|
||||||
|
Some(Audience::Multi(ref claims)) => {
|
||||||
|
if claims.contains(&aud) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("'aud' claim does not match")
|
Err("'aud' claim does not match")
|
||||||
|
@ -447,12 +491,12 @@ fn apply_validation(claims: &PartialClaims,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply all requested validations to a partial claim set.
|
/// Apply all requested validations to a partial claim set.
|
||||||
fn validate_claims(claims: PartialClaims,
|
fn validate_claims(claims: PartialClaims, validations: Vec<Validation>) -> JWTResult<()> {
|
||||||
validations: Vec<Validation>) -> JWTResult<()> {
|
let validation_errors: Vec<_> = validations
|
||||||
let validation_errors: Vec<_> = validations.into_iter()
|
.into_iter()
|
||||||
.map(|v| apply_validation(&claims, v))
|
.map(|v| apply_validation(&claims, v))
|
||||||
.filter_map(|result| match result {
|
.filter_map(|result| match result {
|
||||||
Ok(_) => None,
|
Ok(_) => None,
|
||||||
Err(err) => Some(err),
|
Err(err) => Some(err),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
24
third_party/tvl/net/alcoholic_jwt/src/tests.rs
vendored
24
third_party/tvl/net/alcoholic_jwt/src/tests.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (C) 2018 Aprila Bank ASA
|
// Copyright (C) 2019-2022 The TVL Community
|
||||||
//
|
//
|
||||||
// alcoholic_jwt is free software: you can redistribute it and/or
|
// alcoholic_jwt is free software: you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU General Public License as
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
@ -21,14 +21,19 @@ fn test_fragment_decoding() {
|
||||||
let bignum = decode_fragment(fragment).expect("Failed to decode fragment");
|
let bignum = decode_fragment(fragment).expect("Failed to decode fragment");
|
||||||
|
|
||||||
let expected = "19947781743618558124649689124245117083485690334420160711273532766920651190711502679542723943527557680293732686428091794139998732541701457212387600480039297092835433997837314251024513773285252960725418984381935183495143908023024822433135775773958512751261112853383693442999603704969543668619221464654540065497665889289271044207667765128672709218996183649696030570183970367596949687544839066873508106034650634722970893169823917299050098551447676778961773465887890052852528696684907153295689693676910831376066659456592813140662563597179711588277621736656871685099184755908108451080261403193680966083938080206832839445289";
|
let expected = "19947781743618558124649689124245117083485690334420160711273532766920651190711502679542723943527557680293732686428091794139998732541701457212387600480039297092835433997837314251024513773285252960725418984381935183495143908023024822433135775773958512751261112853383693442999603704969543668619221464654540065497665889289271044207667765128672709218996183649696030570183970367596949687544839066873508106034650634722970893169823917299050098551447676778961773465887890052852528696684907153295689693676910831376066659456592813140662563597179711588277621736656871685099184755908108451080261403193680966083938080206832839445289";
|
||||||
assert_eq!(expected, format!("{}", bignum), "Decoded fragment should match ");
|
assert_eq!(
|
||||||
|
expected,
|
||||||
|
format!("{}", bignum),
|
||||||
|
"Decoded fragment should match "
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_find_jwks() {
|
fn test_decode_find_jwks() {
|
||||||
let json = "{\"keys\":[{\"kty\":\"RSA\",\"alg\":\"RS256\",\"use\":\"sig\",\"kid\":\"mUjI\\/rIMLLtung35BKZfdbrqtlEAAYJ4JX\\/SKvnLxJc=\",\"n\":\"ngRRjNbXgPW29oNtF0JgsyyfTwPyEL0u_X16s453X2AOc33XGFxVKLEQ7R_TiMenaKcr-tPifYqgps_deyi0XOr4I3SOdOMtAVKDZJCANe--CANOHZb-meIfjKhCHisvT90fm5Apd6qPRVsXsZ7A8pmClZHKM5fwZUkBv8NsPLm2Xy2sGOZIiwP_7z8m3j0abUzniPQsx2b3xcWimB9vRtshFHN1KgPUf1ALQ5xzLfJnlFkCxC7kmOxKC7_NpQ4kJR_DKzKFV_r3HxTqf-jddHcXIrrMcLQXCSyeLQtLaz7whQ4F-EfL42z4XgwPr4ji3sct2gWL13EqlbE5DDxLKQ\",\"e\":\"GK7oLCDbNPAF59LhvyseqcG04hDnPs58qGYolr_HHmaR4lulWJ90ozx6e4Ut363yKG2p9vwvivR5UIC-aLPtqT2qr-OtjhBFzUFVaMGZ6mPCvMKk0AgMYdOHvWTgBSqQtNJTvl1yYLnhcWyoE2fLQhoEbY9qUyCBCEOScXOZRDpnmBtz5I8q5yYMV6a920J24T_IYbxHgkGcEU2SGg-b1cOMD7Rja7vCfV---CQ2pR4leQ0jufzudDoe7z3mziJm-Ihcdrz2Ujy5kPEMdz6R55prJ-ENKrkD_X4u5aSlSRaetwmHS3oAVkjr1JwUNbqnpM-kOqieqHEp8LUmez-Znw\"}]}";
|
let json = "{\"keys\":[{\"kty\":\"RSA\",\"alg\":\"RS256\",\"use\":\"sig\",\"kid\":\"mUjI\\/rIMLLtung35BKZfdbrqtlEAAYJ4JX\\/SKvnLxJc=\",\"n\":\"ngRRjNbXgPW29oNtF0JgsyyfTwPyEL0u_X16s453X2AOc33XGFxVKLEQ7R_TiMenaKcr-tPifYqgps_deyi0XOr4I3SOdOMtAVKDZJCANe--CANOHZb-meIfjKhCHisvT90fm5Apd6qPRVsXsZ7A8pmClZHKM5fwZUkBv8NsPLm2Xy2sGOZIiwP_7z8m3j0abUzniPQsx2b3xcWimB9vRtshFHN1KgPUf1ALQ5xzLfJnlFkCxC7kmOxKC7_NpQ4kJR_DKzKFV_r3HxTqf-jddHcXIrrMcLQXCSyeLQtLaz7whQ4F-EfL42z4XgwPr4ji3sct2gWL13EqlbE5DDxLKQ\",\"e\":\"GK7oLCDbNPAF59LhvyseqcG04hDnPs58qGYolr_HHmaR4lulWJ90ozx6e4Ut363yKG2p9vwvivR5UIC-aLPtqT2qr-OtjhBFzUFVaMGZ6mPCvMKk0AgMYdOHvWTgBSqQtNJTvl1yYLnhcWyoE2fLQhoEbY9qUyCBCEOScXOZRDpnmBtz5I8q5yYMV6a920J24T_IYbxHgkGcEU2SGg-b1cOMD7Rja7vCfV---CQ2pR4leQ0jufzudDoe7z3mziJm-Ihcdrz2Ujy5kPEMdz6R55prJ-ENKrkD_X4u5aSlSRaetwmHS3oAVkjr1JwUNbqnpM-kOqieqHEp8LUmez-Znw\"}]}";
|
||||||
let jwks: JWKS = serde_json::from_str(json).expect("Failed to decode JWKS");
|
let jwks: JWKS = serde_json::from_str(json).expect("Failed to decode JWKS");
|
||||||
let jwk = jwks.find("mUjI/rIMLLtung35BKZfdbrqtlEAAYJ4JX/SKvnLxJc=")
|
let jwk = jwks
|
||||||
|
.find("mUjI/rIMLLtung35BKZfdbrqtlEAAYJ4JX/SKvnLxJc=")
|
||||||
.expect("Failed to find required JWK");
|
.expect("Failed to find required JWK");
|
||||||
|
|
||||||
public_key_from_jwk(&jwk).expect("Failed to construct public key from JWK");
|
public_key_from_jwk(&jwk).expect("Failed to construct public key from JWK");
|
||||||
|
@ -39,18 +44,21 @@ fn test_token_kid() {
|
||||||
let jwt = "eyJraWQiOiI4ckRxOFB3MEZaY2FvWFdURVZRbzcrVGYyWXpTTDFmQnhOS1BDZWJhYWk0PSIsImFsZyI6IlJTMjU2IiwidHlwIjoiSldUIn0.eyJpc3MiOiJhdXRoLnRlc3QuYXByaWxhLm5vIiwiaWF0IjoxNTM2MDUwNjkzLCJleHAiOjE1MzYwNTQyOTMsInN1YiI6IjQyIiwiZXh0Ijoic21va2V0ZXN0IiwicHJ2IjoiYXJpc3RpIiwic2NwIjoicHJvY2VzcyJ9.gOLsv98109qLkmRK6Dn7WWRHLW7o8W78WZcWvFZoxPLzVO0qvRXXRLYc9h5chpfvcWreLZ4f1cOdvxv31_qnCRSQQPOeQ7r7hj_sPEDzhKjk-q2aoNHaGGJg1vabI--9EFkFsGQfoS7UbMMssS44dgR68XEnKtjn0Vys-Vzbvz_CBSCH6yQhRLik2SU2jR2L7BoFvh4LGZ6EKoQWzm8Z-CHXLGLUs4Hp5aPhF46dGzgAzwlPFW4t9G4DciX1uB4vv1XnfTc5wqJch6ltjKMde1GZwLR757a8dJSBcmGWze3UNE2YH_VLD7NCwH2kkqr3gh8rn7lWKG4AUIYPxsw9CB";
|
let jwt = "eyJraWQiOiI4ckRxOFB3MEZaY2FvWFdURVZRbzcrVGYyWXpTTDFmQnhOS1BDZWJhYWk0PSIsImFsZyI6IlJTMjU2IiwidHlwIjoiSldUIn0.eyJpc3MiOiJhdXRoLnRlc3QuYXByaWxhLm5vIiwiaWF0IjoxNTM2MDUwNjkzLCJleHAiOjE1MzYwNTQyOTMsInN1YiI6IjQyIiwiZXh0Ijoic21va2V0ZXN0IiwicHJ2IjoiYXJpc3RpIiwic2NwIjoicHJvY2VzcyJ9.gOLsv98109qLkmRK6Dn7WWRHLW7o8W78WZcWvFZoxPLzVO0qvRXXRLYc9h5chpfvcWreLZ4f1cOdvxv31_qnCRSQQPOeQ7r7hj_sPEDzhKjk-q2aoNHaGGJg1vabI--9EFkFsGQfoS7UbMMssS44dgR68XEnKtjn0Vys-Vzbvz_CBSCH6yQhRLik2SU2jR2L7BoFvh4LGZ6EKoQWzm8Z-CHXLGLUs4Hp5aPhF46dGzgAzwlPFW4t9G4DciX1uB4vv1XnfTc5wqJch6ltjKMde1GZwLR757a8dJSBcmGWze3UNE2YH_VLD7NCwH2kkqr3gh8rn7lWKG4AUIYPxsw9CB";
|
||||||
|
|
||||||
let kid = token_kid(&jwt).expect("Failed to extract token KID");
|
let kid = token_kid(&jwt).expect("Failed to extract token KID");
|
||||||
assert_eq!(Some("8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=".into()),
|
assert_eq!(
|
||||||
kid, "Extracted KID did not match expected KID");
|
Some("8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=".into()),
|
||||||
|
kid,
|
||||||
|
"Extracted KID did not match expected KID"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_validate_jwt() {
|
fn test_validate_jwt() {
|
||||||
let jwks_json = "{\"keys\":[{\"kty\":\"RSA\",\"alg\":\"RS256\",\"use\":\"sig\",\"kid\":\"8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=\",\"n\":\"l4UTgk1zr-8C8utt0E57DtBV6qqAPWzVRrIuQS2j0_hp2CviaNl5XzGRDnB8gwk0Hx95YOhJupAe6RNq5ok3fDdxL7DLvppJNRLz3Ag9CsmDLcbXgNEQys33fBJaPw1v3GcaFC4tisU5p-o1f5RfWwvwdBtdBfGiwT1GRvbc5sFx6M4iYjg9uv1lNKW60PqSJW4iDYrfqzZmB0zF1SJ0BL_rnQZ1Wi_UkFmNe9arM8W9tI9T3Ie59HITFuyVSTCt6qQEtSfa1e5PiBaVuV3qoFI2jPBiVZQ6LPGBWEDyz4QtrHLdECPPoTF30NN6TSVwwlRbCuUUrdNdXdjYe2dMFQ\",\"e\":\"DhaD5zC7mzaDvHO192wKT_9sfsVmdy8w8T8C9VG17_b1jG2srd3cmc6Ycw-0blDf53Wrpi9-KGZXKHX6_uIuJK249WhkP7N1SHrTJxO0sUJ8AhK482PLF09Qtu6cUfJqY1X1y1S2vACJZItU4Vjr3YAfiVGQXeA8frAf7Sm4O1CBStCyg6yCcIbGojII0jfh2vSB-GD9ok1F69Nmk-R-bClyqMCV_Oq-5a0gqClVS8pDyGYMgKTww2RHgZaFSUcG13KeLMQsG2UOB2OjSC8FkOXK00NBlAjU3d0Vv-IamaLIszO7FQBY3Oh0uxNOvIE9ofQyCOpB-xIK6V9CTTphxw\"}]}";
|
let jwks_json = "{\"keys\":[{\"kty\":\"RSA\",\"alg\":\"RS256\",\"use\":\"sig\",\"kid\":\"8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=\",\"n\":\"l4UTgk1zr-8C8utt0E57DtBV6qqAPWzVRrIuQS2j0_hp2CviaNl5XzGRDnB8gwk0Hx95YOhJupAe6RNq5ok3fDdxL7DLvppJNRLz3Ag9CsmDLcbXgNEQys33fBJaPw1v3GcaFC4tisU5p-o1f5RfWwvwdBtdBfGiwT1GRvbc5sFx6M4iYjg9uv1lNKW60PqSJW4iDYrfqzZmB0zF1SJ0BL_rnQZ1Wi_UkFmNe9arM8W9tI9T3Ie59HITFuyVSTCt6qQEtSfa1e5PiBaVuV3qoFI2jPBiVZQ6LPGBWEDyz4QtrHLdECPPoTF30NN6TSVwwlRbCuUUrdNdXdjYe2dMFQ\",\"e\":\"DhaD5zC7mzaDvHO192wKT_9sfsVmdy8w8T8C9VG17_b1jG2srd3cmc6Ycw-0blDf53Wrpi9-KGZXKHX6_uIuJK249WhkP7N1SHrTJxO0sUJ8AhK482PLF09Qtu6cUfJqY1X1y1S2vACJZItU4Vjr3YAfiVGQXeA8frAf7Sm4O1CBStCyg6yCcIbGojII0jfh2vSB-GD9ok1F69Nmk-R-bClyqMCV_Oq-5a0gqClVS8pDyGYMgKTww2RHgZaFSUcG13KeLMQsG2UOB2OjSC8FkOXK00NBlAjU3d0Vv-IamaLIszO7FQBY3Oh0uxNOvIE9ofQyCOpB-xIK6V9CTTphxw\"}]}";
|
||||||
|
|
||||||
let jwks: JWKS = serde_json::from_str(jwks_json)
|
let jwks: JWKS = serde_json::from_str(jwks_json).expect("Failed to decode JWKS");
|
||||||
.expect("Failed to decode JWKS");
|
|
||||||
|
|
||||||
let jwk = jwks.find("8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=")
|
let jwk = jwks
|
||||||
|
.find("8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=")
|
||||||
.expect("Failed to find required JWK");
|
.expect("Failed to find required JWK");
|
||||||
|
|
||||||
let pkey = public_key_from_jwk(&jwk).expect("Failed to construct public key");
|
let pkey = public_key_from_jwk(&jwk).expect("Failed to construct public key");
|
||||||
|
|
180
third_party/tvl/net/crimp/Cargo.lock
generated
vendored
Normal file
180
third_party/tvl/net/crimp/Cargo.lock
generated
vendored
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crimp"
|
||||||
|
version = "0.2.2"
|
||||||
|
dependencies = [
|
||||||
|
"curl",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curl"
|
||||||
|
version = "0.4.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37d855aeef205b43f65a5001e0997d81f8efca7badad4fad7d897aa7f0d0651f"
|
||||||
|
dependencies = [
|
||||||
|
"curl-sys",
|
||||||
|
"libc",
|
||||||
|
"openssl-probe",
|
||||||
|
"openssl-sys",
|
||||||
|
"schannel",
|
||||||
|
"socket2",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curl-sys"
|
||||||
|
version = "0.4.55+curl-7.83.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23734ec77368ec583c2e61dd3f0b0e5c98b93abe6d2a004ca06b91dd7e3e2762"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"libz-sys",
|
||||||
|
"openssl-sys",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.125"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libz-sys"
|
||||||
|
version = "1.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92e7e15d7610cce1d9752e137625f14e61a28cd45929b6e12e47b50fe154ee2e"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-probe"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.137"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.81"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
8
third_party/tvl/net/crimp/Cargo.toml
vendored
8
third_party/tvl/net/crimp/Cargo.toml
vendored
|
@ -1,12 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
name = "crimp"
|
name = "crimp"
|
||||||
description = "Higher-level Rust API for cURL bindings"
|
description = "Higher-level Rust API for cURL bindings"
|
||||||
version = "0.2.2"
|
version = "4087.0.0"
|
||||||
authors = ["Vincent Ambo <mail@tazj.in>"]
|
authors = ["Vincent Ambo <tazjin@tvl.su>"]
|
||||||
keywords = [ "http", "curl" ]
|
keywords = [ "http", "curl" ]
|
||||||
categories = [ "api-bindings" ]
|
categories = [ "api-bindings" ]
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
repository = "https://github.com/tazjin/crimp"
|
homepage = "https://code.tvl.fyi/about/net/crimp"
|
||||||
|
repository = "https://code.tvl.fyi/depot.git:/net/crimp.git"
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ "json" ]
|
default = [ "json" ]
|
||||||
|
|
13
third_party/tvl/net/crimp/README.md
vendored
13
third_party/tvl/net/crimp/README.md
vendored
|
@ -1,7 +1,6 @@
|
||||||
crimp
|
crimp
|
||||||
=====
|
=====
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/tazjin/crimp.svg?branch=master)](https://travis-ci.org/tazjin/crimp)
|
|
||||||
[![](https://img.shields.io/crates/v/crimp.svg)](https://crates.io/crates/crimp)
|
[![](https://img.shields.io/crates/v/crimp.svg)](https://crates.io/crates/crimp)
|
||||||
[![](https://docs.rs/crimp/badge.svg)](https://docs.rs/crimp)
|
[![](https://docs.rs/crimp/badge.svg)](https://docs.rs/crimp)
|
||||||
|
|
||||||
|
@ -11,5 +10,17 @@ cURL.
|
||||||
The documentation for this crate is primarily in the [module
|
The documentation for this crate is primarily in the [module
|
||||||
documentation][]
|
documentation][]
|
||||||
|
|
||||||
|
-------
|
||||||
|
|
||||||
|
This project is developed in the [TVL monorepo][depot]. To work on it,
|
||||||
|
you can either use a local clone of the entire repository or clone
|
||||||
|
just the `crimp` subtree:
|
||||||
|
|
||||||
|
https://code.tvl.fyi/depot.git:/net/crimp.git
|
||||||
|
|
||||||
|
Please follow the TVL [contribution guidelines][contributing].
|
||||||
|
|
||||||
[Rust bindings]: https://docs.rs/curl
|
[Rust bindings]: https://docs.rs/curl
|
||||||
[module documentation]: https://docs.rs/crimp
|
[module documentation]: https://docs.rs/crimp
|
||||||
|
[depot]: https://code.tvl.fyi/
|
||||||
|
[contributing]: https://code.tvl.fyi/about/docs/CONTRIBUTING.md
|
||||||
|
|
9
third_party/tvl/net/crimp/default.nix
vendored
Normal file
9
third_party/tvl/net/crimp/default.nix
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
|
depot.third_party.naersk.buildPackage {
|
||||||
|
src = ./.;
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
openssl
|
||||||
|
pkgconfig
|
||||||
|
];
|
||||||
|
}
|
137
third_party/tvl/net/crimp/src/lib.rs
vendored
137
third_party/tvl/net/crimp/src/lib.rs
vendored
|
@ -33,9 +33,12 @@
|
||||||
//! use crimp::Request;
|
//! use crimp::Request;
|
||||||
//!
|
//!
|
||||||
//! let response = Request::get("http://httpbin.org/get")
|
//! let response = Request::get("http://httpbin.org/get")
|
||||||
//! .user_agent("crimp test suite").unwrap()
|
//! .user_agent("crimp test suite")
|
||||||
//! .send().unwrap()
|
//! .unwrap()
|
||||||
//! .as_string().unwrap();
|
//! .send()
|
||||||
|
//! .unwrap()
|
||||||
|
//! .as_string()
|
||||||
|
//! .unwrap();
|
||||||
//!
|
//!
|
||||||
//! println!("Status: {}\nBody: {}", response.status, response.body);
|
//! println!("Status: {}\nBody: {}", response.status, response.body);
|
||||||
//! # assert_eq!(response.status, 200);
|
//! # assert_eq!(response.status, 200);
|
||||||
|
@ -54,10 +57,9 @@
|
||||||
//!
|
//!
|
||||||
//! All optional features are enabled by default.
|
//! All optional features are enabled by default.
|
||||||
//!
|
//!
|
||||||
//! * `json`: Adds `Request::json` and `Response::as_json` methods
|
//! * `json`: Adds `Request::json` and `Response::as_json` methods which can be used for convenient
|
||||||
//! which can be used for convenient serialisation of
|
//! serialisation of request/response bodies using `serde_json`. This feature adds a dependency on
|
||||||
//! request/response bodies using `serde_json`. This feature adds a
|
//! the `serde` and `serde_json` crates.
|
||||||
//! dependency on the `serde` and `serde_json` crates.
|
|
||||||
//!
|
//!
|
||||||
//! ## Initialisation
|
//! ## Initialisation
|
||||||
//!
|
//!
|
||||||
|
@ -72,32 +74,42 @@
|
||||||
|
|
||||||
extern crate curl;
|
extern crate curl;
|
||||||
|
|
||||||
#[cfg(feature = "json")] extern crate serde;
|
#[cfg(feature = "json")]
|
||||||
#[cfg(feature = "json")] extern crate serde_json;
|
extern crate serde;
|
||||||
|
#[cfg(feature = "json")]
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
pub use curl::init;
|
pub use curl::init;
|
||||||
|
|
||||||
use curl::easy::{Auth, Easy, Form, List, Transfer, ReadError, WriteError};
|
use curl::easy::{Auth, Easy, Form, List, ReadError, Transfer, WriteError};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::string::{FromUtf8Error, ToString};
|
use std::string::{FromUtf8Error, ToString};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[cfg(feature = "json")] use serde::Serialize;
|
#[cfg(feature = "json")]
|
||||||
#[cfg(feature = "json")] use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
#[cfg(feature = "json")]
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
/// HTTP method to use for the request.
|
/// HTTP method to use for the request.
|
||||||
enum Method {
|
enum Method {
|
||||||
Get, Post, Put, Patch, Delete
|
Get,
|
||||||
|
Post,
|
||||||
|
Put,
|
||||||
|
Patch,
|
||||||
|
Delete,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Certificate types for client-certificate key pairs.
|
/// Certificate types for client-certificate key pairs.
|
||||||
pub enum CertType {
|
pub enum CertType {
|
||||||
P12, PEM, DER
|
P12,
|
||||||
|
PEM,
|
||||||
|
DER,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder structure for an HTTP request.
|
/// Builder structure for an HTTP request.
|
||||||
|
@ -145,7 +157,7 @@ pub struct Response<T> {
|
||||||
pub body: T,
|
pub body: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> Request<'a> {
|
impl<'a> Request<'a> {
|
||||||
/// Initiate an HTTP request with the given method and URL.
|
/// Initiate an HTTP request with the given method and URL.
|
||||||
fn new(method: Method, url: &'a str) -> Self {
|
fn new(method: Method, url: &'a str) -> Self {
|
||||||
Request {
|
Request {
|
||||||
|
@ -158,19 +170,29 @@ impl <'a> Request<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initiate a GET request with the given URL.
|
/// Initiate a GET request with the given URL.
|
||||||
pub fn get(url: &'a str) -> Self { Request::new(Method::Get, url) }
|
pub fn get(url: &'a str) -> Self {
|
||||||
|
Request::new(Method::Get, url)
|
||||||
|
}
|
||||||
|
|
||||||
/// Initiate a POST request with the given URL.
|
/// Initiate a POST request with the given URL.
|
||||||
pub fn post(url: &'a str) -> Self { Request::new(Method::Post, url) }
|
pub fn post(url: &'a str) -> Self {
|
||||||
|
Request::new(Method::Post, url)
|
||||||
|
}
|
||||||
|
|
||||||
/// Initiate a PUT request with the given URL.
|
/// Initiate a PUT request with the given URL.
|
||||||
pub fn put(url: &'a str) -> Self { Request::new(Method::Put, url) }
|
pub fn put(url: &'a str) -> Self {
|
||||||
|
Request::new(Method::Put, url)
|
||||||
|
}
|
||||||
|
|
||||||
/// Initiate a PATCH request with the given URL.
|
/// Initiate a PATCH request with the given URL.
|
||||||
pub fn patch(url: &'a str) -> Self { Request::new(Method::Patch, url) }
|
pub fn patch(url: &'a str) -> Self {
|
||||||
|
Request::new(Method::Patch, url)
|
||||||
|
}
|
||||||
|
|
||||||
/// Initiate a DELETE request with the given URL.
|
/// Initiate a DELETE request with the given URL.
|
||||||
pub fn delete(url: &'a str) -> Self { Request::new(Method::Delete, url) }
|
pub fn delete(url: &'a str) -> Self {
|
||||||
|
Request::new(Method::Delete, url)
|
||||||
|
}
|
||||||
|
|
||||||
/// Add an HTTP header to a request.
|
/// Add an HTTP header to a request.
|
||||||
pub fn header(mut self, k: &str, v: &str) -> Result<Self, curl::Error> {
|
pub fn header(mut self, k: &str, v: &str) -> Result<Self, curl::Error> {
|
||||||
|
@ -188,7 +210,8 @@ impl <'a> Request<'a> {
|
||||||
/// Set the `Authorization` header to a `Bearer` value with the
|
/// Set the `Authorization` header to a `Bearer` value with the
|
||||||
/// supplied token.
|
/// supplied token.
|
||||||
pub fn bearer_auth(mut self, token: &str) -> Result<Self, curl::Error> {
|
pub fn bearer_auth(mut self, token: &str) -> Result<Self, curl::Error> {
|
||||||
self.headers.append(&format!("Authorization: Bearer {}", token))?;
|
self.headers
|
||||||
|
.append(&format!("Authorization: Bearer {}", token))?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,8 +235,11 @@ impl <'a> Request<'a> {
|
||||||
/// Consult the documentation for the `ssl_cert` and `ssl_key`
|
/// Consult the documentation for the `ssl_cert` and `ssl_key`
|
||||||
/// functions in `curl::easy::Easy2` for details on supported
|
/// functions in `curl::easy::Easy2` for details on supported
|
||||||
/// formats and defaults.
|
/// formats and defaults.
|
||||||
pub fn tls_client_cert<P: AsRef<Path>>(mut self, cert_type: CertType, cert: P)
|
pub fn tls_client_cert<P: AsRef<Path>>(
|
||||||
-> Result<Self, curl::Error> {
|
mut self,
|
||||||
|
cert_type: CertType,
|
||||||
|
cert: P,
|
||||||
|
) -> Result<Self, curl::Error> {
|
||||||
self.handle.ssl_cert(cert)?;
|
self.handle.ssl_cert(cert)?;
|
||||||
self.handle.ssl_cert_type(match cert_type {
|
self.handle.ssl_cert_type(match cert_type {
|
||||||
CertType::P12 => "P12",
|
CertType::P12 => "P12",
|
||||||
|
@ -262,13 +288,17 @@ impl <'a> Request<'a> {
|
||||||
/// ```
|
/// ```
|
||||||
/// # use crimp::Request;
|
/// # use crimp::Request;
|
||||||
/// let response = Request::get("https://httpbin.org/get")
|
/// let response = Request::get("https://httpbin.org/get")
|
||||||
/// .with_handle(|mut handle| handle.referer("Example-Referer")).unwrap()
|
/// .with_handle(|mut handle| handle.referer("Example-Referer"))
|
||||||
/// .send().unwrap();
|
/// .unwrap()
|
||||||
|
/// .send()
|
||||||
|
/// .unwrap();
|
||||||
/// #
|
/// #
|
||||||
/// # assert!(response.is_success());
|
/// # assert!(response.is_success());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn with_handle<F>(mut self, function: F) -> Result<Self, curl::Error>
|
pub fn with_handle<F>(mut self, function: F) -> Result<Self, curl::Error>
|
||||||
where F: FnOnce(&mut Easy) -> Result<(), curl::Error> {
|
where
|
||||||
|
F: FnOnce(&mut Easy) -> Result<(), curl::Error>,
|
||||||
|
{
|
||||||
function(&mut self.handle)?;
|
function(&mut self.handle)?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
@ -293,12 +323,15 @@ impl <'a> Request<'a> {
|
||||||
/// let mut form = Form::new();
|
/// let mut form = Form::new();
|
||||||
/// form.part("some-name")
|
/// form.part("some-name")
|
||||||
/// .contents("some-data".as_bytes())
|
/// .contents("some-data".as_bytes())
|
||||||
/// .add().unwrap();
|
/// .add()
|
||||||
|
/// .unwrap();
|
||||||
///
|
///
|
||||||
/// let response = Request::post("https://httpbin.org/post")
|
/// let response = Request::post("https://httpbin.org/post")
|
||||||
/// .user_agent("crimp test suite").unwrap()
|
/// .user_agent("crimp test suite")
|
||||||
|
/// .unwrap()
|
||||||
/// .form(form)
|
/// .form(form)
|
||||||
/// .send().unwrap();
|
/// .send()
|
||||||
|
/// .unwrap();
|
||||||
/// #
|
/// #
|
||||||
/// # assert_eq!(200, response.status, "form POST should succeed");
|
/// # assert_eq!(200, response.status, "form POST should succeed");
|
||||||
/// # assert_eq!(
|
/// # assert_eq!(
|
||||||
|
@ -330,10 +363,10 @@ impl <'a> Request<'a> {
|
||||||
self.handle.url(self.url)?;
|
self.handle.url(self.url)?;
|
||||||
|
|
||||||
match self.method {
|
match self.method {
|
||||||
Method::Get => self.handle.get(true)?,
|
Method::Get => self.handle.get(true)?,
|
||||||
Method::Post => self.handle.post(true)?,
|
Method::Post => self.handle.post(true)?,
|
||||||
Method::Put => self.handle.put(true)?,
|
Method::Put => self.handle.put(true)?,
|
||||||
Method::Patch => self.handle.custom_request("PATCH")?,
|
Method::Patch => self.handle.custom_request("PATCH")?,
|
||||||
Method::Delete => self.handle.custom_request("DELETE")?,
|
Method::Delete => self.handle.custom_request("DELETE")?,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,21 +384,22 @@ impl <'a> Request<'a> {
|
||||||
|
|
||||||
// Optionally set content type if a body payload is configured
|
// Optionally set content type if a body payload is configured
|
||||||
// and configure the expected body size (or form payload).
|
// and configure the expected body size (or form payload).
|
||||||
match self.body {
|
match self.body {
|
||||||
Body::Bytes { content_type, data } => {
|
Body::Bytes { content_type, data } => {
|
||||||
self.handle.post_field_size(data.len() as u64)?;
|
self.handle.post_field_size(data.len() as u64)?;
|
||||||
self.headers.append(&format!("Content-Type: {}", content_type))?;
|
self.headers
|
||||||
},
|
.append(&format!("Content-Type: {}", content_type))?;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
Body::Json(ref data) => {
|
Body::Json(ref data) => {
|
||||||
self.handle.post_field_size(data.len() as u64)?;
|
self.handle.post_field_size(data.len() as u64)?;
|
||||||
self.headers.append("Content-Type: application/json")?;
|
self.headers.append("Content-Type: application/json")?;
|
||||||
},
|
}
|
||||||
|
|
||||||
// Do not set content-type header at all if there is no
|
// Do not set content-type header at all if there is no
|
||||||
// body, or if the form handler was invoked above.
|
// body, or if the form handler was invoked above.
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Configure headers on the request:
|
// Configure headers on the request:
|
||||||
|
@ -407,9 +441,7 @@ impl <'a> Request<'a> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
headers.insert(
|
headers.insert(split[0].trim().to_string(), split[1].trim().to_string());
|
||||||
split[0].trim().to_string(), split[1].trim().to_string()
|
|
||||||
);
|
|
||||||
true
|
true
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -427,7 +459,7 @@ impl <'a> Request<'a> {
|
||||||
Ok(Response {
|
Ok(Response {
|
||||||
status: self.handle.response_code()?,
|
status: self.handle.response_code()?,
|
||||||
headers,
|
headers,
|
||||||
body
|
body,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -438,13 +470,14 @@ impl <'a> Request<'a> {
|
||||||
///
|
///
|
||||||
/// As we manually set the expected upload size, cURL will call the
|
/// As we manually set the expected upload size, cURL will call the
|
||||||
/// read callback repeatedly until it has all the data it needs.
|
/// read callback repeatedly until it has all the data it needs.
|
||||||
fn chunked_read_function<'easy, 'data>(transfer: &mut Transfer<'easy, 'data>,
|
fn chunked_read_function<'easy, 'data>(
|
||||||
data: &'data [u8]) -> Result<(), curl::Error> {
|
transfer: &mut Transfer<'easy, 'data>,
|
||||||
|
data: &'data [u8],
|
||||||
|
) -> Result<(), curl::Error> {
|
||||||
let mut data = data;
|
let mut data = data;
|
||||||
|
|
||||||
transfer.read_function(move |mut into| {
|
transfer.read_function(move |mut into| {
|
||||||
let written = into.write(data)
|
let written = into.write(data).map_err(|_| ReadError::Abort)?;
|
||||||
.map_err(|_| ReadError::Abort)?;
|
|
||||||
|
|
||||||
data = &data[written..];
|
data = &data[written..];
|
||||||
|
|
||||||
|
@ -452,7 +485,7 @@ fn chunked_read_function<'easy, 'data>(transfer: &mut Transfer<'easy, 'data>,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T> Response<T> {
|
impl<T> Response<T> {
|
||||||
/// Check whether the status code of this HTTP response is a
|
/// Check whether the status code of this HTTP response is a
|
||||||
/// success (i.e. in the 200-299 range).
|
/// success (i.e. in the 200-299 range).
|
||||||
pub fn is_success(&self) -> bool {
|
pub fn is_success(&self) -> bool {
|
||||||
|
@ -466,9 +499,11 @@ impl <T> Response<T> {
|
||||||
/// This function exists for convenience to avoid having to write
|
/// This function exists for convenience to avoid having to write
|
||||||
/// repetitive `if !response.is_success() { ... }` blocks.
|
/// repetitive `if !response.is_success() { ... }` blocks.
|
||||||
pub fn error_for_status<F, E>(self, closure: F) -> Result<Self, E>
|
pub fn error_for_status<F, E>(self, closure: F) -> Result<Self, E>
|
||||||
where F: FnOnce(Self) -> E {
|
where
|
||||||
|
F: FnOnce(Self) -> E,
|
||||||
|
{
|
||||||
if !self.is_success() {
|
if !self.is_success() {
|
||||||
return Err(closure(self))
|
return Err(closure(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
|
93
third_party/tvl/net/crimp/src/tests.rs
vendored
93
third_party/tvl/net/crimp/src/tests.rs
vendored
|
@ -6,7 +6,7 @@
|
||||||
// docker run --rm -p 4662:80 kennethreitz/httpbin
|
// docker run --rm -p 4662:80 kennethreitz/httpbin
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use serde_json::{Value, json};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
// These tests check whether the correct HTTP method is used in the
|
// These tests check whether the correct HTTP method is used in the
|
||||||
// requests.
|
// requests.
|
||||||
|
@ -14,7 +14,8 @@ use serde_json::{Value, json};
|
||||||
#[test]
|
#[test]
|
||||||
fn test_http_get() {
|
fn test_http_get() {
|
||||||
let resp = Request::get("http://127.0.0.1:4662/get")
|
let resp = Request::get("http://127.0.0.1:4662/get")
|
||||||
.send().expect("failed to send request");
|
.send()
|
||||||
|
.expect("failed to send request");
|
||||||
|
|
||||||
assert!(resp.is_success(), "request should have succeeded");
|
assert!(resp.is_success(), "request should have succeeded");
|
||||||
}
|
}
|
||||||
|
@ -22,7 +23,8 @@ fn test_http_get() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_http_delete() {
|
fn test_http_delete() {
|
||||||
let resp = Request::delete("http://127.0.0.1:4662/delete")
|
let resp = Request::delete("http://127.0.0.1:4662/delete")
|
||||||
.send().expect("failed to send request");
|
.send()
|
||||||
|
.expect("failed to send request");
|
||||||
|
|
||||||
assert_eq!(200, resp.status, "response status should be 200 OK");
|
assert_eq!(200, resp.status, "response status should be 200 OK");
|
||||||
}
|
}
|
||||||
|
@ -30,7 +32,8 @@ fn test_http_delete() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_http_put() {
|
fn test_http_put() {
|
||||||
let resp = Request::put("http://127.0.0.1:4662/put")
|
let resp = Request::put("http://127.0.0.1:4662/put")
|
||||||
.send().expect("failed to send request");
|
.send()
|
||||||
|
.expect("failed to send request");
|
||||||
|
|
||||||
assert_eq!(200, resp.status, "response status should be 200 OK");
|
assert_eq!(200, resp.status, "response status should be 200 OK");
|
||||||
}
|
}
|
||||||
|
@ -38,7 +41,8 @@ fn test_http_put() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_http_patch() {
|
fn test_http_patch() {
|
||||||
let resp = Request::patch("http://127.0.0.1:4662/patch")
|
let resp = Request::patch("http://127.0.0.1:4662/patch")
|
||||||
.send().expect("failed to send request");
|
.send()
|
||||||
|
.expect("failed to send request");
|
||||||
|
|
||||||
assert_eq!(200, resp.status, "response status should be 200 OK");
|
assert_eq!(200, resp.status, "response status should be 200 OK");
|
||||||
}
|
}
|
||||||
|
@ -50,18 +54,25 @@ fn test_http_patch() {
|
||||||
fn test_http_post() {
|
fn test_http_post() {
|
||||||
let body = "test body";
|
let body = "test body";
|
||||||
let response = Request::post("http://127.0.0.1:4662/post")
|
let response = Request::post("http://127.0.0.1:4662/post")
|
||||||
.user_agent("crimp test suite").expect("failed to set user-agent")
|
.user_agent("crimp test suite")
|
||||||
.timeout(Duration::from_secs(5)).expect("failed to set request timeout")
|
.expect("failed to set user-agent")
|
||||||
|
.timeout(Duration::from_secs(5))
|
||||||
|
.expect("failed to set request timeout")
|
||||||
.body("text/plain", &body.as_bytes())
|
.body("text/plain", &body.as_bytes())
|
||||||
.send().expect("failed to send request")
|
.send()
|
||||||
.as_json::<Value>().expect("failed to deserialize response");
|
.expect("failed to send request")
|
||||||
|
.as_json::<Value>()
|
||||||
|
.expect("failed to deserialize response");
|
||||||
|
|
||||||
let data = response.body;
|
let data = response.body;
|
||||||
|
|
||||||
assert_eq!(200, response.status, "response status should be 200 OK");
|
assert_eq!(200, response.status, "response status should be 200 OK");
|
||||||
|
|
||||||
assert_eq!(data.get("data").unwrap(), &json!("test body"),
|
assert_eq!(
|
||||||
"test body should have been POSTed");
|
data.get("data").unwrap(),
|
||||||
|
&json!("test body"),
|
||||||
|
"test body should have been POSTed"
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
data.get("headers").unwrap().get("Content-Type").unwrap(),
|
data.get("headers").unwrap().get("Content-Type").unwrap(),
|
||||||
|
@ -70,26 +81,34 @@ fn test_http_post() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "json")] #[test]
|
#[cfg(feature = "json")]
|
||||||
|
#[test]
|
||||||
fn test_http_post_json() {
|
fn test_http_post_json() {
|
||||||
let body = json!({
|
let body = json!({
|
||||||
"purpose": "testing!"
|
"purpose": "testing!"
|
||||||
});
|
});
|
||||||
|
|
||||||
let response = Request::post("http://127.0.0.1:4662/post")
|
let response = Request::post("http://127.0.0.1:4662/post")
|
||||||
.user_agent("crimp test suite").expect("failed to set user-agent")
|
.user_agent("crimp test suite")
|
||||||
.timeout(Duration::from_secs(5)).expect("failed to set request timeout")
|
.expect("failed to set user-agent")
|
||||||
.json(&body).expect("request serialization failed")
|
.timeout(Duration::from_secs(5))
|
||||||
.send().expect("failed to send request")
|
.expect("failed to set request timeout")
|
||||||
.as_json::<Value>().expect("failed to deserialize response");
|
.json(&body)
|
||||||
|
.expect("request serialization failed")
|
||||||
|
.send()
|
||||||
|
.expect("failed to send request")
|
||||||
|
.as_json::<Value>()
|
||||||
|
.expect("failed to deserialize response");
|
||||||
|
|
||||||
let data = response.body;
|
let data = response.body;
|
||||||
|
|
||||||
assert_eq!(200, response.status, "response status should be 200 OK");
|
assert_eq!(200, response.status, "response status should be 200 OK");
|
||||||
|
|
||||||
assert_eq!(data.get("json").unwrap(), &body,
|
assert_eq!(
|
||||||
"test body should have been POSTed");
|
data.get("json").unwrap(),
|
||||||
|
&body,
|
||||||
|
"test body should have been POSTed"
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
data.get("headers").unwrap().get("Content-Type").unwrap(),
|
data.get("headers").unwrap().get("Content-Type").unwrap(),
|
||||||
|
@ -104,8 +123,10 @@ fn test_http_post_json() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bearer_auth() {
|
fn test_bearer_auth() {
|
||||||
let response = Request::get("http://127.0.0.1:4662/bearer")
|
let response = Request::get("http://127.0.0.1:4662/bearer")
|
||||||
.bearer_auth("some-token").expect("failed to set auth header")
|
.bearer_auth("some-token")
|
||||||
.send().expect("failed to send request");
|
.expect("failed to set auth header")
|
||||||
|
.send()
|
||||||
|
.expect("failed to send request");
|
||||||
|
|
||||||
assert!(response.is_success(), "authorized request should succeed");
|
assert!(response.is_success(), "authorized request should succeed");
|
||||||
}
|
}
|
||||||
|
@ -115,8 +136,10 @@ fn test_basic_auth() {
|
||||||
let request = Request::get("http://127.0.0.1:4662/basic-auth/alan_watts/oneness");
|
let request = Request::get("http://127.0.0.1:4662/basic-auth/alan_watts/oneness");
|
||||||
|
|
||||||
let response = request
|
let response = request
|
||||||
.basic_auth("alan_watts", "oneness").expect("failed to set auth header")
|
.basic_auth("alan_watts", "oneness")
|
||||||
.send().expect("failed to send request");
|
.expect("failed to set auth header")
|
||||||
|
.send()
|
||||||
|
.expect("failed to send request");
|
||||||
|
|
||||||
assert!(response.is_success(), "authorized request should succeed");
|
assert!(response.is_success(), "authorized request should succeed");
|
||||||
}
|
}
|
||||||
|
@ -129,14 +152,20 @@ fn test_large_body() {
|
||||||
|
|
||||||
let resp = Request::post("http://127.0.0.1:4662/post")
|
let resp = Request::post("http://127.0.0.1:4662/post")
|
||||||
.body("application/octet-stream", &[0; BODY_SIZE])
|
.body("application/octet-stream", &[0; BODY_SIZE])
|
||||||
.send().expect("sending request")
|
.send()
|
||||||
.as_json::<Value>().expect("JSON deserialisation");
|
.expect("sending request")
|
||||||
|
.as_json::<Value>()
|
||||||
|
.expect("JSON deserialisation");
|
||||||
|
|
||||||
// httpbin returns the uploaded data as a string in the `data`
|
// httpbin returns the uploaded data as a string in the `data`
|
||||||
// field.
|
// field.
|
||||||
let data = resp.body.get("data").unwrap().as_str().unwrap();
|
let data = resp.body.get("data").unwrap().as_str().unwrap();
|
||||||
|
|
||||||
assert_eq!(BODY_SIZE, data.len(), "uploaded data length should be correct");
|
assert_eq!(
|
||||||
|
BODY_SIZE,
|
||||||
|
data.len(),
|
||||||
|
"uploaded data length should be correct"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests for various other features.
|
// Tests for various other features.
|
||||||
|
@ -144,9 +173,13 @@ fn test_large_body() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_for_status() {
|
fn test_error_for_status() {
|
||||||
let response = Request::get("http://127.0.0.1:4662/patch")
|
let response = Request::get("http://127.0.0.1:4662/patch")
|
||||||
.send().expect("failed to send request")
|
.send()
|
||||||
|
.expect("failed to send request")
|
||||||
.error_for_status(|resp| format!("Response error code: {}", resp.status));
|
.error_for_status(|resp| format!("Response error code: {}", resp.status));
|
||||||
|
|
||||||
assert_eq!(Err("Response error code: 405".into()), response,
|
assert_eq!(
|
||||||
"returned error should be converted into Result::Err");
|
Err("Response error code: 405".into()),
|
||||||
|
response,
|
||||||
|
"returned error should be converted into Result::Err"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
2
third_party/tvl/nix/binify/default.nix
vendored
2
third_party/tvl/nix/binify/default.nix
vendored
|
@ -10,7 +10,7 @@
|
||||||
# with `binify { exe = …; name = "hello" }`.
|
# with `binify { exe = …; name = "hello" }`.
|
||||||
{ exe, name }:
|
{ exe, name }:
|
||||||
|
|
||||||
pkgs.runCommandLocal "${name}-bin" {} ''
|
pkgs.runCommandLocal "${name}-bin" { } ''
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
ln -sT ${lib.escapeShellArg exe} $out/bin/${lib.escapeShellArg name}
|
ln -sT ${lib.escapeShellArg exe} $out/bin/${lib.escapeShellArg name}
|
||||||
''
|
''
|
||||||
|
|
4
third_party/tvl/nix/bufCheck/default.nix
vendored
4
third_party/tvl/nix/bufCheck/default.nix
vendored
|
@ -3,7 +3,7 @@
|
||||||
{ depot, pkgs, ... }:
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
pkgs.writeShellScriptBin "ci-buf-check" ''
|
pkgs.writeShellScriptBin "ci-buf-check" ''
|
||||||
${depot.third_party.bufbuild}/bin/buf check lint --input "${depot.depotPath}"
|
${depot.third_party.bufbuild}/bin/buf check lint --input .
|
||||||
# Report-only
|
# Report-only
|
||||||
${depot.third_party.bufbuild}/bin/buf check breaking --input "${depot.depotPath}" --against-input "${depot.depotPath}/.git#branch=canon" || true
|
${depot.third_party.bufbuild}/bin/buf check breaking --input "." --against-input "./.git#branch=canon" || true
|
||||||
''
|
''
|
||||||
|
|
132
third_party/tvl/nix/buildGo/default.nix
vendored
132
third_party/tvl/nix/buildGo/default.nix
vendored
|
@ -4,9 +4,9 @@
|
||||||
# buildGo provides Nix functions to build Go packages in the style of Bazel's
|
# buildGo provides Nix functions to build Go packages in the style of Bazel's
|
||||||
# rules_go.
|
# rules_go.
|
||||||
|
|
||||||
{ pkgs ? import <nixpkgs> {}
|
{ pkgs ? import <nixpkgs> { }
|
||||||
, gopkgs
|
, ...
|
||||||
, ... }:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (builtins)
|
inherit (builtins)
|
||||||
|
@ -22,7 +22,7 @@ let
|
||||||
replaceStrings
|
replaceStrings
|
||||||
toString;
|
toString;
|
||||||
|
|
||||||
inherit (pkgs) lib go runCommand fetchFromGitHub protobuf symlinkJoin removeReferencesTo;
|
inherit (pkgs) lib go runCommand fetchFromGitHub protobuf symlinkJoin;
|
||||||
|
|
||||||
# Helpers for low-level Go compiler invocations
|
# Helpers for low-level Go compiler invocations
|
||||||
spaceOut = lib.concatStringsSep " ";
|
spaceOut = lib.concatStringsSep " ";
|
||||||
|
@ -41,9 +41,7 @@ let
|
||||||
|
|
||||||
xFlags = x_defs: spaceOut (map (k: "-X ${k}=${x_defs."${k}"}") (attrNames x_defs));
|
xFlags = x_defs: spaceOut (map (k: "-X ${k}=${x_defs."${k}"}") (attrNames x_defs));
|
||||||
|
|
||||||
pathToName = p: replaceStrings ["/"] ["_"] (toString p);
|
pathToName = p: replaceStrings [ "/" ] [ "_" ] (toString p);
|
||||||
|
|
||||||
removeRefs = refs: "${removeReferencesTo}/bin/remove-references-to ${lib.concatMapStrings (ref: " -t ${ref}") ([ go ] ++ refs)}";
|
|
||||||
|
|
||||||
# Add an `overrideGo` attribute to a function result that works
|
# Add an `overrideGo` attribute to a function result that works
|
||||||
# similar to `overrideAttrs`, but is used specifically for the
|
# similar to `overrideAttrs`, but is used specifically for the
|
||||||
|
@ -55,51 +53,52 @@ let
|
||||||
# High-level build functions
|
# High-level build functions
|
||||||
|
|
||||||
# Build a Go program out of the specified files and dependencies.
|
# Build a Go program out of the specified files and dependencies.
|
||||||
program = { name, srcs, deps ? [], x_defs ? {} }:
|
program = { name, srcs, deps ? [ ], x_defs ? { } }:
|
||||||
let uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
let uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
||||||
in runCommand name {} ''
|
in runCommand name { } ''
|
||||||
${go}/bin/go tool compile -o ${name}.a -trimpath="$PWD;${go}" ${includeSources uniqueDeps} ${spaceOut srcs}
|
${go}/bin/go tool compile -o ${name}.a -trimpath=$PWD -trimpath=${go} ${includeSources uniqueDeps} ${spaceOut srcs}
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
export GOROOT_FINAL=go
|
export GOROOT_FINAL=go
|
||||||
${go}/bin/go tool link -o $out/bin/${name} -buildid nix ${xFlags x_defs} ${includeLibs uniqueDeps} ${name}.a
|
${go}/bin/go tool link -o $out/bin/${name} -buildid nix ${xFlags x_defs} ${includeLibs uniqueDeps} ${name}.a
|
||||||
${removeRefs srcs} $out/bin/${name}
|
'';
|
||||||
'';
|
|
||||||
|
|
||||||
# Build a Go library assembled out of the specified files.
|
# Build a Go library assembled out of the specified files.
|
||||||
#
|
#
|
||||||
# This outputs both the sources and compiled binary, as both are
|
# This outputs both the sources and compiled binary, as both are
|
||||||
# needed when downstream packages depend on it.
|
# needed when downstream packages depend on it.
|
||||||
package = { name, srcs, deps ? [], path ? name, sfiles ? [] }:
|
package = { name, srcs, deps ? [ ], path ? name, sfiles ? [ ] }:
|
||||||
let
|
let
|
||||||
uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
||||||
|
|
||||||
# The build steps below need to be executed conditionally for Go
|
# The build steps below need to be executed conditionally for Go
|
||||||
# assembly if the analyser detected any *.s files.
|
# assembly if the analyser detected any *.s files.
|
||||||
#
|
#
|
||||||
# This is required for several popular packages (e.g. x/sys).
|
# This is required for several popular packages (e.g. x/sys).
|
||||||
ifAsm = do: lib.optionalString (sfiles != []) do;
|
ifAsm = do: lib.optionalString (sfiles != [ ]) do;
|
||||||
asmBuild = ifAsm ''
|
asmBuild = ifAsm ''
|
||||||
${go}/bin/go tool asm -trimpath $PWD -I $PWD -I ${go}/share/go/pkg/include -D GOOS_linux -D GOARCH_amd64 -gensymabis -o ./symabis ${spaceOut sfiles}
|
${go}/bin/go tool asm -trimpath $PWD -I $PWD -I ${go}/share/go/pkg/include -D GOOS_linux -D GOARCH_amd64 -gensymabis -o ./symabis ${spaceOut sfiles}
|
||||||
${go}/bin/go tool asm -trimpath $PWD -I $PWD -I ${go}/share/go/pkg/include -D GOOS_linux -D GOARCH_amd64 -o ./asm.o ${spaceOut sfiles}
|
${go}/bin/go tool asm -trimpath $PWD -I $PWD -I ${go}/share/go/pkg/include -D GOOS_linux -D GOARCH_amd64 -o ./asm.o ${spaceOut sfiles}
|
||||||
'';
|
'';
|
||||||
asmLink = ifAsm "-symabis ./symabis -asmhdr $out/go_asm.h";
|
asmLink = ifAsm "-symabis ./symabis -asmhdr $out/go_asm.h";
|
||||||
asmPack = ifAsm ''
|
asmPack = ifAsm ''
|
||||||
${go}/bin/go tool pack r $out/${path}.a ./asm.o
|
${go}/bin/go tool pack r $out/${path}.a ./asm.o
|
||||||
'';
|
'';
|
||||||
|
|
||||||
gopkg = (runCommand "golib-${name}" {} ''
|
gopkg = (runCommand "golib-${name}" { } ''
|
||||||
mkdir -p $out/${path}
|
mkdir -p $out/${path}
|
||||||
${srcList path (map (s: "${s}") srcs)}
|
${srcList path (map (s: "${s}") srcs)}
|
||||||
${asmBuild}
|
${asmBuild}
|
||||||
${go}/bin/go tool compile -pack ${asmLink} -o $out/${path}.a -trimpath="$PWD;${go}" -p ${path} ${includeSources uniqueDeps} ${spaceOut srcs}
|
${go}/bin/go tool compile -pack ${asmLink} -o $out/${path}.a -trimpath=$PWD -trimpath=${go} -p ${path} ${includeSources uniqueDeps} ${spaceOut srcs}
|
||||||
${asmPack}
|
${asmPack}
|
||||||
${removeRefs srcs} $out/${path}.a
|
'').overrideAttrs (_: {
|
||||||
'') // {
|
passthru = {
|
||||||
inherit gopkg;
|
inherit gopkg;
|
||||||
goDeps = uniqueDeps;
|
goDeps = uniqueDeps;
|
||||||
goImportPath = path;
|
goImportPath = path;
|
||||||
};
|
};
|
||||||
in gopkg;
|
});
|
||||||
|
in
|
||||||
|
gopkg;
|
||||||
|
|
||||||
# Build a tree of Go libraries out of an external Go source
|
# Build a tree of Go libraries out of an external Go source
|
||||||
# directory that follows the standard Go layout and was not built
|
# directory that follows the standard Go layout and was not built
|
||||||
|
@ -111,50 +110,31 @@ let
|
||||||
|
|
||||||
# Import support libraries needed for protobuf & gRPC support
|
# Import support libraries needed for protobuf & gRPC support
|
||||||
protoLibs = import ./proto.nix {
|
protoLibs = import ./proto.nix {
|
||||||
inherit gopkgs;
|
inherit external;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Build a Go library out of the specified protobuf definition.
|
# Build a Go library out of the specified protobuf definition.
|
||||||
proto = { name, proto ? null, protos ? [ proto ], path ? name, goPackage ? name, withGrpc ? false, extraSrcs ? [], extraDeps ? [] }:
|
proto = { name, proto, path ? name, goPackage ? name, extraDeps ? [ ] }: (makeOverridable package) {
|
||||||
let
|
|
||||||
protosDir = runCommand "protos" {} ''
|
|
||||||
mkdir $out
|
|
||||||
${lib.concatMapStrings (p: "cp ${p} $out/${baseNameOf p}\n") protos}
|
|
||||||
'';
|
|
||||||
mname = prefix: lib.concatMapStrings (p: "${prefix}M${baseNameOf p}=${path} ") protos;
|
|
||||||
in (makeOverridable package) {
|
|
||||||
inherit name path;
|
inherit name path;
|
||||||
deps = [ protoLibs.goProto.proto.gopkg ] ++ extraDeps;
|
deps = [ protoLibs.goProto.proto.gopkg ] ++ extraDeps;
|
||||||
srcs = lib.concatMap (proto: lib.singleton (runCommand "goproto-${name}-${baseNameOf proto}.pb.go" {} ''
|
srcs = lib.singleton (runCommand "goproto-${name}.pb.go" { } ''
|
||||||
${protobuf}/bin/protoc \
|
cp ${proto} ${baseNameOf proto}
|
||||||
-I ${protosDir} \
|
${protobuf}/bin/protoc --plugin=${protoLibs.goProto.protoc-gen-go.gopkg}/bin/protoc-gen-go \
|
||||||
--plugin=${protoLibs.goProto.cmd.protoc-gen-go.gopkg}/bin/protoc-gen-go \
|
--go_out=plugins=grpc,import_path=${baseNameOf path}:. ${baseNameOf proto}
|
||||||
--go_out=. \
|
mv ./${goPackage}/*.pb.go $out
|
||||||
--go_opt=paths=source_relative \
|
'');
|
||||||
${mname "--go_opt="} \
|
|
||||||
${protosDir}/${baseNameOf proto}
|
|
||||||
mv ./*.pb.go $out
|
|
||||||
'') ++ lib.optional withGrpc (runCommand "gogrpcproto-${name}-${baseNameOf proto}.pb.go" {} ''
|
|
||||||
${protobuf}/bin/protoc \
|
|
||||||
-I ${protosDir} \
|
|
||||||
--plugin=${protoLibs.goGrpc.cmd.protoc-gen-go-grpc.gopkg}/bin/protoc-gen-go-grpc \
|
|
||||||
--go-grpc_out=. \
|
|
||||||
--go-grpc_opt=paths=source_relative \
|
|
||||||
${mname "--go-grpc_opt="} \
|
|
||||||
${protosDir}/${baseNameOf proto}
|
|
||||||
mv ./*.pb.go $out 2>/dev/null || echo "package ${goPackage}" >> $out
|
|
||||||
'')) protos ++ extraSrcs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Build a Go library out of the specified gRPC definition.
|
# Build a Go library out of the specified gRPC definition.
|
||||||
grpc = { extraDeps ? [], ... }@args: proto (args // { withGrpc = true; extraDeps = extraDeps ++ [ protoLibs.goGrpc.gopkg ]; });
|
grpc = args: proto (args // { extraDeps = [ protoLibs.goGrpc.gopkg ]; });
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# Only the high-level builder functions are exposed, but made
|
# Only the high-level builder functions are exposed, but made
|
||||||
# overrideable.
|
# overrideable.
|
||||||
program = makeOverridable program;
|
program = makeOverridable program;
|
||||||
package = makeOverridable package;
|
package = makeOverridable package;
|
||||||
proto = proto;
|
proto = makeOverridable proto;
|
||||||
grpc = makeOverridable grpc;
|
grpc = makeOverridable grpc;
|
||||||
external = makeOverridable external;
|
external = makeOverridable external;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
# users a quick introduction to how to use buildGo.
|
# users a quick introduction to how to use buildGo.
|
||||||
|
|
||||||
let
|
let
|
||||||
buildGo = import ../default.nix {};
|
buildGo = import ../default.nix { };
|
||||||
|
|
||||||
# Example use of buildGo.package, which creates an importable Go
|
# Example use of buildGo.package, which creates an importable Go
|
||||||
# package from the specified source files.
|
# package from the specified source files.
|
||||||
|
@ -29,7 +29,8 @@ let
|
||||||
# Example use of buildGo.program, which builds an executable using
|
# Example use of buildGo.program, which builds an executable using
|
||||||
# the specified name and dependencies (which in turn must have been
|
# the specified name and dependencies (which in turn must have been
|
||||||
# created via buildGo.package etc.)
|
# created via buildGo.package etc.)
|
||||||
in buildGo.program {
|
in
|
||||||
|
buildGo.program {
|
||||||
name = "example";
|
name = "example";
|
||||||
|
|
||||||
srcs = [
|
srcs = [
|
||||||
|
|
48
third_party/tvl/nix/buildGo/external/default.nix
vendored
48
third_party/tvl/nix/buildGo/external/default.nix
vendored
|
@ -17,12 +17,12 @@ let
|
||||||
|
|
||||||
inherit (pkgs) lib runCommand go jq ripgrep;
|
inherit (pkgs) lib runCommand go jq ripgrep;
|
||||||
|
|
||||||
pathToName = p: replaceStrings ["/"] ["_"] (toString p);
|
pathToName = p: replaceStrings [ "/" ] [ "_" ] (toString p);
|
||||||
|
|
||||||
# Collect all non-vendored dependencies from the Go standard library
|
# Collect all non-vendored dependencies from the Go standard library
|
||||||
# into a file that can be used to filter them out when processing
|
# into a file that can be used to filter them out when processing
|
||||||
# dependencies.
|
# dependencies.
|
||||||
stdlibPackages = runCommand "stdlib-pkgs.json" {} ''
|
stdlibPackages = runCommand "stdlib-pkgs.json" { } ''
|
||||||
export HOME=$PWD
|
export HOME=$PWD
|
||||||
export GOPATH=/dev/null
|
export GOPATH=/dev/null
|
||||||
${go}/bin/go list std | \
|
${go}/bin/go list std | \
|
||||||
|
@ -45,20 +45,28 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
mkset = path: value:
|
mkset = path: value:
|
||||||
if path == [] then { gopkg = value; }
|
if path == [ ] then { gopkg = value; }
|
||||||
else { "${head path}" = mkset (tail path) value; };
|
else { "${head path}" = mkset (tail path) value; };
|
||||||
|
|
||||||
last = l: elemAt l ((length l) - 1);
|
last = l: elemAt l ((length l) - 1);
|
||||||
|
|
||||||
toPackage = self: src: path: depMap: entry:
|
toPackage = self: src: path: depMap: entry:
|
||||||
let
|
let
|
||||||
localDeps = map (d: lib.attrByPath (d ++ [ "gopkg" ]) (
|
localDeps = map
|
||||||
throw "missing local dependency '${lib.concatStringsSep "." d}' in '${path}'"
|
(d: lib.attrByPath (d ++ [ "gopkg" ])
|
||||||
) self) entry.localDeps;
|
(
|
||||||
|
throw "missing local dependency '${lib.concatStringsSep "." d}' in '${path}'"
|
||||||
|
)
|
||||||
|
self)
|
||||||
|
entry.localDeps;
|
||||||
|
|
||||||
foreignDeps = map (d: lib.attrByPath [ d ] (
|
foreignDeps = map
|
||||||
throw "missing foreign dependency '${d}' in '${path}'"
|
(d: lib.attrByPath [ d.path ]
|
||||||
) depMap) entry.foreignDeps;
|
(
|
||||||
|
throw "missing foreign dependency '${d.path}' in '${path}, imported at ${d.position}'"
|
||||||
|
)
|
||||||
|
depMap)
|
||||||
|
entry.foreignDeps;
|
||||||
|
|
||||||
args = {
|
args = {
|
||||||
srcs = map (f: src + ("/" + f)) entry.files;
|
srcs = map (f: src + ("/" + f)) entry.files;
|
||||||
|
@ -74,22 +82,28 @@ let
|
||||||
binArgs = args // {
|
binArgs = args // {
|
||||||
name = (last ((lib.splitString "/" path) ++ entry.locator));
|
name = (last ((lib.splitString "/" path) ++ entry.locator));
|
||||||
};
|
};
|
||||||
in if entry.isCommand then (program binArgs) else (package libArgs);
|
in
|
||||||
|
if entry.isCommand then (program binArgs) else (package libArgs);
|
||||||
|
|
||||||
in { src, path, deps ? [] }: let
|
in
|
||||||
|
{ src, path, deps ? [ ] }:
|
||||||
|
let
|
||||||
# Build a map of dependencies (from their import paths to their
|
# Build a map of dependencies (from their import paths to their
|
||||||
# derivation) so that they can be conditionally imported only in
|
# derivation) so that they can be conditionally imported only in
|
||||||
# sub-packages that require them.
|
# sub-packages that require them.
|
||||||
depMap = listToAttrs (map (d: {
|
depMap = listToAttrs (map
|
||||||
name = d.goImportPath;
|
(d: {
|
||||||
value = d;
|
name = d.goImportPath;
|
||||||
}) (map (d: d.gopkg) deps));
|
value = d;
|
||||||
|
})
|
||||||
|
(map (d: d.gopkg) deps));
|
||||||
|
|
||||||
name = pathToName path;
|
name = pathToName path;
|
||||||
analysisOutput = runCommand "${name}-structure.json" {} ''
|
analysisOutput = runCommand "${name}-structure.json" { } ''
|
||||||
${analyser}/bin/analyser -path ${path} -source ${src} > $out
|
${analyser}/bin/analyser -path ${path} -source ${src} > $out
|
||||||
'';
|
'';
|
||||||
analysis = fromJSON (readFile analysisOutput);
|
analysis = fromJSON (readFile analysisOutput);
|
||||||
in lib.fix(self: foldl' lib.recursiveUpdate {} (
|
in
|
||||||
|
lib.fix (self: foldl' lib.recursiveUpdate { } (
|
||||||
map (entry: mkset entry.locator (toPackage self src path depMap entry)) analysis
|
map (entry: mkset entry.locator (toPackage self src path depMap entry)) analysis
|
||||||
))
|
))
|
||||||
|
|
29
third_party/tvl/nix/buildGo/external/main.go
vendored
29
third_party/tvl/nix/buildGo/external/main.go
vendored
|
@ -29,13 +29,19 @@ var stdlibList string
|
||||||
// Return information includes the local (relative from project root)
|
// Return information includes the local (relative from project root)
|
||||||
// and external (none-stdlib) dependencies of this package.
|
// and external (none-stdlib) dependencies of this package.
|
||||||
type pkg struct {
|
type pkg struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Locator []string `json:"locator"`
|
Locator []string `json:"locator"`
|
||||||
Files []string `json:"files"`
|
Files []string `json:"files"`
|
||||||
SFiles []string `json:"sfiles"`
|
SFiles []string `json:"sfiles"`
|
||||||
LocalDeps [][]string `json:"localDeps"`
|
LocalDeps [][]string `json:"localDeps"`
|
||||||
ForeignDeps []string `json:"foreignDeps"`
|
ForeignDeps []foreignDep `json:"foreignDeps"`
|
||||||
IsCommand bool `json:"isCommand"`
|
IsCommand bool `json:"isCommand"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type foreignDep struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
// filename, column and line number of the import, if known
|
||||||
|
Position string `json:"position"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// findGoDirs returns a filepath.WalkFunc that identifies all
|
// findGoDirs returns a filepath.WalkFunc that identifies all
|
||||||
|
@ -88,7 +94,7 @@ func analysePackage(root, source, importpath string, stdlib map[string]bool) (pk
|
||||||
}
|
}
|
||||||
|
|
||||||
local := [][]string{}
|
local := [][]string{}
|
||||||
foreign := []string{}
|
foreign := []foreignDep{}
|
||||||
|
|
||||||
for _, i := range p.Imports {
|
for _, i := range p.Imports {
|
||||||
if stdlib[i] {
|
if stdlib[i] {
|
||||||
|
@ -100,7 +106,12 @@ func analysePackage(root, source, importpath string, stdlib map[string]bool) (pk
|
||||||
} else if strings.HasPrefix(i, importpath+"/") {
|
} else if strings.HasPrefix(i, importpath+"/") {
|
||||||
local = append(local, strings.Split(strings.TrimPrefix(i, importpath+"/"), "/"))
|
local = append(local, strings.Split(strings.TrimPrefix(i, importpath+"/"), "/"))
|
||||||
} else {
|
} else {
|
||||||
foreign = append(foreign, i)
|
// The import positions is a map keyed on the import name.
|
||||||
|
// The value is a list, presumably because an import can appear
|
||||||
|
// multiple times in a package. Let’s just take the first one,
|
||||||
|
// should be enough for a good error message.
|
||||||
|
firstPos := p.ImportPos[i][0].String()
|
||||||
|
foreign = append(foreign, foreignDep{Path: i, Position: firstPos})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
81
third_party/tvl/nix/buildGo/proto.nix
vendored
81
third_party/tvl/nix/buildGo/proto.nix
vendored
|
@ -4,11 +4,84 @@
|
||||||
# This file provides derivations for the dependencies of a gRPC
|
# This file provides derivations for the dependencies of a gRPC
|
||||||
# service in Go.
|
# service in Go.
|
||||||
|
|
||||||
{ gopkgs }:
|
{ external }:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (builtins) fetchGit map;
|
inherit (builtins) fetchGit map;
|
||||||
in rec {
|
in
|
||||||
goProto = gopkgs."google.golang.org".protobuf;
|
rec {
|
||||||
goGrpc = gopkgs."google.golang.org".grpc;
|
goProto = external {
|
||||||
|
path = "github.com/golang/protobuf";
|
||||||
|
src = fetchGit {
|
||||||
|
url = "https://github.com/golang/protobuf";
|
||||||
|
rev = "ed6926b37a637426117ccab59282c3839528a700";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
xnet = external {
|
||||||
|
path = "golang.org/x/net";
|
||||||
|
|
||||||
|
src = fetchGit {
|
||||||
|
url = "https://go.googlesource.com/net";
|
||||||
|
rev = "ffdde105785063a81acd95bdf89ea53f6e0aac2d";
|
||||||
|
};
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
xtext.secure.bidirule
|
||||||
|
xtext.unicode.bidi
|
||||||
|
xtext.unicode.norm
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
xsys = external {
|
||||||
|
path = "golang.org/x/sys";
|
||||||
|
src = fetchGit {
|
||||||
|
url = "https://go.googlesource.com/sys";
|
||||||
|
rev = "bd437916bb0eb726b873ee8e9b2dcf212d32e2fd";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
xtext = external {
|
||||||
|
path = "golang.org/x/text";
|
||||||
|
src = fetchGit {
|
||||||
|
url = "https://go.googlesource.com/text";
|
||||||
|
rev = "cbf43d21aaebfdfeb81d91a5f444d13a3046e686";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
genproto = external {
|
||||||
|
path = "google.golang.org/genproto";
|
||||||
|
src = fetchGit {
|
||||||
|
url = "https://github.com/google/go-genproto";
|
||||||
|
# necessary because https://github.com/NixOS/nix/issues/1923
|
||||||
|
ref = "main";
|
||||||
|
rev = "83cc0476cb11ea0da33dacd4c6354ab192de6fe6";
|
||||||
|
};
|
||||||
|
|
||||||
|
deps = with goProto; [
|
||||||
|
proto
|
||||||
|
ptypes.any
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
goGrpc = external {
|
||||||
|
path = "google.golang.org/grpc";
|
||||||
|
deps = ([
|
||||||
|
xnet.trace
|
||||||
|
xnet.http2
|
||||||
|
xsys.unix
|
||||||
|
xnet.http2.hpack
|
||||||
|
genproto.googleapis.rpc.status
|
||||||
|
] ++ (with goProto; [
|
||||||
|
proto
|
||||||
|
ptypes
|
||||||
|
ptypes.duration
|
||||||
|
ptypes.timestamp
|
||||||
|
]));
|
||||||
|
|
||||||
|
src = fetchGit {
|
||||||
|
url = "https://github.com/grpc/grpc-go";
|
||||||
|
rev = "d8e3da36ac481ef00e510ca119f6b68177713689";
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
157
third_party/tvl/nix/buildLisp/README.md
vendored
157
third_party/tvl/nix/buildLisp/README.md
vendored
|
@ -6,18 +6,24 @@ This is a build system for Common Lisp, written in Nix.
|
||||||
It aims to offer an alternative to ASDF for users who live in a
|
It aims to offer an alternative to ASDF for users who live in a
|
||||||
Nix-based ecosystem. This offers several advantages over ASDF:
|
Nix-based ecosystem. This offers several advantages over ASDF:
|
||||||
|
|
||||||
* Simpler (logic-less) package definitions
|
* Simpler (almost logic-less) package definitions
|
||||||
* Easy linking of native dependencies (from Nix)
|
* Easy linking of native dependencies (from Nix)
|
||||||
* Composability with Nix tooling for other languages
|
* Composability with Nix tooling for other languages
|
||||||
* Effective, per-system caching strategies
|
* Effective, per-system caching strategies
|
||||||
* Easy overriding of dependencies and whatnot
|
* Easy overriding of dependencies and whatnot
|
||||||
|
* Convenient support for multiple Common Lisp implementations
|
||||||
* ... and more!
|
* ... and more!
|
||||||
|
|
||||||
The project is still in its early stages and some important
|
The project is still in its early stages and some important
|
||||||
restrictions should be highlighted:
|
restrictions should be highlighted:
|
||||||
|
|
||||||
* Only SBCL is supported (though the plan is to add support for at
|
* Extending `buildLisp` with support for a custom implementation
|
||||||
least ABCL and Clozure CL, and maybe make it extensible)
|
currently requires some knowledge of internals and may not be
|
||||||
|
considered stable yet.
|
||||||
|
* Parallel compilation is not possible: Since buildLisp doesn't encode
|
||||||
|
dependencies between components (i. e. source files) like ASDF,
|
||||||
|
it must compile source files in sequence to avoid errors due to
|
||||||
|
undefined symbols.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
@ -32,6 +38,7 @@ restrictions should be highlighted:
|
||||||
| `deps` | `list<drv>` | List of dependencies | no |
|
| `deps` | `list<drv>` | List of dependencies | no |
|
||||||
| `native` | `list<drv>` | List of native dependencies | no |
|
| `native` | `list<drv>` | List of native dependencies | no |
|
||||||
| `test` | see "Tests" | Specification for test suite | no |
|
| `test` | see "Tests" | Specification for test suite | no |
|
||||||
|
| `implementation` | see "Implementations" | Common Lisp implementation to use | no |
|
||||||
|
|
||||||
The output of invoking this is a directory containing a FASL file
|
The output of invoking this is a directory containing a FASL file
|
||||||
that is the concatenated result of all compiled sources.
|
that is the concatenated result of all compiled sources.
|
||||||
|
@ -46,6 +53,7 @@ restrictions should be highlighted:
|
||||||
| `native` | `list<drv>` | List of native dependencies | no |
|
| `native` | `list<drv>` | List of native dependencies | no |
|
||||||
| `main` | `string` | Entrypoint function | no |
|
| `main` | `string` | Entrypoint function | no |
|
||||||
| `test` | see "Tests" | Specification for test suite | no |
|
| `test` | see "Tests" | Specification for test suite | no |
|
||||||
|
| `implementation` | see "Implementations" | Common Lisp implementation to use | no |
|
||||||
|
|
||||||
The `main` parameter should be the name of a function and defaults
|
The `main` parameter should be the name of a function and defaults
|
||||||
to `${name}:main` (i.e. the *exported* `main` function of the
|
to `${name}:main` (i.e. the *exported* `main` function of the
|
||||||
|
@ -64,13 +72,6 @@ restrictions should be highlighted:
|
||||||
built-in library and returns a "package" that simply requires this
|
built-in library and returns a "package" that simply requires this
|
||||||
library.
|
library.
|
||||||
|
|
||||||
* `buildLisp.sbclWith`: Creates an SBCL pre-loaded with various dependencies.
|
|
||||||
|
|
||||||
This function takes a single argument which is a list of Lisp
|
|
||||||
libraries programs or programs. It creates an SBCL that is
|
|
||||||
pre-loaded with all of that Lisp code and can be used as the host
|
|
||||||
for e.g. Sly or SLIME.
|
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
Both `buildLisp.library` and `buildLisp.program` take an optional argument
|
Both `buildLisp.library` and `buildLisp.program` take an optional argument
|
||||||
|
@ -115,3 +116,139 @@ in buildLisp.program {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Development REPLs
|
||||||
|
|
||||||
|
`buildLisp` builds loadable variants of both `program` and `library` derivations
|
||||||
|
(usually FASL files). Therefore it can provide a convenient way to obtain an
|
||||||
|
instance of any implementation preloaded with `buildLisp`-derivations. This
|
||||||
|
is especially useful to use as a host for Sly or SLIME.
|
||||||
|
|
||||||
|
* `buildLisp.sbcl.lispWith`, `buildLisp.ccl.lispWith`, ...:
|
||||||
|
Creates a wrapper script preloading a Lisp implementation with various dependencies.
|
||||||
|
|
||||||
|
This function takes a single argument which is a list of Lisp
|
||||||
|
libraries programs or programs. The desired Lisp implementation
|
||||||
|
will load all given derivations and all their dependencies on
|
||||||
|
startup.
|
||||||
|
|
||||||
|
The shortcut `buildLisp.sbclWith` for `buildLisp.sbcl.lispWith` is also provided.
|
||||||
|
|
||||||
|
* `repl` passthru attribute: `derivation.repl` is provided as a shortcut
|
||||||
|
for `buildLisp.${implementationName}.lispWith [ derivation ]`.
|
||||||
|
`derivation.ccl.repl`, `derivation.sbcl.repl` etc. work as well, of course
|
||||||
|
(see also "Implementations" section).
|
||||||
|
|
||||||
|
## Implementations
|
||||||
|
|
||||||
|
Both `buildLisp.library` and `buildLisp.program` allow specifying a different
|
||||||
|
Common Lisp implementation than the default one (which is SBCL). When an
|
||||||
|
implementation is passed, `buildLisp` makes sure all dependencies are built
|
||||||
|
with that implementation as well since build artifacts from different
|
||||||
|
implementation will be incompatible with each other.
|
||||||
|
|
||||||
|
The argument taken by `implementation` is a special attribute set which
|
||||||
|
describes how to do certain tasks for a given implementation, like building
|
||||||
|
or loading a library. In case you want to use a custom implementation
|
||||||
|
description, the precise structure needed is documented in `buildLisp`'s
|
||||||
|
source code for now. `buildLisp` also exposes the following already
|
||||||
|
working implementation sets:
|
||||||
|
|
||||||
|
* `buildLisp.sbcl`: [SBCL][sbcl], our default implementation
|
||||||
|
|
||||||
|
* `buildLisp.ccl`: [CCL][ccl], similar to SBCL, but with very good macOS support
|
||||||
|
|
||||||
|
* `buildLisp.ecl`: [ECL][ecl] setup to produce statically linked binaries and
|
||||||
|
libraries. Note that its runtime library is LGPL, so [extra conditions][lgpl-static]
|
||||||
|
must be fulfilled when distributing binaries produced this way.
|
||||||
|
|
||||||
|
* Support for ABCL is planned.
|
||||||
|
|
||||||
|
For every of these “known” implementations, `buildLisp` will create a `passthru`
|
||||||
|
attribute named like the implementation which points to a variant of the derivation
|
||||||
|
built with said implementation. Say we have a derivation, `myDrv`, built using SBCL:
|
||||||
|
While `myDrv` and `myDrv.sbcl` are built using SBCL, `myDrv.ecl`, `myDrv.ccl` etc.
|
||||||
|
build the derivation and all its dependencies using ECL and CCL respectively.
|
||||||
|
|
||||||
|
This is useful to test portability of your derivation, but is also used internally
|
||||||
|
to speed up the “normalization” of the dependency graph. Thus it is important to
|
||||||
|
make sure that your custom implementation's name doesn't clash with one of the
|
||||||
|
“known” ones.
|
||||||
|
|
||||||
|
## Handling Implementation Specifics
|
||||||
|
|
||||||
|
When targeting multiple Common Lisp implementation, it is often necessary to
|
||||||
|
handle differing interfaces for OS interaction or to make use of special
|
||||||
|
implementation features. For this reason, `buildLisp` allows specifying
|
||||||
|
dependencies and source files for specific implementations only. This can
|
||||||
|
be utilized by having an attribute set in the list for the `deps` or `srcs`
|
||||||
|
argument: `buildLisp` will pick the value of the attribute named like the
|
||||||
|
used implementation or `default` and ignore the set completely if both
|
||||||
|
are missing.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ buildLisp, lispPkgs }:
|
||||||
|
|
||||||
|
buildLisp.library {
|
||||||
|
name = "mylib";
|
||||||
|
|
||||||
|
srcs = [
|
||||||
|
# These are included always of course
|
||||||
|
./package.lisp
|
||||||
|
./portable-lib.lisp
|
||||||
|
|
||||||
|
# Choose right impl-* file
|
||||||
|
{
|
||||||
|
sbcl = ./impl-sbcl.lisp;
|
||||||
|
ccl = ./impl-ccl.lisp;
|
||||||
|
ecl = ./impl-ecl.lisp;
|
||||||
|
}
|
||||||
|
|
||||||
|
# We can also use this to inject extra files
|
||||||
|
{ ecl = ./extra-ecl-optimizations.lisp; }
|
||||||
|
];
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
# Use SBCL's special bundled package, flexi-streams otherwise
|
||||||
|
{
|
||||||
|
sbcl = buildLisp.bundled "sb-rotate-byte";
|
||||||
|
default = lispPkgs.flexi-streams;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally a `brokenOn` parameter is accepted which takes a list of
|
||||||
|
implementation names on which the derivation is not expected to work.
|
||||||
|
This only influences `meta.ci.targets` which is read by depot's CI to
|
||||||
|
check which variants (see "Implementations") of the derivation to
|
||||||
|
build, so it may not be useful outside of depot.
|
||||||
|
|
||||||
|
## Influencing the Lisp Runtime
|
||||||
|
|
||||||
|
Lisp implementations which create an executable by dumping an image
|
||||||
|
usually parse a few implementation-specific command line options on
|
||||||
|
executable startup that influence runtime settings related to things
|
||||||
|
like GC. `buildLisp` generates a wrapper which makes sure that this
|
||||||
|
never interferes with the argument parsing implemented in the actual
|
||||||
|
application, but sometimes it is useful to run an executable with
|
||||||
|
special settings. To allow this, the content of `NIX_BUILDLISP_LISP_ARGS`
|
||||||
|
is passed to the lisp implementation.
|
||||||
|
|
||||||
|
For example, you can make the underlying SBCL print its version for
|
||||||
|
any executable built with `buildLisp` (and SBCL) like this:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ env NIX_BUILDLISP_LISP_ARGS="--version" ./result/bin/🕰️
|
||||||
|
SBCL 2.1.2.nixos
|
||||||
|
```
|
||||||
|
|
||||||
|
In practice you'd probably want to specify options like
|
||||||
|
`--dynamic-space-size` or `--tls-limit` (try passing `--help` for a
|
||||||
|
full list). Naturally, these options are completely different for
|
||||||
|
different implementations.
|
||||||
|
|
||||||
|
[sbcl]: http://www.sbcl.org/
|
||||||
|
[ccl]: https://ccl.clozure.com/
|
||||||
|
[ecl]: https://common-lisp.net/project/ecl/
|
||||||
|
[lgpl-static]: https://www.gnu.org/licenses/gpl-faq.en.html#LGPLStaticVsDynamic
|
||||||
|
|
855
third_party/tvl/nix/buildLisp/default.nix
vendored
855
third_party/tvl/nix/buildLisp/default.nix
vendored
|
@ -4,67 +4,95 @@
|
||||||
# buildLisp is designed to enforce conventions and do away with the
|
# buildLisp is designed to enforce conventions and do away with the
|
||||||
# free-for-all of existing Lisp build systems.
|
# free-for-all of existing Lisp build systems.
|
||||||
|
|
||||||
{ pkgs ? import <nixpkgs> {}, ... }:
|
{ pkgs ? import <nixpkgs> { }, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (builtins) map elemAt match filter;
|
inherit (builtins) map elemAt match filter;
|
||||||
inherit (pkgs) lib runCommandNoCC makeWrapper writeText writeShellScriptBin sbcl;
|
inherit (pkgs) lib runCommandNoCC makeWrapper writeText writeShellScriptBin sbcl ecl-static ccl;
|
||||||
|
inherit (pkgs.stdenv) targetPlatform;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Internal helper definitions
|
# Internal helper definitions
|
||||||
#
|
#
|
||||||
|
|
||||||
# 'genLoadLisp' generates Lisp code that instructs SBCL to load all
|
defaultImplementation = impls.sbcl;
|
||||||
# the provided Lisp libraries.
|
|
||||||
genLoadLisp = deps: lib.concatStringsSep "\n"
|
|
||||||
(map (lib: "(load \"${lib}/${lib.lispName}.fasl\")") (allDeps deps));
|
|
||||||
|
|
||||||
# 'genCompileLisp' generates a Lisp file that instructs SBCL to
|
# Many Common Lisp implementations (like ECL and CCL) will occasionally drop
|
||||||
# compile the provided list of Lisp source files to $out.
|
# you into an interactive debugger even when executing something as a script.
|
||||||
genCompileLisp = srcs: deps: writeText "compile.lisp" ''
|
# In nix builds we don't want such a situation: Any error should make the
|
||||||
;; This file compiles the specified sources into the Nix build
|
# script exit non-zero. Luckily the ANSI standard specifies *debugger-hook*
|
||||||
;; directory, creating one FASL file for each source.
|
# which is invoked before the debugger letting us just do that.
|
||||||
(require 'sb-posix)
|
disableDebugger = writeText "disable-debugger.lisp" ''
|
||||||
|
(setf *debugger-hook*
|
||||||
${genLoadLisp deps}
|
(lambda (error hook)
|
||||||
|
(declare (ignore hook))
|
||||||
(defun nix-compile-lisp (file srcfile)
|
(format *error-output* "~%Unhandled error: ~a~%" error)
|
||||||
(let ((outfile (make-pathname :type "fasl"
|
#+ccl (quit 1)
|
||||||
:directory (or (sb-posix:getenv "NIX_BUILD_TOP")
|
#+ecl (ext:quit 1)))
|
||||||
(error "not running in a Nix build"))
|
|
||||||
:name (substitute #\- #\/ srcfile))))
|
|
||||||
(multiple-value-bind (_outfile _warnings-p failure-p)
|
|
||||||
(compile-file srcfile :output-file outfile)
|
|
||||||
(if failure-p (sb-posix:exit 1)
|
|
||||||
(progn
|
|
||||||
;; For the case of multiple files belonging to the same
|
|
||||||
;; library being compiled, load them in order:
|
|
||||||
(load outfile)
|
|
||||||
|
|
||||||
;; Write them to the FASL list in the same order:
|
|
||||||
(format file "cat ~a~%" (namestring outfile)))))))
|
|
||||||
|
|
||||||
(let ((*compile-verbose* t)
|
|
||||||
;; FASL files are compiled into the working directory of the
|
|
||||||
;; build and *then* moved to the correct out location.
|
|
||||||
(pwd (sb-posix:getcwd)))
|
|
||||||
|
|
||||||
(with-open-file (file "cat_fasls"
|
|
||||||
:direction :output
|
|
||||||
:if-does-not-exist :create)
|
|
||||||
|
|
||||||
;; These forms were inserted by the Nix build:
|
|
||||||
${
|
|
||||||
lib.concatStringsSep "\n" (map (src: "(nix-compile-lisp file \"${src}\")") srcs)
|
|
||||||
}
|
|
||||||
))
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# 'genTestLisp' generates a Lisp file that loads all sources and deps and
|
# Process a list of arbitrary values which also contains “implementation
|
||||||
# executes expression
|
# filter sets” which describe conditonal inclusion of elements depending
|
||||||
genTestLisp = name: srcs: deps: expression: writeText "${name}.lisp" ''
|
# on the CL implementation used. Elements are processed in the following
|
||||||
|
# manner:
|
||||||
|
#
|
||||||
|
# * Paths, strings, derivations are left as is
|
||||||
|
# * A non-derivation attribute set is processed like this:
|
||||||
|
# 1. If it has an attribute equal to impl.name, replace with its value.
|
||||||
|
# 2. Alternatively use the value of the "default" attribute.
|
||||||
|
# 3. In all other cases delete the element from the list.
|
||||||
|
#
|
||||||
|
# This can be used to express dependencies or source files which are specific
|
||||||
|
# to certain implementations:
|
||||||
|
#
|
||||||
|
# srcs = [
|
||||||
|
# # mixable with unconditional entries
|
||||||
|
# ./package.lisp
|
||||||
|
#
|
||||||
|
# # implementation specific source files
|
||||||
|
# {
|
||||||
|
# ccl = ./impl-ccl.lisp;
|
||||||
|
# sbcl = ./impl-sbcl.lisp;
|
||||||
|
# ecl = ./impl-ecl.lisp;
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
#
|
||||||
|
# deps = [
|
||||||
|
# # this dependency is ignored if impl.name != "sbcl"
|
||||||
|
# { sbcl = buildLisp.bundled "sb-posix"; }
|
||||||
|
#
|
||||||
|
# # only special casing for a single implementation
|
||||||
|
# {
|
||||||
|
# sbcl = buildLisp.bundled "uiop";
|
||||||
|
# default = buildLisp.bundled "asdf";
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
implFilter = impl: xs:
|
||||||
|
let
|
||||||
|
isFilterSet = x: builtins.isAttrs x && !(lib.isDerivation x);
|
||||||
|
in
|
||||||
|
builtins.map
|
||||||
|
(
|
||||||
|
x: if isFilterSet x then x.${impl.name} or x.default else x
|
||||||
|
)
|
||||||
|
(builtins.filter
|
||||||
|
(
|
||||||
|
x: !(isFilterSet x) || x ? ${impl.name} || x ? default
|
||||||
|
)
|
||||||
|
xs);
|
||||||
|
|
||||||
|
# Generates lisp code which instructs the given lisp implementation to load
|
||||||
|
# all the given dependencies.
|
||||||
|
genLoadLispGeneric = impl: deps:
|
||||||
|
lib.concatStringsSep "\n"
|
||||||
|
(map (lib: "(load \"${lib}/${lib.lispName}.${impl.faslExt}\")")
|
||||||
|
(allDeps impl deps));
|
||||||
|
|
||||||
|
# 'genTestLispGeneric' generates a Lisp file that loads all sources and deps
|
||||||
|
# and executes expression for a given implementation description.
|
||||||
|
genTestLispGeneric = impl: { name, srcs, deps, expression }: writeText "${name}.lisp" ''
|
||||||
;; Dependencies
|
;; Dependencies
|
||||||
${genLoadLisp deps}
|
${impl.genLoadLisp deps}
|
||||||
|
|
||||||
;; Sources
|
;; Sources
|
||||||
${lib.concatStringsSep "\n" (map (src: "(load \"${src}\")") srcs)}
|
${lib.concatStringsSep "\n" (map (src: "(load \"${src}\")") srcs)}
|
||||||
|
@ -78,10 +106,23 @@ let
|
||||||
dependsOn = a: b: builtins.elem a b.lispDeps;
|
dependsOn = a: b: builtins.elem a b.lispDeps;
|
||||||
|
|
||||||
# 'allDeps' flattens the list of dependencies (and their
|
# 'allDeps' flattens the list of dependencies (and their
|
||||||
# dependencies) into one ordered list of unique deps.
|
# dependencies) into one ordered list of unique deps which
|
||||||
allDeps = deps: (lib.toposort dependsOn (lib.unique (
|
# all use the given implementation.
|
||||||
lib.flatten (deps ++ (map (d: d.lispDeps) deps))
|
allDeps = impl: deps:
|
||||||
))).result;
|
let
|
||||||
|
# The override _should_ propagate itself recursively, as every derivation
|
||||||
|
# would only expose its actually used dependencies. Use implementation
|
||||||
|
# attribute created by withExtras if present, override in all other cases
|
||||||
|
# (mainly bundled).
|
||||||
|
deps' = builtins.map
|
||||||
|
(dep: dep."${impl.name}" or (dep.overrideLisp (_: {
|
||||||
|
implementation = impl;
|
||||||
|
})))
|
||||||
|
deps;
|
||||||
|
in
|
||||||
|
(lib.toposort dependsOn (lib.unique (
|
||||||
|
lib.flatten (deps' ++ (map (d: d.lispDeps) deps'))
|
||||||
|
))).result;
|
||||||
|
|
||||||
# 'allNative' extracts all native dependencies of a dependency list
|
# 'allNative' extracts all native dependencies of a dependency list
|
||||||
# to ensure that library load paths are set correctly during all
|
# to ensure that library load paths are set correctly during all
|
||||||
|
@ -90,26 +131,6 @@ let
|
||||||
lib.flatten (native ++ (map (d: d.lispNativeDeps) deps))
|
lib.flatten (native ++ (map (d: d.lispNativeDeps) deps))
|
||||||
);
|
);
|
||||||
|
|
||||||
# 'genDumpLisp' generates a Lisp file that instructs SBCL to dump
|
|
||||||
# the currently loaded image as an executable to $out/bin/$name.
|
|
||||||
#
|
|
||||||
# TODO(tazjin): Compression is currently unsupported because the
|
|
||||||
# SBCL in nixpkgs is, by default, not compiled with zlib support.
|
|
||||||
genDumpLisp = name: main: deps: writeText "dump.lisp" ''
|
|
||||||
(require 'sb-posix)
|
|
||||||
|
|
||||||
${genLoadLisp deps}
|
|
||||||
|
|
||||||
(let* ((bindir (concatenate 'string (sb-posix:getenv "out") "/bin"))
|
|
||||||
(outpath (make-pathname :name "${name}"
|
|
||||||
:directory bindir)))
|
|
||||||
(save-lisp-and-die outpath
|
|
||||||
:executable t
|
|
||||||
:toplevel (function ${main})
|
|
||||||
:purify t))
|
|
||||||
;;
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Add an `overrideLisp` attribute to a function result that works
|
# Add an `overrideLisp` attribute to a function result that works
|
||||||
# similar to `overrideAttrs`, but is used specifically for the
|
# similar to `overrideAttrs`, but is used specifically for the
|
||||||
# arguments passed to Lisp builders.
|
# arguments passed to Lisp builders.
|
||||||
|
@ -117,142 +138,642 @@ let
|
||||||
overrideLisp = new: makeOverridable f (orig // (new orig));
|
overrideLisp = new: makeOverridable f (orig // (new orig));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# This is a wrapper arround 'makeOverridable' which performs its
|
||||||
|
# function, but also adds a the following additional attributes to the
|
||||||
|
# resulting derivation, namely a repl attribute which builds a `lispWith`
|
||||||
|
# derivation for the current implementation and additional attributes for
|
||||||
|
# every all implementations. So `drv.sbcl` would build the derivation
|
||||||
|
# with SBCL regardless of what was specified in the initial arguments.
|
||||||
|
withExtras = f: args:
|
||||||
|
let
|
||||||
|
drv = (makeOverridable f) args;
|
||||||
|
in
|
||||||
|
lib.fix (self:
|
||||||
|
drv.overrideLisp
|
||||||
|
(old:
|
||||||
|
let
|
||||||
|
implementation = old.implementation or defaultImplementation;
|
||||||
|
brokenOn = old.brokenOn or [ ];
|
||||||
|
targets = lib.subtractLists (brokenOn ++ [ implementation.name ])
|
||||||
|
(builtins.attrNames impls);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
passthru = (old.passthru or { }) // {
|
||||||
|
repl = implementation.lispWith [ self ];
|
||||||
|
|
||||||
|
# meta is done via passthru to minimize rebuilds caused by overriding
|
||||||
|
meta = (old.passthru.meta or { }) // {
|
||||||
|
ci = (old.passthru.meta.ci or { }) // {
|
||||||
|
inherit targets;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // builtins.listToAttrs (builtins.map
|
||||||
|
(impl: {
|
||||||
|
inherit (impl) name;
|
||||||
|
value = self.overrideLisp (_: {
|
||||||
|
implementation = impl;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
(builtins.attrValues impls));
|
||||||
|
}) // {
|
||||||
|
overrideLisp = new: withExtras f (args // new args);
|
||||||
|
});
|
||||||
|
|
||||||
# 'testSuite' builds a Common Lisp test suite that loads all of srcs and deps,
|
# 'testSuite' builds a Common Lisp test suite that loads all of srcs and deps,
|
||||||
# and then executes expression to check its result
|
# and then executes expression to check its result
|
||||||
testSuite = { name, expression, srcs, deps ? [], native ? [] }:
|
testSuite = { name, expression, srcs, deps ? [ ], native ? [ ], implementation }:
|
||||||
let
|
let
|
||||||
lispNativeDeps = allNative native deps;
|
lispDeps = allDeps implementation (implFilter implementation deps);
|
||||||
lispDeps = allDeps deps;
|
lispNativeDeps = allNative native lispDeps;
|
||||||
in runCommandNoCC name {
|
filteredSrcs = implFilter implementation srcs;
|
||||||
LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
|
in
|
||||||
LANG = "C.UTF-8";
|
runCommandNoCC name
|
||||||
} ''
|
{
|
||||||
|
LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
|
||||||
|
LANG = "C.UTF-8";
|
||||||
|
} ''
|
||||||
echo "Running test suite ${name}"
|
echo "Running test suite ${name}"
|
||||||
|
|
||||||
${sbcl}/bin/sbcl --script ${genTestLisp name srcs deps expression} \
|
${implementation.runScript} ${
|
||||||
| tee $out
|
implementation.genTestLisp {
|
||||||
|
inherit name expression;
|
||||||
|
srcs = filteredSrcs;
|
||||||
|
deps = lispDeps;
|
||||||
|
}
|
||||||
|
} | tee $out
|
||||||
|
|
||||||
echo "Test suite ${name} succeeded"
|
echo "Test suite ${name} succeeded"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# 'impls' is an attribute set of attribute sets which describe how to do common
|
||||||
|
# tasks when building for different Common Lisp implementations. Each
|
||||||
|
# implementation set has the following members:
|
||||||
|
#
|
||||||
|
# Required members:
|
||||||
|
#
|
||||||
|
# - runScript :: string
|
||||||
|
# Describes how to invoke the implementation from the shell, so it runs a
|
||||||
|
# lisp file as a script and exits.
|
||||||
|
# - faslExt :: string
|
||||||
|
# File extension of the implementations loadable (FASL) files.
|
||||||
|
# Implementations are free to generate native object files, but with the way
|
||||||
|
# buildLisp works it is required that we can also 'load' libraries, so
|
||||||
|
# (additionally) building a FASL or equivalent is required.
|
||||||
|
# - genLoadLisp :: [ dependency ] -> string
|
||||||
|
# Returns lisp code to 'load' the given dependencies. 'genLoadLispGeneric'
|
||||||
|
# should work for most dependencies.
|
||||||
|
# - genCompileLisp :: { name, srcs, deps } -> file
|
||||||
|
# Builds a lisp file which instructs the implementation to build a library
|
||||||
|
# from the given source files when executed. After running at least
|
||||||
|
# the file "$out/${name}.${impls.${implementation}.faslExt}" should have
|
||||||
|
# been created.
|
||||||
|
# - genDumpLisp :: { name, main, deps } -> file
|
||||||
|
# Builds a lisp file which instructs the implementation to build an
|
||||||
|
# executable which runs 'main' (and exits) where 'main' is available from
|
||||||
|
# 'deps'. The executable should be created as "$out/bin/${name}", usually
|
||||||
|
# by dumping the lisp image with the replaced toplevel function replaced.
|
||||||
|
# - wrapProgram :: boolean
|
||||||
|
# Whether to wrap the resulting binary / image with a wrapper script setting
|
||||||
|
# `LD_LIBRARY_PATH`.
|
||||||
|
# - genTestLisp :: { name, srcs, deps, expression } -> file
|
||||||
|
# Builds a lisp file which loads the given 'deps' and 'srcs' files and
|
||||||
|
# then evaluates 'expression'. Depending on whether 'expression' returns
|
||||||
|
# true or false, the script must exit with a zero or non-zero exit code.
|
||||||
|
# 'genTestLispGeneric' will work for most implementations.
|
||||||
|
# - lispWith :: [ dependency ] -> drv
|
||||||
|
# Builds a script (or dumped image) which when executed loads (or has
|
||||||
|
# loaded) all given dependencies. When built this should create an executable
|
||||||
|
# at "$out/bin/${implementation}".
|
||||||
|
#
|
||||||
|
# Optional members:
|
||||||
|
#
|
||||||
|
# - bundled :: string -> library
|
||||||
|
# Allows giving an implementation specific builder for a bundled library.
|
||||||
|
# This function is used as a replacement for the internal defaultBundled
|
||||||
|
# function and only needs to support one implementation. The returned derivation
|
||||||
|
# must behave like one built by 'library' (in particular have the same files
|
||||||
|
# available in "$out" and the same 'passthru' attributes), but may be built
|
||||||
|
# completely differently.
|
||||||
|
impls = lib.mapAttrs (name: v: { inherit name; } // v) {
|
||||||
|
sbcl = {
|
||||||
|
runScript = "${sbcl}/bin/sbcl --script";
|
||||||
|
faslExt = "fasl";
|
||||||
|
|
||||||
|
# 'genLoadLisp' generates Lisp code that instructs SBCL to load all
|
||||||
|
# the provided Lisp libraries.
|
||||||
|
genLoadLisp = genLoadLispGeneric impls.sbcl;
|
||||||
|
|
||||||
|
# 'genCompileLisp' generates a Lisp file that instructs SBCL to
|
||||||
|
# compile the provided list of Lisp source files to "$out/${name}.fasl".
|
||||||
|
genCompileLisp = { name, srcs, deps }: writeText "sbcl-compile.lisp" ''
|
||||||
|
;; This file compiles the specified sources into the Nix build
|
||||||
|
;; directory, creating one FASL file for each source.
|
||||||
|
(require 'sb-posix)
|
||||||
|
|
||||||
|
${impls.sbcl.genLoadLisp deps}
|
||||||
|
|
||||||
|
(defun nix-compile-lisp (srcfile)
|
||||||
|
(let ((outfile (make-pathname :type "fasl"
|
||||||
|
:directory (or (sb-posix:getenv "NIX_BUILD_TOP")
|
||||||
|
(error "not running in a Nix build"))
|
||||||
|
:name (substitute #\- #\/ srcfile))))
|
||||||
|
(multiple-value-bind (out-truename _warnings-p failure-p)
|
||||||
|
(compile-file srcfile :output-file outfile)
|
||||||
|
(if failure-p (sb-posix:exit 1)
|
||||||
|
(progn
|
||||||
|
;; For the case of multiple files belonging to the same
|
||||||
|
;; library being compiled, load them in order:
|
||||||
|
(load out-truename)
|
||||||
|
|
||||||
|
;; Return pathname as a string for cat-ting it later
|
||||||
|
(namestring out-truename))))))
|
||||||
|
|
||||||
|
(let ((*compile-verbose* t)
|
||||||
|
(catted-fasl (make-pathname :type "fasl"
|
||||||
|
:directory (or (sb-posix:getenv "out")
|
||||||
|
(error "not running in a Nix build"))
|
||||||
|
:name "${name}")))
|
||||||
|
|
||||||
|
(with-open-file (file catted-fasl
|
||||||
|
:direction :output
|
||||||
|
:if-does-not-exist :create)
|
||||||
|
|
||||||
|
;; SBCL's FASL files can just be bundled together using cat
|
||||||
|
(sb-ext:run-program "cat"
|
||||||
|
(mapcar #'nix-compile-lisp
|
||||||
|
;; These forms were inserted by the Nix build:
|
||||||
|
'(${
|
||||||
|
lib.concatMapStringsSep "\n" (src: "\"${src}\"") srcs
|
||||||
|
}))
|
||||||
|
:output file :search t)))
|
||||||
|
'';
|
||||||
|
|
||||||
|
# 'genDumpLisp' generates a Lisp file that instructs SBCL to dump
|
||||||
|
# the currently loaded image as an executable to $out/bin/$name.
|
||||||
|
#
|
||||||
|
# TODO(tazjin): Compression is currently unsupported because the
|
||||||
|
# SBCL in nixpkgs is, by default, not compiled with zlib support.
|
||||||
|
genDumpLisp = { name, main, deps }: writeText "sbcl-dump.lisp" ''
|
||||||
|
(require 'sb-posix)
|
||||||
|
|
||||||
|
${impls.sbcl.genLoadLisp deps}
|
||||||
|
|
||||||
|
(let* ((bindir (concatenate 'string (sb-posix:getenv "out") "/bin"))
|
||||||
|
(outpath (make-pathname :name "${name}"
|
||||||
|
:directory bindir)))
|
||||||
|
|
||||||
|
;; Tell UIOP that argv[0] will refer to running image, not the lisp impl
|
||||||
|
(when (find-package :uiop)
|
||||||
|
(eval `(setq ,(find-symbol "*IMAGE-DUMPED-P*" :uiop) :executable)))
|
||||||
|
|
||||||
|
(save-lisp-and-die outpath
|
||||||
|
:executable t
|
||||||
|
:toplevel
|
||||||
|
(lambda ()
|
||||||
|
;; Filter out everything prior to the `--` we
|
||||||
|
;; insert in the wrapper to prevent SBCL from
|
||||||
|
;; parsing arguments at startup
|
||||||
|
(setf sb-ext:*posix-argv*
|
||||||
|
(delete "--" sb-ext:*posix-argv*
|
||||||
|
:test #'string= :count 1))
|
||||||
|
(${main}))
|
||||||
|
:purify t))
|
||||||
|
'';
|
||||||
|
|
||||||
|
wrapProgram = true;
|
||||||
|
|
||||||
|
genTestLisp = genTestLispGeneric impls.sbcl;
|
||||||
|
|
||||||
|
lispWith = deps:
|
||||||
|
let lispDeps = filter (d: !d.lispBinary) (allDeps impls.sbcl deps);
|
||||||
|
in writeShellScriptBin "sbcl" ''
|
||||||
|
export LD_LIBRARY_PATH="${lib.makeLibraryPath (allNative [] lispDeps)}"
|
||||||
|
export LANG="C.UTF-8"
|
||||||
|
exec ${sbcl}/bin/sbcl ${
|
||||||
|
lib.optionalString (deps != [])
|
||||||
|
"--load ${writeText "load.lisp" (impls.sbcl.genLoadLisp lispDeps)}"
|
||||||
|
} $@
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
ecl = {
|
||||||
|
runScript = "${ecl-static}/bin/ecl --load ${disableDebugger} --shell";
|
||||||
|
faslExt = "fasc";
|
||||||
|
genLoadLisp = genLoadLispGeneric impls.ecl;
|
||||||
|
genCompileLisp = { name, srcs, deps }: writeText "ecl-compile.lisp" ''
|
||||||
|
;; This seems to be required to bring make the 'c' package available
|
||||||
|
;; early, otherwise ECL tends to fail with a read failure…
|
||||||
|
(ext:install-c-compiler)
|
||||||
|
|
||||||
|
;; Load dependencies
|
||||||
|
${impls.ecl.genLoadLisp deps}
|
||||||
|
|
||||||
|
(defun getenv-or-fail (var)
|
||||||
|
(or (ext:getenv var)
|
||||||
|
(error (format nil "Missing expected environment variable ~A" var))))
|
||||||
|
|
||||||
|
(defun nix-compile-file (srcfile &key native)
|
||||||
|
"Compile the given srcfile into a compilation unit in :out-dir using
|
||||||
|
a unique name based on srcfile as the filename which is returned after
|
||||||
|
compilation. If :native is true, create an native object file,
|
||||||
|
otherwise a byte-compile fasc file is built and immediately loaded."
|
||||||
|
|
||||||
|
(let* ((unique-name (substitute #\_ #\/ srcfile))
|
||||||
|
(out-file (make-pathname :type (if native "o" "fasc")
|
||||||
|
:directory (getenv-or-fail "NIX_BUILD_TOP")
|
||||||
|
:name unique-name)))
|
||||||
|
(multiple-value-bind (out-truename _warnings-p failure-p)
|
||||||
|
(compile-file srcfile :system-p native
|
||||||
|
:load (not native)
|
||||||
|
:output-file out-file
|
||||||
|
:verbose t :print t)
|
||||||
|
(if failure-p (ext:quit 1) out-truename))))
|
||||||
|
|
||||||
|
(let* ((out-dir (getenv-or-fail "out"))
|
||||||
|
(nix-build-dir (getenv-or-fail "NIX_BUILD_TOP"))
|
||||||
|
(srcs
|
||||||
|
;; These forms are inserted by the Nix build
|
||||||
|
'(${lib.concatMapStringsSep "\n" (src: "\"${src}\"") srcs})))
|
||||||
|
|
||||||
|
;; First, we'll byte compile loadable FASL files and load them
|
||||||
|
;; immediately. Since we are using a statically linked ECL, there's
|
||||||
|
;; no way to load native objects, so we rely on byte compilation
|
||||||
|
;; for all our loading — which is crucial in compilation of course.
|
||||||
|
(ext:install-bytecodes-compiler)
|
||||||
|
|
||||||
|
;; ECL's bytecode FASLs can just be concatenated to create a bundle
|
||||||
|
;; at least since a recent bugfix which we apply as a patch.
|
||||||
|
;; See also: https://gitlab.com/embeddable-common-lisp/ecl/-/issues/649
|
||||||
|
(let ((bundle-out (make-pathname :type "fasc" :name "${name}"
|
||||||
|
:directory out-dir)))
|
||||||
|
|
||||||
|
(with-open-file (fasc-stream bundle-out :direction :output)
|
||||||
|
(ext:run-program "cat"
|
||||||
|
(mapcar (lambda (f)
|
||||||
|
(namestring
|
||||||
|
(nix-compile-file f :native nil)))
|
||||||
|
srcs)
|
||||||
|
:output fasc-stream)))
|
||||||
|
|
||||||
|
(ext:install-c-compiler)
|
||||||
|
|
||||||
|
;; Build a (natively compiled) static archive (.a) file. We want to
|
||||||
|
;; use this for (statically) linking an executable later. The bytecode
|
||||||
|
;; dance is only required because we can't load such archives.
|
||||||
|
(c:build-static-library
|
||||||
|
(make-pathname :type "a" :name "${name}" :directory out-dir)
|
||||||
|
:lisp-files (mapcar (lambda (x)
|
||||||
|
(nix-compile-file x :native t))
|
||||||
|
srcs)))
|
||||||
|
'';
|
||||||
|
genDumpLisp = { name, main, deps }: writeText "ecl-dump.lisp" ''
|
||||||
|
(defun getenv-or-fail (var)
|
||||||
|
(or (ext:getenv var)
|
||||||
|
(error (format nil "Missing expected environment variable ~A" var))))
|
||||||
|
|
||||||
|
${impls.ecl.genLoadLisp deps}
|
||||||
|
|
||||||
|
;; makes a 'c' package available that can link executables
|
||||||
|
(ext:install-c-compiler)
|
||||||
|
|
||||||
|
(c:build-program
|
||||||
|
(merge-pathnames (make-pathname :directory '(:relative "bin")
|
||||||
|
:name "${name}")
|
||||||
|
(truename (getenv-or-fail "out")))
|
||||||
|
:epilogue-code `(progn
|
||||||
|
;; UIOP doesn't understand ECL, so we need to make it
|
||||||
|
;; aware that we are a proper executable, causing it
|
||||||
|
;; to handle argument parsing and such properly. Since
|
||||||
|
;; this needs to work even when we're not using UIOP,
|
||||||
|
;; we need to do some compile-time acrobatics.
|
||||||
|
,(when (find-package :uiop)
|
||||||
|
`(setf ,(find-symbol "*IMAGE-DUMPED-P*" :uiop) :executable))
|
||||||
|
;; Run the actual application…
|
||||||
|
(${main})
|
||||||
|
;; … and exit.
|
||||||
|
(ext:quit))
|
||||||
|
;; ECL can't remember these from its own build…
|
||||||
|
:ld-flags '("-static")
|
||||||
|
:lisp-files
|
||||||
|
;; The following forms are inserted by the Nix build
|
||||||
|
'(${
|
||||||
|
lib.concatMapStrings (dep: ''
|
||||||
|
"${dep}/${dep.lispName}.a"
|
||||||
|
'') (allDeps impls.ecl deps)
|
||||||
|
}))
|
||||||
|
'';
|
||||||
|
|
||||||
|
wrapProgram = false;
|
||||||
|
|
||||||
|
genTestLisp = genTestLispGeneric impls.ecl;
|
||||||
|
|
||||||
|
lispWith = deps:
|
||||||
|
let lispDeps = filter (d: !d.lispBinary) (allDeps impls.ecl deps);
|
||||||
|
in writeShellScriptBin "ecl" ''
|
||||||
|
exec ${ecl-static}/bin/ecl ${
|
||||||
|
lib.optionalString (deps != [])
|
||||||
|
"--load ${writeText "load.lisp" (impls.ecl.genLoadLisp lispDeps)}"
|
||||||
|
} $@
|
||||||
|
'';
|
||||||
|
|
||||||
|
bundled = name: runCommandNoCC "${name}-cllib"
|
||||||
|
{
|
||||||
|
passthru = {
|
||||||
|
lispName = name;
|
||||||
|
lispNativeDeps = [ ];
|
||||||
|
lispDeps = [ ];
|
||||||
|
lispBinary = false;
|
||||||
|
repl = impls.ecl.lispWith [ (impls.ecl.bundled name) ];
|
||||||
|
};
|
||||||
|
} ''
|
||||||
|
mkdir -p "$out"
|
||||||
|
ln -s "${ecl-static}/lib/ecl-${ecl-static.version}/${name}.${impls.ecl.faslExt}" -t "$out"
|
||||||
|
ln -s "${ecl-static}/lib/ecl-${ecl-static.version}/lib${name}.a" "$out/${name}.a"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
ccl = {
|
||||||
|
# Relatively bespoke wrapper script necessary to make CCL just™ execute
|
||||||
|
# a lisp file as a script.
|
||||||
|
runScript = pkgs.writers.writeBash "ccl" ''
|
||||||
|
# don't print intro message etc.
|
||||||
|
args=("--quiet")
|
||||||
|
|
||||||
|
# makes CCL crash on error instead of entering the debugger
|
||||||
|
args+=("--load" "${disableDebugger}")
|
||||||
|
|
||||||
|
# load files from command line in order
|
||||||
|
for f in "$@"; do
|
||||||
|
args+=("--load" "$f")
|
||||||
|
done
|
||||||
|
|
||||||
|
# Exit if everything was processed successfully
|
||||||
|
args+=("--eval" "(quit)")
|
||||||
|
|
||||||
|
exec ${ccl}/bin/ccl ''${args[@]}
|
||||||
|
'';
|
||||||
|
|
||||||
|
# See https://ccl.clozure.com/docs/ccl.html#building-definitions
|
||||||
|
faslExt =
|
||||||
|
/**/
|
||||||
|
if targetPlatform.isPowerPC && targetPlatform.is32bit then "pfsl"
|
||||||
|
else if targetPlatform.isPowerPC && targetPlatform.is64bit then "p64fsl"
|
||||||
|
else if targetPlatform.isx86_64 && targetPlatform.isLinux then "lx64fsl"
|
||||||
|
else if targetPlatform.isx86_32 && targetPlatform.isLinux then "lx32fsl"
|
||||||
|
else if targetPlatform.isAarch32 && targetPlatform.isLinux then "lafsl"
|
||||||
|
else if targetPlatform.isx86_32 && targetPlatform.isDarwin then "dx32fsl"
|
||||||
|
else if targetPlatform.isx86_64 && targetPlatform.isDarwin then "dx64fsl"
|
||||||
|
else if targetPlatform.isx86_64 && targetPlatform.isDarwin then "dx64fsl"
|
||||||
|
else if targetPlatform.isx86_32 && targetPlatform.isFreeBSD then "fx32fsl"
|
||||||
|
else if targetPlatform.isx86_64 && targetPlatform.isFreeBSD then "fx64fsl"
|
||||||
|
else if targetPlatform.isx86_32 && targetPlatform.isWindows then "wx32fsl"
|
||||||
|
else if targetPlatform.isx86_64 && targetPlatform.isWindows then "wx64fsl"
|
||||||
|
else builtins.throw "Don't know what FASLs are called for this platform: "
|
||||||
|
+ pkgs.stdenv.targetPlatform.system;
|
||||||
|
|
||||||
|
genLoadLisp = genLoadLispGeneric impls.ccl;
|
||||||
|
|
||||||
|
genCompileLisp = { name, srcs, deps }: writeText "ccl-compile.lisp" ''
|
||||||
|
${impls.ccl.genLoadLisp deps}
|
||||||
|
|
||||||
|
(defun getenv-or-fail (var)
|
||||||
|
(or (getenv var)
|
||||||
|
(error (format nil "Missing expected environment variable ~A" var))))
|
||||||
|
|
||||||
|
(defun nix-compile-file (srcfile)
|
||||||
|
"Trivial wrapper around COMPILE-FILE which causes CCL to exit if
|
||||||
|
compilation fails and LOADs the compiled file on success."
|
||||||
|
(let ((output (make-pathname :name (substitute #\_ #\/ srcfile)
|
||||||
|
:type "${impls.ccl.faslExt}"
|
||||||
|
:directory (getenv-or-fail "NIX_BUILD_TOP"))))
|
||||||
|
(multiple-value-bind (out-truename _warnings-p failure-p)
|
||||||
|
(compile-file srcfile :output-file output :print t :verbose t)
|
||||||
|
(declare (ignore _warnings-p))
|
||||||
|
(if failure-p (quit 1)
|
||||||
|
(progn (load out-truename) out-truename)))))
|
||||||
|
|
||||||
|
(fasl-concatenate (make-pathname :name "${name}" :type "${impls.ccl.faslExt}"
|
||||||
|
:directory (getenv-or-fail "out"))
|
||||||
|
(mapcar #'nix-compile-file
|
||||||
|
;; These forms where inserted by the Nix build
|
||||||
|
'(${
|
||||||
|
lib.concatMapStrings (src: ''
|
||||||
|
"${src}"
|
||||||
|
'') srcs
|
||||||
|
})))
|
||||||
|
'';
|
||||||
|
|
||||||
|
genDumpLisp = { name, main, deps }: writeText "ccl-dump.lisp" ''
|
||||||
|
${impls.ccl.genLoadLisp deps}
|
||||||
|
|
||||||
|
(let* ((out (or (getenv "out") (error "Not running in a Nix build")))
|
||||||
|
(bindir (concatenate 'string out "/bin/"))
|
||||||
|
(executable (make-pathname :directory bindir :name "${name}")))
|
||||||
|
|
||||||
|
;; Tell UIOP that argv[0] will refer to running image, not the lisp impl
|
||||||
|
(when (find-package :uiop)
|
||||||
|
(eval `(setf ,(find-symbol "*IMAGE-DUMPED-P*" :uiop) :executable)))
|
||||||
|
|
||||||
|
(save-application executable
|
||||||
|
:purify t
|
||||||
|
:error-handler :quit
|
||||||
|
:toplevel-function
|
||||||
|
(lambda ()
|
||||||
|
;; Filter out everything prior to the `--` we
|
||||||
|
;; insert in the wrapper to prevent SBCL from
|
||||||
|
;; parsing arguments at startup
|
||||||
|
(setf ccl:*command-line-argument-list*
|
||||||
|
(delete "--" ccl:*command-line-argument-list*
|
||||||
|
:test #'string= :count 1))
|
||||||
|
(${main}))
|
||||||
|
:mode #o755
|
||||||
|
;; TODO(sterni): use :native t on macOS
|
||||||
|
:prepend-kernel t))
|
||||||
|
'';
|
||||||
|
|
||||||
|
wrapProgram = true;
|
||||||
|
|
||||||
|
genTestLisp = genTestLispGeneric impls.ccl;
|
||||||
|
|
||||||
|
lispWith = deps:
|
||||||
|
let lispDeps = filter (d: !d.lispBinary) (allDeps impls.ccl deps);
|
||||||
|
in writeShellScriptBin "ccl" ''
|
||||||
|
export LD_LIBRARY_PATH="${lib.makeLibraryPath (allNative [] lispDeps)}"
|
||||||
|
exec ${ccl}/bin/ccl ${
|
||||||
|
lib.optionalString (deps != [])
|
||||||
|
"--load ${writeText "load.lisp" (impls.ccl.genLoadLisp lispDeps)}"
|
||||||
|
} "$@"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
#
|
#
|
||||||
# Public API functions
|
# Public API functions
|
||||||
#
|
#
|
||||||
|
|
||||||
# 'library' builds a list of Common Lisp files into a single FASL
|
# 'library' builds a list of Common Lisp files into an implementation
|
||||||
# which can then be loaded into SBCL.
|
# specific library format, usually a single FASL file, which can then be
|
||||||
|
# loaded and built into an executable via 'program'.
|
||||||
library =
|
library =
|
||||||
{ name
|
{ name
|
||||||
|
, implementation ? defaultImplementation
|
||||||
|
, brokenOn ? [ ] # TODO(sterni): make this a warning
|
||||||
, srcs
|
, srcs
|
||||||
, deps ? []
|
, deps ? [ ]
|
||||||
, native ? []
|
, native ? [ ]
|
||||||
, tests ? null
|
, tests ? null
|
||||||
|
, passthru ? { }
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
lispNativeDeps = (allNative native deps);
|
filteredDeps = implFilter implementation deps;
|
||||||
lispDeps = allDeps deps;
|
filteredSrcs = implFilter implementation srcs;
|
||||||
testDrv = if ! isNull tests
|
lispNativeDeps = (allNative native filteredDeps);
|
||||||
then testSuite {
|
lispDeps = allDeps implementation filteredDeps;
|
||||||
name = tests.name or "${name}-test";
|
testDrv =
|
||||||
srcs = srcs ++ (tests.srcs or []);
|
if ! isNull tests
|
||||||
deps = deps ++ (tests.deps or []);
|
then
|
||||||
expression = tests.expression;
|
testSuite
|
||||||
}
|
{
|
||||||
|
name = tests.name or "${name}-test";
|
||||||
|
srcs = filteredSrcs ++ (tests.srcs or [ ]);
|
||||||
|
deps = filteredDeps ++ (tests.deps or [ ]);
|
||||||
|
expression = tests.expression;
|
||||||
|
inherit implementation;
|
||||||
|
}
|
||||||
else null;
|
else null;
|
||||||
in lib.fix (self: runCommandNoCC "${name}-cllib" {
|
in
|
||||||
LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
|
lib.fix (self: runCommandNoCC "${name}-cllib"
|
||||||
LANG = "C.UTF-8";
|
{
|
||||||
} ''
|
LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
|
||||||
|
LANG = "C.UTF-8";
|
||||||
|
passthru = passthru // {
|
||||||
|
inherit lispNativeDeps lispDeps;
|
||||||
|
lispName = name;
|
||||||
|
lispBinary = false;
|
||||||
|
tests = testDrv;
|
||||||
|
};
|
||||||
|
} ''
|
||||||
${if ! isNull testDrv
|
${if ! isNull testDrv
|
||||||
then "echo 'Test ${testDrv} succeeded'"
|
then "echo 'Test ${testDrv} succeeded'"
|
||||||
else "echo 'No tests run'"}
|
else "echo 'No tests run'"}
|
||||||
${sbcl}/bin/sbcl --script ${genCompileLisp srcs lispDeps}
|
|
||||||
|
|
||||||
echo "Compilation finished, assembling FASL files"
|
|
||||||
|
|
||||||
# FASL files can be combined by simply concatenating them
|
|
||||||
# together, but it needs to be in the compilation order.
|
|
||||||
mkdir $out
|
mkdir $out
|
||||||
|
|
||||||
chmod +x cat_fasls
|
${implementation.runScript} ${
|
||||||
./cat_fasls > $out/${name}.fasl
|
implementation.genCompileLisp {
|
||||||
'' // {
|
srcs = filteredSrcs;
|
||||||
inherit lispNativeDeps lispDeps;
|
inherit name;
|
||||||
lispName = name;
|
deps = lispDeps;
|
||||||
lispBinary = false;
|
}
|
||||||
tests = testDrv;
|
}
|
||||||
sbcl = sbclWith [ self ];
|
'');
|
||||||
});
|
|
||||||
|
|
||||||
# 'program' creates an executable containing a dumped image of the
|
# 'program' creates an executable, usually containing a dumped image of the
|
||||||
# specified sources and dependencies.
|
# specified sources and dependencies.
|
||||||
program =
|
program =
|
||||||
{ name
|
{ name
|
||||||
|
, implementation ? defaultImplementation
|
||||||
|
, brokenOn ? [ ] # TODO(sterni): make this a warning
|
||||||
, main ? "${name}:main"
|
, main ? "${name}:main"
|
||||||
, srcs
|
, srcs
|
||||||
, deps ? []
|
, deps ? [ ]
|
||||||
, native ? []
|
, native ? [ ]
|
||||||
, tests ? null
|
, tests ? null
|
||||||
|
, passthru ? { }
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
lispDeps = allDeps deps;
|
filteredSrcs = implFilter implementation srcs;
|
||||||
|
filteredDeps = implFilter implementation deps;
|
||||||
|
lispDeps = allDeps implementation filteredDeps;
|
||||||
libPath = lib.makeLibraryPath (allNative native lispDeps);
|
libPath = lib.makeLibraryPath (allNative native lispDeps);
|
||||||
selfLib = library {
|
# overriding is used internally to propagate the implementation to use
|
||||||
inherit name srcs native;
|
selfLib = (makeOverridable library) {
|
||||||
|
inherit name native brokenOn;
|
||||||
deps = lispDeps;
|
deps = lispDeps;
|
||||||
|
srcs = filteredSrcs;
|
||||||
};
|
};
|
||||||
testDrv = if ! isNull tests
|
testDrv =
|
||||||
then testSuite {
|
if ! isNull tests
|
||||||
name = tests.name or "${name}-test";
|
then
|
||||||
srcs =
|
testSuite
|
||||||
(
|
{
|
||||||
srcs ++ (tests.srcs or []));
|
name = tests.name or "${name}-test";
|
||||||
deps = deps ++ (tests.deps or []);
|
srcs =
|
||||||
expression = tests.expression;
|
(
|
||||||
}
|
# testSuite does run implFilter as well
|
||||||
|
filteredSrcs ++ (tests.srcs or [ ])
|
||||||
|
);
|
||||||
|
deps = filteredDeps ++ (tests.deps or [ ]);
|
||||||
|
expression = tests.expression;
|
||||||
|
inherit implementation;
|
||||||
|
}
|
||||||
else null;
|
else null;
|
||||||
in lib.fix (self: runCommandNoCC "${name}" {
|
in
|
||||||
nativeBuildInputs = [ makeWrapper ];
|
lib.fix (self: runCommandNoCC "${name}"
|
||||||
LD_LIBRARY_PATH = libPath;
|
{
|
||||||
LANG = "C.UTF-8";
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
} ''
|
LD_LIBRARY_PATH = libPath;
|
||||||
${if ! isNull testDrv
|
LANG = "C.UTF-8";
|
||||||
then "echo 'Test ${testDrv} succeeded'"
|
passthru = passthru // {
|
||||||
else ""}
|
lispName = name;
|
||||||
mkdir -p $out/bin
|
lispDeps = [ selfLib ];
|
||||||
|
lispNativeDeps = native;
|
||||||
${sbcl}/bin/sbcl --script ${
|
lispBinary = true;
|
||||||
genDumpLisp name main ([ selfLib ] ++ lispDeps)
|
tests = testDrv;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
(''
|
||||||
|
${if ! isNull testDrv
|
||||||
|
then "echo 'Test ${testDrv} succeeded'"
|
||||||
|
else ""}
|
||||||
|
mkdir -p $out/bin
|
||||||
|
|
||||||
wrapProgram $out/bin/${name} --prefix LD_LIBRARY_PATH : "${libPath}"
|
${implementation.runScript} ${
|
||||||
'' // {
|
implementation.genDumpLisp {
|
||||||
lispName = name;
|
inherit name main;
|
||||||
lispDeps = [ selfLib ] ++ (tests.deps or []);
|
deps = ([ selfLib ] ++ lispDeps);
|
||||||
lispNativeDeps = native;
|
}
|
||||||
lispBinary = true;
|
}
|
||||||
tests = testDrv;
|
'' + lib.optionalString implementation.wrapProgram ''
|
||||||
sbcl = sbclWith [ self ];
|
wrapProgram $out/bin/${name} \
|
||||||
});
|
--prefix LD_LIBRARY_PATH : "${libPath}" \
|
||||||
|
--add-flags "\$NIX_BUILDLISP_LISP_ARGS --"
|
||||||
|
''));
|
||||||
|
|
||||||
# 'bundled' creates a "library" that calls 'require' on a built-in
|
# 'bundled' creates a "library" which makes a built-in package available,
|
||||||
# package, such as any of SBCL's sb-* packages.
|
# such as any of SBCL's sb-* packages or ASDF. By default this is done
|
||||||
bundled = name: (makeOverridable library) {
|
# by calling 'require', but implementations are free to provide their
|
||||||
inherit name;
|
# own specific bundled function.
|
||||||
srcs = lib.singleton (builtins.toFile "${name}.lisp" "(require '${name})");
|
bundled = name:
|
||||||
};
|
let
|
||||||
|
# TODO(sterni): allow overriding args to underlying 'library' (e. g. srcs)
|
||||||
|
defaultBundled = implementation: name: library {
|
||||||
|
inherit name implementation;
|
||||||
|
srcs = lib.singleton (builtins.toFile "${name}.lisp" "(require '${name})");
|
||||||
|
};
|
||||||
|
|
||||||
|
bundled' =
|
||||||
|
{ implementation ? defaultImplementation
|
||||||
|
, name
|
||||||
|
}:
|
||||||
|
implementation.bundled or (defaultBundled implementation) name;
|
||||||
|
|
||||||
|
in
|
||||||
|
(makeOverridable bundled') {
|
||||||
|
inherit name;
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
library = withExtras library;
|
||||||
|
program = withExtras program;
|
||||||
|
inherit bundled;
|
||||||
|
|
||||||
# 'sbclWith' creates an image with the specified libraries /
|
# 'sbclWith' creates an image with the specified libraries /
|
||||||
# programs loaded.
|
# programs loaded in SBCL.
|
||||||
sbclWith = deps:
|
sbclWith = impls.sbcl.lispWith;
|
||||||
let lispDeps = filter (d: !d.lispBinary) (allDeps deps);
|
|
||||||
in writeShellScriptBin "sbcl" ''
|
inherit (impls)
|
||||||
export LD_LIBRARY_PATH=${lib.makeLibraryPath (allNative [] lispDeps)};
|
sbcl
|
||||||
exec ${sbcl}/bin/sbcl ${lib.optionalString (deps != []) "--load ${writeText "load.lisp" (genLoadLisp lispDeps)}"} $@
|
ecl
|
||||||
'';
|
ccl
|
||||||
in {
|
;
|
||||||
library = makeOverridable library;
|
|
||||||
program = makeOverridable program;
|
|
||||||
sbclWith = makeOverridable sbclWith;
|
|
||||||
bundled = makeOverridable bundled;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,15 +14,16 @@ let
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# Example Lisp program.
|
# Example Lisp program.
|
||||||
#
|
#
|
||||||
# This builds & writes an executable for a program using the library
|
# This builds & writes an executable for a program using the library
|
||||||
# above to disk.
|
# above to disk.
|
||||||
#
|
#
|
||||||
# By default, buildLisp.program expects the entry point to be
|
# By default, buildLisp.program expects the entry point to be
|
||||||
# `$name:main`. This can be overridden by configuring the `main`
|
# `$name:main`. This can be overridden by configuring the `main`
|
||||||
# attribute.
|
# attribute.
|
||||||
in buildLisp.program {
|
in
|
||||||
|
buildLisp.program {
|
||||||
name = "example";
|
name = "example";
|
||||||
deps = [ libExample ];
|
deps = [ libExample ];
|
||||||
|
|
||||||
|
|
36
third_party/tvl/nix/buildLisp/tests/argv0.nix
vendored
Normal file
36
third_party/tvl/nix/buildLisp/tests/argv0.nix
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{ depot, pkgs, ... }:
|
||||||
|
|
||||||
|
depot.nix.buildLisp.program {
|
||||||
|
name = "argv0-test";
|
||||||
|
|
||||||
|
srcs = [
|
||||||
|
(pkgs.writeText "argv0-test.lisp" ''
|
||||||
|
(defpackage :argv0-test (:use :common-lisp :uiop) (:export :main))
|
||||||
|
(in-package :argv0-test)
|
||||||
|
|
||||||
|
(defun main ()
|
||||||
|
(format t "~A~%" (uiop:argv0)))
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
{
|
||||||
|
sbcl = depot.nix.buildLisp.bundled "uiop";
|
||||||
|
default = depot.nix.buildLisp.bundled "asdf";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
passthru.meta.ci = {
|
||||||
|
extraSteps.verify = {
|
||||||
|
label = "verify argv[0] output";
|
||||||
|
needsOutput = true;
|
||||||
|
command = pkgs.writeShellScript "check-argv0" ''
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
for invocation in "$(pwd)/result/bin/argv0-test" "./result/bin/argv0-test"; do
|
||||||
|
test "$invocation" = "$("$invocation")"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
3
third_party/tvl/nix/buildManPages/OWNERS
vendored
Normal file
3
third_party/tvl/nix/buildManPages/OWNERS
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
inherited: true
|
||||||
|
owners:
|
||||||
|
- sterni
|
103
third_party/tvl/nix/buildManPages/default.nix
vendored
Normal file
103
third_party/tvl/nix/buildManPages/default.nix
vendored
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
{ depot, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (pkgs)
|
||||||
|
gzip
|
||||||
|
mandoc
|
||||||
|
coreutils
|
||||||
|
;
|
||||||
|
|
||||||
|
inherit (depot.nix)
|
||||||
|
runExecline
|
||||||
|
getBins
|
||||||
|
;
|
||||||
|
|
||||||
|
bins = getBins mandoc [ "mandoc" ]
|
||||||
|
// getBins gzip [ "gzip" ]
|
||||||
|
// getBins coreutils [ "mkdir" "ln" "cp" ]
|
||||||
|
;
|
||||||
|
|
||||||
|
defaultGzip = true;
|
||||||
|
|
||||||
|
basename = gzip: { name, section, ... }:
|
||||||
|
"${name}.${toString section}${lib.optionalString gzip ".gz"}";
|
||||||
|
|
||||||
|
manDir = { section, ... }:
|
||||||
|
"\${out}/share/man/man${toString section}";
|
||||||
|
|
||||||
|
target = gzip: args:
|
||||||
|
"${manDir args}/${basename gzip args}";
|
||||||
|
|
||||||
|
buildManPage =
|
||||||
|
{ requireLint ? false
|
||||||
|
, gzip ? defaultGzip
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
{ content
|
||||||
|
, ...
|
||||||
|
}@page:
|
||||||
|
let
|
||||||
|
source = builtins.toFile (basename false page) content;
|
||||||
|
in
|
||||||
|
runExecline (basename gzip page) { } ([
|
||||||
|
(if requireLint then "if" else "foreground")
|
||||||
|
[
|
||||||
|
bins.mandoc
|
||||||
|
"-mdoc"
|
||||||
|
"-T"
|
||||||
|
"lint"
|
||||||
|
source
|
||||||
|
]
|
||||||
|
"importas"
|
||||||
|
"out"
|
||||||
|
"out"
|
||||||
|
] ++ (if gzip then [
|
||||||
|
"redirfd"
|
||||||
|
"-w"
|
||||||
|
"1"
|
||||||
|
"$out"
|
||||||
|
bins.gzip
|
||||||
|
"-c"
|
||||||
|
source
|
||||||
|
] else [
|
||||||
|
bins.cp
|
||||||
|
"--reflink=auto"
|
||||||
|
source
|
||||||
|
"$out"
|
||||||
|
]));
|
||||||
|
|
||||||
|
buildManPages =
|
||||||
|
name:
|
||||||
|
{ derivationArgs ? { }
|
||||||
|
, gzip ? defaultGzip
|
||||||
|
, ...
|
||||||
|
}@args:
|
||||||
|
pages:
|
||||||
|
runExecline "${name}-man-pages"
|
||||||
|
{
|
||||||
|
inherit derivationArgs;
|
||||||
|
}
|
||||||
|
([
|
||||||
|
"importas"
|
||||||
|
"out"
|
||||||
|
"out"
|
||||||
|
] ++ lib.concatMap
|
||||||
|
({ name, section, content }@page: [
|
||||||
|
"if"
|
||||||
|
[ bins.mkdir "-p" (manDir page) ]
|
||||||
|
"if"
|
||||||
|
[
|
||||||
|
bins.ln
|
||||||
|
"-s"
|
||||||
|
(buildManPage args page)
|
||||||
|
(target gzip page)
|
||||||
|
]
|
||||||
|
])
|
||||||
|
pages);
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
__functor = _: buildManPages;
|
||||||
|
|
||||||
|
single = buildManPage;
|
||||||
|
}
|
34
third_party/tvl/nix/buildTypedGo/default.nix
vendored
34
third_party/tvl/nix/buildTypedGo/default.nix
vendored
|
@ -1,34 +0,0 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
#
|
|
||||||
# A crude wrapper around //nix/buildGo that supports the Go 2 alpha.
|
|
||||||
#
|
|
||||||
# The way the alpha is implemented is via a transpiler from typed to
|
|
||||||
# untyped Go.
|
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (builtins)
|
|
||||||
baseNameOf
|
|
||||||
stringLength
|
|
||||||
substring;
|
|
||||||
|
|
||||||
inherit (depot.nix.buildGo) gpackage program;
|
|
||||||
|
|
||||||
go2goext = file: substring 0 ((stringLength file) - 1) file;
|
|
||||||
go2go = file: pkgs.runCommandNoCC "${go2goext (baseNameOf file)}" {} ''
|
|
||||||
cp ${file} .
|
|
||||||
${pkgs.go}/bin/go tool go2go translate *.go2
|
|
||||||
mv *.go $out
|
|
||||||
'';
|
|
||||||
|
|
||||||
in rec {
|
|
||||||
program = { name, srcs, deps ? [], x_defs ? {} }: depot.nix.buildGo.program {
|
|
||||||
inherit name deps x_defs;
|
|
||||||
srcs = map go2go srcs;
|
|
||||||
};
|
|
||||||
|
|
||||||
package = { name, srcs, deps ? [], path ? name, sfiles ? [] }: depot.nix.buildGo.package {
|
|
||||||
inherit name deps path sfiles;
|
|
||||||
srcs = map go2go srcs;
|
|
||||||
};
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue