#!/bin/bash
#  net/webdav - WebDAV support
set -e
lib_load 'net/tool/rsync'
######
# Settings
net_webdav_client_packages=( cadaver )
######
# Library Configuration
net_webdav_config_init() {
	lib_setting_vars webdav_host
	lib_setting_vars --null webdav_port
	lib_setting_vars --null webdav_root
	webdav_host=localhost
	# WebDAV property namespace
	lib_setting_vars --null webdav_namespace
	lib_setting_vars -ro webdav_netrc
	lib_setting_vars -ro webdav_stagedir
	lib_setting_vars -ro webdav_exportdir
	webdav_exportdir='.'
}
net_webdav_config_check() {
	webdav_netrc="${webdav_netrc:-${HOME}/.netrc}"
	webdav_stagedir="${webdav_stagedir:-$script_tempdir/stage}"
}
######
# Internal Functions
run_cadaver() {
	run_pushd "$webdav_stagedir"
	run cadaver "$@"
	run_popd
}
pipe_to_cadaver() {
	local tmp
	tmp=$(cmd_tempfile)
	"$@" >"$tmp"
	debug "running cadaver script:"$'\n'"$(<"$tmp")"
	run_cadaver <"$tmp"
}
webdav_filename() {
	echo "$1" \
		| ( iconv -f utf-8 -t ascii//translit \
			|| error "$1: unable to encode name" ) \
		| sed -e 's, - ,-,g' -e 's, ,-,g' -e 's,\?,-,g'
}
######
# WebDAV CLI
# webdav_dispatch() - Runs a webdav command
webdav_dispatch() { lib_cmd_dispatch webdav "$@"; }
webdav_usage() {
	cat <<USAGE
<cmd> ...
WebDAV Commands:
	host ...			Host credential commands
	stage ...			Staging directory commands
	remote ...			WebDAV remote/server commands
USAGE
}
######
# .netrc Management
webdav_host() { cmd_dispatch "$@"; }
webdav_host_usage() {
	cat <<USAGE
WebDAV Host Commands:
	init				Creates empty host credential file
	add <host> <user> <passwd>	Adds credentials for a host
	delete <host>			Removes credentials for a host
USAGE
}
webdav_host_init() {
	touch "$webdav_netrc"
	chmod 600 "$webdav_netrc"
}
webdav_host_add() {
	has_args "3" "$@"
	local name=$1
	local user=$2
	local pass=$3
	echo "machine $name login $user password $pass" >> "$webdav_netrc"
}
webdav_host_delete() {
	has_args "1" "$@"
	local name=$1
	local tmp
	tmp=$(cmd_tempfile)
	grep -v "^machine $name " "$webdav_netrc" >"$tmp"
	run mv "$tmp" "$webdav_netrc"
}
######
# Script generation
webdav_script_open() {
	echo "lcd '$webdav_stagedir'"
	local url="$webdav_host"
	[ -z "$webdav_port" ] || url="$url:$webdav_port"
	echo "open '$url'"
	[ -z "$webdav_namespace" ] || echo "set namespace '$webdav_namespace'"
}
webdav_script_close() {
	echo close
}
webdav_script_import_dir() {
	echo "echo '$1: creating collection...'"
	echo "mkcol '$1'"
}
webdav_script_import_file() {
	echo "echo '$2: importing...'"
	echo "put '$1' '$2'"
}
webdav_script_import_symlink() {
	debug "$2: skipping symlink ($3)"
}
webdav_script_import_default() {
	error "$2: unknown item type"
}
webdav_script_import_item() {
	local src=$1
	local dst="$webdav_root${src#$webdav_stagedir}"
	if [ -d "$src" ]; then
		webdav_script_import_dir "$dst"
	elif [ -f "$src" ]; then
		webdav_script_import_file "$src" "$dst"
	elif [ -L "$src" ]; then
		local tgt
		tgt=$(readlink "$src")
		webdav_script_import_symlink "$src" "$dst" "$tgt"
	else
		webdav_script_import_default "$src" "$dst"
	fi
}
webdav_script_import() {
	info "searching for files to stage..."
	local -a files
	webdav_stage_find files "$@"
	echo 'echo "webdav import: connecting to server..."'
	webdav_script_open
	for_each webdav_script_import_item "${files[@]}"
	echo 'echo "webdav import: cleaning up..."'
	webdav_script_close
	echo 'echo "webdav import: ... done."'
	info "webdav import: ... found ${#files[@]} items!"
}
webdav_script_export() {
	webdav_script_open
	# TODO
	webdav_script_close
}
######
# WebDAV Server Interface
webdav_remote() { cmd_dispatch "$@"; }
webdav_remote_usage() {
	cat <<USAGE
...
WebDAV Remote Commands:
	import [<path>+]		Imports from staging to WebDAV server
	export [<path>+]		Exports from WebDAV server to staging
USAGE
}
webdav_remote_import() { pipe_to_cadaver webdav_script_import "$@"; }
webdav_remote_export() { pipe_to_cadaver webdav_script_export "$@"; }
######
# WebDAV Staging interface
webdav_stage_filename() { echo "$webdav_stagedir/$(webdav_filename "$1")"; }
webdav_stage_relname() { echo "${1#$webdav_stagedir}"; }
webdav_stage() { cmd_dispatch "$@"; }
webdav_stage_usage() {
	cat <<USAGE
<cmd> ...
WebDAV Staging Commands:
	list [<path>+]			Lists files in stanging directory
	import <path>+			Imports files to staging directory
	export [<path>+]		Exports files to \$webdav_exportdir'
					(default: $webdav_exportdir)
	shell [<path>]			Starts shell in "\$stagedir\$path"
WebDAV Staging Synchronization:
	push [<path>+]			Uploads files from staging to server
	fetch [<path>+]			Downloads files from server to staging
USAGE
}
webdav_stage_find() {
	min_args 1 "$@"
	local var=$1
	shift
	local -a wsf_files=( "$@" )
	[ "$*" ] || wsf_files=( "" )
	list_map webdav_stage_filename wsf_files
	file_find wsf_files "${wsf_files[@]}"
	eval "$var=( \"\${wsf_files[@]}\" )"
}
webdav_stage_findrel() {
	local var=$1
	webdav_stage_find "$@"
	list_map webdav_stage_relname $var
}
webdav_stage_shell() {
	local path=$1
	run_pushd "$(webdav_stage_filename "$path")"
	$SHELL
	run_popd
}
webdav_stage_list() {
	local -a file_find_opts=( -type f )
	local -a files
	webdav_stage_findrel files "$@"
	local IFS=$'\n'
	echo "${files[*]}"
}
webdav_stage_import() {
	min_args 1 "$@"
	local -a files
	file_find files "$@"
	run_mkdir "$webdav_stagedir"
	for_each webdav_stage_import_file "${files[@]}"
}
webdav_stage_import_file() {
	local src=$1
	local dst
	dst="$(webdav_stage_filename "$src")"
	run_mkdir "$(dirname "$dst")"
	rsync_run --archive "$src" "$dst"
}
webdav_stage_export() {
	: # TODO
}
webdav_stage_push() {
	local ssh_host="$webdav_host"
	run_ssh mkdir -p "$webdav_stagedir"
	if [ "$*" ]; then
		for_each webdav_stage_push_part "$@"
	else
		webdav_stage_push_part "/"
	fi
}
webdav_stage_push_part() {
	has_args 1 "$@"
	local part=$1
	[ "${part#/}" != "$part" ] || part="/$part"
	local src="$webdav_stagedir$part"
	local dst="$webdav_host:$webdav_stagedir$part"
	local -a opts=( --archive --checksum --progress --stats --links )
	rsync_run "${opts[@]}" "$src" "$dst"
}
webdav_stage_fetch() {
	: # TODO
}
 
Generated on Fri Jul 28 14:35:56 PDT 2017 by mcsh d14 v0.23.0.