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
|
||||
# from Nix.
|
||||
|
||||
export PATH="${PWD}/bin:${PATH}"
|
||||
export REPO_ROOT="${PWD}"
|
||||
out=$(nix-build -A tools.depot-deps --no-out-link)
|
||||
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
|
||||
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)
|
||||
|
||||
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
|
||||
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:
|
||||
- tazjin
|
||||
- lukegb
|
||||
- grfn
|
||||
- sterni
|
||||
|
|
40
third_party/tvl/README.md
vendored
40
third_party/tvl/README.md
vendored
|
@ -1,19 +1,16 @@
|
|||
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
|
||||
lounge][tvl], containing our personal tools and infrastructure. Everything in
|
||||
here is built using [Nix][].
|
||||
This repository is the [monorepo][] for the community around [The
|
||||
Virus Lounge][tvl], containing our personal tools and infrastructure.
|
||||
Everything in here is built using [Nix][].
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
## Services
|
||||
|
@ -41,15 +38,20 @@ Twitter][].
|
|||
dynamically via
|
||||
[`//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
|
||||
configuration is tracked in `//ops/nixos`.
|
||||
configuration is tracked in `//ops/{modules,machines}`.
|
||||
|
||||
## 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)
|
||||
contains the Nix code which automatically registers projects in our Nix
|
||||
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
|
||||
we use for a variety of things throughout the repository
|
||||
* `//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
|
||||
software. Currently only SBCL is supported. Lisp programs in this repository
|
||||
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
|
||||
be of interest.
|
||||
|
@ -84,9 +90,9 @@ Some examples:
|
|||
* `//users/tazjin/homepage` && `//users/tazjin/blog`: A Nix-based static site
|
||||
generator which generates the web page and Atom feed for
|
||||
[tazj.in](https://tazj.in)
|
||||
* `//users/tazjin/finito`: A persistent finite-state machine library for Rust.
|
||||
* `//users/glittershark/xanthous`: A (WIP) TUI RPG, written in Haskell.
|
||||
* `//users/grfn/xanthous`: A (WIP) TUI RPG, written in Haskell.
|
||||
* `//users/tazjin/emacs`: tazjin's Emacs & EXWM configuration
|
||||
* `//users/tazjin/finito`: A persistent finite-state machine library for Rust.
|
||||
|
||||
# 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
|
||||
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
|
||||
[tvl]: https://tvl.fyi
|
||||
[Nix]: https://nixos.org/nix
|
||||
[an experiment]: https://tvl.fyi/monorepo-doc
|
||||
[on Twitter]: https://twitter.com/tazjin
|
||||
[panettone]: https://cs.tvl.fyi/depot@canon/-/tree/web/panettone
|
||||
[tvix]: https://cs.tvl.fyi/depot/-/blob/third_party/nix/README.md
|
||||
[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
|
||||
# (see read-tree.nix for details) and constructing a matching attribute set
|
||||
# (see //nix/readTree for details) and constructing a matching attribute set
|
||||
# tree.
|
||||
#
|
||||
# This makes packages accessible via the Nixery instance that is configured to
|
||||
# use this repository as its nixpkgs source.
|
||||
|
||||
{ ... }@args:
|
||||
|
||||
with builtins;
|
||||
{ nixpkgsBisectPath ? null
|
||||
, parentTargetMap ? null
|
||||
, nixpkgsConfig ? { }
|
||||
, ...
|
||||
}@args:
|
||||
|
||||
let
|
||||
# This definition of fix is identical to <nixpkgs>.lib.fix, but the global
|
||||
# package set is not available here.
|
||||
fix = f: let x = f x; in x;
|
||||
inherit (builtins)
|
||||
filter
|
||||
;
|
||||
|
||||
# Global configuration that all packages are called with.
|
||||
config = depot: {
|
||||
inherit depot;
|
||||
readTree = import ./nix/readTree { };
|
||||
|
||||
# Expose lib & ciBuilds attributes to packages.
|
||||
inherit (depot) ciBuilds lib;
|
||||
# Disallow access to //users from other depot parts.
|
||||
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
|
||||
# imports for certain subdirectories)
|
||||
pkgs = depot.third_party;
|
||||
exceptions = [
|
||||
# whitby is allowed to access //users for several reasons:
|
||||
#
|
||||
# 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: {
|
||||
fun = readTree ./fun;
|
||||
lisp = readTree ./lisp;
|
||||
net = readTree ./net;
|
||||
nix = readTree ./nix;
|
||||
ops = readTree ./ops;
|
||||
third_party = readTree ./third_party;
|
||||
tools = readTree ./tools;
|
||||
users = readTree ./users;
|
||||
web = readTree ./web;
|
||||
exceptions = [
|
||||
# For the same reason as above, whitby is exempt to serve the
|
||||
# corp website.
|
||||
[ "ops" "machines" "whitby" ]
|
||||
[ "ops" "nixos" ]
|
||||
[ "ops" "machines" "all-systems" ]
|
||||
];
|
||||
};
|
||||
|
||||
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
|
||||
# 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?
|
||||
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
|
||||
# of build targets with anything that looks buildable.
|
||||
in
|
||||
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
|
||||
# 'meta.targets' attribute containing a list of keys in itself. This
|
||||
# enables target specifications that do not exist on disk directly.
|
||||
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;
|
||||
};
|
||||
|
||||
# Note that it is intended for exceptional circumstance, such as
|
||||
# debugging by bisecting nixpkgs.
|
||||
externalArgs = args;
|
||||
}) // {
|
||||
# Make the path to the depot available for things that might need it
|
||||
# (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.
|
||||
#
|
||||
# Note: To prevent infinite recursion, this *must* be a nested
|
||||
# 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
|
||||
# generate pipelines because that also leads to infinite
|
||||
# recursion.
|
||||
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
|
||||
// (localPkgs (readTree' self.config))
|
||||
|
||||
# Load overrides into the top-level.
|
||||
#
|
||||
# This can be used to move things from third_party into the top-level, too (such
|
||||
# as `lib`).
|
||||
// (readTree' { depot = self; pkgs = self.third_party; }) ./overrides
|
||||
)
|
||||
# Derivation that gcroots all depot targets.
|
||||
ci.gcroot = with self.third_party.nixpkgs; makeSetupHook
|
||||
{
|
||||
name = "depot-gcroot";
|
||||
deps = self.ci.targets;
|
||||
}
|
||||
emptyFile;
|
||||
})
|
||||
|
|
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!
|
||||
* `test`: Added missing tests / fixed tests
|
||||
* `chore`: Maintenance work
|
||||
* `subtree`: Operations involving `git subtree`
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
|
|
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
|
||||
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"`).
|
||||
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
|
||||
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
|
||||
your job to figure out.
|
||||
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).
|
||||
|
||||
## 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
|
||||
[OWNERS]: https://cl.tvl.fyi/plugins/owners/Documentation/config.md
|
||||
[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
|
||||
[hackint]: https://hackint.org
|
||||
|
|
|
@ -9,7 +9,7 @@ Open items:
|
|||
the closure of a given source directory, using [depot-scan].
|
||||
|
||||
```bash
|
||||
DEPOT_ROOT="${depot.depotPath}"
|
||||
DEPOT_ROOT="${depot.path}"
|
||||
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
CLIENT_ROOT="$XDG_DATA_HOME/tvlc/clients"
|
||||
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"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
|
@ -27,17 +28,20 @@ var (
|
|||
gerritAuthUsername = flag.String("gerrit_ssh_auth_username", "", "Gerrit SSH username")
|
||||
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")
|
||||
ircUser = flag.String("irc_user", "clbot", "User 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")
|
||||
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")
|
||||
|
||||
notifyRepo = flag.String("notify_repo", "depot", "Repo name to notify about")
|
||||
notifyBranches = stringSetFlag{}
|
||||
|
||||
neverPing = flag.String("never_ping", "marcus", "Comma-separated terms that should never ping users")
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -111,11 +115,21 @@ func runIRC(ctx context.Context, ircCfg irc.ClientConfig, sendMsg <-chan string)
|
|||
|
||||
(func() {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
ircClient := irc.NewClient(ircConn, ircCfg)
|
||||
ircClientCtx, cancel := context.WithCancel(ctx)
|
||||
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{
|
||||
p.Uploader.Username,
|
||||
p.Uploader.Name,
|
||||
p.Uploader.Email,
|
||||
a.Username,
|
||||
a.Name,
|
||||
a.Email,
|
||||
}
|
||||
for _, opt := range options {
|
||||
if opt != "" {
|
||||
|
@ -165,6 +179,20 @@ func noping(user string) string {
|
|||
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 {
|
||||
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 {
|
||||
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:
|
||||
if e.Change.Project != *notifyRepo || !notifyBranches[e.Change.Branch] {
|
||||
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 != "" {
|
||||
sendMsgChan <- parsedMsg
|
||||
|
|
|
@ -4,17 +4,17 @@ use std::rc::Rc;
|
|||
use std::sync::RwLock;
|
||||
|
||||
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) {
|
||||
(self.f)()
|
||||
}
|
||||
}
|
||||
|
||||
// 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 }
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,9 @@ type ErrorHandle<T> = Rc<RwLock<Option<T>>>;
|
|||
///////////////////
|
||||
|
||||
#[derive(Debug)] // Debug trait for some default way to print the type.
|
||||
enum Error { DropError }
|
||||
enum Error {
|
||||
DropError,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Create a place to store the error.
|
||||
|
@ -60,7 +62,7 @@ fn main() {
|
|||
|
||||
match *drop_err.read().unwrap() {
|
||||
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!
|
||||
|
||||
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) {
|
||||
(self.f)()
|
||||
}
|
||||
}
|
||||
|
||||
// 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 }
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// Go's defer in Rust, with a little twist!
|
||||
|
||||
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) {
|
||||
(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
|
||||
inherit (depot) elmPackages;
|
||||
inherit (depot.third_party) cacert iana-etc libredirect stdenv runCommandNoCC writeText;
|
||||
inherit (pkgs) cacert iana-etc libredirect stdenv runCommandNoCC writeText;
|
||||
elmPackages = depot.third_party.elmPackages_0_18;
|
||||
|
||||
frontend = stdenv.mkDerivation {
|
||||
name = "gemma-frontend.html";
|
||||
|
@ -33,7 +33,8 @@ let
|
|||
cp ${frontend} $out/index.html
|
||||
''}/")
|
||||
'';
|
||||
in depot.nix.buildLisp.program {
|
||||
in
|
||||
depot.nix.buildLisp.program {
|
||||
name = "gemma";
|
||||
|
||||
deps = with depot.third_party.lisp; [
|
||||
|
@ -47,4 +48,10 @@ in depot.nix.buildLisp.program {
|
|||
./src/gemma.lisp
|
||||
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
|
||||
inherit (pkgs) python python3 python3Packages;
|
||||
inherit (pkgs) python3 python3Packages;
|
||||
|
||||
opts = {
|
||||
pname = "idualctl";
|
||||
pname = "idualctl";
|
||||
version = "0.1";
|
||||
src = ./.;
|
||||
src = ./.;
|
||||
|
||||
propagatedBuildInputs = [
|
||||
python.broadlink
|
||||
depot.third_party.python.broadlink
|
||||
];
|
||||
};
|
||||
package = python3Packages.buildPythonPackage opts;
|
||||
script = python3Packages.buildPythonApplication opts;
|
||||
in {
|
||||
script = python3Packages.buildPythonApplication opts;
|
||||
in
|
||||
depot.nix.readTree.drvTargets {
|
||||
inherit script;
|
||||
python = python3.withPackages (_: [ package ]);
|
||||
python = python3.withPackages (_: [ package ]);
|
||||
setAlarm = pkgs.writeShellScriptBin "set-alarm" ''
|
||||
echo "setting an alarm for ''${1}"
|
||||
${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
|
||||
pkgs = depot.third_party;
|
||||
in
|
||||
pkgs.naersk.buildPackage {
|
||||
depot.third_party.naersk.buildPackage {
|
||||
name = "paroxysm";
|
||||
version = "0.0.2";
|
||||
src = ./.;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ depot, ... }:
|
||||
{ depot, pkgs, ... }:
|
||||
|
||||
depot.third_party.dockerTools.buildLayeredImage {
|
||||
pkgs.dockerTools.buildLayeredImage {
|
||||
name = "paroxysm";
|
||||
contents = [ depot.fun.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 diesel::pg::PgConnection;
|
||||
use diesel::prelude::*;
|
||||
use failure::format_err;
|
||||
use failure::Error;
|
||||
use failure::{format_err, Error};
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// 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 diesel::pg::PgConnection;
|
||||
use diesel::r2d2::{ConnectionManager, Pool};
|
||||
use failure::format_err;
|
||||
use failure::Error;
|
||||
use failure::{format_err, Error};
|
||||
use irc::client::prelude::*;
|
||||
use lazy_static::lazy_static;
|
||||
use log::{debug, info, warn};
|
||||
|
@ -153,8 +152,9 @@ impl App {
|
|||
// Use `nick` here, so things like "grfn: see glittershark" work.
|
||||
let val = if let Some(last) = chan_lastmsgs.get(nick_to_grab) {
|
||||
if last.starts_with("\x01ACTION ") {
|
||||
// Yes, this is inefficient, but it's better than writing some hacky CTCP parsing code
|
||||
// I guess (also, characters are hard, so just blindly slicing seems like a bad idea)
|
||||
// Yes, this is inefficient, but it's better than writing some hacky CTCP parsing
|
||||
// code I guess (also, characters are hard, so just blindly slicing
|
||||
// seems like a bad idea)
|
||||
format!(
|
||||
"* {} {}",
|
||||
nick_to_grab,
|
||||
|
@ -208,7 +208,7 @@ impl App {
|
|||
pub fn handle_query(
|
||||
&mut self,
|
||||
target: &str,
|
||||
nick: &str,
|
||||
_nick: &str,
|
||||
chan: &str,
|
||||
query: Captures,
|
||||
) -> Result<(), Error> {
|
||||
|
@ -239,7 +239,7 @@ impl App {
|
|||
}
|
||||
// step 2: attempt to POST it to eta's pastebin
|
||||
// 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")?
|
||||
.header("Linx-Expiry", "7200")? // 2 hours
|
||||
.body("text/plain", data_to_upload.as_bytes())
|
||||
|
@ -301,8 +301,12 @@ impl App {
|
|||
}
|
||||
}
|
||||
None => {
|
||||
self.client
|
||||
.send_notice(target, format!("\x02{}\x0f: never heard of it", subj))?;
|
||||
// If someone just posts "??????????", don't spam the channel with
|
||||
// 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(())
|
||||
|
|
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"`
|
||||
}
|
||||
|
||||
var supressionUsernames map[string]bool
|
||||
var suppressionUsernames map[string]bool
|
||||
var noMkov map[string]bool
|
||||
|
||||
func main() {
|
||||
redisc := redis.NewClient(&redis.Options{
|
||||
|
@ -30,7 +31,27 @@ func main() {
|
|||
})
|
||||
|
||||
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() {
|
||||
for {
|
||||
|
@ -81,8 +102,11 @@ func main() {
|
|||
func generateMesasge(msg incomingIRC, redisc *redis.Client) string {
|
||||
text := msg.Params[1]
|
||||
username := strings.ToLower(msg.Name)
|
||||
supressionUsernames[username] = true
|
||||
supressionUsernames[username+":"] = true
|
||||
suppressionUsernames[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.Replace(text, ",", "", -1)
|
||||
|
@ -92,16 +116,19 @@ func generateMesasge(msg incomingIRC, redisc *redis.Client) string {
|
|||
text = strings.Replace(text, "?", "", -1)
|
||||
|
||||
words := strings.Split(text, " ")
|
||||
lastWord := propwords(username, words[0], redisc)
|
||||
lastWord := propwords(msg.Name, words[0], redisc)
|
||||
|
||||
if supressionUsernames[words[0]] {
|
||||
if len(words[0]) < 2 {
|
||||
words[0] = "vee"
|
||||
}
|
||||
words[0] = fmt.Sprintf("%s.%s", string(words[0][0]), words[0][1:])
|
||||
if noMkov[username] {
|
||||
lastWord = blockoutWord(lastWord)
|
||||
words[0] = blockoutWord(words[0])
|
||||
}
|
||||
|
||||
lastWord = filterHighlights(lastWord)
|
||||
|
||||
if lastWord == "_END_" {
|
||||
if noMkov[username] {
|
||||
return blockoutWord(words[0])
|
||||
}
|
||||
return words[0]
|
||||
}
|
||||
outputMsg := words[0] + " " + lastWord + " "
|
||||
|
@ -112,13 +139,12 @@ func generateMesasge(msg incomingIRC, redisc *redis.Client) string {
|
|||
return outputMsg
|
||||
}
|
||||
|
||||
if supressionUsernames[lastWord] {
|
||||
if len(lastWord) < 2 {
|
||||
lastWord = "vee"
|
||||
}
|
||||
lastWord = fmt.Sprintf("%s.%s", string(lastWord[0]), lastWord[1:])
|
||||
if noMkov[username] {
|
||||
lastWord = blockoutWord(lastWord)
|
||||
}
|
||||
|
||||
lastWord = filterHighlights(lastWord)
|
||||
|
||||
outputMsg += lastWord + " "
|
||||
if len(outputMsg) > 100 {
|
||||
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 {
|
||||
userHash := redisc.HGetAll(fmt.Sprintf("%s-%s", username, start))
|
||||
userHashMap, err := userHash.Result()
|
||||
|
@ -190,7 +238,9 @@ func learnFromMessage(msg incomingIRC, redisc *redis.Client) {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
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
|
||||
inherit (pkgs) gopkgs;
|
||||
inherit (depot.third_party) gopkgs;
|
||||
|
||||
uggc = depot.nix.buildGo.program {
|
||||
name = "uggc";
|
||||
srcs = [
|
||||
|
@ -11,7 +12,8 @@ let
|
|||
gopkgs."github.com".pkg.browser.gopkg
|
||||
];
|
||||
};
|
||||
in uggc.overrideAttrs(old: {
|
||||
in
|
||||
uggc.overrideAttrs (old: {
|
||||
buildCommand = old.buildCommand + ''
|
||||
install -D ${./uggc.desktop} $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
|
||||
./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)
|
||||
(declaim (optimize (safety 3)))
|
||||
|
||||
(defmacro comment (&rest _))
|
||||
(defmacro comment (&rest _)
|
||||
(declare (ignore _)))
|
||||
|
||||
(defun posp (n) (> n 0))
|
||||
|
||||
|
@ -41,7 +42,7 @@
|
|||
(defun chunk-list (size list &key (start 0) end)
|
||||
"Returns successive chunks of list of size SIZE, starting at START and ending
|
||||
at END."
|
||||
(declare (inline check-list/bounded check-list/simple))
|
||||
(declare (inline chunk-list/bounded chunk-list/unbounded))
|
||||
(check-type size (integer 1))
|
||||
(let ((list (nthcdr start list)))
|
||||
(when list
|
||||
|
@ -76,24 +77,36 @@ separated by SEP."
|
|||
(defparameter dottime-format
|
||||
'((:year 4) #\- (:month 2) #\- (:day 2)
|
||||
#\T
|
||||
(:hour 2) #\· (:min 2) "+00") ; TODO(grfn): Allow passing offset
|
||||
(:hour 2) #\· (:min 2))
|
||||
"`:LOCAL-TIME' format specifier for dottime")
|
||||
|
||||
(defun format-dottime (timestamp)
|
||||
"Return TIMESTAMP formatted as dottime, using a +00 offset"
|
||||
(defun format-dottime (timestamp &optional (offset 0))
|
||||
"Return TIMESTAMP formatted as dottime, with a specified offset or +00"
|
||||
(check-type timestamp local-time:timestamp)
|
||||
(local-time:format-timestring nil timestamp
|
||||
:format dottime-format
|
||||
:timezone local-time:+utc-zone+))
|
||||
(concatenate 'string
|
||||
(local-time:format-timestring nil timestamp
|
||||
: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
|
||||
(format-dottime (local-time:now)))
|
||||
(format-dottime (local-time:now))
|
||||
(format-dottime (local-time:now) 2))
|
||||
|
||||
(defun try-parse-integer (str)
|
||||
"Attempt to parse STR as an integer, returning nil if it is invalid."
|
||||
(check-type str string)
|
||||
(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
|
||||
|
|
2
third_party/tvl/lisp/klatre/package.lisp
vendored
2
third_party/tvl/lisp/klatre/package.lisp
vendored
|
@ -10,7 +10,7 @@
|
|||
|
||||
;; String handling
|
||||
#:+dottime-format+ #:format-dottime
|
||||
#:try-parse-integer
|
||||
#:try-parse-integer #:format-dottime-offset
|
||||
|
||||
;; Function utilities
|
||||
#: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]
|
||||
name = "alcoholic_jwt"
|
||||
description = "Library for validation of RS256 JWTs"
|
||||
version = "1.0.0"
|
||||
authors = ["Vincent Ambo <vincent@aprila.no>"]
|
||||
version = "4091.0.0"
|
||||
authors = ["Vincent Ambo <tazjin@tvl.su>"]
|
||||
keywords = ["jwt", "token", "jwks"]
|
||||
categories = ["authentication"]
|
||||
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]
|
||||
base64 = "0.10"
|
||||
base64 = "0.13"
|
||||
openssl = "0.10"
|
||||
serde = "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
|
||||
=============
|
||||
|
||||
[![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
|
||||
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`
|
||||
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/
|
||||
[Aprila]: https://www.aprila.no/
|
||||
[JWKS]: https://tools.ietf.org/html/rfc7517
|
||||
[`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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
|
@ -67,23 +67,26 @@
|
|||
//!
|
||||
//! [JWKS]: https://tools.ietf.org/html/rfc7517
|
||||
|
||||
#[macro_use] extern crate serde_derive;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate base64;
|
||||
extern crate openssl;
|
||||
extern crate serde;
|
||||
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::error::ErrorStack;
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::pkey::{Public, PKey};
|
||||
use openssl::pkey::{PKey, Public};
|
||||
use openssl::rsa::Rsa;
|
||||
use openssl::sign::Verifier;
|
||||
use serde::de::DeserializeOwned;
|
||||
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)]
|
||||
mod tests;
|
||||
|
@ -101,12 +104,16 @@ fn jwt_forgiving() -> Config {
|
|||
/// JWT algorithm used. The only supported algorithm is currently
|
||||
/// RS256.
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
enum KeyAlgorithm { RS256 }
|
||||
enum KeyAlgorithm {
|
||||
RS256,
|
||||
}
|
||||
|
||||
/// Type of key contained in a JWT. The only supported key type is
|
||||
/// currently RSA.
|
||||
#[derive(Clone, Deserialize, Debug)]
|
||||
enum KeyType { RSA }
|
||||
enum KeyType {
|
||||
RSA,
|
||||
}
|
||||
|
||||
/// Representation of a single JSON Web Key. See [RFC
|
||||
/// 7517](https://tools.ietf.org/html/rfc7517#section-4).
|
||||
|
@ -146,7 +153,7 @@ impl JWKS {
|
|||
|
||||
/// Representation of an undecoded JSON Web Token. See [RFC
|
||||
/// 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.
|
||||
///
|
||||
|
@ -214,18 +221,56 @@ pub enum ValidationError {
|
|||
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>;
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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.
|
||||
|
@ -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
|
||||
/// for validation.
|
||||
pub fn validate(token: &str,
|
||||
jwk: &JWK,
|
||||
validations: Vec<Validation>) -> JWTResult<ValidJWT> {
|
||||
pub fn validate(token: &str, jwk: &JWK, validations: Vec<Validation>) -> JWTResult<ValidJWT> {
|
||||
let jwt = JWT(token);
|
||||
let public_key = public_key_from_jwk(&jwk)?;
|
||||
validate_jwt_signature(&jwt, public_key)?;
|
||||
|
@ -279,7 +322,7 @@ pub fn validate(token: &str,
|
|||
if parts.len() != 3 {
|
||||
// This is unlikely considering that validation has already
|
||||
// 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:
|
||||
|
@ -351,7 +394,7 @@ fn validate_jwt_signature(jwt: &JWT, key: Rsa<Public>) -> JWTResult<()> {
|
|||
verifier.update(data.as_bytes())?;
|
||||
|
||||
match verifier.verify(&sig)? {
|
||||
true => Ok(()),
|
||||
true => Ok(()),
|
||||
false => Err(ValidationError::InvalidSignature),
|
||||
}
|
||||
}
|
||||
|
@ -362,7 +405,7 @@ fn validate_jwt_signature(jwt: &JWT, key: Rsa<Public>) -> JWTResult<()> {
|
|||
#[serde(untagged)]
|
||||
enum Audience {
|
||||
Single(String),
|
||||
Multi(Vec<String>)
|
||||
Multi(Vec<String>),
|
||||
}
|
||||
|
||||
/// 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.
|
||||
fn apply_validation(claims: &PartialClaims,
|
||||
validation: Validation) -> Result<(), &'static str> {
|
||||
fn apply_validation(claims: &PartialClaims, validation: Validation) -> Result<(), &'static str> {
|
||||
match validation {
|
||||
// Validate that an 'iss' claim is present and matches the
|
||||
// supplied value.
|
||||
Validation::Issuer(iss) => {
|
||||
match claims.iss {
|
||||
None => Err("'iss' claim is missing"),
|
||||
Some(ref claim) => if *claim == iss {
|
||||
Validation::Issuer(iss) => match claims.iss {
|
||||
None => Err("'iss' claim is missing"),
|
||||
Some(ref claim) => {
|
||||
if *claim == iss {
|
||||
Ok(())
|
||||
} else {
|
||||
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
|
||||
// supplied value.
|
||||
Validation::Audience(aud) => {
|
||||
match claims.aud {
|
||||
None => Err("'aud' claim is missing"),
|
||||
Some(Audience::Single(ref claim)) => if *claim == aud {
|
||||
Validation::Audience(aud) => match claims.aud {
|
||||
None => Err("'aud' claim is missing"),
|
||||
Some(Audience::Single(ref claim)) => {
|
||||
if *claim == aud {
|
||||
Ok(())
|
||||
} else {
|
||||
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(())
|
||||
} else {
|
||||
Err("'aud' claim does not match")
|
||||
|
@ -447,12 +491,12 @@ fn apply_validation(claims: &PartialClaims,
|
|||
}
|
||||
|
||||
/// Apply all requested validations to a partial claim set.
|
||||
fn validate_claims(claims: PartialClaims,
|
||||
validations: Vec<Validation>) -> JWTResult<()> {
|
||||
let validation_errors: Vec<_> = validations.into_iter()
|
||||
fn validate_claims(claims: PartialClaims, validations: Vec<Validation>) -> JWTResult<()> {
|
||||
let validation_errors: Vec<_> = validations
|
||||
.into_iter()
|
||||
.map(|v| apply_validation(&claims, v))
|
||||
.filter_map(|result| match result {
|
||||
Ok(_) => None,
|
||||
Ok(_) => None,
|
||||
Err(err) => Some(err),
|
||||
})
|
||||
.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
|
||||
// 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 expected = "19947781743618558124649689124245117083485690334420160711273532766920651190711502679542723943527557680293732686428091794139998732541701457212387600480039297092835433997837314251024513773285252960725418984381935183495143908023024822433135775773958512751261112853383693442999603704969543668619221464654540065497665889289271044207667765128672709218996183649696030570183970367596949687544839066873508106034650634722970893169823917299050098551447676778961773465887890052852528696684907153295689693676910831376066659456592813140662563597179711588277621736656871685099184755908108451080261403193680966083938080206832839445289";
|
||||
assert_eq!(expected, format!("{}", bignum), "Decoded fragment should match ");
|
||||
assert_eq!(
|
||||
expected,
|
||||
format!("{}", bignum),
|
||||
"Decoded fragment should match "
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
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 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");
|
||||
|
||||
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 kid = token_kid(&jwt).expect("Failed to extract token KID");
|
||||
assert_eq!(Some("8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=".into()),
|
||||
kid, "Extracted KID did not match expected KID");
|
||||
assert_eq!(
|
||||
Some("8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=".into()),
|
||||
kid,
|
||||
"Extracted KID did not match expected KID"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
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: JWKS = serde_json::from_str(jwks_json)
|
||||
.expect("Failed to decode JWKS");
|
||||
let jwks: JWKS = serde_json::from_str(jwks_json).expect("Failed to decode JWKS");
|
||||
|
||||
let jwk = jwks.find("8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=")
|
||||
let jwk = jwks
|
||||
.find("8rDq8Pw0FZcaoXWTEVQo7+Tf2YzSL1fBxNKPCebaai4=")
|
||||
.expect("Failed to find required JWK");
|
||||
|
||||
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]
|
||||
name = "crimp"
|
||||
description = "Higher-level Rust API for cURL bindings"
|
||||
version = "0.2.2"
|
||||
authors = ["Vincent Ambo <mail@tazj.in>"]
|
||||
version = "4087.0.0"
|
||||
authors = ["Vincent Ambo <tazjin@tvl.su>"]
|
||||
keywords = [ "http", "curl" ]
|
||||
categories = [ "api-bindings" ]
|
||||
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]
|
||||
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
|
||||
=====
|
||||
|
||||
[![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://docs.rs/crimp/badge.svg)](https://docs.rs/crimp)
|
||||
|
||||
|
@ -11,5 +10,17 @@ cURL.
|
|||
The documentation for this crate is primarily in the [module
|
||||
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
|
||||
[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;
|
||||
//!
|
||||
//! let response = Request::get("http://httpbin.org/get")
|
||||
//! .user_agent("crimp test suite").unwrap()
|
||||
//! .send().unwrap()
|
||||
//! .as_string().unwrap();
|
||||
//! .user_agent("crimp test suite")
|
||||
//! .unwrap()
|
||||
//! .send()
|
||||
//! .unwrap()
|
||||
//! .as_string()
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! println!("Status: {}\nBody: {}", response.status, response.body);
|
||||
//! # assert_eq!(response.status, 200);
|
||||
|
@ -54,10 +57,9 @@
|
|||
//!
|
||||
//! All optional features are enabled by default.
|
||||
//!
|
||||
//! * `json`: Adds `Request::json` and `Response::as_json` methods
|
||||
//! which can be used for convenient serialisation of
|
||||
//! request/response bodies using `serde_json`. This feature adds a
|
||||
//! dependency on the `serde` and `serde_json` crates.
|
||||
//! * `json`: Adds `Request::json` and `Response::as_json` methods which can be used for convenient
|
||||
//! serialisation of request/response bodies using `serde_json`. This feature adds a dependency on
|
||||
//! the `serde` and `serde_json` crates.
|
||||
//!
|
||||
//! ## Initialisation
|
||||
//!
|
||||
|
@ -72,32 +74,42 @@
|
|||
|
||||
extern crate curl;
|
||||
|
||||
#[cfg(feature = "json")] extern crate serde;
|
||||
#[cfg(feature = "json")] extern crate serde_json;
|
||||
#[cfg(feature = "json")]
|
||||
extern crate serde;
|
||||
#[cfg(feature = "json")]
|
||||
extern crate serde_json;
|
||||
|
||||
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::io::Write;
|
||||
use std::path::Path;
|
||||
use std::string::{FromUtf8Error, ToString};
|
||||
use std::time::Duration;
|
||||
|
||||
#[cfg(feature = "json")] use serde::Serialize;
|
||||
#[cfg(feature = "json")] use serde::de::DeserializeOwned;
|
||||
#[cfg(feature = "json")]
|
||||
use serde::de::DeserializeOwned;
|
||||
#[cfg(feature = "json")]
|
||||
use serde::Serialize;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// HTTP method to use for the request.
|
||||
enum Method {
|
||||
Get, Post, Put, Patch, Delete
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Patch,
|
||||
Delete,
|
||||
}
|
||||
|
||||
/// Certificate types for client-certificate key pairs.
|
||||
pub enum CertType {
|
||||
P12, PEM, DER
|
||||
P12,
|
||||
PEM,
|
||||
DER,
|
||||
}
|
||||
|
||||
/// Builder structure for an HTTP request.
|
||||
|
@ -145,7 +157,7 @@ pub struct Response<T> {
|
|||
pub body: T,
|
||||
}
|
||||
|
||||
impl <'a> Request<'a> {
|
||||
impl<'a> Request<'a> {
|
||||
/// Initiate an HTTP request with the given method and URL.
|
||||
fn new(method: Method, url: &'a str) -> Self {
|
||||
Request {
|
||||
|
@ -158,19 +170,29 @@ impl <'a> Request<'a> {
|
|||
}
|
||||
|
||||
/// 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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
/// supplied token.
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -212,8 +235,11 @@ impl <'a> Request<'a> {
|
|||
/// Consult the documentation for the `ssl_cert` and `ssl_key`
|
||||
/// functions in `curl::easy::Easy2` for details on supported
|
||||
/// formats and defaults.
|
||||
pub fn tls_client_cert<P: AsRef<Path>>(mut self, cert_type: CertType, cert: P)
|
||||
-> Result<Self, curl::Error> {
|
||||
pub fn tls_client_cert<P: AsRef<Path>>(
|
||||
mut self,
|
||||
cert_type: CertType,
|
||||
cert: P,
|
||||
) -> Result<Self, curl::Error> {
|
||||
self.handle.ssl_cert(cert)?;
|
||||
self.handle.ssl_cert_type(match cert_type {
|
||||
CertType::P12 => "P12",
|
||||
|
@ -262,13 +288,17 @@ impl <'a> Request<'a> {
|
|||
/// ```
|
||||
/// # use crimp::Request;
|
||||
/// let response = Request::get("https://httpbin.org/get")
|
||||
/// .with_handle(|mut handle| handle.referer("Example-Referer")).unwrap()
|
||||
/// .send().unwrap();
|
||||
/// .with_handle(|mut handle| handle.referer("Example-Referer"))
|
||||
/// .unwrap()
|
||||
/// .send()
|
||||
/// .unwrap();
|
||||
/// #
|
||||
/// # assert!(response.is_success());
|
||||
/// ```
|
||||
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)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
@ -293,12 +323,15 @@ impl <'a> Request<'a> {
|
|||
/// let mut form = Form::new();
|
||||
/// form.part("some-name")
|
||||
/// .contents("some-data".as_bytes())
|
||||
/// .add().unwrap();
|
||||
/// .add()
|
||||
/// .unwrap();
|
||||
///
|
||||
/// let response = Request::post("https://httpbin.org/post")
|
||||
/// .user_agent("crimp test suite").unwrap()
|
||||
/// .user_agent("crimp test suite")
|
||||
/// .unwrap()
|
||||
/// .form(form)
|
||||
/// .send().unwrap();
|
||||
/// .send()
|
||||
/// .unwrap();
|
||||
/// #
|
||||
/// # assert_eq!(200, response.status, "form POST should succeed");
|
||||
/// # assert_eq!(
|
||||
|
@ -330,10 +363,10 @@ impl <'a> Request<'a> {
|
|||
self.handle.url(self.url)?;
|
||||
|
||||
match self.method {
|
||||
Method::Get => self.handle.get(true)?,
|
||||
Method::Post => self.handle.post(true)?,
|
||||
Method::Put => self.handle.put(true)?,
|
||||
Method::Patch => self.handle.custom_request("PATCH")?,
|
||||
Method::Get => self.handle.get(true)?,
|
||||
Method::Post => self.handle.post(true)?,
|
||||
Method::Put => self.handle.put(true)?,
|
||||
Method::Patch => self.handle.custom_request("PATCH")?,
|
||||
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
|
||||
// and configure the expected body size (or form payload).
|
||||
match self.body {
|
||||
match self.body {
|
||||
Body::Bytes { content_type, data } => {
|
||||
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")]
|
||||
Body::Json(ref data) => {
|
||||
self.handle.post_field_size(data.len() as u64)?;
|
||||
self.headers.append("Content-Type: application/json")?;
|
||||
},
|
||||
}
|
||||
|
||||
// Do not set content-type header at all if there is no
|
||||
// body, or if the form handler was invoked above.
|
||||
_ => (),
|
||||
// Do not set content-type header at all if there is no
|
||||
// body, or if the form handler was invoked above.
|
||||
_ => (),
|
||||
};
|
||||
|
||||
// Configure headers on the request:
|
||||
|
@ -407,9 +441,7 @@ impl <'a> Request<'a> {
|
|||
return true;
|
||||
}
|
||||
|
||||
headers.insert(
|
||||
split[0].trim().to_string(), split[1].trim().to_string()
|
||||
);
|
||||
headers.insert(split[0].trim().to_string(), split[1].trim().to_string());
|
||||
true
|
||||
})?;
|
||||
|
||||
|
@ -427,7 +459,7 @@ impl <'a> Request<'a> {
|
|||
Ok(Response {
|
||||
status: self.handle.response_code()?,
|
||||
headers,
|
||||
body
|
||||
body,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -438,13 +470,14 @@ impl <'a> Request<'a> {
|
|||
///
|
||||
/// As we manually set the expected upload size, cURL will call the
|
||||
/// read callback repeatedly until it has all the data it needs.
|
||||
fn chunked_read_function<'easy, 'data>(transfer: &mut Transfer<'easy, 'data>,
|
||||
data: &'data [u8]) -> Result<(), curl::Error> {
|
||||
fn chunked_read_function<'easy, 'data>(
|
||||
transfer: &mut Transfer<'easy, 'data>,
|
||||
data: &'data [u8],
|
||||
) -> Result<(), curl::Error> {
|
||||
let mut data = data;
|
||||
|
||||
transfer.read_function(move |mut into| {
|
||||
let written = into.write(data)
|
||||
.map_err(|_| ReadError::Abort)?;
|
||||
let written = into.write(data).map_err(|_| ReadError::Abort)?;
|
||||
|
||||
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
|
||||
/// success (i.e. in the 200-299 range).
|
||||
pub fn is_success(&self) -> bool {
|
||||
|
@ -466,9 +499,11 @@ impl <T> Response<T> {
|
|||
/// This function exists for convenience to avoid having to write
|
||||
/// repetitive `if !response.is_success() { ... }` blocks.
|
||||
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() {
|
||||
return Err(closure(self))
|
||||
return Err(closure(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
|
||||
|
||||
use super::*;
|
||||
use serde_json::{Value, json};
|
||||
use serde_json::{json, Value};
|
||||
|
||||
// These tests check whether the correct HTTP method is used in the
|
||||
// requests.
|
||||
|
@ -14,7 +14,8 @@ use serde_json::{Value, json};
|
|||
#[test]
|
||||
fn test_http_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");
|
||||
}
|
||||
|
@ -22,7 +23,8 @@ fn test_http_get() {
|
|||
#[test]
|
||||
fn test_http_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");
|
||||
}
|
||||
|
@ -30,7 +32,8 @@ fn test_http_delete() {
|
|||
#[test]
|
||||
fn test_http_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");
|
||||
}
|
||||
|
@ -38,7 +41,8 @@ fn test_http_put() {
|
|||
#[test]
|
||||
fn test_http_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");
|
||||
}
|
||||
|
@ -50,18 +54,25 @@ fn test_http_patch() {
|
|||
fn test_http_post() {
|
||||
let body = "test body";
|
||||
let response = Request::post("http://127.0.0.1:4662/post")
|
||||
.user_agent("crimp test suite").expect("failed to set user-agent")
|
||||
.timeout(Duration::from_secs(5)).expect("failed to set request timeout")
|
||||
.user_agent("crimp test suite")
|
||||
.expect("failed to set user-agent")
|
||||
.timeout(Duration::from_secs(5))
|
||||
.expect("failed to set request timeout")
|
||||
.body("text/plain", &body.as_bytes())
|
||||
.send().expect("failed to send request")
|
||||
.as_json::<Value>().expect("failed to deserialize response");
|
||||
.send()
|
||||
.expect("failed to send request")
|
||||
.as_json::<Value>()
|
||||
.expect("failed to deserialize response");
|
||||
|
||||
let data = response.body;
|
||||
|
||||
assert_eq!(200, response.status, "response status should be 200 OK");
|
||||
|
||||
assert_eq!(data.get("data").unwrap(), &json!("test body"),
|
||||
"test body should have been POSTed");
|
||||
assert_eq!(
|
||||
data.get("data").unwrap(),
|
||||
&json!("test body"),
|
||||
"test body should have been POSTed"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
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() {
|
||||
let body = json!({
|
||||
"purpose": "testing!"
|
||||
});
|
||||
|
||||
let response = Request::post("http://127.0.0.1:4662/post")
|
||||
.user_agent("crimp test suite").expect("failed to set user-agent")
|
||||
.timeout(Duration::from_secs(5)).expect("failed to set request timeout")
|
||||
.json(&body).expect("request serialization failed")
|
||||
.send().expect("failed to send request")
|
||||
.as_json::<Value>().expect("failed to deserialize response");
|
||||
|
||||
.user_agent("crimp test suite")
|
||||
.expect("failed to set user-agent")
|
||||
.timeout(Duration::from_secs(5))
|
||||
.expect("failed to set request timeout")
|
||||
.json(&body)
|
||||
.expect("request serialization failed")
|
||||
.send()
|
||||
.expect("failed to send request")
|
||||
.as_json::<Value>()
|
||||
.expect("failed to deserialize response");
|
||||
|
||||
let data = response.body;
|
||||
|
||||
assert_eq!(200, response.status, "response status should be 200 OK");
|
||||
|
||||
assert_eq!(data.get("json").unwrap(), &body,
|
||||
"test body should have been POSTed");
|
||||
assert_eq!(
|
||||
data.get("json").unwrap(),
|
||||
&body,
|
||||
"test body should have been POSTed"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
data.get("headers").unwrap().get("Content-Type").unwrap(),
|
||||
|
@ -104,8 +123,10 @@ fn test_http_post_json() {
|
|||
#[test]
|
||||
fn test_bearer_auth() {
|
||||
let response = Request::get("http://127.0.0.1:4662/bearer")
|
||||
.bearer_auth("some-token").expect("failed to set auth header")
|
||||
.send().expect("failed to send request");
|
||||
.bearer_auth("some-token")
|
||||
.expect("failed to set auth header")
|
||||
.send()
|
||||
.expect("failed to send request");
|
||||
|
||||
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 response = request
|
||||
.basic_auth("alan_watts", "oneness").expect("failed to set auth header")
|
||||
.send().expect("failed to send request");
|
||||
.basic_auth("alan_watts", "oneness")
|
||||
.expect("failed to set auth header")
|
||||
.send()
|
||||
.expect("failed to send request");
|
||||
|
||||
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")
|
||||
.body("application/octet-stream", &[0; BODY_SIZE])
|
||||
.send().expect("sending request")
|
||||
.as_json::<Value>().expect("JSON deserialisation");
|
||||
.send()
|
||||
.expect("sending request")
|
||||
.as_json::<Value>()
|
||||
.expect("JSON deserialisation");
|
||||
|
||||
// httpbin returns the uploaded data as a string in the `data`
|
||||
// field.
|
||||
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.
|
||||
|
@ -144,9 +173,13 @@ fn test_large_body() {
|
|||
#[test]
|
||||
fn test_error_for_status() {
|
||||
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));
|
||||
|
||||
assert_eq!(Err("Response error code: 405".into()), response,
|
||||
"returned error should be converted into Result::Err");
|
||||
assert_eq!(
|
||||
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" }`.
|
||||
{ exe, name }:
|
||||
|
||||
pkgs.runCommandLocal "${name}-bin" {} ''
|
||||
pkgs.runCommandLocal "${name}-bin" { } ''
|
||||
mkdir -p $out/bin
|
||||
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, ... }:
|
||||
|
||||
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
|
||||
${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
|
||||
# rules_go.
|
||||
|
||||
{ pkgs ? import <nixpkgs> {}
|
||||
, gopkgs
|
||||
, ... }:
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, ...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (builtins)
|
||||
|
@ -22,7 +22,7 @@ let
|
|||
replaceStrings
|
||||
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
|
||||
spaceOut = lib.concatStringsSep " ";
|
||||
|
@ -41,9 +41,7 @@ let
|
|||
|
||||
xFlags = x_defs: spaceOut (map (k: "-X ${k}=${x_defs."${k}"}") (attrNames x_defs));
|
||||
|
||||
pathToName = p: replaceStrings ["/"] ["_"] (toString p);
|
||||
|
||||
removeRefs = refs: "${removeReferencesTo}/bin/remove-references-to ${lib.concatMapStrings (ref: " -t ${ref}") ([ go ] ++ refs)}";
|
||||
pathToName = p: replaceStrings [ "/" ] [ "_" ] (toString p);
|
||||
|
||||
# Add an `overrideGo` attribute to a function result that works
|
||||
# similar to `overrideAttrs`, but is used specifically for the
|
||||
|
@ -55,51 +53,52 @@ let
|
|||
# High-level build functions
|
||||
|
||||
# Build a Go program out of the specified files and dependencies.
|
||||
program = { name, srcs, deps ? [], x_defs ? {} }:
|
||||
let uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
||||
in runCommand name {} ''
|
||||
${go}/bin/go tool compile -o ${name}.a -trimpath="$PWD;${go}" ${includeSources uniqueDeps} ${spaceOut srcs}
|
||||
mkdir -p $out/bin
|
||||
export GOROOT_FINAL=go
|
||||
${go}/bin/go tool link -o $out/bin/${name} -buildid nix ${xFlags x_defs} ${includeLibs uniqueDeps} ${name}.a
|
||||
${removeRefs srcs} $out/bin/${name}
|
||||
'';
|
||||
program = { name, srcs, deps ? [ ], x_defs ? { } }:
|
||||
let uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
||||
in runCommand name { } ''
|
||||
${go}/bin/go tool compile -o ${name}.a -trimpath=$PWD -trimpath=${go} ${includeSources uniqueDeps} ${spaceOut srcs}
|
||||
mkdir -p $out/bin
|
||||
export GOROOT_FINAL=go
|
||||
${go}/bin/go tool link -o $out/bin/${name} -buildid nix ${xFlags x_defs} ${includeLibs uniqueDeps} ${name}.a
|
||||
'';
|
||||
|
||||
# Build a Go library assembled out of the specified files.
|
||||
#
|
||||
# This outputs both the sources and compiled binary, as both are
|
||||
# needed when downstream packages depend on it.
|
||||
package = { name, srcs, deps ? [], path ? name, sfiles ? [] }:
|
||||
let
|
||||
uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
||||
package = { name, srcs, deps ? [ ], path ? name, sfiles ? [ ] }:
|
||||
let
|
||||
uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
||||
|
||||
# The build steps below need to be executed conditionally for Go
|
||||
# assembly if the analyser detected any *.s files.
|
||||
#
|
||||
# This is required for several popular packages (e.g. x/sys).
|
||||
ifAsm = do: lib.optionalString (sfiles != []) do;
|
||||
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 -o ./asm.o ${spaceOut sfiles}
|
||||
'';
|
||||
asmLink = ifAsm "-symabis ./symabis -asmhdr $out/go_asm.h";
|
||||
asmPack = ifAsm ''
|
||||
${go}/bin/go tool pack r $out/${path}.a ./asm.o
|
||||
'';
|
||||
# The build steps below need to be executed conditionally for Go
|
||||
# assembly if the analyser detected any *.s files.
|
||||
#
|
||||
# This is required for several popular packages (e.g. x/sys).
|
||||
ifAsm = do: lib.optionalString (sfiles != [ ]) do;
|
||||
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 -o ./asm.o ${spaceOut sfiles}
|
||||
'';
|
||||
asmLink = ifAsm "-symabis ./symabis -asmhdr $out/go_asm.h";
|
||||
asmPack = ifAsm ''
|
||||
${go}/bin/go tool pack r $out/${path}.a ./asm.o
|
||||
'';
|
||||
|
||||
gopkg = (runCommand "golib-${name}" {} ''
|
||||
mkdir -p $out/${path}
|
||||
${srcList path (map (s: "${s}") srcs)}
|
||||
${asmBuild}
|
||||
${go}/bin/go tool compile -pack ${asmLink} -o $out/${path}.a -trimpath="$PWD;${go}" -p ${path} ${includeSources uniqueDeps} ${spaceOut srcs}
|
||||
${asmPack}
|
||||
${removeRefs srcs} $out/${path}.a
|
||||
'') // {
|
||||
inherit gopkg;
|
||||
goDeps = uniqueDeps;
|
||||
goImportPath = path;
|
||||
};
|
||||
in gopkg;
|
||||
gopkg = (runCommand "golib-${name}" { } ''
|
||||
mkdir -p $out/${path}
|
||||
${srcList path (map (s: "${s}") srcs)}
|
||||
${asmBuild}
|
||||
${go}/bin/go tool compile -pack ${asmLink} -o $out/${path}.a -trimpath=$PWD -trimpath=${go} -p ${path} ${includeSources uniqueDeps} ${spaceOut srcs}
|
||||
${asmPack}
|
||||
'').overrideAttrs (_: {
|
||||
passthru = {
|
||||
inherit gopkg;
|
||||
goDeps = uniqueDeps;
|
||||
goImportPath = path;
|
||||
};
|
||||
});
|
||||
in
|
||||
gopkg;
|
||||
|
||||
# Build a tree of Go libraries out of an external Go source
|
||||
# directory that follows the standard Go layout and was not built
|
||||
|
@ -111,50 +110,31 @@ let
|
|||
|
||||
# Import support libraries needed for protobuf & gRPC support
|
||||
protoLibs = import ./proto.nix {
|
||||
inherit gopkgs;
|
||||
inherit external;
|
||||
};
|
||||
|
||||
# Build a Go library out of the specified protobuf definition.
|
||||
proto = { name, proto ? null, protos ? [ proto ], path ? name, goPackage ? name, withGrpc ? false, extraSrcs ? [], extraDeps ? [] }:
|
||||
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) {
|
||||
proto = { name, proto, path ? name, goPackage ? name, extraDeps ? [ ] }: (makeOverridable package) {
|
||||
inherit name path;
|
||||
deps = [ protoLibs.goProto.proto.gopkg ] ++ extraDeps;
|
||||
srcs = lib.concatMap (proto: lib.singleton (runCommand "goproto-${name}-${baseNameOf proto}.pb.go" {} ''
|
||||
${protobuf}/bin/protoc \
|
||||
-I ${protosDir} \
|
||||
--plugin=${protoLibs.goProto.cmd.protoc-gen-go.gopkg}/bin/protoc-gen-go \
|
||||
--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;
|
||||
srcs = lib.singleton (runCommand "goproto-${name}.pb.go" { } ''
|
||||
cp ${proto} ${baseNameOf proto}
|
||||
${protobuf}/bin/protoc --plugin=${protoLibs.goProto.protoc-gen-go.gopkg}/bin/protoc-gen-go \
|
||||
--go_out=plugins=grpc,import_path=${baseNameOf path}:. ${baseNameOf proto}
|
||||
mv ./${goPackage}/*.pb.go $out
|
||||
'');
|
||||
};
|
||||
|
||||
# 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
|
||||
# overrideable.
|
||||
program = makeOverridable program;
|
||||
package = makeOverridable package;
|
||||
proto = proto;
|
||||
proto = makeOverridable proto;
|
||||
grpc = makeOverridable grpc;
|
||||
external = makeOverridable external;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# users a quick introduction to how to use buildGo.
|
||||
|
||||
let
|
||||
buildGo = import ../default.nix {};
|
||||
buildGo = import ../default.nix { };
|
||||
|
||||
# Example use of buildGo.package, which creates an importable Go
|
||||
# package from the specified source files.
|
||||
|
@ -29,7 +29,8 @@ let
|
|||
# Example use of buildGo.program, which builds an executable using
|
||||
# the specified name and dependencies (which in turn must have been
|
||||
# created via buildGo.package etc.)
|
||||
in buildGo.program {
|
||||
in
|
||||
buildGo.program {
|
||||
name = "example";
|
||||
|
||||
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;
|
||||
|
||||
pathToName = p: replaceStrings ["/"] ["_"] (toString p);
|
||||
pathToName = p: replaceStrings [ "/" ] [ "_" ] (toString p);
|
||||
|
||||
# Collect all non-vendored dependencies from the Go standard library
|
||||
# into a file that can be used to filter them out when processing
|
||||
# dependencies.
|
||||
stdlibPackages = runCommand "stdlib-pkgs.json" {} ''
|
||||
stdlibPackages = runCommand "stdlib-pkgs.json" { } ''
|
||||
export HOME=$PWD
|
||||
export GOPATH=/dev/null
|
||||
${go}/bin/go list std | \
|
||||
|
@ -45,20 +45,28 @@ let
|
|||
};
|
||||
|
||||
mkset = path: value:
|
||||
if path == [] then { gopkg = value; }
|
||||
if path == [ ] then { gopkg = value; }
|
||||
else { "${head path}" = mkset (tail path) value; };
|
||||
|
||||
last = l: elemAt l ((length l) - 1);
|
||||
|
||||
toPackage = self: src: path: depMap: entry:
|
||||
let
|
||||
localDeps = map (d: lib.attrByPath (d ++ [ "gopkg" ]) (
|
||||
throw "missing local dependency '${lib.concatStringsSep "." d}' in '${path}'"
|
||||
) self) entry.localDeps;
|
||||
localDeps = map
|
||||
(d: lib.attrByPath (d ++ [ "gopkg" ])
|
||||
(
|
||||
throw "missing local dependency '${lib.concatStringsSep "." d}' in '${path}'"
|
||||
)
|
||||
self)
|
||||
entry.localDeps;
|
||||
|
||||
foreignDeps = map (d: lib.attrByPath [ d ] (
|
||||
throw "missing foreign dependency '${d}' in '${path}'"
|
||||
) depMap) entry.foreignDeps;
|
||||
foreignDeps = map
|
||||
(d: lib.attrByPath [ d.path ]
|
||||
(
|
||||
throw "missing foreign dependency '${d.path}' in '${path}, imported at ${d.position}'"
|
||||
)
|
||||
depMap)
|
||||
entry.foreignDeps;
|
||||
|
||||
args = {
|
||||
srcs = map (f: src + ("/" + f)) entry.files;
|
||||
|
@ -74,22 +82,28 @@ let
|
|||
binArgs = args // {
|
||||
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
|
||||
# derivation) so that they can be conditionally imported only in
|
||||
# sub-packages that require them.
|
||||
depMap = listToAttrs (map (d: {
|
||||
name = d.goImportPath;
|
||||
value = d;
|
||||
}) (map (d: d.gopkg) deps));
|
||||
depMap = listToAttrs (map
|
||||
(d: {
|
||||
name = d.goImportPath;
|
||||
value = d;
|
||||
})
|
||||
(map (d: d.gopkg) deps));
|
||||
|
||||
name = pathToName path;
|
||||
analysisOutput = runCommand "${name}-structure.json" {} ''
|
||||
analysisOutput = runCommand "${name}-structure.json" { } ''
|
||||
${analyser}/bin/analyser -path ${path} -source ${src} > $out
|
||||
'';
|
||||
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
|
||||
))
|
||||
|
|
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)
|
||||
// and external (none-stdlib) dependencies of this package.
|
||||
type pkg struct {
|
||||
Name string `json:"name"`
|
||||
Locator []string `json:"locator"`
|
||||
Files []string `json:"files"`
|
||||
SFiles []string `json:"sfiles"`
|
||||
LocalDeps [][]string `json:"localDeps"`
|
||||
ForeignDeps []string `json:"foreignDeps"`
|
||||
IsCommand bool `json:"isCommand"`
|
||||
Name string `json:"name"`
|
||||
Locator []string `json:"locator"`
|
||||
Files []string `json:"files"`
|
||||
SFiles []string `json:"sfiles"`
|
||||
LocalDeps [][]string `json:"localDeps"`
|
||||
ForeignDeps []foreignDep `json:"foreignDeps"`
|
||||
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
|
||||
|
@ -88,7 +94,7 @@ func analysePackage(root, source, importpath string, stdlib map[string]bool) (pk
|
|||
}
|
||||
|
||||
local := [][]string{}
|
||||
foreign := []string{}
|
||||
foreign := []foreignDep{}
|
||||
|
||||
for _, i := range p.Imports {
|
||||
if stdlib[i] {
|
||||
|
@ -100,7 +106,12 @@ func analysePackage(root, source, importpath string, stdlib map[string]bool) (pk
|
|||
} else if strings.HasPrefix(i, importpath+"/") {
|
||||
local = append(local, strings.Split(strings.TrimPrefix(i, importpath+"/"), "/"))
|
||||
} 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
|
||||
# service in Go.
|
||||
|
||||
{ gopkgs }:
|
||||
{ external }:
|
||||
|
||||
let
|
||||
inherit (builtins) fetchGit map;
|
||||
in rec {
|
||||
goProto = gopkgs."google.golang.org".protobuf;
|
||||
goGrpc = gopkgs."google.golang.org".grpc;
|
||||
in
|
||||
rec {
|
||||
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
|
||||
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)
|
||||
* Composability with Nix tooling for other languages
|
||||
* Effective, per-system caching strategies
|
||||
* Easy overriding of dependencies and whatnot
|
||||
* Convenient support for multiple Common Lisp implementations
|
||||
* ... and more!
|
||||
|
||||
The project is still in its early stages and some important
|
||||
restrictions should be highlighted:
|
||||
|
||||
* Only SBCL is supported (though the plan is to add support for at
|
||||
least ABCL and Clozure CL, and maybe make it extensible)
|
||||
* Extending `buildLisp` with support for a custom implementation
|
||||
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
|
||||
|
||||
|
@ -32,6 +38,7 @@ restrictions should be highlighted:
|
|||
| `deps` | `list<drv>` | List of dependencies | no |
|
||||
| `native` | `list<drv>` | List of native dependencies | 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
|
||||
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 |
|
||||
| `main` | `string` | Entrypoint function | 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
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
# free-for-all of existing Lisp build systems.
|
||||
|
||||
{ pkgs ? import <nixpkgs> {}, ... }:
|
||||
{ pkgs ? import <nixpkgs> { }, ... }:
|
||||
|
||||
let
|
||||
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
|
||||
#
|
||||
|
||||
# 'genLoadLisp' generates Lisp code that instructs SBCL to load all
|
||||
# the provided Lisp libraries.
|
||||
genLoadLisp = deps: lib.concatStringsSep "\n"
|
||||
(map (lib: "(load \"${lib}/${lib.lispName}.fasl\")") (allDeps deps));
|
||||
defaultImplementation = impls.sbcl;
|
||||
|
||||
# 'genCompileLisp' generates a Lisp file that instructs SBCL to
|
||||
# compile the provided list of Lisp source files to $out.
|
||||
genCompileLisp = srcs: deps: writeText "compile.lisp" ''
|
||||
;; This file compiles the specified sources into the Nix build
|
||||
;; directory, creating one FASL file for each source.
|
||||
(require 'sb-posix)
|
||||
|
||||
${genLoadLisp deps}
|
||||
|
||||
(defun nix-compile-lisp (file 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 (_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)
|
||||
}
|
||||
))
|
||||
# Many Common Lisp implementations (like ECL and CCL) will occasionally drop
|
||||
# you into an interactive debugger even when executing something as a script.
|
||||
# In nix builds we don't want such a situation: Any error should make the
|
||||
# script exit non-zero. Luckily the ANSI standard specifies *debugger-hook*
|
||||
# which is invoked before the debugger letting us just do that.
|
||||
disableDebugger = writeText "disable-debugger.lisp" ''
|
||||
(setf *debugger-hook*
|
||||
(lambda (error hook)
|
||||
(declare (ignore hook))
|
||||
(format *error-output* "~%Unhandled error: ~a~%" error)
|
||||
#+ccl (quit 1)
|
||||
#+ecl (ext:quit 1)))
|
||||
'';
|
||||
|
||||
# 'genTestLisp' generates a Lisp file that loads all sources and deps and
|
||||
# executes expression
|
||||
genTestLisp = name: srcs: deps: expression: writeText "${name}.lisp" ''
|
||||
# Process a list of arbitrary values which also contains “implementation
|
||||
# filter sets” which describe conditonal inclusion of elements depending
|
||||
# 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
|
||||
${genLoadLisp deps}
|
||||
${impl.genLoadLisp deps}
|
||||
|
||||
;; Sources
|
||||
${lib.concatStringsSep "\n" (map (src: "(load \"${src}\")") srcs)}
|
||||
|
@ -78,10 +106,23 @@ let
|
|||
dependsOn = a: b: builtins.elem a b.lispDeps;
|
||||
|
||||
# 'allDeps' flattens the list of dependencies (and their
|
||||
# dependencies) into one ordered list of unique deps.
|
||||
allDeps = deps: (lib.toposort dependsOn (lib.unique (
|
||||
lib.flatten (deps ++ (map (d: d.lispDeps) deps))
|
||||
))).result;
|
||||
# dependencies) into one ordered list of unique deps which
|
||||
# all use the given implementation.
|
||||
allDeps = impl: deps:
|
||||
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
|
||||
# to ensure that library load paths are set correctly during all
|
||||
|
@ -90,26 +131,6 @@ let
|
|||
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
|
||||
# similar to `overrideAttrs`, but is used specifically for the
|
||||
# arguments passed to Lisp builders.
|
||||
|
@ -117,142 +138,642 @@ let
|
|||
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,
|
||||
# and then executes expression to check its result
|
||||
testSuite = { name, expression, srcs, deps ? [], native ? [] }:
|
||||
testSuite = { name, expression, srcs, deps ? [ ], native ? [ ], implementation }:
|
||||
let
|
||||
lispNativeDeps = allNative native deps;
|
||||
lispDeps = allDeps deps;
|
||||
in runCommandNoCC name {
|
||||
LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
|
||||
LANG = "C.UTF-8";
|
||||
} ''
|
||||
lispDeps = allDeps implementation (implFilter implementation deps);
|
||||
lispNativeDeps = allNative native lispDeps;
|
||||
filteredSrcs = implFilter implementation srcs;
|
||||
in
|
||||
runCommandNoCC name
|
||||
{
|
||||
LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
|
||||
LANG = "C.UTF-8";
|
||||
} ''
|
||||
echo "Running test suite ${name}"
|
||||
|
||||
${sbcl}/bin/sbcl --script ${genTestLisp name srcs deps expression} \
|
||||
| tee $out
|
||||
${implementation.runScript} ${
|
||||
implementation.genTestLisp {
|
||||
inherit name expression;
|
||||
srcs = filteredSrcs;
|
||||
deps = lispDeps;
|
||||
}
|
||||
} | tee $out
|
||||
|
||||
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
|
||||
#
|
||||
|
||||
# 'library' builds a list of Common Lisp files into a single FASL
|
||||
# which can then be loaded into SBCL.
|
||||
# 'library' builds a list of Common Lisp files into an implementation
|
||||
# specific library format, usually a single FASL file, which can then be
|
||||
# loaded and built into an executable via 'program'.
|
||||
library =
|
||||
{ name
|
||||
, implementation ? defaultImplementation
|
||||
, brokenOn ? [ ] # TODO(sterni): make this a warning
|
||||
, srcs
|
||||
, deps ? []
|
||||
, native ? []
|
||||
, deps ? [ ]
|
||||
, native ? [ ]
|
||||
, tests ? null
|
||||
, passthru ? { }
|
||||
}:
|
||||
let
|
||||
lispNativeDeps = (allNative native deps);
|
||||
lispDeps = allDeps deps;
|
||||
testDrv = if ! isNull tests
|
||||
then testSuite {
|
||||
name = tests.name or "${name}-test";
|
||||
srcs = srcs ++ (tests.srcs or []);
|
||||
deps = deps ++ (tests.deps or []);
|
||||
expression = tests.expression;
|
||||
}
|
||||
filteredDeps = implFilter implementation deps;
|
||||
filteredSrcs = implFilter implementation srcs;
|
||||
lispNativeDeps = (allNative native filteredDeps);
|
||||
lispDeps = allDeps implementation filteredDeps;
|
||||
testDrv =
|
||||
if ! isNull tests
|
||||
then
|
||||
testSuite
|
||||
{
|
||||
name = tests.name or "${name}-test";
|
||||
srcs = filteredSrcs ++ (tests.srcs or [ ]);
|
||||
deps = filteredDeps ++ (tests.deps or [ ]);
|
||||
expression = tests.expression;
|
||||
inherit implementation;
|
||||
}
|
||||
else null;
|
||||
in lib.fix (self: runCommandNoCC "${name}-cllib" {
|
||||
LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
|
||||
LANG = "C.UTF-8";
|
||||
} ''
|
||||
in
|
||||
lib.fix (self: runCommandNoCC "${name}-cllib"
|
||||
{
|
||||
LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
|
||||
LANG = "C.UTF-8";
|
||||
passthru = passthru // {
|
||||
inherit lispNativeDeps lispDeps;
|
||||
lispName = name;
|
||||
lispBinary = false;
|
||||
tests = testDrv;
|
||||
};
|
||||
} ''
|
||||
${if ! isNull testDrv
|
||||
then "echo 'Test ${testDrv} succeeded'"
|
||||
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
|
||||
|
||||
chmod +x cat_fasls
|
||||
./cat_fasls > $out/${name}.fasl
|
||||
'' // {
|
||||
inherit lispNativeDeps lispDeps;
|
||||
lispName = name;
|
||||
lispBinary = false;
|
||||
tests = testDrv;
|
||||
sbcl = sbclWith [ self ];
|
||||
});
|
||||
${implementation.runScript} ${
|
||||
implementation.genCompileLisp {
|
||||
srcs = filteredSrcs;
|
||||
inherit name;
|
||||
deps = lispDeps;
|
||||
}
|
||||
}
|
||||
'');
|
||||
|
||||
# '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.
|
||||
program =
|
||||
{ name
|
||||
, implementation ? defaultImplementation
|
||||
, brokenOn ? [ ] # TODO(sterni): make this a warning
|
||||
, main ? "${name}:main"
|
||||
, srcs
|
||||
, deps ? []
|
||||
, native ? []
|
||||
, deps ? [ ]
|
||||
, native ? [ ]
|
||||
, tests ? null
|
||||
, passthru ? { }
|
||||
}:
|
||||
let
|
||||
lispDeps = allDeps deps;
|
||||
filteredSrcs = implFilter implementation srcs;
|
||||
filteredDeps = implFilter implementation deps;
|
||||
lispDeps = allDeps implementation filteredDeps;
|
||||
libPath = lib.makeLibraryPath (allNative native lispDeps);
|
||||
selfLib = library {
|
||||
inherit name srcs native;
|
||||
# overriding is used internally to propagate the implementation to use
|
||||
selfLib = (makeOverridable library) {
|
||||
inherit name native brokenOn;
|
||||
deps = lispDeps;
|
||||
srcs = filteredSrcs;
|
||||
};
|
||||
testDrv = if ! isNull tests
|
||||
then testSuite {
|
||||
name = tests.name or "${name}-test";
|
||||
srcs =
|
||||
(
|
||||
srcs ++ (tests.srcs or []));
|
||||
deps = deps ++ (tests.deps or []);
|
||||
expression = tests.expression;
|
||||
}
|
||||
testDrv =
|
||||
if ! isNull tests
|
||||
then
|
||||
testSuite
|
||||
{
|
||||
name = tests.name or "${name}-test";
|
||||
srcs =
|
||||
(
|
||||
# testSuite does run implFilter as well
|
||||
filteredSrcs ++ (tests.srcs or [ ])
|
||||
);
|
||||
deps = filteredDeps ++ (tests.deps or [ ]);
|
||||
expression = tests.expression;
|
||||
inherit implementation;
|
||||
}
|
||||
else null;
|
||||
in lib.fix (self: runCommandNoCC "${name}" {
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
LD_LIBRARY_PATH = libPath;
|
||||
LANG = "C.UTF-8";
|
||||
} ''
|
||||
${if ! isNull testDrv
|
||||
then "echo 'Test ${testDrv} succeeded'"
|
||||
else ""}
|
||||
mkdir -p $out/bin
|
||||
|
||||
${sbcl}/bin/sbcl --script ${
|
||||
genDumpLisp name main ([ selfLib ] ++ lispDeps)
|
||||
in
|
||||
lib.fix (self: runCommandNoCC "${name}"
|
||||
{
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
LD_LIBRARY_PATH = libPath;
|
||||
LANG = "C.UTF-8";
|
||||
passthru = passthru // {
|
||||
lispName = name;
|
||||
lispDeps = [ selfLib ];
|
||||
lispNativeDeps = native;
|
||||
lispBinary = true;
|
||||
tests = testDrv;
|
||||
};
|
||||
}
|
||||
(''
|
||||
${if ! isNull testDrv
|
||||
then "echo 'Test ${testDrv} succeeded'"
|
||||
else ""}
|
||||
mkdir -p $out/bin
|
||||
|
||||
wrapProgram $out/bin/${name} --prefix LD_LIBRARY_PATH : "${libPath}"
|
||||
'' // {
|
||||
lispName = name;
|
||||
lispDeps = [ selfLib ] ++ (tests.deps or []);
|
||||
lispNativeDeps = native;
|
||||
lispBinary = true;
|
||||
tests = testDrv;
|
||||
sbcl = sbclWith [ self ];
|
||||
});
|
||||
${implementation.runScript} ${
|
||||
implementation.genDumpLisp {
|
||||
inherit name main;
|
||||
deps = ([ selfLib ] ++ lispDeps);
|
||||
}
|
||||
}
|
||||
'' + lib.optionalString implementation.wrapProgram ''
|
||||
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
|
||||
# package, such as any of SBCL's sb-* packages.
|
||||
bundled = name: (makeOverridable library) {
|
||||
inherit name;
|
||||
srcs = lib.singleton (builtins.toFile "${name}.lisp" "(require '${name})");
|
||||
};
|
||||
# 'bundled' creates a "library" which makes a built-in package available,
|
||||
# such as any of SBCL's sb-* packages or ASDF. By default this is done
|
||||
# by calling 'require', but implementations are free to provide their
|
||||
# own specific bundled function.
|
||||
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 /
|
||||
# programs loaded.
|
||||
sbclWith = deps:
|
||||
let lispDeps = filter (d: !d.lispBinary) (allDeps deps);
|
||||
in writeShellScriptBin "sbcl" ''
|
||||
export LD_LIBRARY_PATH=${lib.makeLibraryPath (allNative [] lispDeps)};
|
||||
exec ${sbcl}/bin/sbcl ${lib.optionalString (deps != []) "--load ${writeText "load.lisp" (genLoadLisp lispDeps)}"} $@
|
||||
'';
|
||||
in {
|
||||
library = makeOverridable library;
|
||||
program = makeOverridable program;
|
||||
sbclWith = makeOverridable sbclWith;
|
||||
bundled = makeOverridable bundled;
|
||||
# programs loaded in SBCL.
|
||||
sbclWith = impls.sbcl.lispWith;
|
||||
|
||||
inherit (impls)
|
||||
sbcl
|
||||
ecl
|
||||
ccl
|
||||
;
|
||||
}
|
||||
|
|
|
@ -14,15 +14,16 @@ let
|
|||
];
|
||||
};
|
||||
|
||||
# Example Lisp program.
|
||||
#
|
||||
# This builds & writes an executable for a program using the library
|
||||
# above to disk.
|
||||
#
|
||||
# By default, buildLisp.program expects the entry point to be
|
||||
# `$name:main`. This can be overridden by configuring the `main`
|
||||
# attribute.
|
||||
in buildLisp.program {
|
||||
# Example Lisp program.
|
||||
#
|
||||
# This builds & writes an executable for a program using the library
|
||||
# above to disk.
|
||||
#
|
||||
# By default, buildLisp.program expects the entry point to be
|
||||
# `$name:main`. This can be overridden by configuring the `main`
|
||||
# attribute.
|
||||
in
|
||||
buildLisp.program {
|
||||
name = "example";
|
||||
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