vcsh-2.0.10/0000775000175000017500000000000014604750111011512 5ustar hibbyhibbyvcsh-2.0.10/CONTRIBUTORS0000664000175000017500000000504314604750111013374 0ustar hibbyhibbyAlphabetical list of names of everyone who ever committed to this repository. Auto-generated using `make -B CONTRIBUTORS` Aaron Schumacher Aaron VonderHaar Alessandro Ghedini Alexander Skurikhin Andrew Schwartzmeyer arndtc Aryel Mota Góis Caleb Maclennan Corey Quinn Daniel Shahaf Dato Simó Debian Janitor Dennis Gilmore Devin J. Pohly Dewey Sasser Dieter Plaetinck Don Don March Dridi Boukelmoune Edward Betts Eli Young Eric Bouchut Errietta Kostala Evan Pitstick Fedora Release Engineering Felix Eckhofer Florian Engel Frank Terbeck Gernot Schulz G.raud Gregor Jasny guy hughes Harendra Kumar James Davidson Jeff Fein-Worton Jochen Keil John Karahalis John Whitley Jonathan Sternberg Julien Lecomte Kevin Lyda leycec Lyderic Landry Markus Martin martin f. krafft Martin Kühl Mathias Svensson mek-apelsin Mert Dirik Mikhail Gusarov mirabilos miramir Noah Birnel Pavlos Ratis Richard Hartmann Rob Cornish Roland Hopferwieser Skurikhin Alexander soulofmischief <30357883+soulofmischief@users.noreply.github.com> Thomas Ferris Nicolaisen Thomas Tuegel Thorsten Glaser tikki Tony Valentin Haenel Vincent Demeester Yuval Langer vcsh-2.0.10/vcsh.in0000775000175000017500000005732214604750111013021 0ustar hibbyhibby#!@SHELL@ # Copyright (C) 2011-2015 Richard "RichiH" Hartmann , see CONTRIBUTORS for details. # SPDX-License-Identifier: GPL-2.0-or-later # # While the following is not legally binding, the author would like to explain # the choice of GPLv2+ over GPLv3+. The author prefers GPLv3+ over GPLv2+ but # feels it's better to maintain full compatibility's with Git. In case Git ever # changes its licensing terms, which is admittedly extremely unlikely to the # point of being impossible, this software will most likely follow suit. # This should always be the first line of code to facilitate debugging [ -n "$VCSH_DEBUG" ] && set -vx # If '.r-g' is appended to the version, you are seeing an unreleased # version built from the main branch HEAD. If "-standalone" is appended you are # using a version built explicitly for portability as a standalone script # rather than being installed to a specific system. VCSH_VERSION='@VERSION@@DEPLOYMENT@'; export VCSH_VERSION VCSH_SELF='@TRANSFORMED_PACKAGE_NAME@'; export VCSH_SELF # Ensure all files created are accessible only to the current user. umask 0077 fatal() { echo "$VCSH_SELF: fatal: $1" >&2 [ -z "$2" ] && exit 1 exit "$2" } # We need to run getops as soon as possible so we catch -d and other # options that will modify our behaviour. # Commands are handled at the end of this script. # shellcheck disable=SC2220 while getopts c:dv flag; do case "$flag" in d) set -vx VCSH_DEBUG=1 export VCSH_DEBUG echo 'debug mode on' echo "$VCSH_SELF $VCSH_VERSION" ;; v) VCSH_VERBOSE=1 export VCSH_VERBOSE echo 'verbose mode on' echo "$VCSH_SELF $VCSH_VERSION" ;; c) VCSH_OPTION_CONFIG="$OPTARG" export VCSH_OPTION_CONFIG ;; esac done shift $((OPTIND-1)) source_all() { # Source file even if it's in $PWD and does not have any slashes in it # shellcheck source=/dev/null case "$1" in */*) . "$1";; *) . "$PWD/$1";; esac; } # Read configuration and set defaults if anything's not set [ -n "$VCSH_DEBUG" ] && set -vx : "${XDG_CONFIG_HOME:="$HOME/.config"}" # Read configuration files if there are any # shellcheck source=/dev/null [ -r "/etc/vcsh/config" ] && . "/etc/vcsh/config" # shellcheck source=/dev/null [ -r "$XDG_CONFIG_HOME/vcsh/config" ] && . "$XDG_CONFIG_HOME/vcsh/config" if [ -n "$VCSH_OPTION_CONFIG" ]; then # Source $VCSH_OPTION_CONFIG if it can be read and is in $PWD of $PATH if [ -r "$VCSH_OPTION_CONFIG" ]; then source_all "$VCSH_OPTION_CONFIG" else fatal "Can not read configuration file '$VCSH_OPTION_CONFIG'" 1 fi fi [ -n "$VCSH_DEBUG" ] && set -vx # Read defaults : "${VCSH_REPO_D:="$XDG_CONFIG_HOME/vcsh/repo.d"}"; export VCSH_REPO_D : "${VCSH_HOOK_D:="$XDG_CONFIG_HOME/vcsh/hooks-enabled"}"; export VCSH_HOOK_D : "${VCSH_OVERLAY_D:="$XDG_CONFIG_HOME/vcsh/overlays-enabled"}"; export VCSH_OVERLAY_D : "${VCSH_BASE:="$HOME"}"; export VCSH_BASE : "${VCSH_GITIGNORE:=exact}"; export VCSH_GITIGNORE : "${VCSH_GITATTRIBUTES:=none}"; export VCSH_GITATTRIBUTES : "${VCSH_WORKTREE:=absolute}"; export VCSH_WORKTREE if [ ! "x$VCSH_GITIGNORE" = 'xexact' ] && [ ! "x$VCSH_GITIGNORE" = 'xnone' ] && [ ! "x$VCSH_GITIGNORE" = 'xrecursive' ]; then fatal "'\$VCSH_GITIGNORE' must equal 'exact', 'none', or 'recursive'" 1 fi if [ ! "x$VCSH_WORKTREE" = 'xabsolute' ] && [ ! "x$VCSH_WORKTREE" = 'xrelative' ]; then fatal "'\$VCSH_WORKTREE' must equal 'absolute', or 'relative'" 1 fi # editorconfig-checker-disable help() { echo "usage: $VCSH_SELF options: -c Source file -d Enable debug mode -v Enable verbose mode commands: clone [-b ] \\ \\ [] Clone from an existing repository commit Commit in all repositories delete Delete an existing repository enter Enter repository; spawn new instance of \$SHELL with \$GIT_DIR set. foreach \\ [<-g>] [<-p>] \\ Execute a command for every repository help Display this help text init Initialize a new repository list List all repositories list-tracked \\ [] List all files tracked all or one repositories list-untracked \\ [<-a>] [<-r>] [] List all files not tracked by all or one repositories pull Pull from all vcsh remotes push Push to vcsh remotes rename \\ Rename repository run \\ Use this repository status \\ [--terse] [] Show statuses of all/one vcsh repositories upgrade Upgrade repository to currently recommended settings version Print version information which Find substring in name of any tracked file write-gitignore \\ [] Write .gitignore.d/ via git ls-files Shortcut to run git commands directly Shortcut to enter repository" >&2 } # editorconfig-checker-enable debug() { if [ -n "$VCSH_DEBUG" ]; then echo "$VCSH_SELF: debug: $*"; fi } verbose() { if [ -n "$VCSH_DEBUG" ] || [ -n "$VCSH_VERBOSE" ]; then echo "$VCSH_SELF: verbose: $*" fi } error() { echo "$VCSH_SELF: error: $1" >&2 } info() { echo "$VCSH_SELF: info: $1" } clone() { hook pre-clone # Check if remote is reachable. Abort early if there's a typo, TLS certificate problem, etc @GIT@ ls-remote "$GIT_REMOTE" 2> /dev/null || fatal "Can not reach '$GIT_REMOTE'" init # Test which, if any, given or detected branches can be pulled from. # In a future version, if we need the logic, we could do the following: # git ls-remote ORIGIN # get HEAD commit ID # see what refs/heads/* match that commit ID # set VCSH_BRANCH if only one match # offer a list of all matching refs for the user to choose for VCSH_BRANCH_TEST in "$VCSH_BRANCH" master trunk development; do if [ $(@GIT@ ls-remote "$GIT_REMOTE" "$VCSH_BRANCH_TEST" 2> /dev/null | @WC@ -l ) -lt 1 ]; then info "remote branch '$VCSH_BRANCH_TEST' empty" else info "remote branch '$VCSH_BRANCH_TEST' found" VCSH_BRANCH_REMOTE=$VCSH_BRANCH_TEST break fi done if [ -z "$VCSH_BRANCH_REMOTE" ]; then info "No non-empty remote branches found, aborting. Please run `$0 delete $VCSH_REPO_NAME`, determine the correct branch, and try again." exit fi VCSH_BRANCH=$VCSH_BRANCH_REMOTE # Set up remote @GIT@ remote add origin "$GIT_REMOTE" @GIT@ checkout -b "$VCSH_BRANCH" || return $? @GIT@ config branch."$VCSH_BRANCH".remote origin @GIT@ config branch."$VCSH_BRANCH".merge refs/heads/"$VCSH_BRANCH" GIT_VERSION_MAJOR=$(@GIT@ --version | @SED@ -E -n 's/.* ([0-9]+)\..*/\1/p' ) if [ 1 -lt "$GIT_VERSION_MAJOR" ];then @GIT@ fetch origin "$VCSH_BRANCH" else @GIT@ fetch origin fi hook pre-merge @GIT@ read-tree -n -mu origin/"$VCSH_BRANCH" \ || fatal "will stop after fetching and not try to merge! Once this situation has been resolved, run 'vcsh $VCSH_REPO_NAME pull' to finish cloning." 17 # editorconfig-checker-disable-line @GIT@ -c merge.ff=true merge origin/"$VCSH_BRANCH" hook post-merge hook post-clone retire hook post-clone-retired } commit() { hook_global pre-commit shift # remove the "commit" command. for VCSH_REPO_NAME in $(list); do export VCSH_REPO_NAME echo "$VCSH_REPO_NAME: " GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR use hook_repo pre-commit @GIT@ commit --untracked-files=no --quiet "$@" hook_repo post-commit VCSH_COMMAND_RETURN_CODE=$? echo done hook_global post-commit } delete() { cd "$VCSH_BASE" || fatal "could not enter '$VCSH_BASE'" 11 use info "This operation WILL DESTROY DATA!" files=$(@GIT@ ls-files) echo "These files will be deleted: $files AGAIN, THIS WILL DELETE YOUR DATA! To continue, type 'Yes, do as I say'" read -r answer [ "x$answer" = 'xYes, do as I say' ] || exit 16 for file in $files; do rm -f "$file" || info "could not delete '$file', continuing with deletion" done rm -rf "$GIT_DIR" || error "could not delete '$GIT_DIR'" } enter() { hook pre-enter use $SHELL hook post-enter } foreach() { hook_global pre-foreach # We default to prefixing `git` to all commands passed to foreach, but # allow running in general context with -g command_prefix=@GIT@ # shellcheck disable=SC2220 while getopts gp flag; do case "$flag" in g) unset command_prefix ;; p) VCSH_PRINT_REPO_PREFIX=1 ;; esac done shift $((OPTIND-1)) export VCSH_PRINT_REPO_PREFIX for VCSH_REPO_NAME in $(list); do export VCSH_REPO_NAME GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR use hook_repo pre-foreach if [ -n "${VCSH_PRINT_REPO_PREFIX+x}" ]; then $command_prefix "$@" | @SED@ "s/^/$VCSH_REPO_NAME: /" else echo "$VCSH_REPO_NAME:" $command_prefix "$@" fi hook_repo post-foreach done hook_global post-foreach } git_dir_exists() { [ -d "$GIT_DIR" ] || fatal "no repository found for '$VCSH_REPO_NAME'" 12 } hook_global() { for hook in "$VCSH_HOOK_D/$1"*; do [ -x "$hook" ] || continue verbose "executing '$hook'" "$hook" done } hook_repo() { for hook in "$VCSH_HOOK_D/$VCSH_REPO_NAME.$1"*; do [ -x "$hook" ] || continue verbose "executing '$hook'" "$hook" || fatal "hook [$hook] failed" 1 done } hook() { hook_global "$1" hook_repo "$1" } init() { hook pre-init [ ! -e "$GIT_DIR" ] || fatal "'$GIT_DIR' exists" 10 mkdir -p "$VCSH_BASE" || fatal "could not create '$VCSH_BASE'" 50 cd "$VCSH_BASE" || fatal "could not enter '$VCSH_BASE'" 11 @GIT@ init --shared=false upgrade hook post-init } list() { for repo in "$VCSH_REPO_D"/*.git; do [ -d "$repo" ] && [ -r "$repo" ] && basename "$repo" .git done } list_has_remote() { for VCSH_REPO_NAME in $(list); do GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR # This command returns the tracking branch of the currently-checked-out local # branch, if any. See https://stackoverflow.com/a/9753364 [ -n "$(@GIT@ for-each-ref "$(@GIT@ symbolic-ref -q HEAD)")" ] && echo "$VCSH_REPO_NAME" done } get_files() { GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR @GIT@ ls-files --full-name } list_tracked() { VCSH_REPO_NAME=$2; export VCSH_REPO_NAME if [ -n "$VCSH_REPO_NAME" ]; then get_files | list_tracked_helper else for VCSH_REPO_NAME in $(list); do get_files done | list_tracked_helper fi } list_tracked_helper() { @SED@ "s,^,$(printf '%s\n' "$VCSH_BASE/" | @SED@ 's/[,\&]/\\&/g')," | sort -u } list_tracked_by() { list_tracked '' "$2" } list_untracked() { temp_file_others=$(mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX") || fatal 'Could not create temp file' temp_file_untracked=$(mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX") || fatal 'Could not create temp file' temp_file_untracked_copy=$(mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX") || fatal 'Could not create temp file' # Hack in support for `vcsh list-untracked -r`... exclude_standard_opt='--exclude-standard' directory_opt='--directory' shift while getopts ar flag; do case "$flag" in a) unset exclude_standard_opt ;; r) unset directory_opt ;; esac done shift $((OPTIND-1)) # ...and parse for a potential parameter afterwards. As we shifted things out of $* in during getops, we need to look at $1 VCSH_REPO_NAME=$1; export VCSH_REPO_NAME if [ -n "$VCSH_REPO_NAME" ]; then list_untracked_helper "$VCSH_REPO_NAME" else for VCSH_REPO_NAME in $(list); do list_untracked_helper "$VCSH_REPO_NAME" done fi cat "$temp_file_untracked" unset directory_opt directory_component rm -f "$temp_file_others" "$temp_file_untracked" "$temp_file_untracked_copy" || fatal 'Could not delete temp files' } list_untracked_helper() { export GIT_DIR="$VCSH_REPO_D/$VCSH_REPO_NAME.git" @GIT@ ls-files --others $exclude_standard_opt $directory_opt | ( while read -r line; do echo "$line" directory_component=${line%%/*} [ -d "$directory_component" ] && printf '%s/\n' "$directory_component" done ) | sort -u > "$temp_file_others" if [ -z "$ran_once" ]; then ran_once=1 cp "$temp_file_others" "$temp_file_untracked" || fatal 'Could not copy temp file' fi cp "$temp_file_untracked" "$temp_file_untracked_copy" || fatal 'Could not copy temp file' @COMM@ -12 "$temp_file_others" "$temp_file_untracked_copy" > "$temp_file_untracked" } pull() { hook_global pre-pull for VCSH_REPO_NAME in $(list_has_remote); do export VCSH_REPO_NAME printf '%s: ' "$VCSH_REPO_NAME" GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR use hook_repo pre-pull @GIT@ pull hook_repo post-pull VCSH_COMMAND_RETURN_CODE=$? echo done hook_global post-pull } push() { hook_global pre-push for VCSH_REPO_NAME in $(list_has_remote); do export VCSH_REPO_NAME printf '%s: ' "$VCSH_REPO_NAME" GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR use hook_repo pre-push @GIT@ push hook_repo post-push VCSH_COMMAND_RETURN_CODE=$? echo done hook_global post-push } retire() { unset VCSH_DIRECTORY } rename() { git_dir_exists [ -d "$GIT_DIR_NEW" ] && fatal "'$GIT_DIR_NEW' exists" 54 mv -f "$GIT_DIR" "$GIT_DIR_NEW" || fatal "Could not mv '$GIT_DIR' '$GIT_DIR_NEW'" 52 # Now that the repository has been renamed, we need to fix up its configuration # Overwrite old name.. GIT_DIR=$GIT_DIR_NEW VCSH_REPO_NAME=$VCSH_REPO_NAME_NEW # ..and clobber all old configuration upgrade } run() { hook pre-run use "$@" VCSH_COMMAND_RETURN_CODE=$? hook post-run } status() { if [ -t 1 ]; then COLORING="-c color.status=always" fi if [ -n "$VCSH_REPO_NAME" ]; then status_helper "$VCSH_REPO_NAME" else for VCSH_REPO_NAME in $(list); do STATUS="$(status_helper "$VCSH_REPO_NAME" "$COLORING")" [ -n "$STATUS" ] || [ -z "$VCSH_STATUS_TERSE" ] && echo "$VCSH_REPO_NAME:" [ -n "$STATUS" ] && echo "$STATUS" [ -z "$VCSH_STATUS_TERSE" ] && echo done fi } # Warning: disabled quoting check here due to all of them relating to # wc -l output and a deliberate lack of quoting for git args. # shellcheck disable=SC2086 status_helper() { GIT_DIR=$VCSH_REPO_D/$1.git; export GIT_DIR VCSH_GIT_OPTIONS="-c status.relativePaths=false $2" use # Shellcheck isn't understanding a complex block. # shellcheck disable=SC1083 remote_tracking_branch=$(@GIT@ rev-parse --abbrev-ref --symbolic-full-name @{u} 2> /dev/null) && { commits_behind=$(@GIT@ log ..${remote_tracking_branch} --oneline | @WC@ -l) commits_ahead=$(@GIT@ log ${remote_tracking_branch}.. --oneline | @WC@ -l) [ ${commits_behind} -ne 0 ] && echo "Behind $remote_tracking_branch by $commits_behind commits" [ ${commits_ahead} -ne 0 ] && echo "Ahead of $remote_tracking_branch by $commits_ahead commits" } @GIT@ ${VCSH_GIT_OPTIONS} status --short --untracked-files='no' | @SED@ -E 's@([^ ] +)@\1~/@' VCSH_COMMAND_RETURN_CODE=$? } upgrade() { hook pre-upgrade # fake-bare repositories are not bare, actually. Set this to false # because otherwise Git complains "fatal: core.bare and core.worktree # do not make sense" @GIT@ config core.bare false # core.worktree may be absolute or relative to $GIT_DIR, depending on # user preference if [ ! "x$VCSH_WORKTREE" = 'xabsolute' ]; then @GIT@ config core.worktree "$(cd "$GIT_DIR" && GIT_WORK_TREE=$VCSH_BASE @GIT@ rev-parse --show-cdup)" elif [ ! "x$VCSH_WORKTREE" = 'xrelative' ]; then @GIT@ config core.worktree "$VCSH_BASE" fi [ ! "x$VCSH_GITIGNORE" = 'xnone' ] && @GIT@ config core.excludesfile ".gitignore.d/$VCSH_REPO_NAME" [ ! "x$VCSH_GITATTRIBUTES" = 'xnone' ] && @GIT@ config core.attributesfile ".gitattributes.d/$VCSH_REPO_NAME" @GIT@ config vcsh.vcsh 'true' use [ -e "$VCSH_BASE/.gitignore.d/$VCSH_REPO_NAME" ] && @GIT@ add -f "$VCSH_BASE/.gitignore.d/$VCSH_REPO_NAME" [ -e "$VCSH_BASE/.gitattributes.d/$VCSH_REPO_NAME" ] && @GIT@ add -f "$VCSH_BASE/.gitattributes.d/$VCSH_REPO_NAME" hook post-upgrade } use() { git_dir_exists VCSH_DIRECTORY=$VCSH_REPO_NAME; export VCSH_DIRECTORY } which() { # It's ok to modify VCSH_REPO_NAME in a subshell. # shellcheck disable=SC2030 output=$(for VCSH_REPO_NAME in $(list); do get_files | @GREP@ -- "$VCSH_COMMAND_PARAMETER" | @SED@ "s/^/$VCSH_REPO_NAME: /" done | sort -u) if [ -z "$output" ]; then fatal "'$VCSH_COMMAND_PARAMETER' does not exist" 1 else echo "$output" fi } # Ignore warnings about VCSH_REPO_NAME being changed in a subshell. # shellcheck disable=SC2031 write_gitignore() { # Don't do anything if the user does not want to write gitignore if [ "x$VCSH_GITIGNORE" = 'xnone' ]; then info "Not writing gitignore as '\$VCSH_GITIGNORE' is set to 'none'" exit fi use cd "$VCSH_BASE" || fatal "could not enter '$VCSH_BASE'" 11 # Works in all shells we care about. # shellcheck disable=SC2039,SC3043 local GIT_VERSION GIT_VERSION_MAJOR GIT_VERSION_MINOR GIT_VERSION="$(@GIT@ --version)" GIT_VERSION_MAJOR="$(echo "$GIT_VERSION" | @SED@ -E -n 's/.* ([0-9]+)\..*/\1/p')" GIT_VERSION_MINOR="$(echo "$GIT_VERSION" | @SED@ -E -n 's/.* ([0-9]+)\.([0-9]+)\..*/\2/p')" OLDIFS=$IFS IFS=$(printf '\n\t') gitignores=$(for file in $(@GIT@ ls-files); do while true; do echo "$file"; new=${file%/*} [ x"$file" = x"$new" ] && break file=$new done; done | sort -u) # Contrary to GNU mktemp, mktemp on BSD/OSX requires a template for temp files # Using a template makes GNU mktemp default to $PWD and not #TMPDIR for tempfile location # To make every OS happy, set full path explicitly local tempfile tempfile=$(mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX") || fatal "could not create tempfile: '${tempfile}'" 51 echo '*' > "$tempfile" || fatal "could not write to '$tempfile'" 57 for gitignore in $gitignores; do echo "$gitignore" | @SED@ 's@^@!/@' >> "$tempfile" || fatal "could not write to '$tempfile'" 57 if [ "x$VCSH_GITIGNORE" = 'xrecursive' ] && [ -d "$gitignore" ]; then { echo "$gitignore/*" | @SED@ 's@^@!/@' >> "$tempfile" || fatal "could not write to '$tempfile'" 57; } fi done IFS=$OLDIFS local GIT_IGNORE_PATH GIT_IGNORE_PATH="$VCSH_BASE/.gitignore.d/$VCSH_REPO_NAME" if diff -N "$tempfile" "$GIT_IGNORE_PATH" > /dev/null; then info "'$GIT_IGNORE_PATH' already up to date" rm -f "$tempfile" || fatal "could not delete '$tempfile'" 59 return fi if [ -e "$GIT_IGNORE_PATH" ]; then info "'$GIT_IGNORE_PATH' differs from new data, moving it to '$GIT_IGNORE_PATH.bak'" mv -f "$GIT_IGNORE_PATH"{,.bak} || fatal "could not move '$GIT_IGNORE_PATH' to '$GIT_IGNORE_PATH.bak'" 53 fi mv -f "$tempfile" "$GIT_IGNORE_PATH" || fatal "could not move '$tempfile' to '$GIT_IGNORE_PATH'" 53 } debug "$(@GIT@ version)" if [ ! "x$VCSH_GITIGNORE" = 'xexact' ] && [ ! "x$VCSH_GITIGNORE" = 'xnone' ] && [ ! "x$VCSH_GITIGNORE" = 'xrecursive' ]; then fatal "'\$VCSH_GITIGNORE' must equal 'exact', 'none', or 'recursive'" 1 fi VCSH_COMMAND=$1; export VCSH_COMMAND case $VCSH_COMMAND in clon|clo|cl) VCSH_COMMAND=clone;; commi|comm|com|co|ci) VCSH_COMMAND=commit;; delet|dele|del|de) VCSH_COMMAND=delete;; ente|ent|en) VCSH_COMMAND=enter;; hel|he) VCSH_COMMAND=help;; ini|in) VCSH_COMMAND=init;; pul) VCSH_COMMAND=pull;; pus) VCSH_COMMAND=push;; renam|rena|ren|re) VCSH_COMMAND=rename;; ru) VCSH_COMMAND=run;; statu|stat|sta|st) VCSH_COMMAND=status;; upgrad|upgra|upgr|up) VCSH_COMMAND=upgrade;; versio|versi|vers|ver|ve) VCSH_COMMAND=version;; which|whi|wh) VCSH_COMMAND=which;; write|writ|wri|wr) VCSH_COMMAND=write-gitignore;; esac if [ x"$VCSH_COMMAND" = x'clone' ]; then VCSH_BRANCH= if [ "$2" = -b ]; then VCSH_BRANCH=$3 shift shift fi [ -z "$2" ] && fatal "$VCSH_COMMAND: please specify a remote" 1 GIT_REMOTE="$2" [ -n "$VCSH_BRANCH" ] || if [ "$3" = -b ]; then VCSH_BRANCH=$4 shift shift fi if [ -n "$3" ]; then VCSH_REPO_NAME=$3 [ -z "$VCSH_BRANCH" ] && [ "$4" = -b ] && VCSH_BRANCH=$5 else VCSH_REPO_NAME=$(basename "${GIT_REMOTE#*:}" .git) fi [ -z "$VCSH_REPO_NAME" ] && fatal "$VCSH_COMMAND: could not determine repository name" 1 export VCSH_REPO_NAME [ -n "$VCSH_BRANCH" ] || VCSH_BRANCH=main GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR elif [ "$VCSH_COMMAND" = 'help' ]; then help && exit elif [ "$VCSH_COMMAND" = 'version' ]; then echo "$VCSH_SELF $VCSH_VERSION" @GIT@ version exit elif [ x"$VCSH_COMMAND" = x'which' ]; then [ -z "$2" ] && fatal "$VCSH_COMMAND: please specify a filename" 1 [ -n "$3" ] && fatal "$VCSH_COMMAND: too many parameters" 1 VCSH_COMMAND_PARAMETER=$2; export VCSH_COMMAND_PARAMETER elif [ x"$VCSH_COMMAND" = x'delete' ] || [ x"$VCSH_COMMAND" = x'enter' ] || [ x"$VCSH_COMMAND" = x'init' ] || [ x"$VCSH_COMMAND" = x'list-tracked-by' ] || [ x"$VCSH_COMMAND" = x'rename' ] || [ x"$VCSH_COMMAND" = x'run' ] || [ x"$VCSH_COMMAND" = x'upgrade' ] || [ x"$VCSH_COMMAND" = x'write-gitignore' ]; then if [ -z "$2" ]; then [ -z "$VCSH_REPO_NAME" ] && fatal "$VCSH_COMMAND: please specify repository to work on" 1 else VCSH_REPO_NAME=$2; export VCSH_REPO_NAME fi GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR [ x"$VCSH_COMMAND" = x'rename' ] && [ -z "$3" ] && fatal "$VCSH_COMMAND: please specify a target name" 1 [ x"$VCSH_COMMAND" = x'run' ] && [ -z "$3" ] && fatal "$VCSH_COMMAND: please specify a command" 1 [ x"$VCSH_COMMAND" = x'rename' ] && { VCSH_REPO_NAME_NEW=$3; export VCSH_REPO_NAME_NEW; GIT_DIR_NEW=$VCSH_REPO_D/$VCSH_REPO_NAME_NEW.git; export GIT_DIR_NEW; } [ x"$VCSH_COMMAND" = x'run' ] && shift 2 elif [ x"$VCSH_COMMAND" = x'foreach' ]; then [ -z "$2" ] && fatal "$VCSH_COMMAND: please specify a command" 1 shift 1 elif [ x"$VCSH_COMMAND" = x'commit' ] || [ x"$VCSH_COMMAND" = x'list' ] || [ x"$VCSH_COMMAND" = x'list-tracked' ] || [ x"$VCSH_COMMAND" = x'list-untracked' ] || [ x"$VCSH_COMMAND" = x'pull' ] || [ x"$VCSH_COMMAND" = x'push' ]; then : elif [ x"$VCSH_COMMAND" = x'status' ]; then if [ x"$2" = x'--terse' ]; then VCSH_STATUS_TERSE=1; export VCSH_STATUS_TERSE shift fi VCSH_REPO_NAME=$2; export VCSH_REPO_NAME elif [ -n "$2" ]; then VCSH_COMMAND='run'; export VCSH_COMMAND VCSH_REPO_NAME=$1; export VCSH_REPO_NAME GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR [ -d "$GIT_DIR" ] || { help; exit 1; } shift 1 set -- "@GIT@" "$@" elif [ -n "$VCSH_COMMAND" ]; then VCSH_COMMAND='enter'; export VCSH_COMMAND VCSH_REPO_NAME=$1; export VCSH_REPO_NAME GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR [ -d "$GIT_DIR" ] || { help; exit 1; } else # $1 is empty help && exit 1 fi # Did we receive a directory instead of a name? # Mangle the input to fit normal operation. if echo "$VCSH_REPO_NAME" | @GREP@ -q '/'; then GIT_DIR=$VCSH_REPO_NAME; export GIT_DIR VCSH_REPO_NAME=$(basename "$VCSH_REPO_NAME" .git); export VCSH_REPO_NAME fi check_dir() { check_directory="$1" if [ ! -d "$check_directory" ]; then if [ -e "$check_directory" ]; then fatal "'$check_directory' exists but is not a directory" 13 else verbose "attempting to create '$check_directory'" mkdir -p "$check_directory" || fatal "could not create '$check_directory'" 50 fi fi } check_dir "$VCSH_REPO_D" [ ! "x$VCSH_GITIGNORE" = 'xnone' ] && check_dir "$VCSH_BASE/.gitignore.d" [ ! "x$VCSH_GITATTRIBUTES" = 'xnone' ] && check_dir "$VCSH_BASE/.gitattributes.d" verbose "$VCSH_COMMAND begin" VCSH_COMMAND=$(echo "$VCSH_COMMAND" | @SED@ 's/-/_/g'); export VCSH_COMMAND # Source repo-specific configuration file # shellcheck source=/dev/null [ -r "$XDG_CONFIG_HOME/vcsh/config.d/$VCSH_REPO_NAME" ] \ && . "$XDG_CONFIG_HOME/vcsh/config.d/$VCSH_REPO_NAME" # source overlay functions for overlay in "$VCSH_OVERLAY_D/$VCSH_COMMAND"* "$VCSH_OVERLAY_D/$VCSH_REPO_NAME.$VCSH_COMMAND"*; do [ -r "$overlay" ] || continue info "sourcing '$overlay'" # shellcheck source=/dev/null . "$overlay" done hook pre-command $VCSH_COMMAND "$@" hook post-command verbose "$VCSH_COMMAND end, exiting" exit $VCSH_COMMAND_RETURN_CODE # Local Variables: # mode:shell-script # sh-shell:sh # End: # vim: ft=sh: vcsh-2.0.10/.gitignore0000664000175000017500000000037614604750111013510 0ustar hibbyhibbyvcsh.1 doc/vcsh.1.ronn *.patch *.swp .swp *.bak .version .version-prev Makefile Makefile.in aclocal.m4 autom4te.cache/ build-aux/install-sh build-aux/missing completions/_vcsh completions/vcsh config.log config.status configure aminclude.am /vcsh vcsh-* vcsh-2.0.10/configure.ac0000664000175000017500000000611614604750111014004 0ustar hibbyhibbyAC_PREREQ([2.69]) AC_INIT([vcsh], [m4_esyscmd(build-aux/git-version-gen .tarball-version)]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign tar-pax dist-zstd dist-zip no-dist-gzip color-tests]) AM_SILENT_RULES([yes]) AC_ARG_WITH([standalone], AS_HELP_STRING([--with-standalone], [Use configuration presets for a standalone script deployment @<:@default=no@:>@]), [COMM=comm GIT=git GREP=grep SED=sed WC=wc SHELL=/bin/sh with_deployment=standalone with_man_page=no enable_tests=no with_bash_completion_dir=no with_zsh_completion_dir=no program_suffix=-standalone.sh # By this point, ./configure has already handled its built in # arguments and hence thinks program_suffix has made its way into # program_transform_name. We're backtracking on it, so we have to # do the work again manually. # Code copied from generated ./configure at approx L2104 and 2108... program_transform_name="s&\$&$program_suffix&;$program_transform_name" program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` ], []) QUE_TRANSFORM_PACKAGE_NAME QUE_DEVELOPER_MODE # These macros must be run after processing our standalone setup because # they all expect the program name transformation setup to be complete. QUE_GIT_VERSION QUE_SHELL_COMPLETION_DIRS QUE_DIST_CHECKSUMS AC_PROG_GREP AC_PROG_SED QUE_PROGVAR([comm]) QUE_PROGVAR([git]) QUE_PROGVAR([wc]) AC_ARG_WITH([deployment], AS_HELP_STRING([--with-deployment], [Add deployment string to version @<:@default=@:>@]), [], [with_deployment=]) AC_SUBST([DEPLOYMENT], [${with_deployment:+-$with_deployment}]) AC_ARG_WITH([man-page], AS_HELP_STRING([--with-man-page], [Generate man page @<:@default=yes@:>@]), [], [with_man_page=yes]) AM_CONDITIONAL([ENABLE_MAN_PAGE], [test x"$with_man_page" != x"no"]) AM_COND_IF([SOURCE_IS_GIT], [AM_COND_IF([ENABLE_MAN_PAGE], [QUE_PROGVAR([ronn])]) ]) AM_COND_IF([SOURCE_IS_GIT], m4_define([TESTDEF], [yes]), m4_define([TESTDEF], [no])) AC_ARG_ENABLE([tests], AS_HELP_STRING([--disable-tests], [Configure tooling to run tests @<:@default=TESTDEF@:>@]), [], [enable_tests=TESTDEF]) AM_CONDITIONAL([ENABLE_TESTS], [test x"$enable_tests" != x"no"]) AM_COND_IF([ENABLE_TESTS], [ QUE_PROGVAR([prove]) AX_PROG_PERL_MODULES(Shell::Command, [], AC_MSG_ERROR(Perl module required for testing not found)) AX_PROG_PERL_MODULES(Test::Most, [], AC_MSG_ERROR(Perl module required for testing not found)) ]) AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([vcsh], [chmod +x vcsh]) AC_CONFIG_FILES([doc/vcsh.1.ronn]) AC_OUTPUT vcsh-2.0.10/.github/0000775000175000017500000000000014604750111013052 5ustar hibbyhibbyvcsh-2.0.10/.github/workflows/0000775000175000017500000000000014604750111015107 5ustar hibbyhibbyvcsh-2.0.10/.github/workflows/test.yml0000664000175000017500000000137714604750111016621 0ustar hibbyhibbyname: Test on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: | git fetch --prune --tags ||: - name: Install build dependencies run: | sudo apt install -y ronn - name: Install perl test dependencies uses: perl-actions/install-with-cpanm@v1 with: install: | Shell::Command Test::Most - name: Configure run: | ./bootstrap.sh ./configure - name: Run tests run: | make check - name: Run full cycle packaging check run: | make distcheck vcsh-2.0.10/.github/workflows/lint.yml0000664000175000017500000000124514604750111016602 0ustar hibbyhibbyname: Lint on: [push, pull_request] jobs: editor-config: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Lint code style uses: editorconfig-checker/action-editorconfig-checker@v2 shellcheck: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Configure run: | ./bootstrap.sh ./configure --without-man-page --disable-tests - name: Run shellcheck uses: reviewdog/action-shellcheck@v1 with: pattern: vcsh reporter: github-pr-review github_token: ${{ github.token }} vcsh-2.0.10/.github/workflows/release.yml0000664000175000017500000000427014604750111017255 0ustar hibbyhibbyname: Release on: push: tags: - v[0-9]+.[0-9]+.[0-9]+ - v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+ - v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+ - v[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+ jobs: ghrelease: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: | git fetch --prune --tags ||: - name: Install build dependencies run: | sudo apt install -y ronn - name: Configure run: | echo "VERSION=${GITHUB_REF#refs/*/v}" >> $GITHUB_ENV ./bootstrap.sh ./configure --enable-developer-mode - name: Generate release-specific changelog run: | echo "PRERELEASE=${{ contains(env.VERSION, '-alpha') || contains(env.VERSION, '-beta') || contains(env.VERSION, '-rc') }}" >> $GITHUB_ENV make changelog-HEAD - name: If a final release, make sure changelog matches if: ${{ ! (contains(env.VERSION, '-alpha') || contains(env.VERSION, '-beta') || contains(env.VERSION, '-rc')) }} run: | grep -F "* Release ${{ env.VERSION }}" changelog-HEAD - name: Build source package run: | make dist - name: Publish Release uses: softprops/action-gh-release@v1 with: prerelease: ${{ env.PRERELEASE }} body_path: changelog-HEAD files: | vcsh-${{ env.VERSION }}.tar.zst vcsh-${{ env.VERSION }}.zip vcsh-${{ env.VERSION }}.sha256.txt deploy-standalone: runs-on: ubuntu-latest needs: [ ghrelease ] steps: - name: Checkout uses: actions/checkout@v4 - name: Configure standalone script run: | ./bootstrap.sh ./configure --with-standalone --bindir=/ make DESTDIR=. install-exec sha256sum vcsh-standalone.sh | tee vcsh-standalone.sha256.txt - name: Add standalone deployment to release uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ github.token }} tag: ${{ github.ref }} file_glob: true file: vcsh-standalone.{sh,sha256.txt} vcsh-2.0.10/.github/workflows/build.yml0000664000175000017500000000324314604750111016733 0ustar hibbyhibbyname: Build on: [push, pull_request] jobs: source-dist: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: | git fetch --prune --tags ||: - name: Install build dependencies run: | sudo apt install -y ronn - name: Install perl test dependencies uses: perl-actions/install-with-cpanm@v1.4 with: install: | Shell::Command Test::Most - name: Configure run: | ./bootstrap.sh ./configure --enable-developer-mode - name: Run tests run: | make check - name: Build source package run: | make dist echo VERSION=$(cat .version) >> $GITHUB_ENV - name: Post build artifacts uses: actions/upload-artifact@v4 with: name: vcsh-${{ env.VERSION }} path: vcsh-${{ env.VERSION }}.zip standalone: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: | git fetch --prune --tags ||: - name: Configure standalone script run: | ./bootstrap.sh ./configure --with-standalone --bindir=/ make DESTDIR=. install-exec echo VERSION=$(cat .version) >> $GITHUB_ENV sha256sum vcsh-standalone.sh - name: Post standalone script artifact uses: actions/upload-artifact@v4 with: name: standalone-deployment-${{ env.VERSION }} path: vcsh-standalone.sh vcsh-2.0.10/build-aux/0000775000175000017500000000000014604750111013404 5ustar hibbyhibbyvcsh-2.0.10/build-aux/que_git_version.am0000664000175000017500000000164614604750111017134 0ustar hibbyhibby.SECONDEXPANSION: EXTRA_DIST += build-aux/git-version-gen BUILT_SOURCES += .version CLEANFILES += .version .version-prev _BRANCH_REF != $(AWK) '{print ".git/" $$2}' .git/HEAD 2>/dev/null ||: .version: $(_BRANCH_REF) @if [ -e "$(srcdir)/.tarball-version" ]; then \ printf "$(VERSION)" > $@; \ else \ touch "$@-prev"; \ if [ -e "$@" ]; then \ cp "$@" "$@-prev"; \ fi; \ ./build-aux/git-version-gen "$(srcdir)/.tarball-version" > $@; \ $(CMP) -s "$@" "$@-prev" || autoreconf configure.ac --force; \ fi check-version: check-git-version .PHONY: check-git-version check-git-version: $(PACKAGE_NAME)$(EXEEXT) | .version $(GREP) -Fx '$(VERSION)' $| ./$< --version | $(GREP) -Ff $| installcheck-local-version: ./$(TRANSFORMED_PACKAGE_NAME)$(EXEEXT) --version dist-hook: dist-tarball-version .PHONY: dist-tarball-version dist-tarball-version: printf "$(VERSION)" > "$(distdir)/.tarball-version" # vim: ft=automake vcsh-2.0.10/build-aux/que_shell_completion_dirs.am0000664000175000017500000000070214604750111021155 0ustar hibbyhibbyCOMPLETIONS_OUT_DIR = completions if ENABLE_BASH_COMPLETION bashcompletiondir = $(BASH_COMPLETION_DIR) nodist_bashcompletion_DATA = $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME) CLEANFILES += $(nodist_bashcompletion_DATA) endif if ENABLE_ZSH_COMPLETION zshcompletiondir = $(ZSH_COMPLETION_DIR) nodist_zshcompletion_DATA = $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME) CLEANFILES += $(nodist_zshcompletion_DATA) endif # vim: ft=automake vcsh-2.0.10/build-aux/que_developer_mode.m40000664000175000017500000000214314604750111017511 0ustar hibbyhibby# Like AM_MAINTAINER_MODE, but doesn't touch automake internals and so # can be used freely to control access to project specific developer # tooling without breaking autotools if disabled. AC_DEFUN([QUE_DEVELOPER_MODE], [ m4_case(m4_default([$1], [disable]), [enable], [m4_define([_que_developer_def], [disable])], [disable], [m4_define([_que_developer_def], [enable])], [m4_define([_que_developer_def], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_DEVELOPER_MODE: $1])]) AC_MSG_CHECKING([whether to enable developer-specific portions of Makefiles]) AC_ARG_ENABLE([developer-mode], [AS_HELP_STRING([--]_que_developer_def[-developer-mode], _que_developer_def[ dependencies and make targets only useful for developers])], [USE_DEVELOPER_MODE=$enableval], [USE_DEVELOPER_MODE=]m4_if(_que_developer_def, [enable], [no], [yes])) AC_MSG_RESULT([$USE_DEVELOPER_MODE]) AM_CONDITIONAL([DEVELOPER_MODE], [test $USE_DEVELOPER_MODE = yes]) ]) vcsh-2.0.10/build-aux/que_transform_package_name.m40000664000175000017500000000125614604750111021212 0ustar hibbyhibby# The autotools supplied AC_ARG_PROGRAM enables renaming operations, but it # supplies them as a sed operation that can be applied to multiple binaries. # This isn't convenient to use if we're just renaming the top level package, so # we go ahead and *do* the transformation and save for use as a substitution. AC_DEFUN_ONCE([QUE_TRANSFORM_PACKAGE_NAME], [ AC_PROG_SED TRANSFORMED_PACKAGE_NAME="$(printf "$PACKAGE_NAME" | $SED -e "$(printf "$program_transform_name" | $SED -e 's/\$\$/\$/')")" AC_SUBST([TRANSFORMED_PACKAGE_NAME]) PACKAGE_VAR="$(printf "$PACKAGE_NAME" | $SED -e "s/-/_/g")" AC_SUBST([PACKAGE_VAR]) AC_ARG_PROGRAM ]) vcsh-2.0.10/build-aux/ax_file_escapes.m40000664000175000017500000000137314604750111016764 0ustar hibbyhibby# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_file_escapes.html # =========================================================================== # # SYNOPSIS # # AX_FILE_ESCAPES # # DESCRIPTION # # Writes the specified data to the specified file. # # LICENSE # # Copyright (c) 2008 Tom Howard # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 AC_DEFUN([AX_FILE_ESCAPES],[ AX_DOLLAR="\$" AX_SRB="\\135" AX_SLB="\\133" AX_BS="\\\\" AX_DQ="\"" ]) vcsh-2.0.10/build-aux/que_dist_checksums.am0000664000175000017500000000150714604750111017610 0ustar hibbyhibby# Output both a file that can be attatched to releases and also write STDOUT # for the sake of CI build logs so they can be audited as matching what is # eventually posted. The list of files checksummed is a glob (even though we # know an exact pattern) to avoid errors for formats not generated. checksum_dist = \ shopt -s nullglob ; \ $(SHA256SUM) $(distdir)*.{tar.{gz,bz2,lz,xz,zst},zip} |\ $(TEE) $(distdir).sha256.txt # Since the checksums file isn't an artifact produced by the default source dist # creation process, we have to clean it up ourselves so distcheck can see that # everything round-tripped cleanly. distclean-local: rm -f $(distdir).sha256.txt # Append checksum operation to function that runs after compressing dist archives am__post_remove_distdir = $(am__remove_distdir); $(checksum_dist) # vim: ft=automake vcsh-2.0.10/build-aux/que_shell_completion_dirs.m40000664000175000017500000000325314604750111021104 0ustar hibbyhibbyAC_DEFUN_ONCE([QUE_SHELL_COMPLETION_DIRS], [ QUE_TRANSFORM_PACKAGE_NAME AC_PROG_SED AC_ARG_WITH([bash-completion-dir], AS_HELP_STRING([--with-bash-completion-dir[=PATH]], [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), [], [with_bash_completion_dir=yes]) AM_CONDITIONAL([ENABLE_BASH_COMPLETION], [test "x$with_bash_completion_dir" != "xno"]) AM_COND_IF([ENABLE_BASH_COMPLETION], [PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], [BASH_COMPLETION_DIR="$(pkg-config --define-variable=datadir=$datadir --variable=completionsdir bash-completion)"], [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"])], [BASH_COMPLETION_DIR="$with_bash_completion_dir"]) AC_SUBST([BASH_COMPLETION_DIR]) AC_ARG_WITH([zsh-completion-dir], AS_HELP_STRING([--with-zsh-completion-dir[=PATH]], [Install the zsh auto-completion script in this directory. @<:@default=yes@:>@]), [], [with_zsh_completion_dir=yes]) AM_CONDITIONAL([ENABLE_ZSH_COMPLETION], [test "x$with_zsh_completion_dir" != "xno"]) AM_COND_IF([ENABLE_ZSH_COMPLETION], [ZSH_COMPLETION_DIR="$datadir/zsh/site-functions"], [ZSH_COMPLETION_DIR="$with_zsh_completion_dir"]) AC_SUBST([ZSH_COMPLETION_DIR]) AC_REQUIRE([AX_AM_MACROS]) AX_ADD_AM_MACRO([dnl $(cat build-aux/que_shell_completion_dirs.am) ])dnl ]) vcsh-2.0.10/build-aux/ax_append_to_file.m40000664000175000017500000000140214604750111017303 0ustar hibbyhibby# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_append_to_file.html # =========================================================================== # # SYNOPSIS # # AX_APPEND_TO_FILE([FILE],[DATA]) # # DESCRIPTION # # Appends the specified data to the specified file. # # LICENSE # # Copyright (c) 2008 Tom Howard # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 9 AC_DEFUN([AX_APPEND_TO_FILE],[ AC_REQUIRE([AX_FILE_ESCAPES]) printf "%s" "$2" >> "$1" ]) vcsh-2.0.10/build-aux/que_git_version.m40000664000175000017500000000104714604750111017052 0ustar hibbyhibbyAC_DEFUN_ONCE([QUE_GIT_VERSION], [ AM_CONDITIONAL([SOURCE_IS_GIT], [test -d .git]) AM_CONDITIONAL([SOURCE_IS_DIST], [test -f .tarball-version]) AM_CONDITIONAL([SOURCE_IS_ARCHIVE], [test ! -d .git -a ! -f .tarball-version]) AC_PROG_AWK AC_PROG_GREP QUE_TRANSFORM_PACKAGE_NAME AM_COND_IF([SOURCE_IS_DIST], [], [QUE_PROGVAR([cmp])]) AC_REQUIRE([AX_AM_MACROS]) AX_ADD_AM_MACRO([dnl $(cat build-aux/que_git_version.am) ])dnl ]) vcsh-2.0.10/build-aux/git-version-gen0000775000175000017500000001710214604750111016350 0ustar hibbyhibby#!/usr/bin/env sh # Print a version string. scriptversion=2012-03-18.17; # UTC # Copyright (C) 2007-2012 Free Software Foundation, Inc. # # 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 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. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/. # It may be run two ways: # - from a git repository in which the "git describe" command below # produces useful output (thus requiring at least one signed tag) # - from a non-git-repo directory containing a .tarball-version file, which # presumes this script is invoked like "./git-version-gen .tarball-version". # In order to use intra-version strings in your project, you will need two # separate generated version string files: # # .tarball-version - present only in a distribution tarball, and not in # a checked-out repository. Created with contents that were learned at # the last time autoconf was run, and used by git-version-gen. Must not # be present in either $(srcdir) or $(builddir) for git-version-gen to # give accurate answers during normal development with a checked out tree, # but must be present in a tarball when there is no version control system. # Therefore, it cannot be used in any dependencies. GNUmakefile has # hooks to force a reconfigure at distribution time to get the value # correct, without penalizing normal development with extra reconfigures. # # .version - present in a checked-out repository and in a distribution # tarball. Usable in dependencies, particularly for files that don't # want to depend on config.h but do want to track version changes. # Delete this file prior to any autoconf run where you want to rebuild # files to pick up a version string change; and leave it stale to # minimize rebuild time after unrelated changes to configure sources. # # As with any generated file in a VC'd directory, you should add # /.version to .gitignore, so that you don't accidentally commit it. # .tarball-version is never generated in a VC'd directory, so needn't # be listed there. # # Use the following line in your configure.ac, so that $(VERSION) will # automatically be up-to-date each time configure is run (and note that # since configure.ac no longer includes a version string, Makefile rules # should not depend on configure.ac for version updates). # # AC_INIT([GNU project], # m4_esyscmd([build-aux/git-version-gen .tarball-version]), # [bug-project@example]) # # Then use the following lines in your Makefile.am, so that .version # will be present for dependencies, and so that .version and # .tarball-version will exist in distribution tarballs. # # EXTRA_DIST = $(top_srcdir)/.version # BUILT_SOURCES = $(top_srcdir)/.version # $(top_srcdir)/.version: # echo $(VERSION) > $@-t && mv $@-t $@ # dist-hook: # echo $(VERSION) > $(distdir)/.tarball-version me=$0 version="git-version-gen $scriptversion Copyright 2011 Free Software Foundation, Inc. There is NO warranty. You may redistribute this software under the terms of the GNU General Public License. For more information about these matters, see the files named COPYING." usage="\ Usage: $me [OPTION]... \$srcdir/.tarball-version [TAG-NORMALIZATION-SED-SCRIPT] Print a version string. Options: --prefix prefix of git tags (default 'v') --help display this help and exit --version output version information and exit Running without arguments will suffice in most cases." prefix=v while test $# -gt 0; do case $1 in --help) echo "$usage"; exit 0;; --version) echo "$version"; exit 0;; --prefix) shift; prefix="$1";; -*) echo "$0: Unknown option '$1'." >&2 echo "$0: Try '--help' for more information." >&2 exit 1;; *) if test -z "$tarball_version_file"; then tarball_version_file="$1" elif test -z "$tag_sed_script"; then tag_sed_script="$1" else echo "$0: extra non-option argument '$1'." >&2 exit 1 fi;; esac shift done if test -z "$tarball_version_file"; then echo "$usage" exit 1 fi tag_sed_script="${tag_sed_script:-s/x/x/}" nl=' ' # Avoid meddling by environment variable of the same name. v= v_from_git= # First see if there is a tarball-only version file. # then try "git describe", then default. if test -f $tarball_version_file then v=`cat $tarball_version_file` || v= case $v in *$nl*) v= ;; # reject multi-line output [0-9]*) ;; *) v= ;; esac test -z "$v" \ && echo "$0: WARNING: $tarball_version_file is missing or damaged" 1>&2 fi if test -n "$v" then : # use $v # Otherwise, if there is at least one git commit involving the working # directory, and "git describe" output looks sensible, use that to # derive a version string. elif test "`git log -1 --pretty=format:x . 2>/dev/null`" = x \ && v=`git describe --tags --abbrev=7 --match="$prefix*\.*\.*" HEAD 2>/dev/null \ || git describe --tags --abbrev=7 HEAD 2>/dev/null \ || git log -1 --pretty=format:'v0-HEAD-%h' 2>/dev/null` \ && v=`printf '%s\n' "$v" | sed "$tag_sed_script"` \ && case $v in $prefix[0-9]*) ;; *) (exit 1) ;; esac then # Is this a new git that lists number of commits since the last # tag or the previous older version that did not? # Newer: v6.10-77-g0f8faeb # Older: v6.10-g0f8faeb case $v in *-*-g*) : git describe is okay three part flavor ;; *-g*) : git describe is older two part flavor # Recreate the number of commits and rewrite such that the # result is the same as if we were using the newer version # of git describe. vtag=`echo "$v" | sed 's/-.*//'` commit_list=`git rev-list "$vtag"..HEAD 2>/dev/null` \ || { commit_list=failed; echo "$0: WARNING: git rev-list failed" 1>&2; } numcommits=`echo "$commit_list" | wc -l` v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`; test "$commit_list" = failed && v=UNKNOWN ;; esac v=`echo "$v" | sed 's/-\([0-9]\)/.r\1/'`; v_from_git=1 else v=UNKNOWN fi v=`echo "$v" |sed "s/^$prefix//"` # Test whether to append the "-dirty" suffix only if the version # string we're using came from git. I.e., skip the test if it's "UNKNOWN" # or if it came from .tarball-version. if test -n "$v_from_git"; then # Don't declare a version "dirty" merely because a time stamp has changed. git update-index --refresh > /dev/null 2>&1 dirty=`exec 2>/dev/null;git diff-index --name-only HEAD` || dirty= case "$dirty" in '') ;; *) # Append the suffix only if there isn't one already. case $v in *-dirty) ;; *) v="$v-dirty" ;; esac ;; esac fi # Omit the trailing newline, so that m4_esyscmd can use the result directly. echo "$v" | tr -d "$nl" # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: vcsh-2.0.10/build-aux/ax_prog_perl_modules.m40000664000175000017500000000466314604750111020070 0ustar hibbyhibby# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_prog_perl_modules.html # =========================================================================== # # SYNOPSIS # # AX_PROG_PERL_MODULES([MODULES], [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # # DESCRIPTION # # Checks to see if the given perl modules are available. If true the shell # commands in ACTION-IF-TRUE are executed. If not the shell commands in # ACTION-IF-FALSE are run. Note if $PERL is not set (for example by # calling AC_CHECK_PROG, or AC_PATH_PROG), AC_CHECK_PROG(PERL, perl, perl) # will be run. # # MODULES is a space separated list of module names. To check for a # minimum version of a module, append the version number to the module # name, separated by an equals sign. # # Example: # # AX_PROG_PERL_MODULES( Text::Wrap Net::LDAP=1.0.3, , # AC_MSG_WARN(Need some Perl modules) # # LICENSE # # Copyright (c) 2009 Dean Povey # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 AU_ALIAS([AC_PROG_PERL_MODULES], [AX_PROG_PERL_MODULES]) AC_DEFUN([AX_PROG_PERL_MODULES],[dnl m4_define([ax_perl_modules]) m4_foreach([ax_perl_module], m4_split(m4_normalize([$1])), [ m4_append([ax_perl_modules], [']m4_bpatsubst(ax_perl_module,=,[ ])[' ]) ]) # Make sure we have perl if test -z "$PERL"; then AC_CHECK_PROG(PERL,perl,perl) fi if test "x$PERL" != x; then ax_perl_modules_failed=0 for ax_perl_module in ax_perl_modules; do AC_MSG_CHECKING(for perl module $ax_perl_module) # Would be nice to log result here, but can't rely on autoconf internals $PERL -e "use $ax_perl_module; exit" > /dev/null 2>&1 if test $? -ne 0; then AC_MSG_RESULT(no); ax_perl_modules_failed=1 else AC_MSG_RESULT(ok); fi done # Run optional shell commands if test "$ax_perl_modules_failed" = 0; then : $2 else : $3 fi else AC_MSG_WARN(could not find perl) fi])dnl vcsh-2.0.10/build-aux/que_progvar.m40000664000175000017500000000031214604750111016174 0ustar hibbyhibbyAC_DEFUN([QUE_PROGVAR], [ test -n "$m4_toupper($1)" || { AC_PATH_PROG(m4_toupper($1), m4_default($2,$1)) } test -n "$m4_toupper($1)" || AC_MSG_ERROR([m4_default($2,$1) is required]) ]) vcsh-2.0.10/build-aux/que_dist_checksums.m40000664000175000017500000000052414604750111017531 0ustar hibbyhibbyAC_DEFUN_ONCE([QUE_DIST_CHECKSUMS], [ AM_COND_IF([DEVELOPER_MODE], [ QUE_PROGVAR([sha256sum]) QUE_PROGVAR([tee]) QUE_TRANSFORM_PACKAGE_NAME AC_REQUIRE([AX_AM_MACROS]) AX_ADD_AM_MACRO([dnl $(cat build-aux/que_dist_checksums.am) ])dnl ]) ]) vcsh-2.0.10/build-aux/ax_am_macros.m40000664000175000017500000000224214604750111016277 0ustar hibbyhibby# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_am_macros.html # =========================================================================== # # SYNOPSIS # # AX_AM_MACROS # # DESCRIPTION # # Adds support for macros that create Make rules. You must manually add # the following line # # @INC_AMINCLUDE@ # # to your Makefile.in (or Makefile.am if you use Automake) files. # # LICENSE # # Copyright (c) 2009 Tom Howard # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 11 AC_DEFUN([AX_AM_MACROS], [ AC_MSG_NOTICE([adding automake macro support]) AMINCLUDE="aminclude.am" AC_SUBST(AMINCLUDE) AC_MSG_NOTICE([creating $AMINCLUDE]) AMINCLUDE_TIME=`LC_ALL=C date` AX_PRINT_TO_FILE([$AMINCLUDE],[[ # generated automatically by configure from AX_AUTOMAKE_MACROS # on $AMINCLUDE_TIME ]]) INC_AMINCLUDE="include \$(top_builddir)/$AMINCLUDE" AC_SUBST(INC_AMINCLUDE) ]) vcsh-2.0.10/build-aux/ax_print_to_file.m40000664000175000017500000000137114604750111017175 0ustar hibbyhibby# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_print_to_file.html # =========================================================================== # # SYNOPSIS # # AX_PRINT_TO_FILE([FILE],[DATA]) # # DESCRIPTION # # Writes the specified data to the specified file. # # LICENSE # # Copyright (c) 2008 Tom Howard # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 AC_DEFUN([AX_PRINT_TO_FILE],[ AC_REQUIRE([AX_FILE_ESCAPES]) printf "$2" > "$1" ]) vcsh-2.0.10/build-aux/ax_add_am_macro.m40000664000175000017500000000160214604750111016723 0ustar hibbyhibby# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_add_am_macro.html # =========================================================================== # # SYNOPSIS # # AX_ADD_AM_MACRO([RULE]) # # DESCRIPTION # # Adds the specified rule to $AMINCLUDE. This macro will only work # properly with implementations of Make which allow include statements. # See also AX_ADD_AM_MACRO_STATIC. # # LICENSE # # Copyright (c) 2009 Tom Howard # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 10 AC_DEFUN([AX_ADD_AM_MACRO],[ AC_REQUIRE([AX_AM_MACROS]) AX_APPEND_TO_FILE([$AMINCLUDE],[$1]) ]) vcsh-2.0.10/bootstrap.sh0000775000175000017500000000242114604750111014065 0ustar hibbyhibby#!/usr/bin/env sh set -e incomplete_source () { printf '%s\n' \ "$1. Please either:" \ "* $2," \ "* or use the source packages instead of a repo archive" \ "* or use a full Git clone." >&2 exit 1 } # This enables easy building from Github's snapshot archives if [ ! -e ".git" ]; then if [ ! -f ".tarball-version" ]; then incomplete_source "No version information found" \ "identify the correct version with \`echo \$version > .tarball-version\`" fi else # Just a head start to save a ./configure cycle ./build-aux/git-version-gen .tarball-version > .version fi # Autoreconf uses a perl script to inline includes from Makefile.am into # Makefile.in before ./configure is ever run even once ... which typically means # AX_AUTOMAKE_MACROS forfeit access to substitutions or conditional logic # because they enter the picture after those steps. We're intentially using the # expanded value of @INC_AMINCLUDE@ directly so the include will be inlined. To # bootstrap we must pre-seed an empty file to avoid a 'file not found' error on # first run. Subsequently running ./configure will generate the correct content # based on the configuration flags and also get re-inline into Makefile.in. touch aminclude.am autoreconf --install vcsh-2.0.10/LICENSE.md0000664000175000017500000004302514604750111013122 0ustar hibbyhibbyGNU General Public License ========================== _Version 2, June 1991_ _Copyright © 1989, 1991 Free Software Foundation, Inc.,_ _51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. ### Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: **(1)** copyright the software, and **(2)** offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. ### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION **0.** This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The “Program”, below, refers to any such program or work, and a “work based on the Program” means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term “modification”.) Each licensee is addressed as “you”. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. **1.** You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. **2.** You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: * **a)** You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. * **b)** You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. * **c)** If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. **3.** You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: * **a)** Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, * **b)** Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, * **c)** Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. **4.** You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. **5.** You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. **6.** Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. **7.** If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. **8.** If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. **9.** The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and “any later version”, you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. **10.** If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. ### NO WARRANTY **11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. **12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ### How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. Copyright (C) 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; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w` and `show c` should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w` and `show c`; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a “copyright disclaimer” for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. vcsh-2.0.10/Makefile.am0000664000175000017500000000542514604750111013554 0ustar hibbyhibbyACLOCAL_AMFLAGS = -I build-aux AM_DISTCHECK_CONFIGURE_FLAGS = --enable-developer-mode .ONESHELL: .SECONDARY: .SECONDEXPANSION: .DELETE_ON_ERROR: docdir = $(datarootdir)/doc/$(TRANSFORMED_PACKAGE_NAME) licensedir = $(datarootdir)/licenses/$(TRANSFORMED_PACKAGE_NAME) bin_SCRIPTS = vcsh dist_doc_DATA = changelog doc/INSTALL.md doc/README.md doc/error_codes.md samplehooksdir = $(docdir)/sample_hooks dist_samplehooks_DATA = doc/sample_hooks/post-init-add-origin doc/sample_hooks/post-init-setup-mr doc/sample_hooks/post-merge-unclobber doc/sample_hooks/pre-merge-unclobber dist_license_DATA = LICENSE.md CONTRIBUTORS if ENABLE_MAN_PAGE dist_man_MANS = doc/vcsh.1 endif EXTRA_DIST = completions/vcsh.bash completions/vcsh.zsh build-aux/ax_prog_perl_modules.m4 EXTRA_DIST += t/000-tear-env.t t/001-setup-env.t t/100-init.t t/300-add.t t/950-delete.t t/999-tear-env.t BUILT_SOURCES = CLEANFILES = $(dist_man_MANS) $(bin_SCRIPTS) # A classical use of the autoconf-archive include macro would expand # INC_AMINCLUDE here, but the perl script that inlines include statements # runs before the automake that organizes logic and performs substitution. # Consequentially with a substitution here it becomes impossible to use # automake conditionals and substitutions in the included Makefile fragments. # By entering the expanded value directly we are ready in time for the inlining # functionality and hence can use conditionals in included makefile fragments. include $(top_srcdir)/aminclude.am DISTCLEANFILES = @AMINCLUDE@ if !SOURCE_IS_DIST doc/vcsh.1: doc/vcsh.1.ronn $(RONN) < $< > $@ endif $(COMPLETIONS_OUT_DIR)/$(TRANSFORMED_PACKAGE_NAME): completions/vcsh.bash mkdir -p $(dir $@) install $< $@ $(COMPLETIONS_OUT_DIR)/_$(TRANSFORMED_PACKAGE_NAME): completions/vcsh.zsh mkdir -p $(dir $@) install $< $@ if ENABLE_TESTS _CHECKDEPS = $(PROVE) endif check-local: $(_CHECKDEPS) check-version: check-dep-versions .PHONY: check-dep-versions check-dep-version: $(PACKAGE_NAME) | .version ./$< version | $(GREP) -Ff <($(GIT) version) .PHONY: prove prove: prove .PHONY: test test: prove PHONY_DEVELOPER_TARGETS = lint lint-editor-config lint-shellheck .PHONY: $(PHONY_DEVELOPER_TARGETS) if DEVELOPER_MODE lint: lint-editor-config lint-shellcheck lint-editor-config: ec lint-shellcheck: $(PACKAGE_NAME) shellcheck $< else !DEVELOPER_MODE $(PHONY_DEVELOPER_TARGETS): @: $(error "Please reconfigure using --enable-developer-mode to use developer tooling") endif !DEVELOPER_MODE if SOURCE_IS_GIT CONTRIBUTORS: exec > $@ echo 'Alphabetical list of names of everyone who ever committed to this repository.' echo 'Auto-generated using `make -B CONTRIBUTORS`' echo $(GIT) shortlog -se --all | cut -f1 --complement | sort -u changelog-HEAD: changelog sed -nEe '2d;s/^\t//p;/^$$/q;' $< > $@ endif SOURCE_IS_GIT vcsh-2.0.10/.mailmap0000664000175000017500000000057414604750111013141 0ustar hibbyhibbyRichard Hartmann Richard Hartmann Richard Hartmann Richard Hartmann Kevin Lyda Alexander Skurikhin vcsh-2.0.10/changelog0000664000175000017500000002350514604750111013371 0ustar hibbyhibby2024-04-08 Caleb Maclennan * Release 2.0.10 * Fix release workflow so it builds the man page 2024-04-08 Caleb Maclennan * Release 2.0.9 * Add missing 'commit' sub-command in bash completions * Switch from xz to zst compression for official artifacts * Generate checksums for release artifacts in CI * Use more idiomatic GNU/Autotools patterns 2024-02-27 Caleb Maclennan * Release 2.0.8 * Fix man page source syntax to work with current ronn 2023-12-30 Caleb Maclennan * Release 2.0.7 * Fix build and deploy of standalone/portable script variant 2023-12-29 Caleb Maclennan * Release 2.0.6 * Revert .gitignore.d handling to match revert in Git 2.17→2.18 * Cleanup some configure and build odds and ends * Fix some CI linting and publishing glitches 2022-11-08 Caleb Maclennan * Release 2.0.5 * Replace bashism with POSIX compliant syntax in configure script 2021-10-27 Richard Hartmann * Release 2.0.4 * Fix build failure on non-GNU systems, #321 2021-10-23 Caleb Maclennan * Release 2.0.3 * Fix list-untracked subcommand option parsing * Refactor ‘mkdir && install’ to ‘install -D’ 2021-09-04 Caleb Maclennan * Release 2.0.2 * Fix Makefile portability by swapping cp for install 2021-08-28 Caleb Maclennan * Release 2.0.1 * Stop requiring `ronn` when building from source tarball 2021-08-20 Caleb Maclennan * Release 2.0.0 * Replace homegrown Makefile with Autotools for configure and build * Post source builds as part of automated release process * Switch to versioning scheme to semver * Replace Travis test runner with GitHub Actions * Make VCSH_* variables available to hooks * More carefully handle shell quoting * Improve handling of non-default remote names and branches * Fix per-repo pre/post hook handling * Output path relative to $HOME in ‘vcsh status’ * Add flag to prefix output of ‘vcsh foreach -p’ with repo name * Fix debugging on Windows 10 / Cygwin * Improve option flag handling to allow multiple flags, squash bugs * Don't require Ruby or Perl tooling to build and install * Avoid false-positive conflicts on checkout * Make arg optional for write-ignore subcommand * Fix ZSH completions, improve Bash completions * Allow use of specific path when running Git or any dependency * Fail if hook scripts return failure codes * Check GIT_REMOTE early on clone() * Support renaming script as configuration option * Setup standalone script build profile and attach directly to releases 2021-04-05 Richard Hartmann * Release 1.20190621 * Make version reflected in `vcsh version` correct... 2021-03-29 Richard Hartmann * Release 1.20190620 * This is a safe harbour release. * `release` branch should ensure downstream picks it up 2021-03-29 Richard Hartmann * Release 1.20190619 * Various bugfixes * This is a safe harbour release. * @alerque is now a co-maintainer 2015-12-29 Richard Hartmann * Fix tests to always use C locale, this makes vcsh reproducible * Implement `vcsh foreach` * Implement `vcsh list-untracked -a` * Handle Git older than 2.x gracefully * Fix broken list-tracked-by * Fix regression in `vcsh which` * Skip ignored files in the output of list-untracked * Improve cloning * Clean up docs * Implement `vcsh status --terse` * Improve tests 2015-05-02 Richard Hartmann * Release 1.20150502 * Add tests * Integrate tests with Travis CI * Make `vcsh --list_untracked` GNU-independent * Improve vcsh's code quality * Improve Makefile, documentation, etc 2014-10-26 Richard Hartmann * Release 1.20141026 * FIX fatal() * Improve error handling of clone() 2014-10-25 Richard Hartmann * Release 1.20141025 * `vcsh which dontexist` exits 1 * `vcsh status` shows commits ahead/behind remote tracking branch * Support overlay functions * Support `vcsh list-untracked`, optionally recursively * Support `vcsh list-untracked $repo` * Improve error handling of clone() * Rename `list-tracked-by` to `list-tracked ` * Support repo-specific config files * Various minor improvements * More moo 2014-10-09 Richard Hartmann * Display full paths in list-tracked* * Lots of help improvements 2014-05-08 Richard Hartmann * Revert "Introduce static manpage as part of normal repo" 2014-05-07 Richard Hartmann * Increase portability * Improve hooks * Improve docs * Various minor improvements 2014-03-13 Richard Hartmann * Release 1.20140313 -- the "Git won a prize" edition * Initialize repos with --shared=0600 * Fix cloning from some spefically-named remotes * Support custom gitattribute files * Support filenames with whitespace in gitignores * Pass out git exit codes * Switch to static, pre-built manpage * Improve documentation * Use more portable find(1) syntax * Various minor improvements 2013-12-29 Richard Hartmann * Release 1.20131229 * Fix mktemp bug (GitHub issue #99) * Make code more resilient and efficient * Improve output 2013-12-14 Richard Hartmann * Release 1.20131214 * Revert "Implement basename() in shell" * Fix mktemp on OS X * Fix variable assignment bug * Support shortnames for commands * Improve Makefile * Improve documentation * Various minor improvements 2013-09-09 Richard Hartmann * Release 1.20130909 * Add support for relative worktrees 2013-08-29 Richard Hartmann * Release 1.20130829 * Add support for `vcsh commit` * Add support for `vcsh status ` * Add pre-/post-init hooks * Documentation improvements * Minor cleanups 2013-07-24 Richard Hartmann * Release 1.20130724 * Add support for `vcsh status` * Improve output of `vcsh pull` * Improve output of `vcsh push` * Minor documentation improvements 2013-07-23 Richard Hartmann * Release 1.20130723 * Support $VCSH_GITIGNORE == none * Documentation improvements, * Improved zsh completion * Add support for `vcsh pull` * Add support for `vcsh push` * Add retire() to tear down vcsh ENV * Add clone hooks, including one witout vcsh ENV to allow subsequent cloning of other repos * Fix `vcsh rename` * Improve general code robustness 2013-06-14 Richard Hartmann * Release 1.20130614 * Lots of documentation improvements, major rewrite 2013-05-27 Richard Hartmann * Release 1.3 * Hide hook execution unless verbose is set * Ancher ignore file to root of Git repo * Implemented basename() to save one process spawn * Improve packaged Zsh completion * Renamed `vcsh setup` to `vcsh upgrade` * Various documentation and spelling improvements 2013-04-21 Richard Hartmann * Release 1.2 * Introduce `vcsh version` 2013-03-31 Richard Hartmann * Release 1.1 * Documentation fixes * Use rm -f when removing a git repo * Fix quoting bug (Debian #699093) 2013-02-13 Richard Hartmann * Release 1.0.1 * Improve documentation * Fix parameter bug 2012-06-30 Richard Hartmann * Release 1.0 * Make `vcsh list` more resilient * Lots of doc improvements 2012-02-27 Richard Hartmann * Refactor Makefile * Fix license information in manpage 2012-02-15 Richard Hartmann * Introduce `vcsh which` * hooks will tell you when they are being executed * Formatting & resilience improvements * We have a changelog, now! (yay) 2012-02-03 Richard Hartmann * Improve documentation * More resilient error handling * Add AUTHORS 2012-01-16 Richard Hartmann * Introduce hook support 2011-12-27 Richard Hartmann * Improve documentation 2011-12-26 Richard Hartmann * Introduce and use .config/vcsh/config * More verbose error handling * Introduce `vcsh {list-tracked,list-tracked-by}` * Introduce repo shortcuts (`vcsh zsh commit`) * Rename `vcsh seed-gitignore` to `vcsh write-gitignore` * Add license information 2011-11-29 Richard Hartmann * Bugfixes * Refactor error handling * Make code more resilient * Make vcsh play nice with mr * Introduce vcsh mv and setup 2011-11-23 Richard Hartmann * Bugfixes * Minor refactoring of code 2011-11-22 Richard Hartmann * Bugfixes 2011-11-20 Richard Hartmann * Major refactoring of code * Rewrite help files * Bugfixes 2011-11-19 Richard Hartmann * Bugfixes * Improve XDG compatibility 2011-11-18 Richard Hartmann * Yet more documentation improvements * Makefile * Heed already-defined ENV variables within vcsh * Handle .gitignore.d/$repo automagically 2011-11-11 Richard Hartmann * Major rewrite of all help files * Addition of manpage 2011-10-27 Richard Hartmann * Bugfixes * Make help more verbose * Improve INSTALL 2011-10-18 Richard Hartmann * Fixed bug in vcsh clone & init 2011-10-17 Richard Hartmann * Initial release vcsh-2.0.10/README.md0000664000175000017500000000630614604750111012776 0ustar hibbyhibbyvcsh - Version Control System for $HOME - multiple Git repositories in $HOME [![Test Status](https://github.com/RichiH/vcsh/actions/workflows/test.yml/badge.svg)](https://github.com/RichiH/vcsh/actions/workflows/test.yml) # Index 1. [30 Second How-to](#30-second-how-to) 2. [Introduction](#introduction) 3. [Installation](#installation) 4. [Detailed documentation](#detailed-documentation) 5. [Contact](#contact) # 30 Second How-to While it may appear that there's an overwhelming amount of documentation and while the explanation of the concepts behind `vcsh` needs to touch a few gory details of `git` internals, getting started with `vcsh` is extremely simple. Let's say you want to version control your `vim` configuration: vcsh init vim vcsh vim add ~/.vimrc ~/.vim vcsh vim commit -m 'Initial commit of my Vim configuration' # optionally push your files to a remote vcsh vim remote add origin vcsh vim push -u origin master # from now on you can push additional commits like this vcsh vim push If all that looks a _lot_ like standard `git`, that's no coincidence; it's a design feature. # Introduction [vcsh][vcsh] allows you to maintain several Git repositories in one single directory. They all maintain their working trees without clobbering each other or interfering otherwise. By default, all Git repositories maintained via `vcsh` store the actual files in `$HOME` but you can override this setting if you want to. All this means that you can have one repository per application or application family, i.e. `zsh`, `vim`, `ssh`, etc. This, in turn, allows you to clone custom sets of configurations onto different machines or even for different users; picking and mixing which configurations you want to use where. For example, you may not need to have your `mplayer` configuration on a server or available to root and you may want to maintain different configuration for `ssh` on your personal and your work machines. ## Talks Some people found it useful to look at [slides](https://github.com/RichiH/talks/blob/main/2013/10-linuxcon-eu/linuxcon_eu-2013-10-gitify_your_life.pdf) and videos explaining how `vcsh` works instead of working through the docs. All slides, videos, and further information can be found [on the author's talk page][talks]. # Installation A lot of modern UNIX-based systems offer packages for `vcsh`. In case yours does not, read [INSTALL.md](doc/INSTALL.md) for instructions on installing from sources or even create a package for your system. If you do end up packaging `vcsh` please let us know so we can document package availability. # Detailed documentation For more information, consult the [detailed documentation](doc/README.md). # Contact There are several ways to get in touch with the author and a small but committed community around the general idea of version controlling your (digital) life. * IRC: #vcs-home on irc.oftc.net * Mailing list: [http://lists.madduck.net/listinfo/vcs-home][vcs-home-list] * Pull requests or issues on [https://github.com/RichiH/vcsh][vcsh] [myrepos]: http://myrepos.branchable.com/ [talks]: https://github.com/RichiH/talks [vcsh]: https://github.com/RichiH/vcsh [vcs-home-list]: http://lists.madduck.net/listinfo/vcs-home vcsh-2.0.10/doc/0000775000175000017500000000000014604750111012257 5ustar hibbyhibbyvcsh-2.0.10/doc/sample_hooks/0000775000175000017500000000000014604750111014743 5ustar hibbyhibbyvcsh-2.0.10/doc/sample_hooks/pre-merge-unclobber0000775000175000017500000000072514604750111020531 0ustar hibbyhibby#!/bin/sh # This code does amost exactly what the native vcsh sanity checking code # does except that on finding a potential merge conflict, it moves existing # files out of the way temporarily. Merging (part of `vcsh clone`) happens # cleanly, and a post-merge hook can be used to figure out what to do with # the now-renamed files. for object in $(git ls-tree -r origin/master | awk '{print $4}'); do [ -e "$object" ] && mv "$object" "$object.vcsh-unclobber" done vcsh-2.0.10/doc/sample_hooks/post-init-add-origin0000775000175000017500000000111614604750111020631 0ustar hibbyhibby#!/bin/sh # This adds a remote origin at $GITURL/dotfiles/$VCSH_DIRECTORY which # is helpful for creating new dotfile repositories that you plan to # store on (e.g.) Github. # # You must set $GITURL in order to use this hook. For example, add the # following to your .bashrc (or equivalent for your shell), replacing # YOURUSERNAME with your github username: # # export GITURL="git@github.com:YOURUSERNAME" if [ -z $GITURL ]; then echo "\$GITURL is not set; please see post-init-add-origin hook" exit 1; fi vcsh $VCSH_DIRECTORY remote add origin $GITURL/dotfiles/$VCSH_DIRECTORY vcsh-2.0.10/doc/sample_hooks/post-merge-unclobber0000775000175000017500000000076414604750111020733 0ustar hibbyhibby#!/bin/sh # This finds objects that the pre-merge script moved out of the way to # avoid conflicts when running `vcsh clone` and moves them back to their # original places. The result is that the Git repository gets checked out # without error and the pre-existing files end up back in the working # directory. Git and thus vcsh now see these as un-staged changes to the # working branch and you can deal with them as usual. find . -name '*.vcsh-unclobber' -execdir rename .vcsh-unclobber '' {} \; vcsh-2.0.10/doc/sample_hooks/post-init-setup-mr0000775000175000017500000000046614604750111020377 0ustar hibbyhibby#!/bin/sh # This sets up your new repos with mr. cat > $HOME/.config/mr/available.d/$VCSH_DIRECTORY.vcsh << EOF [\$HOME/.config/vcsh/repo.d/$VCSH_DIRECTORY.git] checkout = vcsh clone $GITURL/dotfiles/$VCSH_DIRECTORY.git EOF ln -s $HOME/.config/mr/available.d/$VCSH_DIRECTORY.vcsh $HOME/.config/mr/config.d/ vcsh-2.0.10/doc/error_codes.md0000664000175000017500000000104614604750111015110 0ustar hibbyhibby* 0: OK * 1: Generic error * 10: Init failed because $GIT\_DIR exists * 11: Could not enter $GIT\_WORK\_TREE * 12: No repository found * 13: Required directory exists but is not a directory * 16: Potentially harmful operation aborted * 17: Files that would be overwritten exist; fix manually * 50: Could not create directory * 51: Could not create file * 52: Could not move directory * 53: Could not move file * 54: Directory exists * 55: File exists * 56: * 57: Could not write to file * 57: Could not delete directory * 59: Could not delete file vcsh-2.0.10/doc/README.md0000664000175000017500000004172514604750111013547 0ustar hibbyhibbyvcsh - Version Control System for $HOME - multiple Git repositories in $HOME # Index 1. [30 Second How-to](#30-second-how-to) 2. [Introduction](#introduction) 3. [Usage Examples](#usage-examples) 4. [Overview](#overview) 5. [Getting Started](#getting-started) 6. [Contact](#contact) # 30 Second How-to While it may appear that there's an overwhelming amount of documentation and while the explanation of the concepts behind `vcsh` needs to touch a few gory details of `git` internals, getting started with `vcsh` is extremely simple. Let's say you want to version control your `vim` configuration: vcsh init vim vcsh vim add ~/.vimrc ~/.vim vcsh vim commit -m 'Initial commit of my Vim configuration' # optionally push your files to a remote vcsh vim remote add origin vcsh vim push -u origin master # from now on you can push additional commits like this vcsh vim push If all that looks a _lot_ like standard `git`, that's no coincidence; it's a design feature. # Introduction [vcsh][vcsh] allows you to maintain several Git repositories in one single directory. They all maintain their working trees without clobbering each other or interfering otherwise. By default, all Git repositories maintained via `vcsh` store the actual files in `$HOME` but you can override this setting if you want to. All this means that you can have one repository per application or application family, i.e. `zsh`, `vim`, `ssh`, etc. This, in turn, allows you to clone custom sets of configurations onto different machines or even for different users; picking and mixing which configurations you want to use where. For example, you may not need to have your `mplayer` configuration on a server or available to root and you may want to maintain different configuration for `ssh` on your personal and your work machines. A lot of modern UNIX-based systems offer packages for `vcsh`. In case yours does not read `INSTALL.md` for install instructions or `PACKAGING.md` to create a package, yourself. If you do end up packaging `vcsh` please let us know so we can give you your own packaging branch in the upstream repository. ## Talks Some people found it useful to look at slides and videos explaining how `vcsh` works instead of working through the docs. All slides, videos, and further information can be found [on the author's talk page][talks]. # Usage Examples There are three different ways to interact with `vcsh` repositories; this section will only show the simplest and easiest way. Certain more advanced use cases require the other two ways, but don't worry about this for now. If you never even bother playing with the other two modes you will still be fine. `vcsh enter` and `vcsh run` will be covered in later sections. | Task | Command | | ----------------------------------------------------- | ------------------------------------------------- | | _Initialize a new repository called "vim"_ | `vcsh init vim` | | _Clone an existing repository_ | `vcsh clone ` | | _Add files to repository "vim"_ | `vcsh vim add ~/.vimrc ~/.vim` | | | `vcsh vim commit -m 'Update Vim configuration'` | | _Add a remote for repository "vim"_ | `vcsh vim remote add origin ` | | | `vcsh vim push origin master:master` | | | `vcsh vim branch --track master origin/master` | | _Push to remote of repository "vim"_ | `vcsh vim push` | | _Pull from remote of repository "vim"_ | `vcsh vim pull` | | _Show status of changed files in all repositories_ | `vcsh status` | | _Pull from all repositories_ | `vcsh pull` | | _Push to all repositories_ | `vcsh push` | # Overview ## From zero to vcsh You put a lot of effort into your configuration and want to both protect and distribute this configuration. Most people who decide to put their dotfiles under version control start with a single repository in `$HOME`, adding all their dotfiles (and possibly more) to it. This works, of course, but can become a nuisance as soon as you try to manage more than one host. The next logical step is to create single-purpose repositories in, for example, `~/.dotfiles` and to create symbolic links into `$HOME`. This gives you the flexibility to check out only certain repositories on different hosts. The downsides of this approach are the necessary manual steps of cloning and symlinking the individual repositories. `vcsh` takes this approach one step further. It enables single-purpose repositories and stores them in a hidden directory. However, it does not create symbolic links in `$HOME`; it puts the actual files right into `$HOME`. As `vcsh` allows you to put an arbitrary number of distinct repositories into your `$HOME`, you will end up with a lot of repositories very quickly. `vcsh` was designed with [myrepos][myrepos], a tool to manage Multiple Repositories, in mind and the two integrate very nicely. The myrepos tool (`mr`) has native support for `vcsh` repositories and the configuration for myrepos is just another set of files that you can track with `vcsh` like any other. This makes setting up any new machine a breeze. It can take literally less than five minutes to go from standard installation to fully set up system. We suggest using [myrepos][myrepos] to manage both `vcsh` and other repositories. The `mr` utility takes care of pulling in and pushing out new data for a variety of version control systems. While the use of myrepos is technically optional, it will be an integral part of the proposed system that follows. For instance, you can use [myrepos][myrepos] to track repositories in home such as `.emacs.d`, which `mr` can clone and update for you automatically. To do this, just add a `mr` configuration file to `available.d` with a `checkout` command to clone the repo, and set the [title] to the desired location, e.g. `$HOME/.emacs.d`. Try the `mr register` command in an existing repository, then view `~/.mrconfig` for an example. ## Default Directory Layout To illustrate, this is what a possible directory structure looks like. $HOME |-- $XDG_CONFIG_HOME (defaults to $HOME/.config) | |-- mr | | |-- available.d | | | |-- zsh.vcsh | | | |-- gitconfigs.vcsh | | | |-- lftp.vcsh | | | |-- offlineimap.vcsh | | | |-- s3cmd.vcsh | | | |-- tmux.vcsh | | | |-- vim.vcsh | | | |-- vimperator.vcsh | | | `-- snippets.git | | `-- config.d | | |-- zsh.vcsh -> ../available.d/zsh.vcsh | | |-- gitconfigs.vcsh -> ../available.d/gitconfigs.vcsh | | |-- tmux.vcsh -> ../available.d/tmux.vcsh | | `-- vim.vcsh -> ../available.d/vim.vcsh | `-- vcsh | |-- config | `-- repo.d | |-- zsh.git -----------+ | |-- gitconfigs.git | | |-- tmux.git | | `-- vim.git | |-- [...] | |-- .zshrc <----------------------+ |-- .gitignore.d | `-- zsh |-- .mrconfig `-- .mrtrust ### available.d The files you see in $XDG\_CONFIG\_HOME/mr/available.d are myrepos configuration files that contain the commands to manage (checkout, update etc.) a single repository. vcsh repo configs end in .vcsh, git configs end in .git, etc. This is optional and your preference. For example, this is what a zsh.vcsh with read-only access to my zshrc repo looks likes. I.e. in this specific example, push can not work as you will be using the author's repository. This is for demonstration, only. Of course, you are more than welcome to clone from this repository and fork your own. [$XDG_CONFIG_HOME/vcsh/repo.d/zsh.git] checkout = vcsh clone 'git://github.com/RichiH/zshrc.git' 'zsh' update = vcsh zsh pull push = vcsh zsh push status = vcsh zsh status gc = vcsh zsh gc [$HOME/.emacs.d] checkout = vcsh clone 'git://github.com/andschwa/emacs.git' '.emacs.d' ### config.d $XDG\_CONFIG\_HOME/mr/available.d contains *all available* repositories. Only files/links present in mr/config.d, however, will be used by myrepos. That means that in this example, only the zsh, gitconfigs, tmux and vim repositories will be checked out. A simple `mr update` run in $HOME will clone or update those four repositories listed in config.d. ### ~/.mrconfig Finally, ~/.mrconfig will tie together all those single files which will allow you to conveniently run `mr up` etc. to manage all repositories. It looks like this: [DEFAULT] include = cat ${XDG_CONFIG_HOME:-$HOME/.config}/mr/config.d/* ### repo.d $XDG\_CONFIG\_HOME/vcsh/repo.d is the directory where all git repositories which are under vcsh's control are located. Since their working trees are configured to be in $HOME, the files contained in those repositories will be put in $HOME directly. Of course, [myrepos][myrepos] will work with this layout if configured according to this document (see above). vcsh will check if any file it would want to create exists. If it exists, vcsh will throw a warning and exit. Move away your old config and try again. Optionally, merge your local and your global configs afterwards and push with `vcsh repo_name push`. ## Moving into a New Host To illustrate further, the following steps could move your desired configuration to a new host. 1. Clone the myrepos repository (containing available.d, config.d etc.); for example: `vcsh clone git://github.com/RichiH/vcsh_mr_template.git mr` 2. Choose your repositories by linking them in config.d (or go with the default you may have already configured by adding symlinks to git). 3. Run myrepos to clone the repositories: `cd; mr update`. 4. Done. Hopefully the above could help explain how this approach saves time by 1. making it easy to manage, clone and update a large number of repositories (thanks to myrepos) and 2. making it unnecessary to create symbolic links in $HOME (thanks to vcsh). If you want to give vcsh a try, follow the instructions below. # Getting Started Below, you will find a few different methods for setting up vcsh: 1. The Template Way 2. The Steal-from-Template Way 3. The Manual Way ### The Template Way #### Prerequisites Make sure none of the following files and directories exist for your test (user). If they do, move them away for now: * `~/.gitignore.d` * `~/.mrconfig` * `$XDG\_CONFIG\_HOME/mr/available.d/mr.vcsh` * `$XDG\_CONFIG\_HOME/mr/available.d/zsh.vcsh` * `$XDG\_CONFIG\_HOME/mr/config.d/mr.vcsh` * `$XDG\_CONFIG\_HOME/vcsh/repo.d/mr.git/` All of the files are part of the template repository, the directory is where the template will be stored. ### Install vcsh #### Debian If you are using Debian Squeeze, you will need to enable backports and the package name for myrepos will be 'mr'. From Wheezy onwards, you can install both directly: apt-get install myrepos vcsh #### Gentoo To install vcsh in Gentoo Linux just give the following command as root: emerge dev-vcs/vcsh Note the portage package for myrepos still has the old project name: emerge dev-vcs/mr #### Arch Linux vcsh is available via this [AUR](https://aur.archlinux.org/packages/vcsh/) package. Likewise myrepos is available [here](https://aur.archlinux.org/packages/myrepos/). You may install both using your favorite AUR helper. e.g. with yaourt: yaourt -Sya myrepos vcsh Or you can do it yourself manually using the documentation on installing AUR packages [on Arch's wiki](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages). If you prefer to use the devel package that installs the git HEAD version it is available [here](https://aur.archlinux.org/packages/vcsh-git/). #### Mac OS X Formulas are available for vcsh as well as git and myrepos through [homebrew](http://brew.sh). The vcsh formula is set to depend on myrepos, so you only need one install command: brew install vcsh #### From source To install the latest version from git: # choose a location for your checkout mkdir -p ~/work/git cd ~/work/git git clone git://github.com/RichiH/vcsh.git cd vcsh sudo ln -s vcsh /usr/local/bin # or add it to your PATH For myrepos: # use checkout location from above cd ~/work/git git clone git://myrepos.branchable.com/ myrepos cd myrepos make install #### Clone the Template vcsh clone git://github.com/RichiH/vcsh_mr_template.git mr #### Enable Your Test Repository mv ~/.zsh ~/zsh.bak mv ~/.zshrc ~/zshrc.bak cd $XDG_CONFIG_HOME/mr/config.d/ ln -s ../available.d/zsh.vcsh . # link, and thereby enable, the zsh repository cd mr up #### Set Up Your Own Repositories Now, it's time to edit the template config and fill it with your own remotes: vim $XDG_CONFIG_HOME/mr/available.d/mr.vcsh vim $XDG_CONFIG_HOME/mr/available.d/zsh.vcsh And then create your own stuff: vcsh init repo_name vcsh repo_name add bar baz quux vcsh repo_name remote add origin git://quuux vcsh repo_name commit vcsh repo_name push cp $XDG_CONFIG_HOME/mr/available.d/mr.vcsh $XDG_CONFIG_HOME/mr/available.d/repo_name.vcsh vim $XDG_CONFIG_HOME/mr/available.d/repo_name.vcsh # add your own repo Done! ### The Steal-from-Template Way You're welcome to clone the example repository: vcsh clone git://github.com/RichiH/vcsh_mr_template.git mr # make sure 'include = cat /usr/share/mr/vcsh' points to an exiting file vim .mrconfig Look around in the clone. It should be reasonably simple to understand. If not, poke me, RichiH, on Freenode (query) or OFTC (#vcs-home). ### The Manual Way This is how my old setup procedure looked like. Adapt it to your own style or copy mine verbatim, either is fine. # Create workspace mkdir -p ~/work/git cd !$ # Clone vcsh and make it available git clone git://github.com/RichiH/vcsh.git vcsh sudo ln -s ~/work/git/vcsh/vcsh /usr/bin/local hash -r Grab my myrepos config. see below for details on how I set this up vcsh clone ssh:///mr.git cd $XDG_CONFIG_HOME/mr/config.d/ ln -s ../available.d/* . [myrepos][myrepos] is used to actually retrieve configs, etc. ~ % cat ~/.mrconfig [DEFAULT] include = cat $XDG_CONFIG_HOME/mr/config.d/* ~ % echo $XDG_CONFIG_HOME /home/richih/.config ~ % ls $XDG_CONFIG_HOME/mr/available.d # random selection of my repos git-annex gitk.vcsh git.vcsh ikiwiki mr.vcsh reportbug.vcsh snippets.git wget.vcsh zsh.vcsh ~ % # then simply ln -s whatever you want on your local machine from # $XDG_CONFIG_HOME/mr/available.d to $XDG_CONFIG_HOME/mr/config.d ~ % cd ~ % mr -j 5 up # myrepos usage ; will be factored out & rewritten ### Keeping repositories Up-to-Date This is the beauty of it all. Once you are set up, just run: mr up mr push Neat. ### Making Changes After you have made some changes, for which you would normally use `git add` and `git commit`, use the vcsh wrapper (like above): vcsh repo_name add bar baz quux vcsh repo_name commit vcsh repo_name push ### Using vcsh without myrepos vcsh encourages you to use [myrepos][myrepos]. It helps you manage a large number of repositories by running the necessary vcsh commands for you. You may choose not to use myrepos, in which case you will have to run those commands manually or by other means. To initialize a new repository: `vcsh init zsh` To clone a repository: `vcsh clone ssh:///zsh.git` To interact with a repository, use the regular Git commands, but prepend them with `vcsh run $repository_name`. For example: vcsh zsh status vcsh zsh add .zshrc vcsh zsh commit Obviously, without myrepos keeping repositories up-to-date, it will have to be done manually. Alternatively, you could try something like this: for repo in `vcsh list`; do vcsh run $repo git pull; done # Contact There are several ways to get in touch with the author and a small but committed community around the general idea of version controlling your (digital) life. * IRC: #vcs-home on irc.oftc.net * Mailing list: [http://lists.madduck.net/listinfo/vcs-home][vcs-home-list] * Pull requests or issues on [https://github.com/RichiH/vcsh][vcsh] [myrepos]: http://myrepos.branchable.com/ [talks]: http://richardhartmann.de/talks/ [vcsh]: https://github.com/RichiH/vcsh [vcs-home-list]: http://lists.madduck.net/listinfo/vcs-home vcsh-2.0.10/doc/vcsh.1.ronn.in0000664000175000017500000002520214604750111014665 0ustar hibbyhibbyvcsh(1) - Version Control System for $HOME - multiple Git repositories in $HOME =============================================================================== ## SYNOPSIS `@TRANSFORMED_PACKAGE_NAME@` [] `@TRANSFORMED_PACKAGE_NAME@` clone [-b ] [] `@TRANSFORMED_PACKAGE_NAME@` delete `@TRANSFORMED_PACKAGE_NAME@` enter `@TRANSFORMED_PACKAGE_NAME@` foreach [-g] `@TRANSFORMED_PACKAGE_NAME@` help `@TRANSFORMED_PACKAGE_NAME@` init `@TRANSFORMED_PACKAGE_NAME@` list `@TRANSFORMED_PACKAGE_NAME@` list-tracked [] `@TRANSFORMED_PACKAGE_NAME@` list-untracked [<-a>] [<-r>] [] `@TRANSFORMED_PACKAGE_NAME@` pull `@TRANSFORMED_PACKAGE_NAME@` push `@TRANSFORMED_PACKAGE_NAME@` rename `@TRANSFORMED_PACKAGE_NAME@` run `@TRANSFORMED_PACKAGE_NAME@` status [] `@TRANSFORMED_PACKAGE_NAME@` upgrade `@TRANSFORMED_PACKAGE_NAME@` version `@TRANSFORMED_PACKAGE_NAME@` which `@TRANSFORMED_PACKAGE_NAME@` write-gitignore [] `@TRANSFORMED_PACKAGE_NAME@` `@TRANSFORMED_PACKAGE_NAME@` ## DESCRIPTION `@TRANSFORMED_PACKAGE_NAME@` allows you to have several `git`(1) repositories, all maintaining their working trees in $HOME without clobbering each other. That, in turn, means you can have one repository per config set (zsh, vim, ssh, etc), picking and choosing which configs you want to use on which machine. `@TRANSFORMED_PACKAGE_NAME@` is using a technique called fake bare Git repositories, keeping <$GIT_DIR> in a different directory from <$GIT_WORK_TREE> which is pointed to <$HOME>. The use of symlinks is not needed in this setup, making for a cleaner setup. `@TRANSFORMED_PACKAGE_NAME@` was designed with `mr`(1) in mind so you might want to install it alongside vcsh. That being said, you can easily use `@TRANSFORMED_PACKAGE_NAME@` without `mr` if you prefer. A sample configuration for `@TRANSFORMED_PACKAGE_NAME@` and `mr` can be found at *https://github.com/RichiH/vcsh_mr_template* and used with `@TRANSFORMED_PACKAGE_NAME@ clone https://github.com/RichiH/vcsh_mr_template mr`. Please note that you can always use a path instead of a name for . This is needed to support mr and other scripts properly and of no concern to an interactive user. ## OPTIONS * -c: Source prior to other configuration files * -d: Enable debug mode * -v: Enable verbose mode ## COMMANDS * clone: Clone an existing repository. If you need to clone a bundle of repositories, look into the `post-clone-retired` hook. You can also use a single git repository with several branches. Use the `-b` option to specify a branch at clone time, the default is `master`. * commit: Commit in all repositories * delete: Delete an existing repository. * enter: Enter repository; spawn new <$SHELL> with <$GIT_DIR> set. * foreach: Execute git command for every vcsh repository. `-g`: Execute in general context. * help: Display help. * init: Initialize an empty repository. * list: List all local vcsh repositories. * list-tracked: List all files tracked by vcsh. If you want to list files tracked by a specific repository, simply append the repository's name last. * list-tracked-by: List files tracked by a repository. This is a legacy command; you should use `list-tracked ` instead. * list-untracked: List all files NOT tracked by vcsh. `-a`: Show all files. By default, the `git ls-files --exclude-standard` is called. `-r`: Recursive mode. By default, the file list is shallow and stops at directory levels where possible. `$repo`: List files not tracked by this specific repository. * pull: Pull from all vcsh remotes. * push: Push to all vcsh remotes. * rename: Rename a repository. * run: Run command with <$GIT_DIR> and <$GIT_WORK_TREE> set. Allows you to run any and all commands without any restrictions. Use with care. Please note that there is a somewhat magic feature for run. Instead of it accepts , as well. Anything that has a slash in it will be assumed to be a path. `@TRANSFORMED_PACKAGE_NAME@ run` will then operate on this directory instead of the one normally generated from the repository's name. This is needed to support mr and other scripts properly and of no concern to an interactive user. * status: Show statuses of all/one vcsh repositories. * upgrade: Upgrade repository to currently recommended settings. * version: Print version information. * which : Find in name of any tracked file. * write-gitignore: Write .gitignore.d/ via `git ls-files`. If is not specified but we're withing a vcsh repository, use that. * : Shortcut to run `git` commands on a repo. Will prepend `git` to . * : Shortcut to run `@TRANSFORMED_PACKAGE_NAME@ enter `. ## ENVIRONMENT As noted earlier, `@TRANSFORMED_PACKAGE_NAME@` will set <$GIT_DIR> and <$GIT_WORK_TREE> to the appropriate values for fake bare Git repositories. ## CONFIG There are several ways to turn the various knobs on `@TRANSFORMED_PACKAGE_NAME@`. In order of ascending precedence, they are: * `VARIABLE=foo @TRANSFORMED_PACKAGE_NAME@` * * <$XDG_CONFIG_HOME/vcsh/config> * `@TRANSFORMED_PACKAGE_NAME@ -c ` Please note that those files are sourced. Any and all commands will be executed in the context of your shell. Interesting knobs you can turn: * <$VCSH_GITATTRIBUTES>: Can be , or any other value. will not maintain Git attributes in a special location. If set to any other value, repo-specific gitattributes files will be maintained. Defaults to . * <$VCSH_GITIGNORE>: Can be , , or . will seed the repo-specific ignore file with all file and directory names which `git ls-files` returns. will not write any ignore file. will descend through all directories recursively additionally to the above. Defaults to . * <$VCSH_WORKTREE>: Can be , or . will set an absolute path; defaulting to <$HOME>. will set a path relative to <$GIT_DIR>. Defaults to . Less interesting knobs you could turn: * <$VCSH_DEBUG>: Enter debug mode. * <$XDG_CONFIG_HOME>: As specified in the 'XDG Base Directory Specification', see Defaults to <$HOME/.config>. * <$VCSH_REPO_D>: The directory where repositories are read from and stored. Defaults to <$XDG_CONFIG_HOME/vcsh/repo.d>. * <$VCSH_HOOK_D>: The directory where hooks are read from. Defaults to <$XDG_CONFIG_HOME/vcsh/hooks-enabled>. * <$VCSH_BASE>: The directory where repositories are checked out to. Defaults to <$HOME>. ## HOOK SYSTEM `@TRANSFORMED_PACKAGE_NAME@` provides a hook system. Hook scripts must be executable and should be placed in <$XDG_CONFIG_HOME/vcsh/hooks-available>. From there, they can be soft-linked into <$XDG_CONFIG_HOME/vcsh/hooks-enabled>; `@TRANSFORMED_PACKAGE_NAME@` will only execute hooks that are in this directory. Hooks follow a simple format. will be run before anything is run. If you want to have more than one script for a certain hook, just append any kind of string to order them. A system of , , etc is suggested; other options would be or . A dot after the hook name is optional. If you want to create hooks for a specific repository, simply prepend the repository's name, followed by a dot, i.e. . Otherwise, the same rules as above apply. The dot between the repository's name and the hook is mandatory, though. Available hooks are , , , , , , , , , , , , , , , , and . If you need more, vcsh is trivial to patch, but please let upstream know so we can ship them by default. ## OVERLAY SYSTEM `@TRANSFORMED_PACKAGE_NAME@` also provides an overlay system. Similar to hooks, the recommended locations are <$XDG_CONFIG_HOME/vcsh/overlays-available> and <$XDG_CONFIG_HOME/vcsh/overlays-enabled>. Overlays follow the same rules as hooks and you are free to overwrite any and all functions. Same as hooks, you can use global or repository-specific overlays by using either <$VCSH_OVERLAY_D/$VCSH_COMMAND> or <$VCSH_OVERLAY_D/$VCSH_REPO_NAME.$VCSH_COMMAND>. Please note that nothing stops you from, e.g. overwriting `status()` in <$VCSH_OVERLAY_D/commit>. As the overlays will be sourced and you are replacing arbitrary functions, any and all features may stop working, or you may even lose data. You have been warned. ## DETAILED HOWTO AND FURTHER READING Manpages are often short and sometimes useless to glean best practices from. While the author tried to avoid this in this case, manpages can not cover detailed howtos. This software also comes with a file called . It contains various approaches to setting up and using vcsh. You can view the file it as plain text or render it into various other formats via Markdown. On Debian-based systems, this file can be found in . ## SECURITY CONSIDERATIONS `@TRANSFORMED_PACKAGE_NAME@` allows you to execute arbitrary commands via `@TRANSFORMED_PACKAGE_NAME@ run`. For example, adding a `sudo`(8) rule for `@TRANSFORMED_PACKAGE_NAME@` would be pretty stupid. Additionally, vcsh will source, i.e. execute, all files listed in . You can put any and all commands into these config files and they will be executed. ## BUGS None are known at this time, but reports and/or patches are more than welcome. ## INTEROPERABILITY If you rely on `git submodule` use `git` 1.7.12 or later. Earlier versions do not clean internal variables properly before descending into submodules, resulting in unhappy end users. ## HISTORY Like most people, the author initially made do with a single repository for all config files, all of which were soft-linked into <$HOME>. Martin F. Krafft aka madduck came up with the concept of fake bare Git repositories. vcsh was initially written by madduck. This version is a re-implementation from scratch with a lot more features. madduck graciously agreed to let the author take over the name. ## AUTHOR This manpage and `@TRANSFORMED_PACKAGE_NAME@` itself were written by Richard "RichiH" Hartmann. ## COPYRIGHT Copyright 2011-2015 Richard Hartmann Licensed under the GNU GPL version 2 or higher. https://github.com/RichiH/vcsh ## SEE ALSO `git`(1), `mr`(1) vcsh-2.0.10/doc/hooks0000664000175000017500000000172314604750111013330 0ustar hibbyhibbyAvailable hooks are: * pre-clone * post-clone * post-clone-retired Use this if you need to operate on different git repositories after cloning. This hook can be useful if your configuration needs some remote repositories, but you do not want to include it into your vcsh repository. For instance, if you use vim plugins manager (vundle, NeoBundle), zsh configuration frameworks (oh-my-zsh, prezto), etc. * pre-command * post-command * pre-enter * post-enter * pre-init * post-init * pre-merge Use this hook to detect and handle merge conflicts before vcsh's native code finds and errors on them. This is useful for allowing clones on top of existing files. * post-merge Use this hook to finish handling any merge conflicts found in the pre-merge hook. * pre-pull * post-pull * pre-push * post-push * pre-run * post-run * pre-upgrade * post-upgrade If you write any interesting or useful hooks, please send them upstream so they can be included in an examples section. vcsh-2.0.10/doc/INSTALL.md0000664000175000017500000001057714604750111013721 0ustar hibbyhibby# Distro Packages Many distributions have packages ready to go. If yours doesn’t, you can install [from source](#installing-from-source). VCSH can also be deployed as a [standalone script](#standalone-script). If you package VCSH for a distro please let us know. ## Arch Linux ``` $ pacman -S vcsh ``` ## CentOS / Fedora / RedHat ```console $ yum install vcsh ``` ## Debian / Deepin / Kali Linux / Parrot / PureOS / Raspbian / Trisquel / Ubuntu ```console $ apt install vcsh ``` ## Gentoo / Funtoo / LiGurOS ```console $ emerge --ask dev-vcs/vcsh ``` ## GNU Guix ```console $ guix install vcsh ``` ## Homebrew (macOS) / Linuxbrew ```console $ brew install vcsh ``` ## KISS Linux ```console $ kiss install vcsh ``` ## MacPorts (macOS) ```console $ port install vcsh ``` ## NIX ```console $ nix-env -i vcsh ``` ## openSUSE ```console $ zypper install vcsh ``` ## Pardus ```console $ pisi install vcsh ``` ## Termux ```console $ pkg install vcsh ``` # Installing from Source First you’ll want a copy of the source code. The easiest to use place to get this is the [latest release](https://github.com/RichiH/vcsh/releases/latest) posted on GitHub. The souree distribution will have a name such as `vcsh-2.0.0.tar.zst`. Note under each release GitHub also show two “Source code” links that will download a snapshot of the repository; this is **not** the file you want (unless you want to jump through extra hoops). The official source release packages with the release version in the file names are the ones you want. Alternatively you may `git clone` the source repository. Note than some extra tooling will be required over using the regular source releases. Building from a clone will require a system with GNU Autotools installed; something not needed if using a source package. Also source releases have prebuilt man pages; to (optionally) build them from a Git clone you will need `ronn`. Finally building from Git clones will check for extra dependencies needed for testing, although tests can be disabled. If starting from a clone, run `./bootstrap.sh` once before doing anything below. Once you have the source, it’s time to let it get aquainted with your system: ```console $ ./configure ``` This command has *lots* of possible options, but the defaults should suite most use cases. See `./configure --help` for details if you have special needs. Once configured, you can build: ```console $ make ``` Lastly you’ll want to install it somewhere. ```console $ make install ``` If you need elevated system permissions you may need to use `sudo make install` for this step. If you don’t have such permissions and wish to install to your home directory, something like this might work: ```console $ ./configure --prefix=/ $ make DESTDIR="$HOME" install-exec ``` This will install to `~/bin/vcsh`; add `~/bin` to your path to use. # Standalone Script A special variant of VCSH can be deployed as a single POSIX shell script with no configure/build step. Deploying it this way leaves you without any man page or shell completion functions (or possibly with mismatched resources installed by your package manager for a different vcsh version). This variant is also dependent or your `$PATH` to have proper versions of dependencies such as `git`. If your user space has different tools by default than your system beware! The standalone variant can be downloaded from any recent entry in [releases](https://github.com/RichiH/vcsh/releases). This method is suited for installation to a user space where you don’t have control over the system packages, e.g.: ```console $ mkdir -p ~/bin $ curl -fsLS https://github.com/RichiH/vcsh/releases/latest/download/vcsh-standalone.sh -o ~/bin/vcsh $ chmod u+x ~/bin/vcsh ``` It could also be used to directly bootstrap a dotfiles repository with something like this: ```console $ sh <(curl -fsLS https://github.com/RichiH/vcsh/releases/latest/download/vcsh-standalone.sh) clone dotfiles ``` While we are enabling cURL-based workflows on purpose, we still encourage you to avoid them where reasonably possible. If you do use it, please consider using a tagged version that you’ve tested to work for you instead of the “latest” keyword. Note: the URL for tagged releases is in a different order than when using the “latest” keyword, substitute a tag name by changing `latest/download` to `download/v2.0.0`. [1]: http://rtomayko.github.io/ronn/ vcsh-2.0.10/completions/0000775000175000017500000000000014604750111014046 5ustar hibbyhibbyvcsh-2.0.10/completions/vcsh.zsh0000664000175000017500000000666014604750111015547 0ustar hibbyhibby#compdef vcsh function __vcsh_repositories () { local -a repos repos=( ${(f)"$(_call_program repositories vcsh list)"} ) _describe -t repositories 'repository' repos } function __vcsh_not_implemented_yet () { _message "Subcommand completion '${1#*-}': not implemented yet" } function _vcsh-clone () { __vcsh_not_implemented_yet "$0" #TODO } function _vcsh-delete () { (( CURRENT == 2 )) && __vcsh_repositories } function _vcsh-enter () { (( CURRENT == 2 )) && __vcsh_repositories } function _vcsh-foreach () { _dispatch vcsh-foreach git } function _vcsh-help () { _nothing } function _vcsh-init () { _nothing } function _vcsh-list () { _nothing } function _vcsh-list-tracked () { (( CURRENT == 2 )) && __vcsh_repositories } function _vcsh-list-untracked () { _nothing } function _vcsh-pull () { _nothing } function _vcsh-push () { _nothing } function _vcsh-rename () { case $CURRENT in 2) __vcsh_repositories ;; 3) _message "new repository name" ;; *) _nothing ;; esac } function _vcsh-run () { (( CURRENT == 2 )) && __vcsh_repositories (( CURRENT == 3 )) && _command_names -e if (( CURRENT >= 4 )); then # see _precommand in zsh words=( "${(@)words[3,-1]}" ) (( CURRENT -= 2 )) _normal fi } function _vcsh-status () { (( CURRENT == 2 )) && __vcsh_repositories } function _vcsh-upgrade () { (( CURRENT == 2 )) && __vcsh_repositories } function _vcsh-version () { _nothing } function _vcsh-which () { _files } function _vcsh-write-gitignore () { (( CURRENT == 2 )) && __vcsh_repositories } function _vcsh () { local curcontext="${curcontext}" ret=1 local state vcshcommand local -a args subcommands local VCSH_REPO_D : ${VCSH_REPO_D:="${XDG_CONFIG_HOME:-"$HOME/.config"}/vcsh/repo.d"} subcommands=( "clone:clone an existing repository" "commit:commit in all repositories" "delete:delete an existing repository" "enter:enter repository; spawn new <\$SHELL>" "foreach:execute for all repos" "help:display help" "init:initialize an empty repository" "list:list all local vcsh repositories" "list-tracked:list all files tracked by vcsh" "list-untracked:list all files not tracked by vcsh" "pull:pull from all vcsh remotes" "push:push to vcsh remotes" "rename:rename a repository" "run:run command with <\$GIT_DIR> and <\$GIT_WORK_TREE> set" "status:show statuses of all/one vcsh repositories" "upgrade:upgrade repository to currently recommended settings" "version:print version information" "which:find in name of any tracked file" "write-gitignore:write .gitignore.d/ via git ls-files" ) args=( '-c[source prior to other configuration files]:config files:_path_files' '-d[enable debug mode]' '-v[enable verbose mode]' '*:: :->subcommand_or_options_or_repo' ) _arguments -C ${args} && ret=0 if [[ ${state} == "subcommand_or_options_or_repo" ]]; then if (( CURRENT == 1 )); then _describe -t subcommands 'vcsh sub-commands' subcommands && ret=0 __vcsh_repositories && ret=0 else vcshcommand="${words[1]}" if ! (( ${+functions[_vcsh-$vcshcommand]} )); then # There is no handler function, so this is probably the name # of a repository. Act accordingly. # FIXME: this may want to use '_dispatch vcsh git' GIT_DIR=$VCSH_REPO_D/$words[1].git _dispatch git git && ret=0 else curcontext="${curcontext%:*:*}:vcsh-${vcshcommand}:" _call_function ret _vcsh-${vcshcommand} && (( ret )) fi fi fi return ret } _vcsh "$@" vcsh-2.0.10/completions/vcsh.bash0000664000175000017500000000670114604750111015654 0ustar hibbyhibby# run git command # based on bash_completion:_command_offset() _vcsh_git_command () { local word_offset=$1 for (( i=0; i < word_offset; i++ )); do for (( j=0; j <= ${#COMP_LINE}; j++ )); do [[ "$COMP_LINE" == "${COMP_WORDS[i]}"* ]] && break COMP_LINE=${COMP_LINE:1} ((COMP_POINT--)) done COMP_LINE=${COMP_LINE#"${COMP_WORDS[i]}"} ((COMP_POINT-=${#COMP_WORDS[i]})) done COMP_LINE="git $COMP_LINE" ((COMP_POINT+=4)) # shift COMP_WORDS elements and adjust COMP_CWORD for (( i=1; i <= COMP_CWORD - word_offset + 1; i++ )); do COMP_WORDS[i]=${COMP_WORDS[i+$word_offset-1]} done for (( i; i <= COMP_CWORD; i++ )); do unset 'COMP_WORDS[i]' done COMP_WORDS[0]=git ((COMP_CWORD -= word_offset - 1)) local cspec cspec=$( complete -p git 2>/dev/null ) if [[ -z $cspec ]]; then if declare -F __load_completion &> /dev/null; then __load_completion git cspec=$( complete -p git 2>/dev/null ) fi fi if [[ -n $cspec ]]; then if [[ ${cspec#* -F } != $cspec ]]; then local func=${cspec#*-F } func=${func%% *} if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then $func git "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}" else $func git "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" fi # restore initial compopts local opt while [[ $cspec == *" -o "* ]]; do # FIXME: should we take "+o opt" into account? cspec=${cspec#*-o } opt=${cspec%% *} compopt -o $opt cspec=${cspec#$opt} done fi fi } _vcsh () { local cur prev words OPTS _init_completion -n = || return local r reponames local -A repos mapfile -t reponames < <(command vcsh list) for r in "${reponames[@]}"; do repos["$r"]="$r"; done unset r reponames local cmds cmds="clone delete enter foreach help init commit list list-tracked list-untracked pull push rename run status upgrade version which write-gitignore" local subcword cmd subcmd for (( subcword=1; subcword < ${#words[@]}-1; subcword++ )); do [[ -n $cmd && ${words[subcword]} != -* ]] && subcmd=${words[subcword]} && break [[ ${words[subcword]} != -* ]] && cmd=${words[subcword]} done if [[ -z $cmd ]]; then case $prev in -c) mapfile -t COMPREPLY < <(compgen -f -- "$cur") return ;; esac case $cur in -*) OPTS='-c -d -h -v' mapfile -t COMPREPLY < <(compgen -W "$OPTS" -- "$cur") return ;; esac mapfile -t COMPREPLY < <(compgen -W "${repos[*]} ${cmds}" -- "$cur") return 0 fi case $cmd in help|init|commit|list|pull|push|version|which) return ;; list-untracked) [[ $cur == -* ]] && \ mapfile -t COMPREPLY < <(compgen -W '-a -r' -- "$cur") && return ;;& run) if [[ -n $subcmd && -n "${repos[$subcmd]}" ]]; then _command_offset $(( subcword+1 )) return fi ;;& delete|enter|list-tracked|list-untracked|rename|run|status|upgrade|write-gitignore) # return repos if [[ -z $subcmd ]]; then mapfile -t COMPREPLY < <(compgen -W "${repos[*]}" -- "$cur") return fi return ;; clone) [[ $cur == -* ]] && \ mapfile -t COMPREPLY < <(compgen -W '-b' -- "$cur") return ;; foreach) [[ $cur == -* ]] \ && mapfile -t COMPREPLY < <(compgen -W "-g" -- "$cur") && return _vcsh_git_command $subcword return ;; esac # git command on repository if [[ -n "${repos[$cmd]}" ]]; then : "${VCSH_REPO_D:=${XDG_CONFIG_HOME:-$HOME/.config}/vcsh/repo.d}" GIT_DIR="${VCSH_REPO_D}/${cmd}.git" _vcsh_git_command "$subcword" fi return 0 } complete -F _vcsh vcsh vcsh-2.0.10/t/0000775000175000017500000000000014604750111011755 5ustar hibbyhibbyvcsh-2.0.10/t/999-tear-env.t0000664000175000017500000000031514604750111014212 0ustar hibbyhibby#!/usr/bin/perl use strict; use warnings; use Shell::Command; use Test::Most; chdir 't' or die $!; if (!-d 'etc') { plan skip_all => 'No need to tear previous env.'; } ok rm_rf 'etc'; done_testing; vcsh-2.0.10/t/950-delete.t0000664000175000017500000000053714604750111013724 0ustar hibbyhibby#!/usr/bin/perl use strict; use warnings; use Cwd 'abs_path'; use Test::Most; chdir 't/etc/' or die $!; $ENV{'HOME'} = abs_path ('.vcsh_home'); $ENV{'XDG_CONFIG_HOME'} = $ENV{'HOME'}.'/.config'; system ("echo 'Yes, do as I say' | ./vcsh delete test1"); my $output = `./vcsh status`; ok $output eq "", 'No repos set up anymore.'; done_testing; vcsh-2.0.10/t/100-init.t0000664000175000017500000000216014604750111013402 0ustar hibbyhibby#!/usr/bin/perl BEGIN { $ENV{LC_ALL} = 'C' } use strict; use warnings; use Cwd 'abs_path'; use Test::Most; chdir 't/etc/' or die $!; $ENV{'HOME'} = abs_path ('.vcsh_home'); $ENV{'XDG_CONFIG_HOME'} = $ENV{'HOME'}.'/.config'; my $output = `./vcsh status`; ok $output eq "", 'No repos set up yet.'; $output = `./vcsh init test1`; ok $output eq "Initialized empty Git repository in " . $ENV{'HOME'} . "/.config/vcsh/repo.d/test1.git/\n"; $output = `./vcsh status`; ok $output eq "test1:\n\n", 'Our new repo is there'; chdir $ENV{"HOME"} . '/.config/vcsh/repo.d/test1.git/' or die $!; ok -f 'HEAD'; ok -f 'config'; ok -f 'description'; ok -d 'hooks'; ok -d 'info'; ok -d 'objects'; ok -d 'refs'; ok -f 'hooks/applypatch-msg.sample'; ok -f 'hooks/commit-msg.sample'; ok -f 'hooks/post-update.sample'; ok -f 'hooks/pre-applypatch.sample'; ok -f 'hooks/pre-commit.sample'; ok -f 'hooks/pre-push.sample'; ok -f 'hooks/pre-rebase.sample'; ok -f 'hooks/prepare-commit-msg.sample'; ok -f 'hooks/update.sample'; ok -f 'info/exclude'; ok -d 'objects/info'; ok -d 'objects/pack'; ok -d 'refs/heads'; ok -d 'refs/tags'; done_testing; vcsh-2.0.10/t/300-add.t0000664000175000017500000000101714604750111013171 0ustar hibbyhibby#!/usr/bin/perl use strict; use warnings; use Cwd 'abs_path'; use Shell::Command; use Test::Most; chdir 't/etc/' or die $!; $ENV{'HOME'} = abs_path ('.vcsh_home'); $ENV{'XDG_CONFIG_HOME'} = $ENV{'HOME'}.'/.config'; chdir '.vcsh_home' or die $!; eval { touch 'a'; }; die $@ if $@; system (".././vcsh test1 add 'a'"); my $output = `.././vcsh status`; ok $output eq "test1: A ~/a ", 'Adding a file works'; $output = `.././vcsh status --terse`; ok $output eq "test1: A ~/a ", 'Terse output works'; done_testing; vcsh-2.0.10/t/000-tear-env.t0000664000175000017500000000032214604750111014155 0ustar hibbyhibby#!/usr/bin/perl use strict; use warnings; use Shell::Command; use Test::Most; chdir 't' or die $!; if (!-d 'etc') { plan skip_all => 'No need to tear down previous env.'; } ok rm_rf 'etc'; done_testing; vcsh-2.0.10/t/001-setup-env.t0000664000175000017500000000062214604750111014366 0ustar hibbyhibby#!/usr/bin/perl use strict; use warnings; use Cwd 'abs_path'; use Test::Most; system ("mkdir -p t/etc"); ok !$?; system ("mkdir -p t/etc/.vcsh_home"); ok !$?; chdir 't/etc/' or die $!; system ("ln -s '../../vcsh'"); ok !$?; $ENV{'HOME'} = abs_path ('.vcsh_home'); $ENV{'XDG_CONFIG_HOME'} = $ENV{'HOME'}.'/.config'; system ("git config --global init.defaultBranch test"); ok !$?; done_testing; vcsh-2.0.10/.editorconfig0000664000175000017500000000046614604750111014175 0ustar hibbyhibbyroot = true [*] end_of_line = lf insert_final_newline = true charset = utf-8 trim_trailing_whitespace = true [{Makefile*,*.mk,*.mk.in}] indent_style = tab indent_size = 4 [*.m4] indent_style = space indent_size = 8 [*.md] trim_trailing_whitespace = false [{vcsh.in,completions/vcsh.*}] indent_style = tab