diff --git a/changelog b/changelog index 52c7ed22c8523df1d9f2e401f481216672df0bf6..2a87fc958545019ed66e7e317d3199a75ba42845 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,16 @@ +2013-03-31 Richard Hartmann <richih.mailinglist@gmail.com> + + * Release 1.1 + * Documentation fixes + * Use rm -f when removing a git repo + * Fix quoting bug (Debian #699093) + +2013-02-13 Richard Hartmann <richih.mailinglist@gmail.com> + + * Release 1.0.1 + * Improve documentation + * Fix parameter bug + 2012-06-30 Richard Hartmann <richih.mailinglist@gmail.com> * Release 1.0 diff --git a/doc/error_codes.md b/doc/error_codes.md index e127e7d6e7d85f9ffa9bd7207446dfd8b22add99..49cb084ee4593b68d06668a631cc1fa367c94bec 100644 --- a/doc/error_codes.md +++ b/doc/error_codes.md @@ -1,7 +1,7 @@ * 0: OK * 1: Generic error -* 10: Init failed because $GIT_DIR exists -* 11: Could not enter $GIT_WORK_TREE +* 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 diff --git a/doc/vcsh.1.ronn b/doc/vcsh.1.ronn index 0fbead9a78c4f30ce0e1d02680a913249c49dbf7..f286dc0b4f57ccb6815b5c91718daadd0815d7df 100644 --- a/doc/vcsh.1.ronn +++ b/doc/vcsh.1.ronn @@ -3,6 +3,8 @@ vcsh(1) - manage config files in $HOME via fake bare git repositories ## SYNOPSIS +`vcsh` [<options>] <command> + `vcsh` clone <url> [<repo>] `vcsh` delete <repo> @@ -21,7 +23,7 @@ vcsh(1) - manage config files in $HOME via fake bare git repositories `vcsh` rename <repo> <newname> -`vcsh` run <repo> <command> +`vcsh` run <repo> <shell command> `vcsh` setup <repo> @@ -29,7 +31,7 @@ vcsh(1) - manage config files in $HOME via fake bare git repositories `vcsh` write-gitignore <repo> -`vcsh` <repo> <gitcommand> +`vcsh` <repo> <git command> `vcsh` <repo> @@ -59,6 +61,17 @@ an interactive user. ## OPTIONS +* -c: + Source <file> prior to other configuration files + +* -d: + Enable debug mode + +* -v: + Enable verbose mode + +## COMMANDS + * clone: Clone an existing repository. @@ -117,6 +130,59 @@ an interactive user. As noted earlier, `vcsh` 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 `vcsh`. In order of +ascending precedence, they are: + +* `VARIABLE=foo vcsh` +* </etc/vcsh/config> +* <$XDG_CONFIG_HOME/vcsh/config> +* `vcsh -c <file>` + +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_GITIGNORE>: + Can be either <exact> or <recursive>. + + <exact> will seed the repo-specific <.gitignore> with all file and directory + names which `git ls-files` returns. + + <recursive> will descend through all directories recursively additionally to + the above. + + Defaults to <exact>. + +Less interesting knobs you could turn: + +* <$VCSH_DEBUG>: + Enter debug mode. + +* <$XDG_CONFIG_HOME>: + As specified in the 'XDG Base Directory Specification', see + <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html> + + 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 `vcsh` provides a hook system. Hook scripts must be executable and should be @@ -141,30 +207,33 @@ but please let upstream know so we can ship them by default. ## DETAILED HOWTO AND FURTHER READING -Man pages are intended to be short and thus often useless to glean best -practices from. This software comes with a file called <README.md>. It contains -various approaches to setting up and using vcsh. You can view the file it as +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 <README.md>. 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 </usr/share/doc/vcsh>. ## SECURITY CONSIDERATIONS -`vcsh` allows you to execute arbitrary commands via `vcsh` run. For example, +`vcsh` allows you to execute arbitrary commands via `vcsh run`. For example, adding a `sudo`(8) rule for `vcsh` would be pretty stupid. -Additionally, vcsh will source, i.e. execute, <$XDG_CONFIG_HOME/vcsh/config>. -You can put any and all commands into this config file and they will be executed. +Additionally, vcsh will source, i.e. execute, all files listed in <CONFIG>. +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. -## KNOWN ISSUES +## INTEROPERABILITY -As of this writing (June 2012), `vcsh` does not work with `git submodule` due -to limitations within `git`. Depending on when you are reading this, you might -want to consider upgrading. +If you rely on `git submodule`, use `git` 1.7.12 or later. Earlier versions +do not clean internal variables properly before descending into a submodule. ## HISTORY diff --git a/vcsh b/vcsh index 358135a48ed814b63218d0fef0b6a68023afae0e..f222fff8abf02f08905180a4d63b0020415969ec 100755 --- a/vcsh +++ b/vcsh @@ -11,24 +11,74 @@ # full compability with git. In case git ever changes its licensing terms, # this software will most likely follow suit. +SELF=$(basename $0) + +fatal() { + echo "$SELF: fatal: $1" >&2 + 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:dv" flag; do + if [ "$1" = '-d' ] || [ "$1" = '--debug' ]; then + set -vx + VCSH_DEBUG=1 + elif [ "$1" = '-v' ];then + VCSH_VERBOSE=1 + elif [ "$1" = '-c' ];then + VCSH_OPTION_CONFIG=$OPTARG + fi + shift 1 +done + +source_all() { + # Source file even if it's in $PWD and does not have any slashes in it + case "$1" in + */*) . "$1";; + *) . "$PWD/$1";; + esac; +} + + +# Read configuration and set defaults if anything's not set [ -n "$VCSH_DEBUG" ] && set -vx [ -z "$XDG_CONFIG_HOME" ] && XDG_CONFIG_HOME="$HOME/.config" + +# Read configuration files if there are any +[ -r "/etc/vcsh/config" ] && . "/etc/vcsh/config" [ -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 [ -z "$VCSH_REPO_D" ] && VCSH_REPO_D="$XDG_CONFIG_HOME/vcsh/repo.d" [ -z "$VCSH_HOOK_D" ] && VCSH_HOOK_D="$XDG_CONFIG_HOME/vcsh/hooks-enabled" [ -z "$VCSH_BASE" ] && VCSH_BASE="$HOME" [ -z "$VCSH_GITIGNORE" ] && VCSH_GITIGNORE='exact' -SELF=$(basename $0) help() { - echo "usage: $SELF <args> + echo "usage: $SELF <options> <command> + options: + -c <file> Source file + -d Enable debug mode + -v Enable verbose mode + + commands: clone <remote> \\ [<repo>] Clone from an existing repository - delete Delete an existing repository - enter Enter repository; spawn new instance of \$SHELL + delete <repo> Delete an existing repository + enter <repo> Enter repository; spawn new instance of \$SHELL help Display this help text init <repo> Initialize a new repository list List all repositories @@ -39,7 +89,7 @@ help() { <newname> Rename repository run <repo> \\ <command> Use this repository - setup Set up repository with recommended settings + setup <repo> Set up repository with recommended settings which <substring> Find substring in name of any tracked file write-gitignore \\ <repo> Write .gitignore.d/<repo> via git ls-files @@ -56,11 +106,6 @@ verbose() { if [ -n "$VCSH_DEBUG" ] || [ -n "$VCSH_VERBOSE" ]; then echo "$SELF: verbose: $@"; fi } -fatal() { - echo "$SELF: fatal: $1" >&2 - exit $2 -} - error() { echo "$SELF: error: $1" >&2 } @@ -93,7 +138,7 @@ clone() { delete() { cd "$VCSH_BASE" || fatal "could not enter '$VCSH_BASE'" 11 use - info "This operation WILL DETROY DATA!" + info "This operation WILL DESTROY DATA!" files=$(git ls-files) echo "These files will be deleted: @@ -106,7 +151,7 @@ To continue, type 'Yes, do as I say'" for file in $files; do rm -f $file || info "could not delete '$file', continuing with deletion" done - rm -r "$GIT_DIR" || error "could not delete '$GIT_DIR'" + rm -rf "$GIT_DIR" || error "could not delete '$GIT_DIR'" } enter() { @@ -169,7 +214,7 @@ rename() { run() { hook pre-run use - $VCSH_EXTERNAL_COMMAND + "$@" hook post-run } @@ -259,7 +304,7 @@ elif [ "$1" = 'delete' ] || export VCSH_REPO_NAME="$2" export GIT_DIR="$VCSH_REPO_D/$VCSH_REPO_NAME.git" [ "$VCSH_COMMAND" = 'rename' ] && export GIT_DIR_NEW="$VCSH_REPO_D/$3.git" - [ "$VCSH_COMMAND" = 'run' ] && shift 2 && export VCSH_EXTERNAL_COMMAND="$*" + [ "$VCSH_COMMAND" = 'run' ] && shift 2 [ "$VCSH_COMMAND" = 'write-gitignore' ] elif [ "$1" = 'list' ] || [ "$1" = 'list-tracked' ]; then @@ -270,7 +315,7 @@ elif [ -n "$2" ]; then export GIT_DIR="$VCSH_REPO_D/$VCSH_REPO_NAME.git" [ -d $GIT_DIR ] || { help; exit 1; } shift 1 - export VCSH_EXTERNAL_COMMAND="git $*" + set -- "git" "$@" elif [ -n "$1" ]; then export VCSH_COMMAND='enter' export VCSH_REPO_NAME="$1" @@ -304,6 +349,6 @@ done verbose "$VCSH_COMMAND begin" export VCSH_COMMAND=$(echo $VCSH_COMMAND | sed 's/-/_/g') hook pre-command -$VCSH_COMMAND +$VCSH_COMMAND "$@" hook post-command verbose "$VCSH_COMMAND end, exiting"