X-Git-Url: https://git.madduck.net/code/vcsh.git/blobdiff_plain/d3b04ac4495a6fe1676aa0f2f6b60a93fd6324e1..c03340ae79c2230828c3b3e15a314e167f637d2e:/vcsh diff --git a/vcsh b/vcsh index e4f6f33..54026cf 100755 --- a/vcsh +++ b/vcsh @@ -24,13 +24,14 @@ SELF=$(basename $0) fatal() { echo "$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. -while getopts "c:dvr" flag; do +while getopts "c:dv" flag; do if [ x"$1" = x'-d' ] || [ x"$1" = x'--debug' ]; then set -vx VCSH_DEBUG=1 @@ -40,8 +41,6 @@ while getopts "c:dvr" flag; do VCSH_VERBOSE=1 echo "verbose mode on" echo "$SELF $VERSION" - elif [ x"$1" = x'-r' ]; then - VCSH_OPTION_RECURSIVE=1 elif [ x"$1" = x'-c' ]; then VCSH_OPTION_CONFIG=$OPTARG fi @@ -77,6 +76,7 @@ fi # Read defaults : ${VCSH_REPO_D:="$XDG_CONFIG_HOME/vcsh/repo.d"} : ${VCSH_HOOK_D:="$XDG_CONFIG_HOME/vcsh/hooks-enabled"} +: ${VCSH_OVERLAY_D:="$XDG_CONFIG_HOME/vcsh/overlays-enabled"} : ${VCSH_BASE:="$HOME"} : ${VCSH_GITIGNORE:=exact} : ${VCSH_GITATTRIBUTES:=none} @@ -111,6 +111,8 @@ help() { list-tracked List all files tracked by vcsh list-tracked-by \\ List files tracked by a repository + list-untracked \\ + [<-r>] [] List all files not tracked by all or one repositories pull Pull from all vcsh remotes push Push to vcsh remotes rename \\ @@ -150,9 +152,10 @@ clone() { git remote add origin "$GIT_REMOTE" git config branch.master.remote origin git config branch.master.merge refs/heads/master - if [ $(git ls-remote origin master 2> /dev/null | wc -l ) -lt 1 ]; then - info "remote is empty, not merging anything" - exit + VCSH_CLONE_ERROR=$(git ls-remote origin master 2>&1) + if [ -n "$VCSH_CLONE_ERROR" ]; then + rm -rf "$GIT_DIR" + fatal "$VCSH_CLONE_ERROR" 1 fi git fetch hook pre-merge @@ -286,48 +289,53 @@ retire() { unset VCSH_DIRECTORY } -command_exists() { - command -v "$1" >/dev/null 2>&1 || fatal "Could not find '$1' command" -} - list_untracked() { - command_exists comm - - temp_file_others=$(mktemp) || fatal 'Could not create temp file' - temp_file_untracked=$(mktemp) || fatal 'Could not create temp file' - temp_file_untracked_copy=$(mktemp) || fatal 'Could not create temp file' - - # create dummy git repo - temp_repo=$(mktemp -d) || fatal 'Could not create temp repo' + command -v 'comm' >/dev/null 2>&1 || fatal "Could not find 'comm'" - cd $temp_repo || fatal 'Could not cd into temp repo' - git init -q - mktemp -q -p $(pwd) > /dev/null || fatal 'Could not create dummy file' - git add . - git commit -q -m "dummy" - cd - > /dev/null 2>&1 || fatal 'Could not cd back' + 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' - [ -z "$VCSH_OPTION_RECURSIVE" ] && directory_opt="--directory" - - export GIT_DIR=$temp_repo/.git - git ls-files --others "$directory_opt" | sort -u > $temp_file_untracked - - for VCSH_REPO_NAME in $(list); do - export GIT_DIR="$VCSH_REPO_D/$VCSH_REPO_NAME.git" - git ls-files --others "$directory_opt" | ( - while read line; do - echo "$line" - printf '%s/\n' "$(echo "$line" | cut -d'/' -f1)" - done - ) | sort -u > $temp_file_others - cp $temp_file_untracked $temp_file_untracked_copy || fatal 'Could not copy temp file' - comm -12 --nocheck-order $temp_file_others $temp_file_untracked_copy > $temp_file_untracked + # Hack in support for `vcsh list-untracked -r`... + directory_opt="--directory" + shift 1 + while getopts "r" flag; do + if [ x"$1" = x'-r' ]; then + unset directory_opt + fi + shift 1 done + # ...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 + + unset directory_opt directory_component rm -f $temp_file_others $temp_file_untracked $temp_file_untracked_copy || fatal 'Could not delete temp files' - rm -rf $temp_repo || fatal 'Could not delete temp repo' +} + +list_untracked_helper() { + export GIT_DIR="$VCSH_REPO_D/$VCSH_REPO_NAME.git" + git ls-files --others "$directory_opt" | ( + while read 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 --nocheck-order $temp_file_others $temp_file_untracked_copy > $temp_file_untracked } rename() { @@ -353,22 +361,23 @@ run() { status() { if [ -n "$VCSH_REPO_NAME" ]; then - GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR - use - git status --short --untracked-files='no' - VCSH_COMMAND_RETURN_CODE=$? + status_helper $VCSH_REPO_NAME else for VCSH_REPO_NAME in $(list); do echo "$VCSH_REPO_NAME:" - GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR - use - git status --short --untracked-files='no' - VCSH_COMMAND_RETURN_CODE=$? + status_helper $VCSH_REPO_NAME echo done fi } +status_helper() { + GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR + use + git status --short --untracked-files='no' + VCSH_COMMAND_RETURN_CODE=$? +} + upgrade() { hook pre-upgrade # fake-bare repositories are not bare, actually. Set this to false @@ -397,6 +406,7 @@ use() { } which() { + [ -e "$VCSH_COMMAND_PARAMETER" ] || fatal "'$VCSH_COMMAND_PARAMETER' does not exist" 1 for VCSH_REPO_NAME in $(list); do for VCSH_FILE in $(get_files); do echo "$VCSH_FILE" | grep -q "$VCSH_COMMAND_PARAMETER" && echo "$VCSH_REPO_NAME: $VCSH_FILE" @@ -557,6 +567,14 @@ check_dir "$VCSH_REPO_D" verbose "$VCSH_COMMAND begin" VCSH_COMMAND=$(echo "$VCSH_COMMAND" | sed 's/-/_/g'); export VCSH_COMMAND + +# 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'" + . "$overlay" +done + hook pre-command $VCSH_COMMAND "$@" hook post-command