diff options
-rw-r--r-- | bin/.gitignore | 1 | ||||
-rw-r--r-- | bin/Makefile | 1 | ||||
-rw-r--r-- | bin/README.7 | 4 | ||||
-rw-r--r-- | bin/git-import.sh | 113 | ||||
-rw-r--r-- | bin/man1/git-import.1 | 49 |
5 files changed, 167 insertions, 1 deletions
diff --git a/bin/.gitignore b/bin/.gitignore index 42269bac..d1e9cb1d 100644 --- a/bin/.gitignore +++ b/bin/.gitignore @@ -12,6 +12,7 @@ enc ever freecell git-comment +git-import glitch hilex htagml diff --git a/bin/Makefile b/bin/Makefile index bb1535d6..428ce7ee 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -15,6 +15,7 @@ BINS += dehtml BINS += dtch BINS += enc BINS += git-comment +BINS += git-import BINS += glitch BINS += hilex BINS += htagml diff --git a/bin/README.7 b/bin/README.7 index 100e183e..9987a0da 100644 --- a/bin/README.7 +++ b/bin/README.7 @@ -1,4 +1,4 @@ -.Dd June 2, 2022 +.Dd September 11, 2023 .Dt BIN 7 .Os "Causal Agency" . @@ -36,6 +36,8 @@ watch files patience game .It Xr git-comment 1 add commit comments +.It Xr git-import 1 +import tarballs into git .It Xr glitch 1 PNG glitcher .It Xr hilex 1 diff --git a/bin/git-import.sh b/bin/git-import.sh new file mode 100644 index 00000000..0bec2c25 --- /dev/null +++ b/bin/git-import.sh @@ -0,0 +1,113 @@ +#!/bin/sh +set -eu + +: ${CURL:=curl} + +die() { + echo "$0: $*" >&2 + exit 1 +} + +strip=1 +message= + +OPTS_SPEC="\ +git import [<options>] <branch> <file> +-- +m,message=! create a commit with the specified message +p,strip= remove the specified number of leading path elements +" +eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@")" + +while [ $# -gt 0 ]; do + opt=$1 + shift + case "$opt" in + (-m) message=$1; shift;; + (-p) strip=$1; shift;; + (--no-strip) strip=0;; + (--) break;; + esac +done +[ $# -gt 0 ] || die "branch name required" +[ $# -gt 1 ] || die "file or url required" +branch=$1 +tarball=$2 +: ${message:="Import ${tarball##*/}"} + +check_index() { + if ! git diff-index --quiet HEAD; then + die "working tree has modifications" + fi +} + +check_head() { + local head full + head=$(git rev-parse --symbolic-full-name HEAD) + full=$(git rev-parse --verify --quiet --symbolic-full-name "$1") || return 0 + if [ "$full" = "$head" ]; then + die "branch (${full}) cannot be HEAD (${head})" + fi +} + +extract_tarball() { + local url strip tarball tmpdir + url=$1 + strip=$2 + if test -f "$url"; then + tarball=$url + else + tarball=$(mktemp) + trap 'rm -f "$tarball"' EXIT + $CURL -L -o "$tarball" "$url" + fi + tmpdir=$(mktemp -d) + tar -x -f "$tarball" -C "$tmpdir" --strip-components "$strip" + echo "$tmpdir" +} + +create_tree() { + local root fullpath path blob mode tree + root=$1 + git read-tree --empty + find "$root" -type f | while read -r fullpath; do + path=${fullpath#${root}/} + blob=$(git hash-object -w --path "$path" "$fullpath") + mode=100644 + if test -L "$fullpath"; then + mode=120000 + elif test -x "$fullpath"; then + mode=100755 + fi + git update-index --add --cacheinfo "$mode,$blob,$path" + done + tree=$(git write-tree) + git read-tree HEAD + echo "$tree" +} + +create_commit() { + local parent tree message + parent=$1 + tree=$2 + message=$3 + git commit-tree ${parent:+-p ${parent}} -m "$message" "$tree" +} + +update_branch() { + local branch parent commit + branch=$1 + parent=$2 + commit=$3 + git update-ref "refs/heads/$branch" "$commit" "$parent" +} + +check_index +check_head "$branch" +root=$(extract_tarball "$tarball" "$strip") +tree=$(create_tree "$root") +rm -fr "$root" +parent=$(git rev-parse --verify --quiet "$branch" || :) +commit=$(create_commit "$parent" "$tree" "$message") +update_branch "$branch" "$parent" "$commit" +git --no-pager show --stat "$commit" diff --git a/bin/man1/git-import.1 b/bin/man1/git-import.1 new file mode 100644 index 00000000..31d224e1 --- /dev/null +++ b/bin/man1/git-import.1 @@ -0,0 +1,49 @@ +.Dd September 11, 2023 +.Dt GIT-IMPORT 1 +.Os +. +.Sh NAME +.Nm git-import +.Nd import a tarball into git +. +.Sh SYNOPSIS +.Nm +.Op Fl m Ar message +.Op Fl p Ar count +.Ar branch +.Ar file +. +.Sh DESCRIPTION +.Nm +imports a tarball +as a new commit on +a git branch. +If +.Ar branch +does not exist, +it will be created. +If +.Ar file +is a URL, +it will be fetched with +.Xr curl 1 . +. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl m Ar message , Fl \-message Ar message +Set the commit message. +.It Fl p Ar count , Fl \-strip Ar count +Remove the specified number +of leading path elements. +The default is 1. +.El +. +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev CURL +The path to +.Xr curl 1 , +used to fetch the tarball +from a URL. +.El |