#!/bin/bash ################################################################################ # Add a collection of files to fossil as "unversioned files" and prefix those # files with the category name. ################################################################################ # # Exit Error Codes: # # The exit error codes are based on the /usr/include/sysexits.h for all # non-zero errors. An exit code of '0' is success. # ############################################################################### # # Bugs: # - Nothing to admit # ############################################################################### # # Todo: # - Add more Todo items # ############################################################################### ############################################################################### # Variables: Read-Only ######################################## # Error Codes readonly Error_Data=65 # EX_DATAERR readonly Error_NoInput=66 # EX_NOINPUT readonly Error_NoPerm=77 # EX_NOPERM readonly Error_TempFail=75 # EX_TEMPFAIL readonly Error_Unavailable=69 # EX_UNAVAILABLE readonly Error_Usage=64 # EX_USAGE ######################################## # Grep Exit Codes readonly Grep_Found_Match=0 readonly Grep_No_Match=1 readonly Grep_Error=2 ######################################## # Page Viewer if [ -n "`command -v less 2> /dev/null`" ] then readonly page_viewer="less --no-init --quit-if-one-screen" elif [ -n "`command -v more 2> /dev/null`" ] then readonly page_viewer="more" else readonly page_viewer="" fi ######################################## # Project Values readonly program_name=`basename $0` readonly project_path=$(fossil info | grep 'local-root:' | sed 's/.*: *\(.*\)[\/]/\1/') ############################################################################### # Variables: Internal action="" ############################################################################### # Variables: Arg Configurable category="" debug_mode="" file_list="" dry_run="" separator=":" ############################################################################### main() { if [ -n "$dry_run" ] then action=ignore fi if [ -n "$debug_mode" ] then echo "--- Internally Defined Values ---" echo " page_viewer: \"$page_viewer\"" echo " program_name: \"$program_name\"" echo " project_path: \"$project_path\"" echo " action: \"$action\"" echo "" echo "--- Argument Based Values ---" echo " category: \"$category\"" echo " dry_run: \"$dry_run\"" echo " separator: \"$separator\"" echo " file_list: \"$file_list\"" exit $Error_TempFail fi add_files } ################################################################################ # Add the unversioned files add_files() { for file_path in $file_list do file=$(basename $file_path) $action fossil uv add $file_path --as $category$separator$file done } ################################################################################ # Do nothing and do it well ignore() { echo $* } ################################################################################ show_usage() { if [ -n "$page_viewer" ] then usage | $page_viewer else usage fi } ################################################################################ usage() { cat <<- USAGE_END Usage: $program_name [Options] Category File [File ...] Options: --debug Display the internal values that would be used to create the requested class then exit. -h, --help Show this message and exit. -n, --dry-run Only print what would be done. No file changes will be made. Note: The destination directory must exist to use this option. -s, --separator CHAR Specify the character that separates the category name from the file name in the repository. Default: ":" Arguments: Category All the files with this category will be exported from the repository. Multiple categories can be provided. File All the files to add. If present, the path to the file will be removed so only the file name will be used when adding to fossil. USAGE_END } ############################################################################### # Parse the args arg_list=() while [ "$1" != "" ] do case $1 in --debug) debug_mode="yes" ;; -h|--help) show_usage exit 0 ;; -n|--dry-run) dry_run="yes" ;; -s|--separator) shift separator="$1" ;; -*) echo "Error: Option \"$1\" is not supported." echo "Use \"-h\" for help:" echo " $program_name -h" exit $Error_Usage ;; *) arg_list+=($1) ;; esac shift done # Bash Array Syntax # ${array_name[@]} Get all elements # ${#array_name[@]} Count all elements # ${array_name[@]:I:N} Get N elements starting at I category=${arg_list[0]} files=${arg_list[@]:1} ############################################################################### # Make sure that all required information is present and valid ### Category ### if [ -z "$category" ] then echo "Error: No category name was provided" echo "Use \"-h\" for help:" echo " $program_name -h" exit $Error_NoInput fi ### File List ### if [ -z "$files" ] then echo "Error: No file(s) were provided" echo "Use \"-h\" for help:" echo " $program_name -h" exit $Error_NoInput fi for X in $files do if [[ $X != /* ]] then file="$(pwd)/$X" else file="$X" fi file=$(readlink --canonicalize $file) echo $file | grep "^$project_path" &> /dev/null if [ "$?" == "$Grep_No_Match" ] then echo "Error: Invalid file, not within project root: $file" echo "Use \"-h\" for help:" echo " $program_name -h" exit $Error_Unavailable fi if [ ! -f "$file" ] then echo "Error: File does not exist: $file" echo "Use \"-h\" for help:" echo " $program_name -h" exit $Error_Data fi file_list="$file_list $file" done ############################################################################### # Everything is now ready main exit 0