X-Git-Url: https://git.madduck.net/code/vcsh.git/blobdiff_plain/6d3e9d21d1bfa0a024bbf5758c6f6e55086deac8..83ae3460b51c674802a6ab4859cbe8450e9e210c:/vcsh?ds=inline diff --git a/vcsh b/vcsh index 4da3547..d1d26ed 100755 --- a/vcsh +++ b/vcsh @@ -22,6 +22,9 @@ VERSION='1.20141026' SELF=$(basename $0) +# Ensure all files created are accessible only to the current user. +umask 0077 + fatal() { echo "$SELF: fatal: $1" >&2 [ -z $2 ] && exit 1 @@ -106,6 +109,9 @@ help() { commit Commit in all repositories delete Delete an existing repository enter Enter repository; spawn new instance of \$SHELL + with \$GIT_DIR set. + foreach [<-g>] + Execute a command for every repository help Display this help text init Initialize a new repository list List all repositories @@ -160,7 +166,12 @@ clone() { You should add files to your new repository." exit fi - git fetch origin "$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 ls-tree -r --name-only origin/"$VCSH_BRANCH" | (while read object; do [ -e "$object" ] && @@ -170,7 +181,7 @@ clone() { [ x"$VCSH_CONFLICT" = x'1' ]) && 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 - git merge origin/"$VCSH_BRANCH" + git -c merge.ff=true merge origin/"$VCSH_BRANCH" hook post-merge hook post-clone retire @@ -179,11 +190,12 @@ clone() { commit() { hook pre-commit + shift # remove the "commit" command. 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 commit --untracked-files=no --quiet + git commit --untracked-files=no --quiet "$@" VCSH_COMMAND_RETURN_CODE=$? echo done @@ -216,6 +228,27 @@ enter() { hook post-enter } +foreach() { + hook pre-foreach + + # We default to prefixing `git` to all commands passed to foreach, but + # allow running in general context with -g + command_prefix=git + while getopts "g" flag; do + if [ x"$1" = x'-g' ]; then + unset command_prefix + fi + shift 1 + done + for VCSH_REPO_NAME in $(list); do + echo "$VCSH_REPO_NAME:" + GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR + use + $command_prefix "$@" + done + hook post-foreach +} + git_dir_exists() { [ -d "$GIT_DIR" ] || fatal "no repository found for '$VCSH_REPO_NAME'" 12 } @@ -233,7 +266,7 @@ 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=0600 + git init --shared=false upgrade hook post-init } @@ -246,7 +279,7 @@ list() { get_files() { GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR - git ls-files + git ls-files --full-name } list_tracked() { @@ -265,7 +298,7 @@ list_tracked_helper() { } list_tracked_by() { - list_tracked $2 + list_tracked '' $2 } list_untracked() { @@ -429,12 +462,14 @@ 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" - done - done | sort -u + 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 } write_gitignore() { @@ -446,14 +481,21 @@ write_gitignore() { use cd "$VCSH_BASE" || fatal "could not enter '$VCSH_BASE'" 11 + local GIT_VERSION="$(git --version)" + local GIT_VERSION_MAJOR=$(echo $GIT_VERSION | sed -E -n 's/.* ([0-9]+)\..*/\1/p') + local 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; + if [ $GIT_VERSION_MAJOR -ge 2 -a $GIT_VERSION_MINOR -ge 7 ]; then + echo "$file"; + else + while true; do + echo "$file"; new=${file%/*} + [ x"$file" = x"$new" ] && break + file=$new + done; + fi done | sort -u) # Contrary to GNU mktemp, mktemp on BSD/OSX requires a template for temp files @@ -556,6 +598,9 @@ elif [ x"$VCSH_COMMAND" = x'delete' ] || [ 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' ] ||