diff --git a/.travis.yml b/.travis.yml index 3d40388..d038f60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,16 @@ -script: ./run_tests.sh +os: + - linux + - osx + +env: + - TEST_SHELLS=bash + - TEST_SHELLS=zsh + +install: + - ./test/support/travisci_deps.sh + before_script: - - sudo apt-get install zsh + - echo -e "test_repo_11\ntest_repo_1" | sort + +script: + - ./run_tests.sh diff --git a/README.markdown b/README.markdown index ec4181c..07abd94 100644 --- a/README.markdown +++ b/README.markdown @@ -1,41 +1,81 @@ -# SCM Breeze [![TravisCI](https://secure.travis-ci.org/ndbroadbent/scm_breeze.png?branch=master)](http://travis-ci.org/ndbroadbent/scm_breeze) -### Streamline your SCM workflow. - -**SCM Breeze** is a set of shell scripts (for `bash` and `zsh`) that enhance your interaction with git. It integrates with your shell to give you numbered file shortcuts, -a repository index with tab completion, and many other useful features. - -
- -## Demo video - -
- -
- -## File Shortcuts - -SCM Breeze makes it really easy to work with changed files, and groups of changed files. -Whenever you view your SCM status, each modified path is stored in a numbered environment variable. -You can configure the variable prefix, which is 'e' by default. + -### Git Status Shortcuts: + +# SCM Breeze [![TravisCI](https://secure.travis-ci.org/scmbreeze/scm_breeze.png?branch=master)](http://travis-ci.org/scmbreeze/scm_breeze) + +> Streamline your SCM workflow. + +**SCM Breeze** is a set of shell scripts (for `bash` and `zsh`) that enhance +your interaction with git. It integrates with your shell to give you numbered +file shortcuts, a repository index with tab completion, and many other useful +features. + +![SCM Breeze Example Gif](http://i.imgur.com/3fD8cpo.gif) + + +- [Installation](#installation) +- [Usage](#usage) + - [File Shortcuts](#file-shortcuts) + - [Keyboard bindings](#keyboard-bindings) + - [Repository Index](#repository-index) + - [Linking External Project Design Directories](#linking-external-project-design-directories) +- [Configuration](#configuration) +- [Updating](#updating) +- [Uninstalling](#uninstalling) +- [Notes about Tab Completion for Aliases](#notes-about-tab-completion-for-aliases) +- [Contributing](#contributing) + + +## Installation + +```bash +git clone git://github.com/scmbreeze/scm_breeze.git ~/.scm_breeze +~/.scm_breeze/install.sh +source ~/.bashrc # or source ~/.zshrc +``` + +The install script creates required default configs and adds the following line +to your `.bashrc` or `.zshrc`: + +`[ -s "$HOME/.scm_breeze/scm_breeze.sh" ] && source "$HOME/.scm_breeze/scm_breeze.sh"` + +**Note:** SCM Breeze performs much faster if you have ruby installed. + + +## Usage + +
+ +### File Shortcuts + +SCM Breeze makes it really easy to work with changed files, and groups of +changed files. Whenever you view your SCM status, each modified path is stored +in a numbered environment variable. You can configure the variable prefix, +which is 'e' by default. + + +#### Git Status Shortcuts:
Git Status With Shortcuts

-### 'ls' shortcuts: + +#### 'ls' shortcuts:
Ls With Shortcuts

