#!/bin/bash
# dev/package/files - package file introspection and management

set -e

lib_load 'sys/tool/sed'
lib_load 'dev/package/load'
lib_load 'dev/package/symbols'


######
# Library Settings

dev_package_files_config_init() {
	lib_setting_arrays -ro package_file_kinds
	package_file_kinds=( dist package sources configs tools libs )

	lib_setting_vars package_grep_file_kind
	package_grep_file_kind=${package_grep_file_kind:-sources}
}


######
# Package source file kinds

# package_file_kind_valid - Returns success if $1 is valid kind of package file
package_file_kind_valid() {
	in_list "$1" "${package_file_kinds[@]}" \
		|| error "$1: invalid kind of package file"
}

# package_file_kind_ext - Prints package directory for a given file kind ($1)
package_file_kind_dir() {
	local kind=$1
	case "$kind" in
	(tools) echo "src" ;;
	(libs) echo "libs" ;;
	(configs) echo "conf" ;;
	(*) error "$kind: no known directory for this kind of package file" ;;
	esac
}

# package_file_kind_ext - Prints file extension for a given file kind ($1)
package_file_kind_ext() {
	local kind=$1
	case "$kind" in
	(tools|libs) echo "in" ;;
	(configs) echo "conf.in" ;;
	(*) error "$kind: no known extension for this kind of package file" ;;
	esac
}


######
# Package source files

# package_file_name - Returns file name for a given file kind ($1) and name ($2)
package_file_name() {
	local kind=$1
	local name=$2
	local dir ext
	dir=$(package_file_kind_dir "$kind")
	ext=$(package_file_kind_ext "$kind")
	echo "$dir/$name.$ext"
}


package_files() { local kind=$1; shift; package_files_$kind "$@"; }
package_files_dist() { find "${DIST[@]}" "$@"; }
package_files_package() { package_files_dist -type f; }
package_files_sources() { package_files_package | grep '\.in$' | grep -v Makefile; }
package_files_configs() { package_files_sources | grep '^conf/'; }
package_files_tools() { package_files_sources | grep '^src/'; }
package_files_libs() { package_files_sources | grep '^libs/'; }

package_sources_or_args() {
	min_args 1 "$@"
	local psoa_var=$1
	shift
	local -a files
	files=$(package_files_sources)
	list_copy_or_args $psoa_var files "$@"
}

# with_package_files - Run a command with all package files
# $1 - Kind of files to use: dist, package, sources, configs, tools, libs
# $2+ - Command and (optional) arguments to run: $("$@" "${kind_of_files[@]}")
with_package_files() {
	min_args 2 "$@"
	local kind=$1
	shift
	local -a files
	files=( $(package_files_$kind) )
	"$@" "${files[@]}"
}

# with_each_package_file - Run a command with each package file
# $1 - Kind of files to use: dist, package, sources, configs, tools, libs
# $2+ - Command and (optional) arguments to run: $(for_each "$*" "${files[@]}")
with_each_package_file() {
	min_args 2 "$@"
	local kind=$1
	shift
	local -a files
	files=( $(package_files_$kind) )
	for_each "$*" "${files[@]}"
}

# is_package_file - Returns success if file is the given kind of package source
is_package_source() {
	local kind=$1
	local file=$2
	local dir
	dir=$(package_file_kind_dir "$kind")
	[ "${file#$dir/}" != "$file" -a "${file%.in}" != "$file" ]
}

# is_package_lib - Returns success if file is a library
is_package_lib() { has_args 1 "$@"; is_package_source libs "$1"; }
# is_package_tool - Returns success if file is a tool
is_package_tool() { has_args 1 "$@"; is_package_source tools "$1"; }


######
# Source file introspection

package_wc() {
	max_args 1 "$@"
	local kind=${1:-sources}
	package_file_kind_valid "$kind"

	with_package_files $kind run wc
}

package_grep() {
	local kind=$package_grep_file_kind
	package_file_kind_valid "$kind" \
		|| error "\$package_grep_file_kind: invalid file kind"
	with_package_files $kind run grep --color=auto -n -e "$@"
}


######
# Source file manipulations

package_sed() {
	local pat=$1
	local str=$2
	local tmp
	tmp=$(cmd_tempfile)
	if ! package_grep "$pat" -l >"$tmp"; then
		debug "$pat: not found"
		return 0
	fi

	[ -s "$tmp" ]

	local -a files
	readarray -t files <"$tmp"
	sed_replace_global "$pat" "$str" -i "${files[@]}"
}

# package_file_rename - Renames package source code files.
package_file_rename() {
	min_args 1 "$@"
	local kind=$1
	shift
	package_file_kind_valid "$kind"

	has_args 2 "$@"
	local old=$1
	local new=$2

	package_file_rename_module "$kind" "$old" "$new"

	local func="package_file_rename_$kind"
	if is_function "$func"; then
		$func "$old" "$new"
	else
		error "$kind: rename: unimplemented for this kind of file"
	fi

	sed_replace "^[\\t ]*$old$" $'\t'"$new" -i "$package_i7"

	local -a files
	files=( $(package_files_sources) "$package_i7" )
	git_add "${files[@]}"
}

# $1 - old name
# $2 - new name
package_file_rename_libs() {
	# rename library symbols
	package_file_rename_symbols libs "$old" "$new"

	# update lib_load references
	package_sed '^\(.*\)lib_load '"[\"']$1[\"']" "\\1lib_load '$2'"
}

# $1 - old name
# $2 - new name
package_file_rename_tools() {
	package_file_rename_module "configs" "$1" "$2"
}

package_file_rename_module() {
	local kind=$1
	local old=$2
	local new=$3

	local src dst
	src=$(package_file_name "$kind" "$old")
	dst=$(package_file_name "$kind" "$new")
	debug "$kind: rename '$src' '$dst'"

	[ -f "$src" ] || error "$kind: $old: source file missing: $src"
	[ ! -f "$dst" ] || error "$kind: $new: destination file exists: $dst"

	git_mv "$src" "$dst"
}

package_file_rename_symbols() {
	local kind=$1
	local old=$(lib_symbol "$2")
	local new=$(lib_symbol "$3")

	local -a funcs
	eval "funcs=( \"\${package_entrypoint_$kind[@]}\" )"

	local package_grep_file_kind=$kind
	for_each "package_file_rename_symbol $old $new" "${funcs[@]}"
}

# $1 - old component symbol
# $2 - new component symbol
# $3 - function
package_file_rename_symbol() { package_sed "${1}_$3" "${2}_$3" || true; }

View the Script Reference Index


Generated on Tue Apr 25 21:20:36 PDT 2017 by mcsh i7 v0.18.0.