summaryrefslogtreecommitdiff
path: root/config/services/git
diff options
context:
space:
mode:
Diffstat (limited to 'config/services/git')
-rw-r--r--config/services/git/default.nix5
-rw-r--r--config/services/git/shell-commands/default.nix12
-rw-r--r--config/services/git/shell-commands/repo/.gitignore1
-rw-r--r--config/services/git/shell-commands/repo/default.nix19
-rw-r--r--config/services/git/shell-commands/repo/src/bashly.yml83
-rw-r--r--config/services/git/shell-commands/repo/src/create_command.sh25
-rw-r--r--config/services/git/shell-commands/repo/src/lib/check-git-repository.sh7
-rw-r--r--config/services/git/shell-commands/repo/src/lib/check-realpath.sh9
-rw-r--r--config/services/git/shell-commands/repo/src/lib/colors.sh14
-rw-r--r--config/services/git/shell-commands/repo/src/lib/is-git-dir.sh3
-rw-r--r--config/services/git/shell-commands/repo/src/lib/show-descr.sh3
-rw-r--r--config/services/git/shell-commands/repo/src/lib/show-privacy.sh12
-rw-r--r--config/services/git/shell-commands/repo/src/lib/show-repo-summary.sh8
-rw-r--r--config/services/git/shell-commands/repo/src/lib/show-repo.sh6
-rw-r--r--config/services/git/shell-commands/repo/src/lib/show-size.sh3
-rw-r--r--config/services/git/shell-commands/repo/src/remove_command.sh10
-rw-r--r--config/services/git/shell-commands/repo/src/set_description_command.sh14
-rw-r--r--config/services/git/shell-commands/repo/src/set_privacy_command.sh17
-rw-r--r--config/services/git/shell-commands/repo/src/show_command.sh35
19 files changed, 285 insertions, 1 deletions
diff --git a/config/services/git/default.nix b/config/services/git/default.nix
index abed2ae..d733b38 100644
--- a/config/services/git/default.nix
+++ b/config/services/git/default.nix
@@ -1,7 +1,10 @@
{ config, pkgs, ... }:
{
- imports = [ ./cgit.nix ];
+ imports = [
+ ./cgit.nix
+ ./shell-commands
+ ];
users.users.git = {
isSystemUser = true;
diff --git a/config/services/git/shell-commands/default.nix b/config/services/git/shell-commands/default.nix
new file mode 100644
index 0000000..b88e6b0
--- /dev/null
+++ b/config/services/git/shell-commands/default.nix
@@ -0,0 +1,12 @@
+{ lib, pkgs, ... }:
+let
+ repo = import ./repo { inherit lib pkgs; };
+ gitShellCommands = "/srv/git/git-shell-commands";
+in
+{
+ system.activationScripts.buildGitShell.text = ''
+ install --mode u=rX,g=,o= --owner git --group git --directory ${gitShellCommands}
+ rm -rf ${gitShellCommands}/*
+ ln -s ${repo} ${gitShellCommands}/repo
+ '';
+}
diff --git a/config/services/git/shell-commands/repo/.gitignore b/config/services/git/shell-commands/repo/.gitignore
new file mode 100644
index 0000000..ffdcec4
--- /dev/null
+++ b/config/services/git/shell-commands/repo/.gitignore
@@ -0,0 +1 @@
+repo \ No newline at end of file
diff --git a/config/services/git/shell-commands/repo/default.nix b/config/services/git/shell-commands/repo/default.nix
new file mode 100644
index 0000000..bbccbfd
--- /dev/null
+++ b/config/services/git/shell-commands/repo/default.nix
@@ -0,0 +1,19 @@
+{ lib, pkgs }:
+
+pkgs.stdenvNoCC.mkDerivation {
+ name = "repo";
+ src = lib.fileset.toSource {
+ root = ./src;
+ fileset = ./src;
+ };
+ buildInputs = [ pkgs.bashly ];
+ unpackPhase = ''
+ ln --symbolic --no-target-directory "$src" src
+ '';
+ buildPhase = ''
+ bashly generate
+ '';
+ installPhase = ''
+ install ./repo "$out"
+ '';
+}
diff --git a/config/services/git/shell-commands/repo/src/bashly.yml b/config/services/git/shell-commands/repo/src/bashly.yml
new file mode 100644
index 0000000..6a216ae
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/bashly.yml
@@ -0,0 +1,83 @@
+name: repo
+help: show and configure repositories
+
+commands:
+- name: show
+ help: show repositories
+ default: true
+
+ args:
+ - name: path
+ required: false
+ help: path in which to list repositories
+
+ flags:
+ - long: --verbose
+ short: -v
+ help: show repository description
+ - long: --tree
+ short: -t
+ help: show intermediate directories
+
+ examples:
+ - "repo show # list all repositories"
+ - "repo show --verbose # list repositories in details"
+ - "repo show about-me # list repositories in the about-me/ folder"
+ - "repo show about-me/cv # show the about-me/cv repository"
+ - "repo show --tree # list all repositories as well as intermediate directories"
+
+- name: set
+ help: configure repository
+
+ commands:
+ - name: description
+ alias: descr
+ help: set repository description
+
+ args:
+ - name: repo
+ required: true
+ help: repository path
+
+ examples:
+ - repo set descr about-me/cv
+
+ - name: privacy
+ alias: prv
+ help: recursively set repository visibility
+
+ args:
+ - name: path
+ required: true
+ help: repository path
+ - name: visibility
+ required: true
+ help: new repository visibility
+ allowed: [public, private]
+
+ examples:
+ - "repo set prv public about-me/cv # change visibility of a single repository"
+ - "repo set prv public about-me # change visibility of all repositories in a tree"
+
+- name: create
+ help: create bare repositories
+
+ args:
+ - name: repo
+ required: true
+ help: repository path
+
+ examples:
+ - repo create path/to/repo
+
+- name: remove
+ alias: rm
+ help: remove repository or empty directory
+
+ args:
+ - name: path
+ required: true
+ help: repository path
+
+ examples:
+ - repo rm path/to/repo
diff --git a/config/services/git/shell-commands/repo/src/create_command.sh b/config/services/git/shell-commands/repo/src/create_command.sh
new file mode 100644
index 0000000..ab8bf3f
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/create_command.sh
@@ -0,0 +1,25 @@
+repo=$(realpath --canonicalize-missing /srv/git/"${args[repo]}")
+
+if [[ ! "$repo" == /srv/git/* ]]
+then
+ red "Forbidden path."
+ exit 2
+fi
+
+subpath=/srv/git
+IFS='/' read -ra dirs <<< "${repo#/srv/git/}"
+for dir in "${dirs[@]}"; do
+ subpath="$subpath/$dir"
+ if [[ ! -d "$subpath" ]]
+ then
+ break
+ fi
+done
+
+mkdir --parents "$repo"
+chmod u=rwX,g=,o= --recursive "$subpath"
+git init --bare "$repo"
+
+args[path]="$repo"
+args[--tree]=1
+repo_show_command
diff --git a/config/services/git/shell-commands/repo/src/lib/check-git-repository.sh b/config/services/git/shell-commands/repo/src/lib/check-git-repository.sh
new file mode 100644
index 0000000..c974890
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/lib/check-git-repository.sh
@@ -0,0 +1,7 @@
+check-git-repository() {
+ if [[ ! $(is-git-dir "$1") ]]
+ then
+ red "Not a git repository."
+ exit 2
+ fi
+}
diff --git a/config/services/git/shell-commands/repo/src/lib/check-realpath.sh b/config/services/git/shell-commands/repo/src/lib/check-realpath.sh
new file mode 100644
index 0000000..c344bd2
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/lib/check-realpath.sh
@@ -0,0 +1,9 @@
+check-realpath() {
+ local path="$1"
+ if [[ ! -e "$path" ]] \
+ || [[ ! "$path" == /srv/git/* ]]
+ then
+ red "Forbidden path."
+ exit 2
+ fi
+}
diff --git a/config/services/git/shell-commands/repo/src/lib/colors.sh b/config/services/git/shell-commands/repo/src/lib/colors.sh
new file mode 100644
index 0000000..a78911d
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/lib/colors.sh
@@ -0,0 +1,14 @@
+print_in_color() {
+ local color="$1"
+ shift
+ if [[ "${NO_COLOR:-}" == "" ]]; then
+ printf "$color%b\e[0m\n" "$*"
+ else
+ printf "%b\n" "$*"
+ fi
+}
+
+red() { print_in_color "\e[31m" "$*"; }
+green() { print_in_color "\e[32m" "$*"; }
+blue() { print_in_color "\e[34m" "$*"; }
+bold() { print_in_color "\e[1m" "$*"; }
diff --git a/config/services/git/shell-commands/repo/src/lib/is-git-dir.sh b/config/services/git/shell-commands/repo/src/lib/is-git-dir.sh
new file mode 100644
index 0000000..d94f2ba
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/lib/is-git-dir.sh
@@ -0,0 +1,3 @@
+is-git-dir() {
+ git rev-parse --resolve-git-dir "$1" 2>/dev/null
+}
diff --git a/config/services/git/shell-commands/repo/src/lib/show-descr.sh b/config/services/git/shell-commands/repo/src/lib/show-descr.sh
new file mode 100644
index 0000000..edf6d34
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/lib/show-descr.sh
@@ -0,0 +1,3 @@
+show-descr() {
+ echo "| $(cat "$1"/description)"
+}
diff --git a/config/services/git/shell-commands/repo/src/lib/show-privacy.sh b/config/services/git/shell-commands/repo/src/lib/show-privacy.sh
new file mode 100644
index 0000000..11df8d1
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/lib/show-privacy.sh
@@ -0,0 +1,12 @@
+show-privacy() {
+ local mode=$(( $(stat -c %a "$1")/10 %10 ))
+ if [[ $mode == 0 ]]
+ then
+ red private
+ elif [[ $mode == 5 ]]
+ then
+ green public
+ else
+ blue unknown
+ fi
+}
diff --git a/config/services/git/shell-commands/repo/src/lib/show-repo-summary.sh b/config/services/git/shell-commands/repo/src/lib/show-repo-summary.sh
new file mode 100644
index 0000000..7c0bf63
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/lib/show-repo-summary.sh
@@ -0,0 +1,8 @@
+show-repo-summary() {
+ local repo="$1"
+ local name="${repo#/srv/git/}"
+ local privacy=$(show-privacy "$repo")
+ local size=$(show-size "$repo")
+ printf "%-16s %4s " "$privacy" "$size"
+ bold "$name"
+}
diff --git a/config/services/git/shell-commands/repo/src/lib/show-repo.sh b/config/services/git/shell-commands/repo/src/lib/show-repo.sh
new file mode 100644
index 0000000..d125341
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/lib/show-repo.sh
@@ -0,0 +1,6 @@
+show-repo() {
+ local repo="$1"
+ show-repo-summary "$repo"
+ printf "%13s" ""
+ show-descr "$repo"
+}
diff --git a/config/services/git/shell-commands/repo/src/lib/show-size.sh b/config/services/git/shell-commands/repo/src/lib/show-size.sh
new file mode 100644
index 0000000..739f61d
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/lib/show-size.sh
@@ -0,0 +1,3 @@
+show-size() {
+ du --human-readable --summarize "$1" | cut --field 1
+}
diff --git a/config/services/git/shell-commands/repo/src/remove_command.sh b/config/services/git/shell-commands/repo/src/remove_command.sh
new file mode 100644
index 0000000..b45406f
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/remove_command.sh
@@ -0,0 +1,10 @@
+path=$(realpath "${args[path]}")
+
+check-realpath "$path"
+
+if [[ $(is-git-dir "$path") ]]
+then
+ rm --recursive "$path"
+else
+ rm --dir "$path"
+fi
diff --git a/config/services/git/shell-commands/repo/src/set_description_command.sh b/config/services/git/shell-commands/repo/src/set_description_command.sh
new file mode 100644
index 0000000..b6b40f0
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/set_description_command.sh
@@ -0,0 +1,14 @@
+repo=$(realpath "${args[repo]}")
+
+echo "$repo"
+check-realpath "$repo"
+check-git-repository "$repo"
+echo "Old description:"
+show-descr "$repo"
+echo "New description:"
+echo -n "| "
+read descr
+echo
+echo "$descr" > "$repo"/description
+show-repo "$repo"
+
diff --git a/config/services/git/shell-commands/repo/src/set_privacy_command.sh b/config/services/git/shell-commands/repo/src/set_privacy_command.sh
new file mode 100644
index 0000000..db033e6
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/set_privacy_command.sh
@@ -0,0 +1,17 @@
+path=$(realpath "${args[path]}")
+
+check-realpath "$path"
+
+case "${args[visibility]}" in
+ public)
+ mode="rX"
+ ;;
+ private)
+ mode=""
+ ;;
+esac
+
+chmod g="$mode" --recursive "$path"
+args[--tree]=1
+args[path]="$path"
+repo_show_command
diff --git a/config/services/git/shell-commands/repo/src/show_command.sh b/config/services/git/shell-commands/repo/src/show_command.sh
new file mode 100644
index 0000000..77bb92f
--- /dev/null
+++ b/config/services/git/shell-commands/repo/src/show_command.sh
@@ -0,0 +1,35 @@
+if [[ -z "${args[path]}" ]]
+then
+ path=/srv/git/
+else
+ path=$(realpath "${args[path]}")
+ check-realpath "$path"
+fi
+
+if [[ $(is-git-dir "$path") ]]
+then
+ args[--verbose]=1
+fi
+
+dirs=$(find "$path" -type f -name HEAD | while read -r head; do
+ dir="${head%/*}"
+ if [[ "${args[--tree]}" ]]
+ then
+ while [[ "$dir" != "/srv/git" && -n "$dir" ]]; do
+ echo "$dir/"
+ dir="${dir%/*}"
+ done
+ else
+ echo "$dir/"
+ fi
+ done | sort -u)
+
+for dir in $dirs
+do
+ if [[ "${args[--verbose]}" ]] && [[ $(is-git-dir "$dir") ]]
+ then
+ show-repo "$dir"
+ else
+ show-repo-summary "$dir"
+ fi
+done