├── .gitignore ├── Makefile ├── completion ├── completion.zsh └── completion.bash ├── README.pod └── src └── broom.sh /.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION = $(shell git describe --tags) 2 | PREFIX = /usr 3 | 4 | all: broom doc 5 | 6 | broom: 7 | mkdir -p out 8 | sed "s/^VERSION=*.*/VERSION=${VERSION}/" < src/broom.sh > out/broom.sh 9 | 10 | doc: 11 | mkdir -p out 12 | pod2man --section=1 --center="Broom Manual" --name="BROOM" --release="broom ${VERSION}" README.pod > out/broom.1 13 | 14 | dist: clean 15 | mkdir -p out/broom-${VERSION} 16 | cp -R src/ completion/ README.pod out/broom-${VERSION} 17 | sed "s/^VERSION = *.*/VERSION = ${VERSION}/" < Makefile > out/broom-${VERSION}/Makefile 18 | cd out && tar cvzf broom-${VERSION}.tar.gz broom-${VERSION} 19 | 20 | clean: 21 | ${RM} -r out 22 | 23 | install: broom doc 24 | install -dm755 ${DESTDIR}${PREFIX}/bin 25 | install -m755 out/broom.sh ${DESTDIR}${PREFIX}/bin/broom 26 | install -dm755 ${DESTDIR}${PREFIX}/share/man/man1 27 | install -m644 out/broom.1 ${DESTDIR}${PREFIX}/share/man/man1/broom.1 28 | install -dm755 ${DESTDIR}/etc/bash_completion.d 29 | install -m644 completion/completion.bash ${DESTDIR}/etc/bash_completion.d/broom 30 | install -dm755 ${DESTDIR}/usr/share/zsh/site-functions 31 | install -m644 completion/completion.zsh ${DESTDIR}/usr/share/zsh/site-functions/_broom 32 | 33 | uninstall: 34 | ${RM} ${DESTDIR}${PREFIX}/bin/broom 35 | ${RM} ${DESTDIR}${PREFIX}/share/man/man1/broom.1 36 | ${RM} ${DESTDIR}/etc/bash_completion.d/broom 37 | ${RM} ${DESTDIR}/usr/share/zsh/site-functions/_broom 38 | -------------------------------------------------------------------------------- /completion/completion.zsh: -------------------------------------------------------------------------------- 1 | #compdef broom 2 | # broom - a disk cleaning utility for developers 3 | # Copyright (c) 2011-2012 Julien Nicoulaud 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining 6 | # a copy of this software and associated documentation files (the 7 | # "Software"), to deal in the Software without restriction, including 8 | # without limitation the rights to use, copy, modify, merge, publish, 9 | # distribute, sublicense, and/or sell copies of the Software, and to 10 | # permit persons to whom the Software is furnished to do so, subject to 11 | # the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be 14 | # included in all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | _arguments \ 26 | '(- 1 *)'{-h,--help}'[show usage message and exit]' \ 27 | '(- 1 *)--version[show program version and exit]' \ 28 | '*'{-v,--verbose}'[increase verbosity level]' \ 29 | '*'{-q,--quiet}'[decrease verbosity level]' \ 30 | {-n,--dry-run}'[do not actually perform actions]' \ 31 | {-t,--tools}'[comma-separated list of tools to use]: :_values -s ',' tool make rake python ant mvn gradle buildr sbt ninja git bundle' \ 32 | '*: :_files -/' 33 | 34 | # vim: ft=zsh sw=2 ts=2 et 35 | -------------------------------------------------------------------------------- /completion/completion.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # broom - a disk cleaning utility for developers 3 | # Copyright (c) 2011-2012 Julien Nicoulaud 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining 6 | # a copy of this software and associated documentation files (the 7 | # "Software"), to deal in the Software without restriction, including 8 | # without limitation the rights to use, copy, modify, merge, publish, 9 | # distribute, sublicense, and/or sell copies of the Software, and to 10 | # permit persons to whom the Software is furnished to do so, subject to 11 | # the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be 14 | # included in all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | _broom() 26 | { 27 | cur=${COMP_WORDS[COMP_CWORD]} 28 | if [ $COMP_CWORD -eq 1 ]; then 29 | COMPREPLY=( $( compgen -W "-h --help --version -v --verbose -q --quiet -n --dry-run -t --tools" -- $cur ) ) 30 | else 31 | first=${COMP_WORDS[1]} 32 | case "$first" in 33 | --version|-h|--help) 34 | COMPREPLY=() 35 | ;; 36 | *) 37 | prev=${COMP_WORDS[COMP_CWORD-1]} 38 | case "$prev" in 39 | -t|--tools) 40 | COMPREPLY=( $(compgen -W "make rake python ant mvn gradle buildr sbt ninja git bundle" $cur) ) 41 | ;; 42 | *) 43 | COMPREPLY=( $(compgen -W "-v --verbose -q --quiet -n --dry-run -t --tools" -- $cur ) ) 44 | ;; 45 | esac 46 | ;; 47 | esac 48 | fi 49 | } 50 | 51 | complete -F _broom -o dirnames broom 52 | -------------------------------------------------------------------------------- /README.pod: -------------------------------------------------------------------------------- 1 | =encoding utf8 2 | 3 | =head1 NAME 4 | 5 | broom - a disk cleaning utility for developers 6 | 7 | =head1 SYNOPSIS 8 | 9 | I [option...] [directory] 10 | 11 | =head1 DESCRIPTION 12 | 13 | broom recursively looks for projects inside a directory and cleans them 14 | by removing build artifacts, optimizing version control system files, etc. 15 | 16 | =head1 OPTIONS 17 | 18 | =over 19 | 20 | =item B<-n, --dry-run> 21 | 22 | Only show commands that would be executed instead of actually performing 23 | them. 24 | 25 | =item B<-t> IB<, --tools=>I 26 | 27 | Comma-separated list of tools to run the cleanup for. The available tools 28 | are: I, I, I, I, I, I, I, 29 | I, I, I and I. By default, all tools are used. 30 | 31 | =item B<-v, --verbose> 32 | 33 | Be more verbose. Pass this option several times to see debug info. 34 | 35 | =item B<-q, --quiet> 36 | 37 | Be less verbose. Pass this option several times to remove all output. 38 | 39 | =item B<-h, --help> 40 | 41 | Show usage information and exit. 42 | 43 | =item B<--version> 44 | 45 | Show version information and exit. 46 | 47 | =back 48 | 49 | =head1 EXAMPLES 50 | 51 | To perform cleanup in the current working directory: 52 | 53 | broom 54 | 55 | To perform cleanup in your projects folder: 56 | 57 | broom ~/projects 58 | 59 | To perform cleanup in your projects folder, with all logging on: 60 | 61 | broom -vvv ~/projects 62 | 63 | To show what commands would be performed, without running them: 64 | 65 | broom -n ~/projects 66 | 67 | 68 | To perform cleanup only for git and make projects: 69 | 70 | broom -t git,make ~/projects 71 | 72 | =head1 FILES 73 | 74 | broom allows to define default execution parameters in the F<~/.broomrc> 75 | file. Here is an example of F<~/.broomrc> file: 76 | 77 | # Use dry run mode by default. 78 | DRY_RUN=true 79 | 80 | # Only show warnings and errors. 81 | LOG_LEVEL=0 82 | 83 | # Run in projects directory. 84 | DIRECTORY=~/projects 85 | 86 | # Only look for some specific kind of projects. 87 | TOOLS=(make python ant git) 88 | 89 | =begin html 90 | 91 | =head1 INSTALLING 92 | 93 | Get the last release here, and follow the steps below to build and install it: 94 | 95 |
 96 | tar xzf broom-*.tar.gz
 97 | cd broom-*/
 98 | make
 99 | sudo make install
