about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKane York <kanepyork@gmail.com>2020-08-17T01·03-0700
committerkanepyork <rikingcoding@gmail.com>2020-08-19T01·23+0000
commit92d4554b622ea85ca08d351f696f48a37c67e8b0 (patch)
treed7f5d041acef637f6e805daaac2550b7719c9f44
parentd6f17f48de91538c5b3623484672c1a81d207cba (diff)
feat(tools/tvlc): init project r/1681
tvlc is a tool for managing sparse git worktrees of the TVL depot.
It is still in development; near-term tasks include a setup script,
Nix dependency resolution, worktree removal, and the dispatch
script.

See cs.tvl.fyi/depot/docs/designs/SPARSE_CHECKOUTS.md for more info.

Change-Id: Iad96656f0206178980fe7dcadd3dffe70d690f8f
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1760
Tested-by: BuildkiteCI
Reviewed-by: tazjin <mail@tazj.in>
-rw-r--r--third_party/default.nix1
-rw-r--r--tools/tvlc/OWNERS3
-rw-r--r--tools/tvlc/common.sh30
-rw-r--r--tools/tvlc/default.nix35
-rwxr-xr-xtools/tvlc/tvlc-new102
5 files changed, 171 insertions, 0 deletions
diff --git a/third_party/default.nix b/third_party/default.nix
index 897602f31e..2c5bfa4ad4 100644
--- a/third_party/default.nix
+++ b/third_party/default.nix
@@ -137,6 +137,7 @@ let
       rustc
       s6-portable-utils
       sbcl
+      shellcheck
       sqlite
       stdenvNoCC
       stern