-These numbers (or ranges of numbers) can be used with any SCM or system command. +These numbers (or ranges of numbers) can be used with any SCM or system +command. -For example, if `ga` was your alias for `git add`, instead of typing something like: +For example, if `ga` was your alias for `git add`, instead of typing something +like: ```bash $ ga assets/git_breeze/config* assets/git_breeze/install.sh @@ -47,8 +87,8 @@ You can type this instead: $ ga $e2 $e3 $e11 ``` -But SCM Breeze aliases `ga` to the `git_add_shortcuts` function, -which is smart enough to expand integers and ranges, so all you need to type is: +But SCM Breeze aliases `ga` to the `git_add_shortcuts` function, which is smart +enough to expand integers and ranges, so all you need to type is: ```bash $ ga 2 3 11 @@ -60,8 +100,8 @@ And if you want to add all unstaged changes (files 1 to 10): $ ga 1-10 ``` -(Note that `ga` will also remove deleted files, unlike the standard `git add` command. -This behaviour can be turned off if you don't like it.) +(Note that `ga` will also remove deleted files, unlike the standard `git add` +command. This behaviour can be turned off if you don't like it.) You can also diff, reset or checkout a file by typing: @@ -73,8 +113,8 @@ $ gco 5 ``` -You can use these shortcuts with system commands by passing your command through `exec_scmb_expand_args` -(default alias is 'ge'): +You can use these shortcuts with system commands by passing your command +through `exec_scmb_expand_args` (default alias is `ge`): ```bash @@ -88,19 +128,21 @@ $ ge echo 1-3 ``` -### Other shortcuts +#### Other shortcuts -SCM Breeze adds a number of aliases to your shell. Use `list_aliases` to view all the aliases and their corresponding commands. -You can filter aliases by adding a search string: `list_aliases git log` +SCM Breeze adds a number of aliases to your shell. Use `list_aliases` to view +all the aliases and their corresponding commands. You can filter aliases by +adding a search string: `list_aliases git log` -There's also a `git_aliases` command, which just shows aliases for `git` commands. You can also pass in additional filters, e.g. `git_aliases log`. +There's also a `git_aliases` command, which just shows aliases for `git` +commands. You can also pass in additional filters, e.g. `git_aliases log`. -## Keyboard bindings +### Keyboard bindings -Some of my most common git commands are `git add` and `git commit`, so I wanted these -to be as streamlined as possible. One way of speeding up commonly used commands is by binding them to -keyboard shortcuts. +Some of my most common git commands are `git add` and `git commit`, so I wanted +these to be as streamlined as possible. One way of speeding up commonly used +commands is by binding them to keyboard shortcuts. Here are the default key bindings: @@ -108,14 +150,13 @@ Here are the default key bindings: * `CTRL`+`x` `SPACE` => `git_commit_all` - commit everything -The commit shortcuts use the `git_commit_prompt` function, which gives a simple prompt like this: +The commit shortcuts use the `git_commit_prompt` function, which gives a simple +prompt like this: -
-Git Commit All -
-
-(When using bash, this commit prompt gives you access to your bash history via the arrow keys.) -
+

(When using bash, this commit prompt gives +you access to your bash history via the arrow keys.)
And if you really want to speed up your workflow, you can type this: @@ -131,23 +172,26 @@ This sends the `HOME` key, followed by `git_add_and_commit`:
-## Repository Index +### Repository Index -The second feature is a repository index for all of your projects and submodules. -This gives you super-fast switching between your project directories, with tab completion, -and it can even tab-complete down to project subdirectories. -This means that you can keep your projects organized in subfolders, -but switch between them as easily as if they were all in one folder. +The second feature is a repository index for all of your projects and +submodules. This gives you super-fast switching between your project +directories, with tab completion, and it can even tab-complete down to project +subdirectories. This means that you can keep your projects organized in +subfolders, but switch between them as easily as if they were all in one +folder. -It's similar to [autojump](https://github.com/joelthelion/autojump), but it doesn't need to 'learn' anything, -and it can do SCM-specific stuff like: +It's similar to [autojump](https://github.com/joelthelion/autojump), but it +doesn't need to 'learn' anything, and it can do SCM-specific stuff like: -* Running a command for all of your repos (useful if you ever need to update a lot of remote URLs) +* Running a command for all of your repos (useful if you ever need to update a + lot of remote URLs) * Update all of your repositories via a cron task The default alias for `git_index` is 'c', which might stand for 'code' -You will first need to configure your repository directory, and then build the index: +You will first need to configure your repository directory, and then build the +index: ```bash $ c --rebuild @@ -155,10 +199,12 @@ $ c --rebuild # => ===== Indexed 64 repos in /home/ndbroadbent/code/.git_index ``` -Then you'll be able to switch between your projects, or show the list of indexed repos. +Then you'll be able to switch between your projects, or show the list of +indexed repos. -To switch to a project directory, you don't need to type the full project name. For example, -to switch to the `capistrano` project, you could type any of the following: +To switch to a project directory, you don't need to type the full project name. +For example, to switch to the `capistrano` project, you could type any of the +following: ```bash $ c capistrano @@ -177,19 +223,20 @@ $ c capistrano/lib/ # => cd ~/code/gems/capistrano/lib ``` -Or if you want to go to a subdirectory within the `~/code` directory, prefix the first argument with a `/`: +Or if you want to go to a subdirectory within the `~/code` directory, prefix +the first argument with a `/`: ```bash ~ $ c /gems ~/code/gems $ ``` -## Linking External Project Design Directories +### Linking External Project Design Directories -When you're creating logos or icons for a project that uses `git`, -have you ever wondered where you should store those `.psd` or `.xcf` files? -Do you commit all of your raw design files, or does it put you off that any changes to those files -will bloat your repository? +When you're creating logos or icons for a project that uses `git`, have you +ever wondered where you should store those `.psd` or `.xcf` files? Do you +commit all of your raw design files, or does it put you off that any changes to +those files will bloat your repository? Here were my goals when I set out to find a solution: @@ -198,164 +245,168 @@ Here were my goals when I set out to find a solution: * The design directory needed to be synchronized across all of my machines The simplest way for me to synchronize files was via my Dropbox account. -However, if you work with a larger team, you could set up a shared design directory on one -of your servers and synchronize it with `rsync`. +However, if you work with a larger team, you could set up a shared design +directory on one of your servers and synchronize it with `rsync`. -### 1) Create and configure a root design directory +#### 1) Create and configure a root design directory I created my root design directory at `~/Dropbox/Design`. -After you've created your root design directory, edit `~/.scmbrc` and set `root_design_dir` -to the directory you just created. -You can also configure the design directory that's created in each of your projects -(default: `design_assets`), as well as the subdirectories you would like to use. -The default base subdirectories are: Images, Backgrounds, Logos, Icons, Mockups, and Screenshots. +After you've created your root design directory, edit `~/.scmbrc` and set +`root_design_dir` to the directory you just created. You can also configure +the design directory that's created in each of your projects (default: +`design_assets`), as well as the subdirectories you would like to use. The +default base subdirectories are: Images, Backgrounds, Logos, Icons, Mockups, +and Screenshots. -After you have changed these settings, remember to run `source ~/.bashrc` or `source ~/.zshrc`. +After you have changed these settings, remember to run `source ~/.bashrc` or +`source ~/.zshrc`. -### 2) Initialize design directories for your projects +#### 2) Initialize design directories for your projects -To set up the design directories and symlinks, go to a project's directory and run: +To set up the design directories and symlinks, go to a project's directory and +run: ```bash design init ``` If your root directory is `~/Dropbox/Design`, directories will be created at -`~/Dropbox/Design/projects/my_project/Backgrounds`, `~/Dropbox/Design/projects/my_project/Icons`, etc. +`~/Dropbox/Design/projects/my_project/Backgrounds`, +`~/Dropbox/Design/projects/my_project/Icons`, etc. -It will then symlink the project from your root design directory into your project's design directory, -so you end up with: +It will then symlink the project from your root design directory into your +project's design directory, so you end up with: * `my_project/design_assets` -> `~/Dropbox/Design/projects/my_project` It also adds this directory to `.git/info/exclude` so that git ignores it. -If you use the git repository index, -you can run the following batch command to set up these directories for all of your git repos at once: +If you use the git repository index, you can run the following batch command to +set up these directories for all of your git repos at once: ```bash git_index --batch-cmd design init ``` - If you want to remove any empty design directories, run: ```bash design trim ``` -And if you want to remove all of a project's design directories, even if they contain files: +And if you want to remove all of a project's design directories, even if they +contain files: ```bash design rm ``` -### 3) Link existing design directories into your projects +#### 3) Link existing design directories into your projects -If you've set up your design directories on one machine, you'll want them -to be synchronized across all of your other development machines. +If you've set up your design directories on one machine, you'll want them to be +synchronized across all of your other development machines. -Just run the following command on your other machines after you've configured the root design directory: +Just run the following command on your other machines after you've configured +the root design directory: ```bash design link ``` -This uses your git index to figure out where to create the symlinks. -If you don't use the git index, the same outcome could be achieved by running 'design init' -for each of the projects. +This uses your git index to figure out where to create the symlinks. If you +don't use the git index, the same outcome could be achieved by running 'design +init' for each of the projects. +## Configuration -## Contributing tools / scripts +SCM Breeze is configured via automatically installed `~/.*.scmbrc` files. To +change git configuration, edit `~/.git.scmbrc`. -If you have any awesome SCM scripts lurking in your `.bashrc` or `.zshrc`, -please feel free to send me a pull request. -It would be cool to make this project into an [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh) for SCMs. +Each feature is modular, so you are free to ignore the parts you don't want to +use. Just comment out the relevant line in `~/.scm_breeze/scm_breeze.sh`. + +**Note:** After changing any settings, you will need to run `source ~/.bashrc` +(or `source ~/.zshrc`) + +I know we grow attached to the aliases we use every day, so I've made the alias +system completely customizable. You have two options when it comes to aliases: -# Installation +### 1) Configure and use the provided SCM Breeze aliases -```bash -git clone git://github.com/ndbroadbent/scm_breeze.git ~/.scm_breeze -~/.scm_breeze/install.sh -source ~/.bashrc # or source ~/.zshrc -``` - -The install script just adds the following line to your `.bashrc` or `.zshrc`: - -`[ -s "$HOME/.scm_breeze/scm_breeze.sh" ] && source "$HOME/.scm_breeze/scm_breeze.sh"` +Just tweak the aliases in `~/.git.scmbrc`. You can also change or remove any +keyboard shortcuts. These aliases also come with tab completion. For example, +you can type `gco ` to tab complete your list of branches. -# Updating +### 2) Use your own aliases -Please run `update_scm_breeze` to fetch the latest code. This will update SCM Breeze from Github, -and will create or patch your `~/.*.scmbrc` config files if any new settings are added. +In your `git.scmbrc` config file, just set the `git_setup_aliases` option to +`no`. Your existing git aliases will then be used, and you will still be able +to use the numeric shortcuts feature. SCM Breeze creates a function to wrap +the 'git' command, which expands numeric arguments, and uses `hub` if +available. -# Uninstall +A few aliases will still be defined for the central SCM Breeze features, such +as `gs` for the extended `git status`, and `ga` for the `git add` function. + +If you already have an alias like `alias gco="git checkout"`, you can now type +`gco 1` to checkout the first file in the output of SCM Breeze's `git status`. + + +## Notes about Tab Completion for Aliases + +### Bash + +If you use your own aliases, SCM Breeze will **not** set up bash tab completion +for your aliases. You will need to set that up yourself. + + +### Zsh + +You just need to set the option: `setopt no_complete_aliases` (oh-my-zsh sets +this by default). Zsh will then expand aliases like `gb` to `git branch`, and +use the completion for that. + + +## Updating + +Please run `update_scm_breeze` to fetch the latest code. This will update SCM +Breeze from Github, and will create or patch your `~/.*.scmbrc` config files if +any new settings are added. + + +## Uninstalling ```bash ~/.scm_breeze/uninstall.sh ``` -The uninstall script removes the following line from your `.bashrc` or `.zshrc`: +The uninstall script removes the following line from your `.bashrc` or +`.zshrc`: `[ -s "$HOME/.scm_breeze/scm_breeze.sh" ] && source "$HOME/.scm_breeze/scm_breeze.sh"` -# Configuration -SCM Breeze is configured via automatically installed `~/.*.scmbrc` files. -To change git configuration, edit `~/.git.scmbrc`. +## Contributing -Each feature is modular, so you are free to ignore the parts you don't want to use. -Just comment out the relevant line in `~/.scm_breeze/scm_breeze.sh`. +SCM Breeze lives on Github at +[`scmbreeze/scm_breeze`](https://github.com/scmbreeze/scm_breeze) -**Note:** After changing any settings, you will need to run `source ~/.bashrc` (or `source ~/.zshrc`) +If you have any awesome SCM scripts lurking in your `.bashrc` or `.zshrc`, +please feel free to send me a pull request. It would be cool to make this +project into an [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh) for +SCMs. -I know we grow attached to the aliases we use every day, so I've made the alias system completely customizable. -You have two options when it comes to aliases: +***Enjoy!*** -### 1) Configure and use the provided SCM Breeze aliases - -Just tweak the aliases in `~/.git.scmbrc`. You can also change or remove any keyboard shortcuts. -These aliases also come with tab completion. For example, you can type `gco ` to tab complete your list of branches. - -### 2) Use your own aliases - -In your `git.scmbrc` config file, just set the `git_setup_aliases` option to `no`. -Your existing git aliases will then be used, and you will still be able to use the numeric shortcuts feature. -SCM Breeze creates a function to wrap the 'git' command, which expands numeric arguments, and uses `hub` if available. - -A few aliases will still be defined for the central SCM Breeze features, such as `gs` for the extended `git status`, -and `ga` for the `git add` function. - -If you already have an alias like `alias gco="git checkout"`, -you can now type `gco 1` to checkout the first file in the output of SCM Breeze's `git status`. - -# Notes about Tab Completion for Aliases - -### Bash - -If you use your own aliases, SCM Breeze will **not** set up bash tab completion for your aliases. -You will need to set that up yourself. - -### Zsh - -You just need to set the option: `setopt no_complete_aliases` (oh-my-zsh sets this by default). -Zsh will then expand aliases like `gb` to `git branch`, and use the completion for that. - -# Contributing - -SCM Breeze lives on Github at [https://github.com/ndbroadbent/scm_breeze](https://github.com/ndbroadbent/scm_breeze) - -Please feel free to fork and send pull requests, especially if you would like to build these features -for Mercurial, SVN, etc. - - -## Enjoy! +## Alternative Projects +1. https://github.com/shinriyo/breeze `fish` support +1. https://github.com/mroth/scmpuff static go binary diff --git a/git.scmbrc.example b/git.scmbrc.example index f7867a6..a1ccca3 100644 --- a/git.scmbrc.example +++ b/git.scmbrc.example @@ -34,13 +34,13 @@ git_alias="g" # 1. 'SCM Breeze' functions git_status_shortcuts_alias="gs" git_add_shortcuts_alias="ga" -git_add_patch_alias="gap" -git_add_updated_alias="gau" -git_show_files_alias="gsf" exec_scmb_expand_args_alias="ge" +git_show_files_alias="gsf" +git_commit_all_alias="gca" +git_grep_shortcuts_alias="gtrep" # 2. Commands that handle paths (with shortcut args expanded) git_checkout_alias="gco" -git_checkout_branch_alias="gcob" +git_checkout_branch_alias="gcb" git_commit_alias="gc" git_commit_verbose_alias="gcv" git_reset_alias="grs" @@ -48,6 +48,8 @@ git_reset_hard_alias="grsh" git_rm_alias="grm" git_blame_alias="gbl" git_diff_alias="gd" +git_diff_no_whitespace_alias="gdnw" +git_diff_file_alias="gdf" git_diff_word_alias="gdw" git_diff_cached_alias="gdc" git_difftool_alias="gdt" @@ -57,6 +59,7 @@ git_fetch_alias="gf" git_fetch_all_alias="gfa" git_fetch_and_rebase_alias="gfr" git_pull_alias="gpl" +git_pull_rebase_alias="gplr" git_push_alias="gps" git_push_force_alias="gpsf" git_pull_then_push_alias="gpls" @@ -65,7 +68,8 @@ git_status_short_alias="gss" git_clean_alias="gce" git_clean_force_alias="gcef" git_add_all_alias="gaa" -git_commit_all_alias="gca" +git_add_patch_alias="gap" +git_add_updated_alias="gau" git_commit_amend_alias="gcm" git_commit_amend_no_msg_alias="gcmh" git_commit_no_msg_alias="gch" @@ -86,7 +90,7 @@ git_merge_only_fast_forward_alias="gmff" git_cherry_pick_alias="gcp" git_log_alias="gl" git_log_all_alias="gla" -git_log_stat_alias="gls" +git_log_stat_alias="glst" git_log_graph_alias="glg" git_show_alias="gsh" git_show_summary="gsm" # (gss taken by git status short) @@ -95,6 +99,13 @@ git_stash_apply_alias="gasha" git_stash_pop_alias="gashp" git_stash_list_alias="gashl" git_tag_alias="gt" +git_submodule_update_alias="gsu" +git_submodule_update_rec_alias="gsur" +git_top_level_alias="gtop" +git_whatchanged_alias="gwc" +git_apply_alias="gapp" +# Hub aliases (https://github.com/github/hub) +git_pull_request_alias="gpr" # Git Keyboard Shortcuts @@ -112,3 +123,5 @@ git_commit_all_with_ci_skip_keys="\C-xv" # CTRL+x, v (Appends [ci skip] to c shell_command_wrapping_enabled="true" # Here you can tweak the list of wrapped commands. scmb_wrapped_shell_commands="vim emacs gedit cat rm cp mv ln cd" +# Add numbered shortcuts to output of ls -l, just like 'git status' +shell_ls_aliases_enabled="true" diff --git a/install.sh b/install.sh index 31f4631..dd025ef 100755 --- a/install.sh +++ b/install.sh @@ -10,11 +10,19 @@ fi # This loads SCM Breeze into the shell session. exec_string="[ -s \"$HOME/.scm_breeze/scm_breeze.sh\" ] && source \"$HOME/.scm_breeze/scm_breeze.sh\"" -# Add line to bashrc and zshrc if not already present. -for rc in bashrc zshrc; do - if [ -s "$HOME/.$rc" ] && ! grep -q "$exec_string" "$HOME/.$rc"; then - printf "\n$exec_string\n" >> "$HOME/.$rc" - printf "== Added SCM Breeze to '~/.$rc'\n" +# Add line to bashrc, zshrc, and bash_profile if not already present. +added_to_profile=false +already_present=false +for rc in bashrc zshrc bash_profile; do + if [ -s "$HOME/.$rc" ]; then + if grep -q "$exec_string" "$HOME/.$rc"; then + printf "== Already installed in '~/.$rc'\n" + already_present=true + else + printf "\n$exec_string\n" >> "$HOME/.$rc" + printf "== Added SCM Breeze to '~/.$rc'\n" + added_to_profile=true + fi fi done @@ -23,5 +31,12 @@ source "$scmbDir/lib/scm_breeze.sh" # Create '~/.*.scmbrc' files from example files _create_or_patch_scmbrc - -echo "== Run 'source ~/.bashrc' or 'source ~/.zshrc' to load SCM Breeze into your current shell." +if [ "$added_to_profile" = true ] || [ "$already_present" = true ]; then + echo "== SCM Breeze Installed! Run 'source ~/.bashrc || source ~/.bash_profile' or 'source ~/.zshrc'" + echo " to load SCM Breeze into your current shell." +else + echo "== Error:" + echo " Found no profile to add SCM Breeze to." + echo " Add line to your shell profile and source it to install manually:" + printf " $exec_string\n" +fi diff --git a/lib/bzr/BUILDME b/lib/bzr/BUILDME deleted file mode 100644 index e69de29..0000000 diff --git a/lib/design.sh b/lib/design.sh index 5106247..125175e 100644 --- a/lib/design.sh +++ b/lib/design.sh @@ -23,7 +23,7 @@ # Add ignore rule to .git/info/exclude if not already present _design_add_git_exclude(){ - local git_dir="$(cd $1 && readlink -m $(git rev-parse --git-dir))" + local git_dir="$(cd $1 && cd `git rev-parse --git-dir` && pwd -P)" if [ -e "$git_dir/info/exclude" ] && ! $(grep -q "$project_design_dir" "$git_dir/info/exclude"); then echo "$project_design_dir" >> "$git_dir/info/exclude" fi @@ -102,5 +102,6 @@ design() { printf "Invalid command.\n\n" design fi + unset IFS } diff --git a/lib/git/aliases.sh b/lib/git/aliases.sh index 91d95de..28b0e31 100644 --- a/lib/git/aliases.sh +++ b/lib/git/aliases.sh @@ -21,12 +21,14 @@ export _git_cmd="$(\which git)" # Wrap git with the 'hub' github wrapper, if installed (https://github.com/defunkt/hub) if type hub > /dev/null 2>&1; then export _git_cmd="hub"; fi +# gh is now deprecated, and merged into the `hub` command line tool. +#if type gh > /dev/null 2>&1; then export _git_cmd="gh"; fi # Create 'git' function that calls hub if defined, and expands all numeric arguments function git(){ # Only expand args for git commands that deal with paths or branches case $1 in - commit|blame|add|log|rebase|merge) + commit|blame|add|log|rebase|merge|difftool) exec_scmb_expand_args "$_git_cmd" "$@";; checkout|diff|rm|reset) exec_scmb_expand_args --relative "$_git_cmd" "$@";; @@ -37,7 +39,7 @@ function git(){ esac } -_alias $git_alias='git' +_alias "$git_alias" "git" # -------------------------------------------------------------------- @@ -64,91 +66,111 @@ _git # Usage: __git_alias __git_alias () { if [ -n "$1" ]; then - local alias_str="$1"; local cmd_prefix="$2"; local cmd="$3"; local cmd_args="${4-}" - alias $alias_str="$cmd_prefix $cmd${cmd_args:+ }$cmd_args" + local alias_str cmd_prefix cmd cmd_args + + alias_str="$1"; cmd_prefix="$2"; cmd="$3"; + if [ $# -gt 2 ]; then + shift 3 2>/dev/null + cmd_args=$@ + fi + + alias $alias_str="$cmd_prefix $cmd${cmd_args:+ }${cmd_args[*]}" if [ "$shell" = "bash" ]; then - __define_git_completion $alias_str $cmd - complete -o default -o nospace -F _git_"$alias_str"_shortcut $alias_str + __define_git_completion "$alias_str" "$cmd" + complete -o default -o nospace -F _git_"$alias_str"_shortcut "$alias_str" fi fi } # -------------------------------------------------------------------- # SCM Breeze functions -_alias $git_status_shortcuts_alias="git_status_shortcuts" -_alias $git_add_shortcuts_alias="git_add_shortcuts" -_alias $exec_scmb_expand_args_alias="exec_scmb_expand_args" -_alias $git_show_files_alias="git_show_affected_files" -_alias $git_commit_all_alias='git_commit_all' +_alias "$git_status_shortcuts_alias" 'git_status_shortcuts' +_alias "$git_add_shortcuts_alias" 'git_add_shortcuts' +_alias "$exec_scmb_expand_args_alias" 'exec_scmb_expand_args' +_alias "$git_show_files_alias" 'git_show_affected_files' +_alias "$git_commit_all_alias" 'git_commit_all' +_alias "$git_grep_shortcuts_alias" 'git_grep_shortcuts' # Git Index alias -_alias $git_index_alias="git_index" +_alias "$git_index_alias" 'git_index' # Only set up the following aliases if 'git_setup_aliases' is 'yes' if [ "$git_setup_aliases" = "yes" ]; then # Commands that deal with paths - __git_alias "$git_checkout_alias" "git" "checkout" - __git_alias "$git_commit_alias" "git" "commit" - __git_alias "$git_commit_verbose_alias" "git" "commit" "--verbose" - __git_alias "$git_reset_alias" "git" "reset" "--" - __git_alias "$git_reset_hard_alias" "git" "reset" "--hard" - __git_alias "$git_rm_alias" "git" "rm" - __git_alias "$git_blame_alias" "git" "blame" - __git_alias "$git_diff_alias" "git" "diff" "--" - __git_alias "$git_diff_word_alias" "git" "diff" "--word-diff" - __git_alias "$git_diff_cached_alias" "git" "diff" "--cached --" - __git_alias "$git_add_patch_alias" "git" "add" "-p" - __git_alias "$git_add_updated_alias" "git" "add" "-u" - __git_alias "$git_difftool_alias" "git" "difftool" + __git_alias "$git_checkout_alias" 'git' 'checkout' + __git_alias "$git_commit_alias" 'git' 'commit' + __git_alias "$git_commit_verbose_alias" 'git' 'commit' '--verbose' + __git_alias "$git_reset_alias" 'git' 'reset' + __git_alias "$git_reset_hard_alias" 'git' 'reset' '--hard' + __git_alias "$git_rm_alias" 'git' 'rm' + __git_alias "$git_blame_alias" 'git' 'blame' + __git_alias "$git_diff_no_whitespace_alias" 'git' 'diff' '-w' + __git_alias "$git_diff_alias" 'git' 'diff' + __git_alias "$git_diff_file_alias" 'git' 'diff' + __git_alias "$git_diff_word_alias" 'git' 'diff' '--word-diff' + __git_alias "$git_diff_cached_alias" 'git' 'diff' '--cached' + __git_alias "$git_add_patch_alias" 'git' 'add' '-p' + __git_alias "$git_add_updated_alias" 'git' 'add' '-u' + __git_alias "$git_difftool_alias" 'git' 'difftool' + # Custom default format for git log git_log_command="log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" - __git_alias "$git_log_alias" "git" "$git_log_command" + __git_alias "$git_log_alias" 'git' "$git_log_command" # Same as the above, but displays all the branches and remotes - __git_alias "$git_log_all_alias" "git" "$git_log_command" "--branches" "--remotes" + __git_alias "$git_log_all_alias" 'git' "$git_log_command" '--branches' '--remotes' # Standard commands - __git_alias "$git_clone_alias" "git" 'clone' - __git_alias "$git_fetch_alias" "git" 'fetch' - __git_alias "$git_checkout_branch_alias" "git" 'checkout' "-b" - __git_alias "$git_pull_alias" "git" 'pull' - __git_alias "$git_push_alias" "git" 'push' - __git_alias "$git_push_force_alias" "git" 'push' '-f' - __git_alias "$git_status_original_alias" "git" 'status' # (Standard git status) - __git_alias "$git_status_short_alias" "git" 'status' '-s' - __git_alias "$git_clean_alias" "git" "clean" - __git_alias "$git_clean_force_alias" "git" "clean" "-fd" - __git_alias "$git_remote_alias" "git" 'remote' '-v' - __git_alias "$git_rebase_alias" "git" 'rebase' - __git_alias "$git_rebase_interactive_alias" "git" 'rebase' "-i" - __git_alias "$git_rebase_alias_continue" "git" 'rebase' "--continue" - __git_alias "$git_rebase_alias_abort" "git" 'rebase' "--abort" - __git_alias "$git_reset_last_commit" "git" "reset HEAD~" - __git_alias "$git_merge_alias" "git" 'merge' - __git_alias "$git_merge_no_fast_forward_alias" "git" "merge" "--no-ff" - __git_alias "$git_merge_only_fast_forward_alias" "git" "merge" "--ff" - __git_alias "$git_cherry_pick_alias" "git" 'cherry-pick' - __git_alias "$git_show_alias" "git" 'show' - __git_alias "$git_show_summary" "git" 'show' '--summary' - __git_alias "$git_stash_alias" "git" 'stash' - __git_alias "$git_stash_apply_alias" "git" 'stash' 'apply' - __git_alias "$git_stash_pop_alias" "git" 'stash' 'pop' - __git_alias "$git_stash_list_alias" "git" 'stash' 'list' - __git_alias "$git_tag_alias" "git" 'tag' - + __git_alias "$git_clone_alias" 'git' 'clone' + __git_alias "$git_fetch_alias" 'git' 'fetch' + __git_alias "$git_checkout_branch_alias" 'git' 'checkout' '-b' + __git_alias "$git_pull_alias" 'git' 'pull' + __git_alias "$git_pull_rebase_alias" 'git' 'pull' '--rebase' + __git_alias "$git_push_alias" 'git' 'push' + __git_alias "$git_push_force_alias" 'git' 'push' '-f' + __git_alias "$git_status_original_alias" 'git' 'status' # (Standard git status) + __git_alias "$git_status_short_alias" 'git' 'status' '-s' + __git_alias "$git_clean_alias" 'git' 'clean' + __git_alias "$git_clean_force_alias" 'git' 'clean' '-fd' + __git_alias "$git_remote_alias" 'git' 'remote' '-v' + __git_alias "$git_rebase_alias" 'git' 'rebase' + __git_alias "$git_rebase_interactive_alias" 'git' 'rebase' '-i' + __git_alias "$git_rebase_alias_continue" 'git' 'rebase' '--continue' + __git_alias "$git_rebase_alias_abort" 'git' 'rebase' '--abort' + __git_alias "$git_reset_last_commit" 'git' 'reset HEAD~' + __git_alias "$git_top_level_alias" 'git' 'rev-parse' '--show-toplevel' + __git_alias "$git_merge_alias" 'git' 'merge' + __git_alias "$git_merge_no_fast_forward_alias" 'git' 'merge' '--no-ff' + __git_alias "$git_merge_only_fast_forward_alias" 'git' 'merge' '--ff' + __git_alias "$git_cherry_pick_alias" 'git' 'cherry-pick' + __git_alias "$git_show_alias" 'git' 'show' + __git_alias "$git_show_summary" 'git' 'show' '--summary' + __git_alias "$git_stash_alias" 'git' 'stash' + __git_alias "$git_stash_apply_alias" 'git' 'stash' 'apply' + __git_alias "$git_stash_pop_alias" 'git' 'stash' 'pop' + __git_alias "$git_stash_list_alias" 'git' 'stash' 'list' + __git_alias "$git_tag_alias" 'git' 'tag' + __git_alias "$git_submodule_update_alias" 'git' 'submodule' 'update' '--init' + __git_alias "$git_submodule_update_rec_alias" 'git' 'submodule' 'update' '--init' '--recursive' + __git_alias "$git_whatchanged_alias" 'git' 'whatchanged' + __git_alias "$git_apply_alias" 'git' 'apply' # Compound/complex commands - _alias $git_fetch_all_alias="git fetch --all" - _alias $git_pull_then_push_alias="git pull && git push" - _alias $git_fetch_and_rebase_alias='git fetch && git rebase' - _alias $git_commit_amend_alias='git commit --amend' + _alias "$git_fetch_all_alias" 'git fetch --all' + _alias "$git_pull_then_push_alias" 'git pull && git push' + _alias "$git_fetch_and_rebase_alias" 'git fetch && git rebase' + _alias "$git_commit_amend_alias" 'git commit --amend' + # Add staged changes to latest commit without prompting for message - _alias $git_commit_amend_no_msg_alias='git commit --amend -C HEAD' - _alias $git_commit_no_msg_alias='git commit -C HEAD' - _alias $git_log_stat_alias='git log --stat --max-count=5' - _alias $git_log_graph_alias='git log --graph --max-count=5' - _alias $git_add_all_alias='git add -A' + _alias "$git_commit_amend_no_msg_alias" 'git commit --amend -C HEAD' + _alias "$git_commit_no_msg_alias" 'git commit -C HEAD' + _alias "$git_log_stat_alias" 'git log --stat --max-count=5' + _alias "$git_log_graph_alias" 'git log --graph --max-count=5' + _alias "$git_add_all_alias" 'git add --all .' + + # Hub aliases (https://github.com/github/hub) + _alias "$git_pull_request_alias" 'git pull-request' fi @@ -168,4 +190,3 @@ if [ $shell = "bash" ]; then else compdef _git_index_tab_completion git_index $git_index_alias fi - diff --git a/lib/git/branch_shortcuts.sh b/lib/git/branch_shortcuts.sh index 1e933b9..61012e2 100644 --- a/lib/git/branch_shortcuts.sh +++ b/lib/git/branch_shortcuts.sh @@ -13,8 +13,9 @@ unalias $git_branch_alias > /dev/null 2>&1; unset -f $git_branch_alias > /dev/null 2>&1 function _scmb_git_branch_shortcuts { fail_if_not_git_repo || return 1 + # Fall back to normal git branch, if any unknown args given - if [[ -n "$@" ]] && [[ "$@" != "-a" ]]; then + if [[ "$($_git_cmd branch | wc -l)" -gt 300 ]] || ([[ -n "$@" ]] && [[ "$@" != "-a" ]]); then exec_scmb_expand_args $_git_cmd branch "$@" return 1 fi @@ -32,14 +33,16 @@ EOF # Set numbered file shortcut in variable local e=1 + IFS=$'\n' for branch in $($_git_cmd branch "$@" | sed "s/^[* ]\{2\}//"); do export $git_env_char$e="$branch" if [ "${scmbDebug:-}" = "true" ]; then echo "Set \$$git_env_char$e => $file"; fi let e++ done + unset IFS } -__git_alias "$git_branch_alias" "_scmb_git_branch_shortcuts" +__git_alias "$git_branch_alias" "_scmb_git_branch_shortcuts" "" __git_alias "$git_branch_all_alias" "_scmb_git_branch_shortcuts" "-a" __git_alias "$git_branch_move_alias" "_scmb_git_branch_shortcuts" "-m" __git_alias "$git_branch_delete_alias" "_scmb_git_branch_shortcuts" "-d" diff --git a/lib/git/fallback/status_shortcuts_shell.sh b/lib/git/fallback/status_shortcuts_shell.sh old mode 100644 new mode 100755 index 86c6694..9368588 --- a/lib/git/fallback/status_shortcuts_shell.sh +++ b/lib/git/fallback/status_shortcuts_shell.sh @@ -114,7 +114,7 @@ git_status_shortcuts() { # so just use plain 'git status' git status fi - IFS=$' \t\n' + unset IFS zsh_reset # Reset zsh environment to default } # Template function for 'git_status_shortcuts'. @@ -127,7 +127,7 @@ _gs_output_file_group() { if [ -z "$project_root" ]; then relative="${stat_file[$i]}" else - dest="$project_root/${stat_file[$i]}" + dest=$(readlink -f "$project_root/${stat_file[$i]}") local pwd=$(readlink -f "$PWD") relative="$(_gs_relative_path "$pwd" "$dest" )" fi diff --git a/lib/git/grep_shortcuts.rb b/lib/git/grep_shortcuts.rb new file mode 100644 index 0000000..9f5ecc4 --- /dev/null +++ b/lib/git/grep_shortcuts.rb @@ -0,0 +1,47 @@ +#!/usr/bin/env ruby +# encoding: UTF-8 + +PROJECT_ROOT = File.exist?(".git") ? Dir.pwd : `\git rev-parse --show-toplevel 2> /dev/null`.strip + +COLORS = { + :rst => "\033[0m", + :del => "\033[0;31m", + :mod => "\033[0;32m", + :new => "\033[0;33m", + :ren => "\033[0;34m", + :cpy => "\033[0;33m", + :typ => "\033[0;35m", + :unt => "\033[0;36m", + :dark => "\033[2;37m", + :branch => "\033[1m", + :header => "\033[0m" +} + +COLOR_MATCH = /\e\[[0-9;]*[mK]/ + +output_files = [] + +stdin = STDIN.set_encoding(Encoding::ASCII_8BIT) + +while stdin.gets + if $. > 1000 + puts "Only showing first 1000 results. Please refine your search." + break + end + print "#{COLORS[:dark]}[#{COLORS[:rst]}#{$.}#{COLORS[:dark]}]#{COLORS[:rst]} " + matches = $_.match(/(^.+?)#{COLOR_MATCH}?:#{COLOR_MATCH}?(\d+)?/) + file = matches[1] + line = matches[2] + output_files << "#{file}#{line ? ":#{line}" : ""}" + puts $_ +end + +print "@@filelist@@::" + +output_files.each_with_index {|f,i| + # If file starts with a '~', treat it as a relative path. + # This is important when dealing with symlinks + print "|" unless i == 0 + print f.start_with?("~") ? f.sub(/~/, '') : File.join(PROJECT_ROOT, f) +} +puts diff --git a/lib/git/grep_shortcuts.sh b/lib/git/grep_shortcuts.sh new file mode 100644 index 0000000..d7024ea --- /dev/null +++ b/lib/git/grep_shortcuts.sh @@ -0,0 +1,24 @@ +git_grep_shortcuts() { + fail_if_not_git_repo || return 1 + git_clear_vars + # Run ruby script, store output + tmp_grep_results="$(git rev-parse --git-dir)/tmp_grep_results_$$" + git grep -n --color=always "$@" | + /usr/bin/env ruby "$scmbDir/lib/git/grep_shortcuts.rb" >"$tmp_grep_results" + + # Fetch list of files from last line of script output + files="$(tail -1 "$tmp_grep_results" | sed 's%@@filelist@@::%%g')" + + # Export numbered env variables for each file + IFS="|" + local e=1 + for file in ${=files}; do + export $git_env_char$e="$file" + let e++ + done + IFS=$' \t\n' + + # Print status + cat "$tmp_grep_results" | sed '$d' | less -SfRMXFi + rm -f "$tmp_grep_results" +} diff --git a/lib/git/keybindings.sh b/lib/git/keybindings.sh index 4ea46c3..11bb698 100644 --- a/lib/git/keybindings.sh +++ b/lib/git/keybindings.sh @@ -27,13 +27,13 @@ if [[ "$git_keyboard_shortcuts_enabled" = "true" ]]; then # Uses emacs style keybindings, so vi mode is not supported for now if ! set -o | grep -q '^vi .*on$'; then if [[ $shell == "zsh" ]]; then - _bind "$git_commit_all_keys" " git_commit_all""\n" - _bind "$git_add_and_commit_keys" " \033[1~ git_add_and_commit ""\n" - _bind "$git_commit_all_with_ci_skip_keys" " \033[1~ APPEND='[ci skip]' git_commit_all ""\n" + _bind "$git_commit_all_keys" " git_commit_all""^M" + _bind "$git_add_and_commit_keys" " \033[1~ git_add_and_commit ""^M" + _bind "$git_commit_all_with_ci_skip_keys" " \033[1~ APPEND='[ci skip]' git_commit_all ""^M" else - _bind "$git_commit_all_keys" "\" git_commit_all\n\"" - _bind "$git_add_and_commit_keys" "\"\033[1~ git_add_and_commit \n\"" - _bind "$git_commit_all_with_ci_skip_keys" "\"\033[1~ APPEND='[ci skip]' git_commit_all \n\"" + _bind "$git_commit_all_keys" "\" git_commit_all^M\"" + _bind "$git_add_and_commit_keys" "\"\C-A git_add_and_commit ^M\"" + _bind "$git_commit_all_with_ci_skip_keys" "\"\C-A APPEND='[ci skip]' git_commit_all ^M\"" fi fi diff --git a/lib/git/repo_index.sh b/lib/git/repo_index.sh index 44964f9..3d2e9c7 100644 --- a/lib/git/repo_index.sh +++ b/lib/git/repo_index.sh @@ -68,8 +68,8 @@ function git_index() { elif [ "$1" = "--list" ] || [ "$1" = "-l" ]; then echo -e "$_bld_col$(_git_index_count)$_txt_col Git repositories in $_bld_col$GIT_REPO_DIR$_txt_col:\n" for repo in $(_git_index_dirs_without_home); do - echo $(basename $repo) : $repo - done | sort | column -t -s ':' + echo $(basename $repo | sed "s/ /_/g") : $repo + done | sort -t ":" -k1,1 | column -t -s ':' elif [ "$1" = "--count-by-host" ]; then echo -e "=== Producing a report of the number of repos per host...\n" _git_index_batch_cmd git remote -v | \grep "origin.*(fetch)" | @@ -116,7 +116,7 @@ function git_index() { fi fi fi - IFS=$' \t\n' + unset IFS } _git_index_dirs_without_home() { @@ -127,11 +127,11 @@ _git_index_dirs_without_home() { function _find_git_repos() { # Find all unarchived projects IFS=$'\n' - for repo in $(find -L "$GIT_REPO_DIR" -maxdepth 4 -name ".git" -type d \! -wholename '*/archive/*'); do + for repo in $(find -L "$GIT_REPO_DIR" -maxdepth 5 -name ".git" -type d \! -wholename '*/archive/*'); do echo ${repo%/.git} # Return project folder, with trailing ':' _find_git_submodules $repo # Detect any submodules done - IFS=$' \t\n' + unset IFS } # List all submodules for a git repo, if any. @@ -148,9 +148,9 @@ function _rebuild_git_index() { # Get repos from src dir and custom dirs, then sort by basename IFS=$'\n' for repo in $(echo -e "$(_find_git_repos)\n$(echo $GIT_REPOS | sed "s/:/\\\\n/g")"); do - echo $(basename $repo | sed "s/ /_/g") $repo - done | sort | cut -d " " -f2- > "$GIT_REPO_DIR/.git_index" - IFS=$' \t\n' + echo $(basename $repo | sed "s/ /_/g"):$repo + done | sort -t ":" -k1,1 | cut -d ":" -f2- >| "$GIT_REPO_DIR/.git_index" + unset IFS if [ "$1" != "--silent" ]; then echo -e "===== Indexed $_bld_col$(_git_index_count)$_txt_col repos in $GIT_REPO_DIR/.git_index" @@ -225,7 +225,7 @@ _git_index_update_all_branches() { echo "=== Skipping $branch: remote and merge refs are not configured." fi done - IFS=$' \t\n' + unset IFS # Update all remotes if there are any branches to update if [ -n "${branches[*]}" ]; then git fetch --all 2> /dev/null; fi @@ -268,7 +268,7 @@ function _git_index_batch_cmd() { cwd="$PWD" if [ -n "$1" ]; then echo -e "== Running command for $_bld_col$(_git_index_count)$_txt_col repos...\n" - IFS=$' \t\n' + unset IFS local base_path for base_path in $(sed -e "s/--.*//" "$GIT_REPO_DIR/.git_index" | \grep . | sort); do builtin cd "$base_path" @@ -313,7 +313,7 @@ if [ $shell = 'bash' ]; then else COMPREPLY=($(compgen -W '$(sed -e "s:.*/::" -e "s:$:/:" "$GIT_REPO_DIR/.git_index" | sort)' -- $curw)) fi - IFS=$' \t\n' + unset IFS return 0 } else diff --git a/lib/git/shell_shortcuts.sh b/lib/git/shell_shortcuts.sh index 9bdbe14..4c427d8 100644 --- a/lib/git/shell_shortcuts.sh +++ b/lib/git/shell_shortcuts.sh @@ -5,9 +5,9 @@ # ------------------------------------------------------------------------------ -if test | sed -E 's///g' 2>/dev/null; then +if sed -E 's///g' /dev/null; then SED_REGEX_ARG="E" -elif test | sed -r 's///g' 2>/dev/null; then +elif sed -r 's///g' /dev/null; then SED_REGEX_ARG="r" else echo "Cannot determine extended regex argument for sed! (Doesn't respond to either -E or -r)" @@ -21,7 +21,7 @@ if [ "$shell_command_wrapping_enabled" = "true" ] || [ "$bash_command_wrapping_e # Do it in a function so we don't bleed variables function _git_wrap_commands() { # Define 'whence' for bash, to get the value of an alias - type whence > /dev/null 2>&1 || function whence() { type "$@" | sed -$SED_REGEX_ARG -e "s/.*is aliased to \`//" -e "s/'$//"; } + type whence > /dev/null 2>&1 || function whence() { LC_MESSAGES="C" type "$@" | sed -$SED_REGEX_ARG -e "s/.*is aliased to \`//" -e "s/'$//"; } local cmd='' for cmd in $(echo $scmb_wrapped_shell_commands); do if [ "${scmbDebug:-}" = "true" ]; then echo "SCMB: Wrapping $cmd..."; fi @@ -35,7 +35,7 @@ if [ "$shell_command_wrapping_enabled" = "true" ] || [ "$bash_command_wrapping_e fi fi - case "$(type $cmd 2>&1)" in + case "$(LC_MESSAGES="C" type $cmd 2>&1)" in # Don't do anything if command already aliased, or not found. *'exec_scmb_expand_args'*) @@ -52,7 +52,7 @@ if [ "$shell_command_wrapping_enabled" = "true" ] || [ "$bash_command_wrapping_e unalias $cmd # Detect original $cmd type, and escape - case "$(type $cmd 2>&1)" in + case "$(LC_MESSAGES="C" type $cmd 2>&1)" in # Escape shell builtins with 'builtin' *'is a shell builtin'*) local escaped_cmd="builtin $cmd";; # Get full path for files with 'find_binary' function @@ -108,50 +108,51 @@ fi # Function wrapper around 'll' # Adds numbered shortcuts to output of ls -l, just like 'git status' -unalias ll > /dev/null 2>&1; unset -f ll > /dev/null 2>&1 -function ls_with_file_shortcuts { - local ll_output - if [ "$_ls_bsd" != "BSD" ]; then - ll_output="$(\ls -lhv --group-directories-first --color "$@")" - else - ll_output="$(CLICOLOR_FORCE=1 \ls -l -G "$@")" - fi +if [ "$shell_ls_aliases_enabled" = "true" ] && which ruby > /dev/null 2>&1; then + unalias ll > /dev/null 2>&1; unset -f ll > /dev/null 2>&1 + function ls_with_file_shortcuts { + local ll_output + if [ "$_ls_bsd" != "BSD" ]; then + ll_output="$(\ls -lhv --group-directories-first --color "$@")" + else + ll_output="$(CLICOLOR_FORCE=1 \ls -l -G "$@")" + fi - if [[ $shell == "zsh" ]]; then - # Ensure sh_word_split is on - if setopt | grep -q shwordsplit; then SHWORDSPLIT_ON=true; fi - setopt shwordsplit - fi + if [[ $shell == "zsh" ]]; then + # Ensure sh_word_split is on + if setopt | grep -q shwordsplit; then SHWORDSPLIT_ON=true; fi + setopt shwordsplit + fi - # Parse path from args - OLDIFS="$IFS"; IFS=$'\n' - for arg in $@; do - if [ -d "$arg" ]; then local rel_path="${arg%/}"; fi - done - IFS="$OLDIFS" + # Parse path from args + IFS=$'\n' + for arg in $@; do + if [ -d "$arg" ]; then local rel_path="${arg%/}"; fi + done + unset IFS - # Replace user/group with user symbol, if defined at ~/.user_sym - # Before : -rw-rw-r-- 1 ndbroadbent ndbroadbent 1.1K Sep 19 21:39 scm_breeze.sh - # After : -rw-rw-r-- 1 𝐍 𝐍 1.1K Sep 19 21:39 scm_breeze.sh - if [ -e $HOME/.user_sym ]; then - # Little bit of ruby golf to rejustify the user/group/size columns after replacement - function rejustify_ls_columns(){ - ruby -e "o=STDIN.read;re=/^(([^ ]* +){2})(([^ ]* +){3})/;\ - u,g,s=o.lines.map{|l|l[re,3]}.compact.map(&:split).transpose.map{|a|a.map(&:size).max+1};\ - puts o.lines.map{|l|l.sub(re){|m|\"%s%-#{u}s %-#{g}s%#{s}s \"%[\$1,*\$3.split]}}" - } + # Replace user/group with user symbol, if defined at ~/.user_sym + # Before : -rw-rw-r-- 1 ndbroadbent ndbroadbent 1.1K Sep 19 21:39 scm_breeze.sh + # After : -rw-rw-r-- 1 𝐍 𝐍 1.1K Sep 19 21:39 scm_breeze.sh + if [ -e $HOME/.user_sym ]; then + # Little bit of ruby golf to rejustify the user/group/size columns after replacement + function rejustify_ls_columns(){ + ruby -e "o=STDIN.read;re=/^(([^ ]* +){2})(([^ ]* +){3})/;\ + u,g,s=o.lines.map{|l|l[re,3]}.compact.map(&:split).transpose.map{|a|a.map(&:size).max+1};\ + puts o.lines.map{|l|l.sub(re){|m|\"%s%-#{u}s %-#{g}s%#{s}s \"%[\$1,*\$3.split]}}" + } - ll_output=$(echo "$ll_output" | \sed -$SED_REGEX_ARG "s/ $USER/ $(/bin/cat $HOME/.user_sym)/g" | rejustify_ls_columns) - fi + ll_output=$(echo "$ll_output" | \sed -$SED_REGEX_ARG "s/ $USER/ $(/bin/cat $HOME/.user_sym)/g" | rejustify_ls_columns) + fi - if [ "$(echo "$ll_output" | wc -l)" -gt "50" ]; then - echo -e "\033[33mToo many files to create shortcuts. Running plain ll command...\033[0m" - echo "$ll_output" - return 1 - fi + if [ "$(echo "$ll_output" | wc -l)" -gt "50" ]; then + echo -e "\033[33mToo many files to create shortcuts. Running plain ll command...\033[0m" + echo "$ll_output" + return 1 + fi - # Use ruby to inject numbers into ls output - echo "$ll_output" | ruby -e "$( \cat < $file"; fi - let e++ - done - IFS="$OLDIFS" + IFS=$'\n' + for file in $ll_files; do + if [ -n "$rel_path" ]; then file="$rel_path/$file"; fi + export $git_env_char$e="$(eval $_abs_path_command \"${file//\"/\\\"}\")" + if [ "${scmbDebug:-}" = "true" ]; then echo "Set \$$git_env_char$e => $file"; fi + let e++ + done + unset IFS - # Turn off shwordsplit unless it was on previously - if [[ $shell == "zsh" ]] && [ -z "$SHWORDSPLIT_ON" ]; then unsetopt shwordsplit; fi -} + # Turn off shwordsplit unless it was on previously + if [[ $shell == "zsh" ]] && [ -z "$SHWORDSPLIT_ON" ]; then unsetopt shwordsplit; fi + } -# Setup aliases -alias ll="exec_scmb_expand_args ls_with_file_shortcuts" -alias la="ll -A" \ No newline at end of file + # Setup aliases + alias ll="exec_scmb_expand_args ls_with_file_shortcuts" + alias la="ll -A" +fi diff --git a/lib/git/status_shortcuts.sh b/lib/git/status_shortcuts.sh index fb823b4..d63bb0c 100644 --- a/lib/git/status_shortcuts.sh +++ b/lib/git/status_shortcuts.sh @@ -43,7 +43,7 @@ git_status_shortcuts() { if [ "${scmbDebug:-}" = "true" ]; then echo "Set \$$git_env_char$e => $file"; fi let e++ done - IFS=$' \t\n' + unset IFS if [ "${scmbDebug:-}" = "true" ]; then echo "------------------------"; fi # Print status @@ -91,7 +91,7 @@ git_silent_add_shortcuts() { echo -e "# Added '$file'" fi done - IFS=$' \t\n' + unset IFS echo "#" fi } @@ -158,7 +158,7 @@ _print_path() { # Execute a command with expanded args, e.g. Delete files 6 to 12: $ ge rm 6-12 # Fails if command is a number or range (probably not worth fixing) exec_scmb_expand_args() { - eval "$(scmb_expand_args "$@" | sed -e "s/\([][()<>^ \"']\)/"'\\\1/g')" + eval "$(scmb_expand_args "$@" | sed -e "s/\([][|;()<>^ \"'&]\)/"'\\\1/g')" } # Clear numbered env variables @@ -166,7 +166,12 @@ git_clear_vars() { local i for (( i=1; i<=$gs_max_changes; i++ )); do # Stop clearing after first empty var - if [[ -z "$(eval echo "\${$git_env_char$i:-}")" ]]; then break; fi + local env_var_i=${git_env_char}${i} + if [[ -z "$(eval echo "\${$env_var_i:-}")" ]]; then + break + else + unset $env_var_i + fi done } @@ -181,7 +186,7 @@ _git_resolve_merge_conflict() { git add "$file" echo -e "# Added $1 version of '$file'" done - IFS=$' \t\n' + unset IFS echo -e "# -- If you have finished resolving conflicts, commit the resolutions with 'git commit'" fi } @@ -233,7 +238,7 @@ git_commit_all() { local appending=" | \033[0;36mappending '\033[1;36m$APPEND\033[0;36m' to commit message.\033[0m" fi echo -e "\033[0;33mCommitting all files (\033[0;31m$changes\033[0;33m)\033[0m$appending" - git_commit_prompt "git add -A" + git_commit_prompt "git add --all ." else echo "# No changed files to commit." fi diff --git a/lib/hg/BUILDME b/lib/hg/BUILDME deleted file mode 100644 index e69de29..0000000 diff --git a/lib/scm_breeze.sh b/lib/scm_breeze.sh index 7d84148..2c692bb 100644 --- a/lib/scm_breeze.sh +++ b/lib/scm_breeze.sh @@ -10,7 +10,13 @@ enable_nullglob() { if [ $shell = "zsh" ]; then setopt NULL_GLOB; else shopt disable_nullglob() { if [ $shell = "zsh" ]; then unsetopt NULL_GLOB; else shopt -u nullglob; fi; } # Alias wrapper that ignores errors if alias is not defined. -_alias(){ alias "$@" 2> /dev/null; } +_safe_alias(){ alias "$@" 2> /dev/null; } +_alias() { + if [ -n "$1" ]; then + local alias_str="$1"; local cmd="$2" + _safe_alias $alias_str="$cmd" + fi +} find_binary(){ if [ $shell = "zsh" ]; then @@ -48,7 +54,7 @@ _create_or_patch_scmbrc() { # If file exists, attempt to update it with any new settings elif [ -n "$1" ]; then # Create diff of example file, substituting example file for user's config. - git diff $1 "$prefix""scmbrc.example" | sed "s/$prefix""scmbrc.example/.$prefix""scmbrc/g" > $patchfile + git diff $1 "$prefix""scmbrc.example" | sed "s/$prefix""scmbrc.example/.$prefix""scmbrc/g" >| $patchfile if [ -s $patchfile ]; then # If patchfile is not empty cd "$HOME" # If the patch cannot be applied cleanly, show the updates and tell user to update file manually. diff --git a/lib/svn/BUILDME b/lib/svn/BUILDME deleted file mode 100644 index e69de29..0000000 diff --git a/run_tests.sh b/run_tests.sh index fff4438..e25c5eb 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -3,8 +3,15 @@ failed=false +# allow list of shells to run tests in to be overriden by environment variable +# if empty or null, use defaults +if [ -z "$TEST_SHELLS" ]; then + TEST_SHELLS="bash zsh" +fi + +echo "== Will run all tests with following shells: ${TEST_SHELLS}" for test in $(find test/lib -name *_test.sh); do - for shell in bash zsh; do + for shell in $TEST_SHELLS; do echo "== Running tests with [$shell]: $test" $shell $test || failed=true done @@ -12,8 +19,8 @@ done if [ "$failed" = "true" ]; then echo "Tests failed!" - return 1; + false else echo "All tests passed!" - return 0; -fi \ No newline at end of file + true +fi diff --git a/scm_breeze.plugin.zsh b/scm_breeze.plugin.zsh new file mode 100644 index 0000000..dbd6a0a --- /dev/null +++ b/scm_breeze.plugin.zsh @@ -0,0 +1,25 @@ +######################################################### +# Forked from http://github.com/ndbroadbent/scm_breeze # +# # +# File Copied and modified from ./install.sh # +# to be compatible with oh-my-zsh's plugin system # +######################################################### + +#!/bin/bash +#locate the dir where this script is stored +export scmbDir="$( cd -P "$( dirname "$0" )" && pwd )" + +# Symlink to ~/.scm_breeze if installing from another path +if [ ! -s "$HOME/.scm_breeze" ] && [ "$scmbDir" != "$HOME/.scm_breeze" ]; then + ln -fs "$scmbDir" "$HOME/.scm_breeze" + + # Load SCM Breeze update scripts + source "$scmbDir/lib/scm_breeze.sh" + # Create '~/.*.scmbrc' files from example files + _create_or_patch_scmbrc +fi + +# This loads SCM Breeze into the shell session. +[ -s "$HOME/.scm_breeze/scm_breeze.sh" ] && source "$HOME/.scm_breeze/scm_breeze.sh" + + diff --git a/scm_breeze.sh b/scm_breeze.sh index 98957d5..4d83349 100644 --- a/scm_breeze.sh +++ b/scm_breeze.sh @@ -22,6 +22,7 @@ if [[ -s "$HOME/.git.scmbrc" ]]; then source "$scmbDir/lib/git/keybindings.sh" source "$scmbDir/lib/git/status_shortcuts.sh" source "$scmbDir/lib/git/branch_shortcuts.sh" + source "$scmbDir/lib/git/grep_shortcuts.sh" source "$scmbDir/lib/git/shell_shortcuts.sh" source "$scmbDir/lib/git/repo_index.sh" source "$scmbDir/lib/git/tools.sh" diff --git a/test/lib/git/repo_index_test.sh b/test/lib/git/repo_index_test.sh index d2afa8e..c866ec4 100755 --- a/test/lib/git/repo_index_test.sh +++ b/test/lib/git/repo_index_test.sh @@ -7,10 +7,14 @@ # # Unit tests for git shell scripts -export scmbDir="$( cd -P "$( dirname "$0" )" && pwd )/../../.." +export scmbDir="$(cd -P "$(dirname "$0")" && pwd)/../../.." # Zsh compatibility -if [ -n "${ZSH_VERSION:-}" ]; then shell="zsh"; SHUNIT_PARENT=$0; setopt shwordsplit; fi +if [ -n "${ZSH_VERSION:-}" ]; then + shell="zsh" + SHUNIT_PARENT=$0 + setopt shwordsplit +fi # Load test helpers source "$scmbDir/test/support/test_helper.sh" @@ -19,7 +23,6 @@ source "$scmbDir/test/support/test_helper.sh" source "$scmbDir/lib/scm_breeze.sh" source "$scmbDir/lib/git/repo_index.sh" - # Setup and tear down #----------------------------------------------------------------------------- oneTimeSetUp() { @@ -34,7 +37,10 @@ oneTimeSetUp() { cd $GIT_REPO_DIR # Setup test repos in temp repo dir for repo in github bitbucket source_forge TestCaps; do - mkdir $repo; cd $repo; git init; cd - > /dev/null + mkdir $repo + cd $repo + git init + cd - >/dev/null done # Add some nested dirs for testing resursive tab completion @@ -47,7 +53,7 @@ oneTimeSetUp() { mkdir submodules_everywhere cd submodules_everywhere git init - cat > .gitmodules <.gitmodules < /dev/null + mkdir $repo + cd $repo + git init + cd - >/dev/null done # Setup some custom repos outside the main repo dir IFS=":" for dir in $GIT_REPOS; do - mkdir -p $dir; cd $dir; git init; + mkdir -p $dir + cd $dir + git init done - IFS=$' \t\n' + unset IFS verboseGitCommands @@ -74,7 +85,7 @@ oneTimeTearDown() { rm -rf "${GIT_REPO_DIR}" IFS=":" for dir in $GIT_REPOS; do rm -rf $dir; done - IFS=$' \t\n' + unset IFS } ensureIndex() { @@ -85,30 +96,32 @@ index_no_newlines() { tr "\\n" " " < $git_index_file } - #----------------------------------------------------------------------------- # Unit tests #----------------------------------------------------------------------------- test_repo_index_command() { - git_index --rebuild > /dev/null + git_index --rebuild >/dev/null # Test that all repos are detected, and sorted alphabetically - assertIncludes "$(index_no_newlines)" "bitbucket.*\ -blue_submodule.*\ -github.*\ -green_submodule.*\ -red_submodule.*\ -source_forge.*\ -submodules_everywhere.*\ -test_repo_11.*\ -test_repo_1" - + assertIncludes "$(index_no_newlines)" $( + cat <> $git_index_file + echo "should not be regenerated" >>$git_index_file _check_git_index # Test that index is not rebuilt unless empty assertIncludes "$(index_no_newlines)" "should not be regenerated" @@ -125,7 +138,7 @@ test_git_index_count() { test_repo_list() { ensureIndex list=$(git_index --list) - assertIncludes "$list" "bitbucket" || return + assertIncludes "$list" "bitbucket" || return assertIncludes "$list" "blue_submodule" || return assertIncludes "$list" "test_repo_11" } @@ -133,16 +146,26 @@ test_repo_list() { # Test matching rules for changing directory test_git_index_changing_directory() { ensureIndex - git_index "github"; assertEquals "$GIT_REPO_DIR/github" "$PWD" - git_index "github/"; assertEquals "$GIT_REPO_DIR/github" "$PWD" - git_index "bucket"; assertEquals "$GIT_REPO_DIR/bitbucket" "$PWD" - git_index "testcaps"; assertEquals "$GIT_REPO_DIR/TestCaps" "$PWD" - git_index "green_sub"; assertEquals "$GIT_REPO_DIR/submodules_everywhere/very/nested/directory/green_submodule" "$PWD" - git_index "_submod"; assertEquals "$GIT_REPO_DIR/submodules_everywhere/very/nested/directory/blue_submodule" "$PWD" - git_index "test_repo_1"; assertEquals "/tmp/test_repo_1" "$PWD" - git_index "test_repo_11"; assertEquals "/tmp/test_repo_11" "$PWD" - git_index "test_repo_"; assertEquals "/tmp/test_repo_11" "$PWD" - git_index "github/videos/octocat/live_action"; assertEquals "$GIT_REPO_DIR/github/videos/octocat/live_action" "$PWD" + git_index "github" + assertEquals "$GIT_REPO_DIR/github" "$PWD" + git_index "github/" + assertEquals "$GIT_REPO_DIR/github" "$PWD" + git_index "bucket" + assertEquals "$GIT_REPO_DIR/bitbucket" "$PWD" + git_index "testcaps" + assertEquals "$GIT_REPO_DIR/TestCaps" "$PWD" + git_index "green_sub" + assertEquals "$GIT_REPO_DIR/submodules_everywhere/very/nested/directory/green_submodule" "$PWD" + git_index "_submod" + assertEquals "$GIT_REPO_DIR/submodules_everywhere/very/nested/directory/blue_submodule" "$PWD" + git_index "test_repo_1" + assertEquals "/tmp/test_repo_1" "$PWD" + git_index "test_repo_11" + assertEquals "/tmp/test_repo_11" "$PWD" + git_index "test_repo_" + assertEquals "/tmp/test_repo_1" "$PWD" + git_index "github/videos/octocat/live_action" + assertEquals "$GIT_REPO_DIR/github/videos/octocat/live_action" "$PWD" } test_git_index_tab_completion() { @@ -163,16 +186,15 @@ test_git_index_tab_completion() { # Test completion for project sub-directories when project ends with '/' COMP_WORDS="github/" _git_index_tab_completion - assertIncludes "$(tab_completions)" "github/videos/" + assertIncludes "$(tab_completions)" "github/videos/" # Check that '.git/' is filtered from completion, but other hidden dirs are available assertNotIncludes "$(tab_completions)" "github/.git/" - assertIncludes "$(tab_completions)" "github/.im_hidden/" + assertIncludes "$(tab_completions)" "github/.im_hidden/" COMP_WORDS="github/videos/" _git_index_tab_completion assertIncludes "$(tab_completions)" "github/videos/octocat/" - # Test that completion checks for other matching projects even if one matches perfectly COMP_WORDS="test_repo_1" _git_index_tab_completion @@ -180,7 +202,6 @@ test_git_index_tab_completion() { fi } - # Test changing to top-level directory (when arg begins with '/') test_changing_to_top_level_directory() { mkdir "$GIT_REPO_DIR/gems" @@ -188,8 +209,6 @@ test_changing_to_top_level_directory() { assertEquals "$GIT_REPO_DIR/gems" "$PWD" } - # load and run shUnit2 # Call this function to run tests source "$scmbDir/test/support/shunit2" - diff --git a/test/lib/git/shell_shortcuts_test.sh b/test/lib/git/shell_shortcuts_test.sh index 3a6843a..f699085 100755 --- a/test/lib/git/shell_shortcuts_test.sh +++ b/test/lib/git/shell_shortcuts_test.sh @@ -21,22 +21,38 @@ fi source "$scmbDir/test/support/test_helper.sh" source "$scmbDir/lib/scm_breeze.sh" +bin_path() { + if [ -n "${ZSH_VERSION:-}" ]; + then where "$@" | tail -1 + else which "$@" + fi +} + # Setup #----------------------------------------------------------------------------- oneTimeSetUp() { export shell_command_wrapping_enabled="true" export scmb_wrapped_shell_commands="not_found cat rm cp mv ln cd sed" + export shell_ls_aliases_enabled="true" alias rvm="test" # Ensure tests run if RVM isn't loaded but $HOME/.rvm is present # Test functions function ln() { ln $@; } + + # Before aliasing, get original locations so we can compare them in the test + unalias mv rm sed cat 2>/dev/null + export mv_path="$(bin_path mv)" + export rm_path="$(bin_path rm)" + export sed_path="$(bin_path sed)" + export cat_path="$(bin_path cat)" + # Test aliases - alias mv="nocorrect mv" - alias rm="rm --option" - alias sed="sed" + alias mv="nocorrect $mv_path" + alias rm="$rm_path --option" + alias sed="$sed_path" # Test already wrapped commands - alias cat="exec_scmb_expand_args /bin/cat" + alias cat="exec_scmb_expand_args $cat_path" # Run shortcut wrapping source "$scmbDir/lib/git/shell_shortcuts.sh" @@ -58,11 +74,11 @@ assertAliasEquals(){ #----------------------------------------------------------------------------- test_shell_command_wrapping() { - assertAliasEquals "exec_scmb_expand_args /bin/rm --option" "rm" - assertAliasEquals "exec_scmb_expand_args nocorrect /bin/mv" "mv" - assertAliasEquals "exec_scmb_expand_args /bin/sed" "sed" - assertAliasEquals "exec_scmb_expand_args /bin/cat" "cat" - assertAliasEquals "exec_scmb_expand_args builtin cd" "cd" + assertAliasEquals "exec_scmb_expand_args nocorrect $mv_path" "mv" + assertAliasEquals "exec_scmb_expand_args $rm_path --option" "rm" + assertAliasEquals "exec_scmb_expand_args $sed_path" "sed" + assertAliasEquals "exec_scmb_expand_args $cat_path" "cat" + assertAliasEquals "exec_scmb_expand_args builtin cd" "cd" assertIncludes "$(declare -f ln)" "ln ()" assertIncludes "$(declare -f ln)" "exec_scmb_expand_args __original_ln" } @@ -71,7 +87,15 @@ test_ls_with_file_shortcuts() { export git_env_char="e" TEST_DIR=$(mktemp -d -t scm_breeze.XXXXXXXXXX) + + # Darwin actually symlinks /var inside /private, but mktemp reports back the + # logical pathat time of file creation. So make sure we always get the + # full physical path to be absolutely certain when doing comparisons later, + # because thats how the Ruby status_shortcuts.rb script is going to obtain + # them. cd $TEST_DIR + TEST_DIR=$(pwd -P) + touch 'test file' 'test_file' mkdir -p "a [b]" 'a "b"' "a 'b'" touch "a \"b\"/c" @@ -82,7 +106,7 @@ test_ls_with_file_shortcuts() { ls_with_file_shortcuts > $temp_file ls_output=$(<$temp_file strip_colors) - # Compare as fixed strings (F), instead of regex (P) + # Compare as fixed strings (F), instead of normal grep behavior assertIncludes "$ls_output" '[1] a "b"' F assertIncludes "$ls_output" "[2] a 'b'" F assertIncludes "$ls_output" '[3] a [b]' F diff --git a/test/lib/git/status_shortcuts_test.sh b/test/lib/git/status_shortcuts_test.sh index aa86d2e..d83d9ca 100755 --- a/test/lib/git/status_shortcuts_test.sh +++ b/test/lib/git/status_shortcuts_test.sh @@ -29,6 +29,7 @@ oneTimeSetUp() { export ga_auto_remove="yes" testRepo=$(mktemp -d -t scm_breeze.XXXXXXXXXX) + testRepo=$(cd $testRepo && pwd -P) } oneTimeTearDown() { @@ -60,6 +61,10 @@ test_scmb_expand_args() { "$(scmb_expand_args -ma "Test Commit Message" "Unquoted")" } +test_command_wrapping_escapes_special_characters() { + assertEquals 'should escape | the pipe' "$(exec_scmb_expand_args echo "should escape | the pipe")" + assertEquals 'should escape ; the semicolon' "$(exec_scmb_expand_args echo "should escape ; the semicolon")" +} test_git_status_shortcuts() { setupTestRepo @@ -252,10 +257,10 @@ test_git_commit_prompt() { assertIncludes "$git_show_output" "$commit_msg" # Test that history was appended correctly. - if [[ $shell == "zsh" ]]; then - test_history="$(history)" + if [[ $shell == "zsh" ]]; then + test_history="$(history)" else - test_history="$(cat $HISTFILE)" + test_history="$(cat $HISTFILE)" fi assertIncludes "$test_history" "$commit_msg" assertIncludes "$test_history" "git commit -m \"$dbl_escaped_msg\"" @@ -285,10 +290,10 @@ test_git_commit_prompt_with_append() { assertIncludes "$git_show_output" "$commit_msg \[ci skip\]" # Test that history was appended correctly. - if [[ $shell == "zsh" ]]; then - test_history="$(history)" + if [[ $shell == "zsh" ]]; then + test_history="$(history)" else - test_history="$(cat $HISTFILE)" + test_history="$(cat $HISTFILE)" fi assertIncludes "$test_history" "$commit_msg \[ci skip\]" assertIncludes "$test_history" "git commit -m \"$commit_msg \[ci skip\]\"" @@ -312,4 +317,3 @@ test_adding_files_with_spaces() { # load and run shUnit2 source "$scmbDir/test/support/shunit2" - diff --git a/test/support/test_helper.sh b/test/support/test_helper.sh index 7407b59..ba9e472 100644 --- a/test/support/test_helper.sh +++ b/test/support/test_helper.sh @@ -15,7 +15,7 @@ fi # Strip color codes from a string strip_colors() { - sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" + perl -pe 's/\e\[[\d;]*m//g' } # Print space separated tab completion options @@ -34,7 +34,7 @@ verboseGitCommands() { #----------------------------------------------------------------------------- _includes() { - if [ -n "$3" ]; then regex="$3"; else regex=P; fi + if [ -n "$3" ]; then regex="$3"; else regex=''; fi if echo "$1" | grep -q$regex "$2"; then echo 0; else echo 1; fi } @@ -46,4 +46,3 @@ assertIncludes() { assertNotIncludes() { assertFalse "'$1' should not have contained '$2'" $(_includes "$@") } - diff --git a/test/support/travisci_deps.sh b/test/support/travisci_deps.sh new file mode 100755 index 0000000..83cc32e --- /dev/null +++ b/test/support/travisci_deps.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# Installs dependencies for travis-ci environments. + +# Install dependencies, which looks to be just bash & zsh. +# +# Darwin has zsh preinstalled already, so only need to install on Ubuntu. +# +# Note: $TRAVIS_OS_NAME will only be set on text boxes with multi-os enabled, +# so use negation test so it will fail gracefully on normal Travis linux setup. +if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then + + # okay, so we know we're probably on a linux box (or at least not an osx box) + # at this point. do we need to install zsh? let's say the default case is no: + needs_zsh=false + + # check if zsh is listed in the TEST_SHELLS environment variable, set by + # our travis-ci build matrix. + if [[ $TEST_SHELLS =~ zsh ]]; then needs_zsh=true; fi + + # if there is NO $TEST_SHELLS env variable persent (which should never happen, + # but maybe someone has been monkeying with the .travis.yml), run_tests.sh is + # going to fall back onto the default of testing everything, so we need zsh. + if [[ -z "$TEST_SHELLS" ]]; then needs_zsh=true; fi + + # finally, we install zsh if needed! + if $needs_zsh ; then + sudo apt-get install zsh + else + echo "No deps required." + fi + +fi diff --git a/uninstall.sh b/uninstall.sh index ca7b83a..f91235a 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,7 +1,15 @@ #!/bin/sh # uninstall by (github: bernardofire) # Remove line from bashrc and zshrc if present. + +sed="sed -i" +if [[ $OSTYPE == "Darwin" ]]; then + sed="sed -i ''" +fi + for rc in bashrc zshrc; do - sed -i '/scm_breeze/d' "$HOME/.$rc" - printf "== Removed SCM Breeze from '$HOME/.$rc'\n" + if [ -f "$HOME/.$rc" ]; then + $sed '/scm_breeze/d' "$HOME/.$rc" && + printf "Removed SCM Breeze from %s\n" "$HOME/.$rc" + fi done