summaryrefslogtreecommitdiff
path: root/modules/blobs
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-03-14 21:26:47 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-03-14 21:26:47 -0400
commit94cacc84d322429e70485dea49bb858f48aa26c8 (patch)
tree2d6a493697e8e1b6db655a3bccc0869251db8e97 /modules/blobs
parent634f61cc8b4e096853c61686ccd535fbd45e9158 (diff)
stuff
Diffstat (limited to 'modules/blobs')
-rw-r--r--modules/blobs/.gitignore1
-rw-r--r--modules/blobs/Makefile.inc.mk11
-rw-r--r--modules/blobs/_shlib.sh.m4129
-rw-r--r--modules/blobs/_stdio.sh74
-rw-r--r--modules/blobs/commit.d.sh40
-rw-r--r--modules/blobs/commit.f.sh48
-rw-r--r--modules/blobs/commit.l.sh (renamed from modules/blobs/print.sh)37
-rw-r--r--modules/blobs/commit.sh51
-rw-r--r--modules/blobs/get.d.sh36
-rw-r--r--modules/blobs/get.f.sh26
-rw-r--r--modules/blobs/get.l.sh33
-rw-r--r--modules/blobs/get.sh22
-rw-r--r--modules/blobs/init.sh0
-rw-r--r--modules/blobs/ls.sh50
-rw-r--r--modules/blobs/tree.sh94
15 files changed, 380 insertions, 272 deletions
diff --git a/modules/blobs/.gitignore b/modules/blobs/.gitignore
new file mode 100644
index 0000000..795fcd0
--- /dev/null
+++ b/modules/blobs/.gitignore
@@ -0,0 +1 @@
+/_shlib.sh
diff --git a/modules/blobs/Makefile.inc.mk b/modules/blobs/Makefile.inc.mk
index 9f3f112..484da13 100644
--- a/modules/blobs/Makefile.inc.mk
+++ b/modules/blobs/Makefile.inc.mk
@@ -1,8 +1,9 @@
-am_src_files += commit.d.sh commit.f.sh commit.sh get.d.sh get.f.sh get.sh ls.sh print.sh tree.sh
-am_out_files += commit.d commit.f commit get.d get.f get ls print tree
+am_src_files += commit.d.sh commit.f.sh commit.l.sh commit.sh get.d.sh get.f.sh get.l.sh get.sh tree.sh init.sh
+am_out_files += commit.d commit.f commit.l commit get.d get.f get.l.sh get tree init
-am_src_files += _stdio.sh
-am_sys_files += $(pkglibexecdir)/modules/$(name)/_stdio.sh
+am_src_files += _shlib.sh.m4
+am_clean_files += _shlib.sh
+am_sys_files += $(pkglibexecdir)/modules/$(name)/_shlib.sh
-$(DESTDIR)$(pkglibexecdir)/modules/$(name)/_stdio.sh: $(srcdir)/_stdio.sh | $(DESTDIR)$(pkglibexecdir)/modules/$(name)
+$(DESTDIR)$(pkglibexecdir)/modules/$(name)/_shlib.sh: $(srcdir)/_shlib.sh | $(DESTDIR)$(pkglibexecdir)/modules/$(name)
$(INSTALL_DATA) $< $@
diff --git a/modules/blobs/_shlib.sh.m4 b/modules/blobs/_shlib.sh.m4
new file mode 100644
index 0000000..567486f
--- /dev/null
+++ b/modules/blobs/_shlib.sh.m4
@@ -0,0 +1,129 @@
+#!/hint/bash
+# Copyright (C) 2009-2010, 2016 Luke Shumaker
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING.
+# If not, see <http://www.gnu.org/licenses>.
+
+m4_include(config.sh)
+
+#
+
+_() {
+ if type gettext &>/dev/null; then
+ TEXTDOMAINDIR=$localedir gettext "$pkgtextdomain" "$1";
+ else
+ printf '%s' "$1";
+ fi
+}
+
+# variables:
+# - usage[]
+# - desc
+# - doc (optional)
+usage() {
+ local form
+ local pfix1="$(_ 'Usage:')"
+ local pfix2="$(_ ' Or:')"
+ local pfix="pfix1"
+ for form in "${usage[@]}"; do
+ printf '%s %q %q %s\n' "$pfix" "$RVS" "$form"
+ pfix="$pfix2"
+ done
+ printf '%s\n' "$(_ "$desc")"
+ if [[ -n "$doc" ]] && [[ "$volume" != '-q' ]]; then
+ printf '\n\n%s\n' "$(_ "$doc")"
+ fi
+}
+
+# variables:
+# - name
+# - ver
+# - copyright
+# - license
+# - volume
+version() {
+ declare -A license_name
+ license_name['GPLv1']='GNU GPL version 1'
+ license_name['GPLv1+']='GNU GPL version 1 or later'
+ license_name['GPLv2']='GNU GPL version 2'
+ license_name['GPLv2+']='GNU GPL version 2 or later'
+ license_name['GPLv3']='GNU GPL version 3'
+ license_name['GPLv3+']='GNU GPL version 3 or later'
+ license_name['LGPLv2']='GNU Library GPL version 2'
+ license_name['LGPLv2+']='GNU Library GPL version 2 or later'
+ license_name['LGPLv2.1']='GNU Lesser GPL version 2.1'
+ license_name['LGPLv2.1+']='GNU Lesser GPL version 2.1 or later'
+ license_name['LGPLv3']='GNU Lesser GPL version 3'
+ license_name['LGPLv3+']='GNU Lesser GPL version 3 or later'
+ licensE_name['AGPLv3']='GNU Affero GPL version 3'
+ licensE_name['AGPLv3+']='GNU Affero GPL version 3 or later'
+ declare -A license_url
+ license_url['GPLv2']='https://gnu.org/licenses/old-licenses/gpl-1.0.html'
+ license_url['GPLv2']='https://gnu.org/licenses/old-licenses/gpl-2.0.html'
+ license_url['GPLv3']='https://gnu.org/licenses/gpl.html'
+ license_url['LGPLv2']='https://gnu.org/licenses/old-licenses/lgpl-2.0.html'
+ license_url['LGPLv2.1']='https://gnu.org/licenses/old-licenses/lgpl-2.1.html'
+ license_url['LGPLv3']='https://gnu.org/licenses/lgpl.html'
+ license_url['AGPLv3']='https://gnu.org/licenses/agpl.html'
+
+ printf "$(_ '%s (RVS) %s\n')" "$name" "$ver"
+ if [ "$volume" != '-q' ]; then
+ printf "$(_ 'Copyright (C) %s\n')" "${copyright[@]}"
+ local url="${license_url[$license]}"
+ if [[ -z "$url" ]]; then
+ url="${license_url[${license%+}]}"
+ fi
+ printf "$(_ 'License %s: %s <%s>.\n')" "$license" "${license_name[$license]}" "$url"
+ printf "$(_ \
+'This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extend permitted by law.
+')"
+ if [[ -z "$author" ]] && [[ "${#copyright[@]}" -eq 1 ]]; then
+ printf -v author "$(_ 'Originally written by %s.')" "$(sed 's/^[0-9, -]*//' <<<"${copyright[0]}")"
+ fi
+ if [[ -n "$author" ]]; then
+ printf '%s\n' "$author"
+ fi
+ fi
+}
+
+verbose() {
+ if [ "$volume" == '-v' ]; then
+ printf "$(_ "$1")\n" "${@:2}" >&2
+ fi
+}
+
+out() {
+ if [ "$volume" != '-q' ]; then
+ printf "$(_ "$1")\n" "${@:2}" >&2
+ fi
+}
+
+warn() {
+ printf "$name: $(_ "$1")\n" "${@:2}" >&2
+}
+
+error() {
+ warn "$@"
+ exit 1
+}
+
+errusage() {
+ if [[ $# -gt 0 ]]; then
+ warn "$@"
+ fi
+ volume='-q'
+ usage >&2
+ exit 1
+}
diff --git a/modules/blobs/_stdio.sh b/modules/blobs/_stdio.sh
deleted file mode 100644
index 0da03f0..0000000
--- a/modules/blobs/_stdio.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/sh
-#name='stdio'
-#ver=0.9
-# Copyright (C) 2009-2010 Luke Shumaker
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; see the file COPYING.
-# If not, see <http://www.gnu.org/licenses>.
-
-verbose() {
- if [ "$volume" == '-v' ]; then
- echo $@ >> /dev/stderr
- fi
-}
-
-out() {
- if [ "$volume" != '-q' ]; then
- echo $@ >> /dev/stderr
- fi
-}
-
-warn () {
- echo "$name: $1" >> /dev/stderr
-}
-
-fatal () {
- warn "$1"
- exit 1
-}
-
-error() {
- warn "$1"
- cat << __error__ >> /dev/stderr
-Usage: $RVS $name $usage
-
-Try \`$RVS help $name' for more options.
-__error__
- exit 1
-}
-
-getvar() {
- if [ -z "$1" ]; then
- error
- else
- echo $1
- fi
-}
-
-version() {
- echo "$name $ver"
- if [ "$volume" != '-q' ]; then
- cat << __disclaimer__
-$name is copyright (C) 2009-2010 Luke Shumaker
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Originally written by Luke Shumaker <LukeShu@sbcglobal.net>.
-__disclaimer__
- fi
- exit 0
-}
-
diff --git a/modules/blobs/commit.d.sh b/modules/blobs/commit.d.sh
index 7fcdd7e..08e9698 100644
--- a/modules/blobs/commit.d.sh
+++ b/modules/blobs/commit.d.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
-# rvs blobs/commit.d - add a directory to the repository
-# Copyright (C) 2009-2010, 2015-2016 Luke Shumaker
-#
+name=blobs/commit.d
+desc='Add a directory to the repository'
+copyright=('2009-2010, 2015-2016 Luke Shumaker')
+license='AGPLv3+'
# This file is part of rvs.
#
# This program is free software: you can redistribute it and/or modify
@@ -17,18 +18,25 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-. "${0%/*}/_stdio.sh"
+usage=('DIRECTORY')
+. "${0%/*}/_shlib.sh"
+
+main() {
+ [[ $# -eq 1 ]] || errusage
+ dir="$1"
-usage='DIRECTORY'
-[[ $# -eq 1 ]] || errusage
-dir="$1"
+ tmpfile="$(mktemp -t "${0##*/}.XXXXXXXXXX")"
+ trap 'rm -f -- "$tmpfile"' EXIT
+ (
+ cd "$dir"
+ shopt -s dotglob nullglob
+ for file in *; do
+ id="$("$RVS" commit "$file")"
+ stat -c $'%a\t%u (%U)\t%g (%G)\t' -- "$file"
+ printf $'%s\t%s\n' "$id" "$file"
+ done > "$tmpfile"
+ )
+ "$RVS" commit.f "$tmpfile" 'd'
+}
-shopt -s dotglob
-cd "$dir"
-tmpfile="$(mktemp -t "${0##*/}.XXXXXXXXXX")"
-for file in *; do
- id="$("$RVS" commit "$file")"
- stat -c $'%a\t%u (%U)\t%g (%G)\t' -- "$file"
- printf $'%s\t%s\n' "$id" "$file"
-done > "$tmpfile"
-"$RVS" commit.f "$tmpfile" d
+main "$@"
diff --git a/modules/blobs/commit.f.sh b/modules/blobs/commit.f.sh
index 098be9d..233f7bb 100644
--- a/modules/blobs/commit.f.sh
+++ b/modules/blobs/commit.f.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
-# rvs blobs/commit.f - add a plain file to the repository
-# Copyright (C) 2009-2010, 2015-2016 Luke Shumaker
-#
+name=blobs/commit.f
+desc='Add a plain file to the repository'
+copyright=('2009-2010, 2015-2016 Luke Shumaker')
+license='AGPLv3+'
# This file is part of rvs.
#
# This program is free software: you can redistribute it and/or modify
@@ -17,21 +18,32 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-. "${0%/*}/_stdio.sh"
-
usage='FILENAME [TYPE]'
-case $# in
- 0) errusage;;
- 1) infile=$1; type=f;;
- 2) infile=$1; type=$2;;
- *) errusage;;
-esac
+doc="Note that FILENAME must be a regular file; character devices such as
+/dev/stdin or /dev/fd/n won't work."
+
+. "${0%/*}/_shlib.sh"
+
+main() {
+ case $# in
+ 0) errusage;;
+ 1) infile=$1; type=f;;
+ 2) infile=$1; type=$2;;
+ *) errusage;;
+ esac
+
+ if ! [[ -f "$infile" ]]; then
+ error 'Not a regular file: %s' "$infile"
+ fi
-hash="$(<"$file" sha1sum | cut -d ' ' -f1)"
-outfile="$RVS_REPO/blobs/$hash"
-if [ ! -f "$outfile" ]; then
- mkdir -p -- "${outfile%/*}"
- < "$infile" gzip -9 > "$outfile"
-fi
-printf '%s:%s\n' "$type" "$hash"
+ hash="$(<"$infile" sha1sum | cut -d ' ' -f1)"
+ outfile="$RVS_REPO/blobs/$hash"
+ if [ ! -f "$outfile" ]; then
+ mkdir -p -- "${outfile%/*}"
+ < "$infile" gzip -9 > "$outfile.tmp"
+ mv -T -- "$outfile.tmp" "$outfile"
+ fi
+ printf '%s:%s\n' "$type" "$hash"
+}
+main "$@"
diff --git a/modules/blobs/print.sh b/modules/blobs/commit.l.sh
index dbc5fb8..54a2527 100644
--- a/modules/blobs/print.sh
+++ b/modules/blobs/commit.l.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
-# rvs files/print - ???
-# Copyright (C) 2009-2010, 2015-2016 Luke Shumaker
-#
+name=blobs/commit.l
+desc='Add a symbolic link to the repository'
+copyright=('2016 Luke Shumaker')
+license='AGPLv3+'
# This file is part of rvs.
#
# This program is free software: you can redistribute it and/or modify
@@ -17,25 +18,17 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-. "${0%/*}/_stdio.sh"
-
-usage='ID'
-[[ $# -eq 1 ]] || errusage
-id=$1
+usage=('DIRECTORY')
+. "${0%/*}/_shlib.sh"
-hash="${id#*:}"
-file="$REPO/blobs/$hash"
+main() {
+ [[ $# -eq 1 ]] || errusage
+ link="$1"
-if [ -e "$file" ]; then
- t="${id%%:*}"
- type=''
- case "$t" in
- f) type='regular file';;
- d) type='directory';;
- l) type='link';;
- esac
- printf 'File Type: %s (%s)\n' "$t" "$type"
-else
- fatal 'no object with ID `%s'\' "$id"
-fi
+ tmpfile="$(mktemp -t "${0##*/}.XXXXXXXXXX")"
+ trap 'rm -f -- "$tmpfile"' EXIT
+ readlink -n -- "$link" > "$tmpfile"
+ "$RVS" commit.f "$tmpfile" 'l'
+}
+main "$@"
diff --git a/modules/blobs/commit.sh b/modules/blobs/commit.sh
index 01bc338..44a2465 100644
--- a/modules/blobs/commit.sh
+++ b/modules/blobs/commit.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
-# rvs blobs/commit - add a file to the repository
-# Copyright (C) 2009-2010, 2015-2016 Luke Shumaker
-#
+name=blobs/commit
+desc='Add files to the repository'
+copyright=('2009-2010, 2015-2016 Luke Shumaker')
+license='AGPLv3+'
# This file is part of rvs.
#
# This program is free software: you can redistribute it and/or modify
@@ -17,23 +18,31 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-. "${0%/*}/_stdio.sh"
-
-usage='[FILES...]'
-if [[ $# -lt 1 ]]; then
- set -- .
-fi
+usage=('[FILES...]')
+. "${0%/*}/_shlib.sh"
-for file in "$@"; do
- local type
- if test -L "$file"; then
- type=l
- elif test -f "$file"; then
- type=f
- elif test -d "$file"; then
- type=d
- else
- error 'Unsupported file type: %s' "$file"
+main() {
+ if [[ $# -lt 1 ]]; then
+ set -- .
fi
- "$RVS" "commit.$type" "$file"
-done
+
+ for file in "$@"; do
+ if ! stat -c '' -- "$file" &>/dev/null; then
+ error 'No such file or directory: %s' "$file"
+ fi
+
+ local type
+ if test -L "$file"; then
+ type=l
+ elif test -f "$file"; then
+ type=f
+ elif test -d "$file"; then
+ type=d
+ else
+ error 'File has unsupported file type: %s' "$file"
+ fi
+ "$RVS" "commit.$type" "$file"
+ done
+}
+
+main "$@"
diff --git a/modules/blobs/get.d.sh b/modules/blobs/get.d.sh
index e67a267..5fdf0b2 100644
--- a/modules/blobs/get.d.sh
+++ b/modules/blobs/get.d.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
-# rvs blobs/get.d - get a directory from the repository
-# Copyright (C) 2009-2010, 2015-2016 Luke Shumaker
-#
+name=blobs/get.d
+desc='Get a directory from the repository'
+copyright=('2009-2010, 2015-2016 Luke Shumaker')
+license='AGPLv3+'
# This file is part of rvs.
#
# This program is free software: you can redistribute it and/or modify
@@ -17,21 +18,22 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-. "${0%/*}/_stdio.sh"
+usage="ID DIRNAME"
+. "${0%/*}/_shlib.sh"
-usage="DIRNAME ID"
-[[ $# -eq 2 ]] || errusage
-name=$1
-id=$2
+main() {
+ [[ $# -eq 2 ]] || errusage
+ dirid=$1
+ dirname=$2
-tmpfile="$(mktemp -t "${0##*/}.XXXXXXXXXX")"
-"$RVS" get.f "$tmpfile" "$id"
+ mkdir -p -- "$dirname"
+ cd "$dirname"
-mkdir -p -- "$name"
-cd "$name"
+ IFS=$'\t'
+ while read -r perm user group id name; do
+ "$RVS" get "$id" "$name"
+ chmod "$perm" "$name"
+ done < <("$RVS" get.f "$dirid" /dev/stdout)
+}
-IFS=$'\t'
-while read -r perm user group id name; do
- "$RVS" get "$name" "$id"
- chmod "$perm" "$name"
-done < "$tmpfile"
+main "$@"
diff --git a/modules/blobs/get.f.sh b/modules/blobs/get.f.sh
index 08aca97..fafb076 100644
--- a/modules/blobs/get.f.sh
+++ b/modules/blobs/get.f.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
-# rvs blobs/get.f - get a plain file from the repository
-# Copyright (C) 2009-2010, 2015-2016 Luke Shumaker
-#
+name=blobs/get.f
+desc='Get a plain file from the repository'
+copyright=('2009-2010, 2015-2016 Luke Shumaker')
+license='AGPLv3+'
# This file is part of rvs.
#
# This program is free software: you can redistribute it and/or modify
@@ -17,13 +18,18 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-. "${0%/*}/_stdio.sh"
+usage="ID FILENAME"
+doc="Unlike commit.f, FILENAME may be a character device such as
+/dev/stdout or /dev/fd/n."
+. "${0%/*}/_shlib.sh"
-usage="FILENAME ID"
-[[ $# -eq 2 ]] || errusage
-name=$1
-id=$2
+main() {
+ [[ $# -eq 2 ]] || errusage
+ id=$1
+ name=$2
-mkdir -p -- "${name%/*}"
-< "$REPO/blobs/${id#*:}" gunzip > "$name"
+ mkdir -p -- "$(dirname -- "$name")"
+ < "$REPO/blobs/${id#*:}" gunzip > "$name"
+}
+main "$@"
diff --git a/modules/blobs/get.l.sh b/modules/blobs/get.l.sh
new file mode 100644
index 0000000..8215cf6
--- /dev/null
+++ b/modules/blobs/get.l.sh
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+name=blobs/get.l
+desc='Get a symbolic link from the repository'
+copyright=('2016 Luke Shumaker')
+license='AGPLv3+'
+# This file is part of rvs.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+usage="ID DIRNAME"
+. "${0%/*}/_shlib.sh"
+
+main() {
+ [[ $# -eq 2 ]] || errusage
+ id=$1
+ name=$2
+
+ mkdir -p -- "$(dirname -- "$name")"
+ ln -sf "$("$RVS" get.f "$id" /dev/stdout)" "$name"
+}
+
+main "$@"
diff --git a/modules/blobs/get.sh b/modules/blobs/get.sh
index b4cc6ff..26fb273 100644
--- a/modules/blobs/get.sh
+++ b/modules/blobs/get.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
-# rvs blobs/get - get a file from the repository
-# Copyright (C) 2009-2010, 2015-2016 Luke Shumaker
-#
+name=blobs/get
+desc='Get a file from the repository'
+copyright='2009-2010, 2015-2016 Luke Shumaker'
+license=('AGPLv3+')
# This file is part of rvs.
#
# This program is free software: you can redistribute it and/or modify
@@ -17,12 +18,15 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-. "${0%/*}/_stdio.sh"
+usage="ID FILENAME"
+. "${0%/*}/_shlib.sh"
-usage="FILENAME ID"
-[[ $# -eq 2 ]] || errusage
-name=$1
-id=$2
+main() {
+ [[ $# -eq 2 ]] || errusage
+ id=$1
+ name=$2
-"$RVS" "get.${id%%:*}" "$name" "$id"
+ "$RVS" "get.${id%%:*}" "$name" "$id"
+}
+main "$@"
diff --git a/modules/blobs/init.sh b/modules/blobs/init.sh
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/modules/blobs/init.sh
diff --git a/modules/blobs/ls.sh b/modules/blobs/ls.sh
deleted file mode 100644
index 76b6743..0000000
--- a/modules/blobs/ls.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env bash
-name='ls'
-ver=0.1
-# Copyright (C) 2010, 2016 Luke Shumaker
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; see the file COPYING.
-# If not, see <http://www.gnu.org/licenses>.
-
-. "${0%/*}/_stdio.sh"
-
-usage="DIR_ID [FORMAT]"
-id="`getvar "$1"`"
-form="${2-%p\t%o\t%g\t%n\t%i}"
-
-# %p - permissions
-# %o - owner
-# %g - group
-# %i - blob id
-# %n - name
-# \t - a tab char
-
-tmp="`mktemp`"
-"$RVS" get.f "$tmp" "$id"
-
-while read line; do
- p="`echo "$line" | cut -f1`"
- o="`echo "$line" | cut -f2`"
- g="`echo "$line" | cut -f3`"
- i="`echo "$line" | cut -f4`"
- n="`echo "$line" | cut -f5-`"
- echo "$form" | sed \
- -e 's:\\t:\t:g' \
- -e "s:%p:${p/:/\\:}:g" \
- -e "s:%o:${o/:/\\:}:g" \
- -e "s:%g:${g/:/\\:}:g" \
- -e "s:%i:${i/:/\\:}:g" \
- -e "s:%n:${n/:/\\:}:g"
-done < "$tmp"
-
diff --git a/modules/blobs/tree.sh b/modules/blobs/tree.sh
index a13b320..f08db42 100644
--- a/modules/blobs/tree.sh
+++ b/modules/blobs/tree.sh
@@ -1,40 +1,74 @@
#!/usr/bin/env bash
-name='tree'
-ver=0.1
-# Copyright (C) 2010, 2016 Luke Shumaker
+name=bolbs/tree
+desc='Recursively show the directory tree of a blob ID'
+copyright=('2010, 2016 Luke Shumaker')
+license=('AGPLv3+')
+# This file is part of rvs.
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
#
-# You should have received a copy of the GNU General Public License
-# along with this program; see the file COPYING.
-# If not, see <http://www.gnu.org/licenses>.
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
-. "${0%/*}/_stdio.sh"
+usage="DIR_ID [NAME [PREFIX [LAST]]]"
+. "${0%/*}/_shlib.sh"
-usage="DIR_ID [NAME] [PREFIX] [LAST]"
-id="`getvar "$1"`"
-name="${2-.}"
-pref="$3"
-last="$4"
+main() {
+ local id name prefix has_prefix last
+ case $# in
+ 0) errusage;;
+ 1) id=$1; name=.;;
+ 2) id=$1; name=$2;; prefix=''; has_prefix=false;;
+ 3) id=$1; name=$2;; prefix=$3; has_prefix=true;;
+ 3) id=$1; name=$2;; prefix=$3; has_prefix=true; last=$4;;
+ *) errusage;;
+ esac
-echo "$pref $name $id"
-pref=' | '
-"$RVS" ls "$id" '%i\t%n' | while read line; do
- i="`echo "$line" | cut -f1`"
- n="`echo "$line" | cut -f2-`"
- t="`"$RVS" blob-gettype "$i"`"
- if [ "$t" = 'd' ]
- "$RVS" tree "$i" "$n" "$pref"
+ local a b c
+ if locale -k LC_MESSAGES | grep -xF 'messages-codeset="UTF-8"' >/dev/null; then
+ a='├── '
+ b='│   '
+ c='└── '
else
- echo "$pref $n $i"
+ a='|-- '
+ b='| '
+ c='`-- '
fi
-done
+ local pfix_self pfix_chld
+ if ! $has_prefix; then
+ pfix_self=''
+ pfix_chld=''
+ else
+ pfix_self="$prefix$a"
+ pfix_chld="$prefix$b"
+ if [[ -n "$last" ]]; then
+ pfix_self="$prefix$c"
+ fi
+ fi
+
+ printf "%s$(_ '%s\t(%s)')\n" "$pfix_self" "$name" "$id"
+ if [[ "$id" == d:* ]]; then
+ local lastname
+ lastname="$("$RVS" get.d "$id" /dev/stdout | sed -n '$/.*\t//p')"
+ local perm user group id name
+ while read -r perm user group id name; do
+ if [[ "$name" != "$lastname" ]]; then
+ "$RVS" tree "$id" "$name" "$pfix_chld"
+ else
+ "$RVS" tree "$id" "$name" "$pfix_chld" t
+ fi
+ done < <("$RVS" get.d "$id" /dev/stdout)
+ fi
+
+}
+
+main "$@"