100 | 
101 | 102 | =end html 103 | 104 | =begin man 105 | 106 | =head1 ISSUES 107 | 108 | Please report issues at https://github.com/nicoulaj/broom/issues. 109 | 110 | =head1 AUTHOR 111 | 112 | Julien Nicoulaud 113 | 114 | =end man 115 | -------------------------------------------------------------------------------- /src/broom.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # broom - a disk cleaning utility for developers 3 | # Copyright (c) 2011-2012 Julien Nicoulaud 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining 6 | # a copy of this software and associated documentation files (the 7 | # "Software"), to deal in the Software without restriction, including 8 | # without limitation the rights to use, copy, modify, merge, publish, 9 | # distribute, sublicense, and/or sell copies of the Software, and to 10 | # permit persons to whom the Software is furnished to do so, subject to 11 | # the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be 14 | # included in all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | VERSION=dev 25 | 26 | # ---------------------------------------------------------------------- 27 | # Tools definitions 28 | # ---------------------------------------------------------------------- 29 | 30 | AVAILABLE_TOOLS=(make rake python ant mvn gradle buildr sbt ninja git bundle) 31 | 32 | # Make 33 | make_project_marker() { echo "Makefile"; } 34 | 35 | # Rake 36 | rake_project_marker() { echo "Rakefile"; } 37 | 38 | # Python distutils 39 | python_project_marker() { echo "setup.py"; } 40 | python_clean_args() { echo "$1 clean"; } 41 | 42 | # Ant 43 | ant_project_marker() { echo "build.xml"; } 44 | 45 | # Maven 46 | mvn_project_marker() { echo "pom.xml"; } 47 | mvn_keep_project() { [[ -f $(dirname `dirname $1`)/pom.xml ]] && return 1 || return 0; } 48 | 49 | # Gradle 50 | gradle_project_marker() { echo "build.gradle"; } 51 | 52 | # Buildr 53 | buildr_project_marker() { echo "buildfile"; } 54 | 55 | # SBT 56 | sbt_project_marker() { echo "{*.sbt,project/**/*.scala}"; } 57 | sbt_cwd() { [[ $1 == *.sbt ]] && echo `dirname $1` || echo "${1%\/project\/*}"; } 58 | 59 | # Ninja 60 | ninja_project_marker() { echo "build.ninja"; } 61 | ninja_clean_args() { echo "-t clean"; } 62 | 63 | # Git gc 64 | git_project_marker() { echo ".git/"; } 65 | git_clean_args() { echo "gc"; } 66 | 67 | # Bundler 68 | bundle_project_marker() { echo "Gemfile"; } 69 | 70 | 71 | # ---------------------------------------------------------------------- 72 | # Main 73 | # ---------------------------------------------------------------------- 74 | 75 | # Define usage function. 76 | usage() { 77 | cat << EOF 78 | usage: $0 [option...] [directory] 79 | 80 | A disk cleaning utility for developers. 81 | 82 | OPTIONS: 83 | -h,--help Show this message and exit. 84 | --version Show version number and exit. 85 | -v,--verbose Increase verbosity level. 86 | -q,--quiet) Decrease verbosity level. 87 | -n,--dry-run) Do not actually perform actions. 88 | -t,--tools) Comma-separated list of tools to use. 89 | Available tools are: ${AVAILABLE_TOOLS[@]}. 90 | EOF 91 | } 92 | 93 | # Define version function. 94 | version() { 95 | cat << EOF 96 | $0 $VERSION 97 | EOF 98 | } 99 | 100 | # Define logging functions. 101 | log() { 102 | level=$1; shift 103 | if [[ $level -lt 0 ]]; then 104 | echo "$@" >&2 105 | else 106 | [[ $LOG_LEVEL -ge $level ]] && echo $@ 107 | fi 108 | } 109 | info() { log 0 $@; } 110 | debug() { log 1 $@; } 111 | error() { log -2 $@; } 112 | warn() { log -1 $@; } 113 | is_log_level() { [[ $LOG_LEVEL -ge $1 ]]; } 114 | 115 | # Check for bash requirements. 116 | [[ ! $BASH_VERSINFO -ge 4 ]] && { 117 | error "This script requires bash>=4, exiting." 118 | exit 1 119 | } 120 | 121 | # Check for getopt requirements. 122 | getopt -h 2>&1 | grep -qe '-l' || { 123 | error "This script requires GNU implementation of getopt, exiting." 124 | exit 1 125 | } 126 | 127 | # Set required bash options. 128 | shopt -s globstar extglob 129 | 130 | # Initialize default execution parameters. 131 | LOG_LEVEL=0 132 | DRY_RUN=false 133 | DIRECTORY=. 134 | TOOLS=(${AVAILABLE_TOOLS[@]}) 135 | 136 | # Load user configuration file if any. 137 | [[ -f $HOME/.broomrc ]] && { 138 | debug "Loading ~/.broomrc" 139 | . $HOME/.broomrc 140 | } 141 | 142 | # Parse and validate options. 143 | set -- `getopt -un$0 -l "help,version,verbose,quiet,dry-run,tools:" -o "hvqnt:" -- "$@"` || usage 144 | while [[ $# -gt 0 ]]; do 145 | case "$1" in 146 | -h|--help) usage; exit 0 ;; 147 | --version) version; exit 0 ;; 148 | -v|--verbose) let LOG_LEVEL++ ;; 149 | -q|--quiet) let LOG_LEVEL-- ;; 150 | -n|--dry-run) DRY_RUN=true ;; 151 | -t|--tools) TOOLS=(${2//,/ }); shift ;; 152 | --) shift; break ;; 153 | -*) usage; exit 1 ;; 154 | *) break ;; 155 | esac 156 | shift 157 | done 158 | 159 | # Parse and validate arguments. 160 | [[ $# -gt 1 ]] && { 161 | error "Error: too many arguments, exiting." 162 | usage 163 | exit 1 164 | } 165 | [[ -n $1 ]] && DIRECTORY=$1 166 | [[ ! -d $DIRECTORY ]] && { 167 | error "Error: could not find directory $DIRECTORY, exiting." 168 | usage 169 | exit 1 170 | } 171 | 172 | # Debug logging. 173 | debug "Running with parameters:" 174 | debug " - dry run: $DRY_RUN" 175 | debug " - log level: $LOG_LEVEL" 176 | debug " - directory: $DIRECTORY" 177 | debug " - tools: ${TOOLS[@]}" 178 | 179 | # Perform cleaning. 180 | trap "exit" INT TERM EXIT 181 | for tool in ${TOOLS[@]}; do 182 | if ! type $tool &> /dev/null; then 183 | warn "Warning: $tool does not seem to be available in PATH, skipping $tool projects cleaning." 184 | elif ! type ${tool}_project_marker &> /dev/null; then 185 | warn "Warning: $tool is not supported, skipping." 186 | else 187 | info "Looking for $tool projects..." 188 | for marker in $(eval echo $DIRECTORY/**/`${tool}_project_marker`); do 189 | if [[ -e $marker ]]; then 190 | project_dir="`dirname $marker`" 191 | if type ${tool}_keep_project &> /dev/null && ! ${tool}_keep_project $marker &> /dev/null; then 192 | debug "Skipping project ${project_dir}." 193 | else 194 | cwd="${project_dir}"; type ${tool}_cwd &> /dev/null && cwd="`${tool}_cwd $marker`" 195 | clean_args="clean"; type ${tool}_clean_args &> /dev/null && clean_args="`${tool}_clean_args $marker`" 196 | clean_command="cd ${cwd} && ${tool} ${clean_args}" 197 | if $DRY_RUN; then 198 | info $clean_command 199 | else 200 | info "Cleaning $tool project `dirname $marker`... " 201 | is_log_level 2 && (eval $clean_command) || (eval $clean_command &> /dev/null) 202 | fi 203 | fi 204 | fi 205 | done 206 | fi 207 | done 208 | 209 | # vim:set ts=2 sw=2 et: 210 | --------------------------------------------------------------------------------