diff --git a/tools/tvlc/OWNERS b/tools/tvlc/OWNERS
new file mode 100644
index 0000000000..9e7830ab21
--- /dev/null
+++ b/tools/tvlc/OWNERS
@@ -0,0 +1,3 @@
+inherited: true
+owners:
+ - riking
diff --git a/tools/tvlc/common.sh b/tools/tvlc/common.sh
new file mode 100644
index 0000000000..2c8cc603cb
--- /dev/null
+++ b/tools/tvlc/common.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+set -eu
+set -o pipefail
+
+XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
+tvlc_root="$XDG_DATA_HOME/tvlc"
+
+if [ -f "$tvlc_root"/nice_checkout_root ]; then
+  nice_checkout_root="$(cat "$tvlc_root"/nice_checkout_root)"
+fi
+nice_checkout_root="${nice_checkout_root:-$HOME/tvlc}"
+
+depot_root=
+if [ -f "$tvlc_root/depot_root" ]; then
+  depot_root="$(cat "$tvlc_root/depot_root")"
+fi
+if [ -d /depot ]; then
+  # don't require config on tvl nixos servers
+  depot_root="${depot_root:-/depot}"
+fi
+if [ -n "$depot_root" ]; then
+  export DEPOT_ROOT="$depot_root"
+fi
+
+if [ ! -d "$tvlc_root" ]; then
+  echo "tvlc: setup required"
+  echo "please run 'tvlc setup' from the depot root"
+  exit 1
+fi
diff --git a/tools/tvlc/default.nix b/tools/tvlc/default.nix
new file mode 100644
index 0000000000..de18af236f
--- /dev/null
+++ b/tools/tvlc/default.nix
@@ -0,0 +1,35 @@
+{ pkgs, depot, ... }:
+
+let
+  commonsh = ./common.sh;
+
+  # TODO(riking): path deduction
+  #tvix-instantiate="${third_party.nix}/bin/nix-instantiate"
+  pathScripts = pkgs.writeShellScript "imports" ''
+  '';
+
+  # setup: git rev-parse --show-toplevel > $tvlc_root/depot_root
+  # setup: mkdir $tvlc_root/clients
+  # setup: echo 1 > $tvlc_root/next_clientid
+
+  tvlcNew = pkgs.stdenv.mkDerivation {
+    name = "tvlc-new";
+    src = ./tvlc-new;
+    doCheck = true;
+
+    unpackPhase = "true";
+    buildPhase = ''
+      substitute ${./tvlc-new} $out --replace common.sh ${commonsh}
+    '';
+    checkPhase = ''
+      ${pkgs.shellcheck}/bin/shellcheck $out ${commonsh} && echo "SHELLCHECK OK"
+    '';
+    installPhase = ''
+      chmod +x $out
+    '';
+  };
+
+in pkgs.stdenv.mkDerivation rec {
+  inherit commonsh;
+  inherit tvlcNew;
+}
diff --git a/tools/tvlc/tvlc-new b/tools/tvlc/tvlc-new
new file mode 100755
index 0000000000..e3e65b4f64
--- /dev/null
+++ b/tools/tvlc/tvlc-new
@@ -0,0 +1,102 @@
+#!/bin/bash
+
+source common.sh
+
+set -eu
+set -o pipefail
+
+function usage() {
+  echo "tvlc new [-n|--name CLIENTNAME] [derivation...]"
+  echo ""
+  cat <<EOF
+  The 'new' command creates a new git sparse checkout with the given name, and
+  contents needed to build the Nix derivation(s) specified on the command line.
+
+  Options:
+    -n/--name client-name: Sets the git branch and nice checkout name for the
+	workspace. If the option is not provided, the name will be based on the
+	first non-option command-line argument.
+    --branch branch-name: Sets the git branch name only.
+EOF
+}
+
+checkout_name=
+branch_name=
+
+options=$(getopt -o 'n:' --long debug --long name: -- "$@")
+eval set -- "$options"
+while true; do
+  case "$1" in
+  -h)
+    usage
+    exit 0
+    ;;
+  -v)
+    version
+    exit 0
+    ;;
+  -n|--name)
+    shift
+    checkout_name="$1"
+    if [ -z "$branch_name" ]; then
+      branch_name=tvlc-"$1"
+    fi
+    ;;
+  --branch)
+    shift
+    branch_name="$1"
+    ;;
+  --)
+    shift
+    break
+    ;;
+  esac
+  shift
+done
+
+if [ $# -eq 0 ]; then
+  echo "error: workspace name, target derivations required"
+  exit 1
+fi
+
+if [ -z "$checkout_name" ]; then
+  # TODO(riking): deduce
+  echo "error: workspace name (-n) required"
+  exit 1
+fi
+
+if [ -d "$nice_checkout_root/$checkout_name" ]; then
+  echo "error: checkout $checkout_name already exists"
+  # nb: shellescape checkout_name because we expect the user to copy-paste it
+  # shellcheck disable=SC1003
+  echo "consider deleting it with tvlc remove '${checkout_name/'/\'}'"
+  exit 1
+fi
+if [ -f "$DEPOT_ROOT/.git/refs/heads/$branch_name" ]; then
+  echo "error: branch $branch_name already exists in git"
+  # shellcheck disable=SC1003
+  echo "consider deleting it with cd $DEPOT_ROOT; git branch -d '${checkout_name/'/\'}'"
+  exit 1
+fi
+
+# TODO(riking): tvlc-get-depends
+
+# bash math
+checkout_id=$(("$(cat "$tvlc_root/next_clientid")"))
+next_checkout_id=$(("$checkout_id"+1))
+echo "$next_checkout_id" > "$tvlc_root/next_clientid"
+
+checkout_dir="$tvlc_root/clients/$checkout_id"
+mkdir "$checkout_dir"
+cd "$DEPOT_ROOT"
+git worktree add --no-checkout -b "$branch_name" "$checkout_dir"
+# BUG: git not creating the /info/ subdir
+mkdir "$DEPOT_ROOT/.git/worktrees/$checkout_id/info"
+
+cd "$checkout_dir"
+git sparse-checkout init --cone
+git sparse-checkout set "$@"
+
+ln -s "$checkout_dir" "$nice_checkout_root"/"$checkout_name"
+
+echo "$nice_checkout_root/$checkout_name"