├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── contrib └── gitnflow-installer.sh ├── git-nflow ├── git-nflow-feature ├── git-nflow-init ├── git-nflow-version ├── gitflow ├── .gitignore ├── .gitmodules ├── AUTHORS ├── Changes.mdown ├── LICENSE ├── Makefile ├── README.mdown ├── bump-version ├── contrib │ ├── gitflow-installer.sh │ └── msysgit-install.cmd ├── git-flow ├── git-flow-feature ├── git-flow-hotfix ├── git-flow-init ├── git-flow-release ├── git-flow-support ├── git-flow-version ├── gitflow-common └── gitflow-shFlags ├── gitnflow-common ├── gitnflow-gitflow-common ├── gitnflow-shFlags └── shflags ├── .githooks ├── generic └── pre-commit.shellcheck ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── doc ├── CHANGES-1.0.md ├── CHANGES-1.2.md ├── CHANGES-1.3.md ├── LICENSE.shunit2 ├── RELEASE_NOTES-1.0.0.txt ├── RELEASE_NOTES-1.0.1.txt ├── RELEASE_NOTES-1.0.2.txt ├── RELEASE_NOTES-1.0.3.txt ├── RELEASE_NOTES-1.2.0.md ├── RELEASE_NOTES-1.2.1.md ├── RELEASE_NOTES-1.2.2.md ├── RELEASE_NOTES-1.2.3.md └── TODO.txt ├── examples ├── debug_output.sh ├── hello_world.sh └── write_date.sh ├── init_githooks.sh ├── lib ├── shunit2 └── versions ├── shflags ├── shflags_defines_test.sh ├── shflags_parsing_test.sh ├── shflags_private_test.sh ├── shflags_public_test.sh ├── shflags_test_helpers └── test_runner /.gitignore: -------------------------------------------------------------------------------- 1 | debian/files 2 | debian/*.substvars 3 | debian/*.debhelper.log 4 | debian/*/* 5 | 6 | .idea 7 | 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "shflags"] 2 | path = shflags 3 | url = https://github.com/kward/shflags.git 4 | [submodule "gitflow"] 5 | path = gitflow 6 | url = https://github.com/nvie/gitflow.git 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2020 binbincivil 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | git-nflow 2 | ======== 3 | 4 | A collection of Git extensions to provide high-level repository operations 5 | for [new git branching model](https://github.com/binbincivil/git-new-flow/wiki). 6 | 7 | git-new-flow分支模型 8 | 9 | Installing git-nflow 10 | ------------------- 11 | ``` 12 | curl -L -O https://raw.githubusercontent.com/binbincivil/git-new-flow/master/contrib/gitnflow-installer.sh 13 | sudo bash gitnflow-installer.sh 14 | ``` 15 | 16 | ### Initialization 17 | 18 | To initialize a new repo with the basic branch structure, use: 19 | 20 | ``` 21 | git nflow init [-d] 22 | ``` 23 | 24 | This will then interactively prompt you with some questions on which branches 25 | you would like to use as development and test and preview and production branches, and how you 26 | would like your prefixes be named. You may simply press Return on any of 27 | those questions to accept the (sane) default suggestions. 28 | 29 | The ``-d`` flag will accept all defaults. 30 | 31 | 32 | ### feature branches 33 | 34 | * To list/start feature branches, use: 35 | ``` 36 | git nflow feature [list] [-v] 37 | git nflow feature start [] 38 | ``` 39 | For feature branches, the `` arg must be a commit on `master`. 40 | 41 | * To track feature branches, use: 42 | ``` 43 | git nflow feature track 44 | ``` 45 | * To push/pull a feature branch to the remote repository, use: 46 | ``` 47 | git nflow feature push 48 | git nflow feature pull 49 | ``` 50 | * To merge feature branch into develop/test/preview branch, use: 51 | ``` 52 | git nflow feature dev [] 53 | git nflow feature test [] 54 | git nflow feature preview [] 55 | ``` 56 | * To finish feature branches(merge branch into master branch), use: 57 | ``` 58 | git nflow feature finish [] 59 | ``` 60 | * To delete feature branches, use: 61 | ``` 62 | git nflow feature delete [] 63 | ``` 64 | 65 | 66 | ### Best Practices 67 | 68 | ``` 69 | alias gnf="git nflow" 70 | alias gnff="git nflow feature" 71 | ``` 72 | -------------------------------------------------------------------------------- /contrib/gitnflow-installer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # git-nflow make-less installer for *nix systems 4 | 5 | # Does this need to be smarter for each host OS? 6 | if [ -z "$INSTALL_PREFIX" ] ; then 7 | INSTALL_PREFIX="/usr/local/bin" 8 | fi 9 | 10 | if [ -z "$REPO_NAME" ] ; then 11 | REPO_NAME="git-new-flow" 12 | fi 13 | 14 | if [ -z "$REPO_HOME" ] ; then 15 | REPO_HOME="https://github.com/binbincivil/git-new-flow.git" 16 | fi 17 | 18 | EXEC_FILES="git-nflow" 19 | SCRIPT_FILES="git-nflow-init git-nflow-feature git-nflow-version gitnflow-common gitnflow-gitflow-common gitnflow-shFlags" 20 | SUBMODULE_GITFLOW="gitnflow-gitflow-common" 21 | SUBMODULE_SHFLAGS="gitnflow-shFlags" 22 | 23 | echo "### gitnflow no-make installer ###" 24 | 25 | case "$1" in 26 | uninstall) 27 | echo "Uninstalling git-nflow from $INSTALL_PREFIX" 28 | if [ -d "$INSTALL_PREFIX" ] ; then 29 | for script_file in $SCRIPT_FILES $EXEC_FILES ; do 30 | echo "rm -vf $INSTALL_PREFIX/$script_file" 31 | rm -vf "$INSTALL_PREFIX/$script_file" 32 | done 33 | else 34 | echo "The '$INSTALL_PREFIX' directory was not found." 35 | echo "Do you need to set INSTALL_PREFIX ?" 36 | fi 37 | exit 38 | ;; 39 | help) 40 | echo "Usage: [environment] gitnflow-installer.sh [install|uninstall]" 41 | echo "Environment:" 42 | echo " INSTALL_PREFIX=$INSTALL_PREFIX" 43 | echo " REPO_HOME=$REPO_HOME" 44 | echo " REPO_NAME=$REPO_NAME" 45 | exit 46 | ;; 47 | *) 48 | echo "Installing git-nflow to $INSTALL_PREFIX" 49 | if [ -d "$REPO_NAME" -a -d "$REPO_NAME/.git" ] ; then 50 | echo "Using existing repo: $REPO_NAME" 51 | lastpwd=$PWD 52 | cd "$REPO_NAME" 53 | git checkout master && git pull origin master 54 | cd "$lastpwd" 55 | else 56 | echo "Cloning repo from GitHub to $REPO_NAME" 57 | git clone "$REPO_HOME" "$REPO_NAME" 58 | fi 59 | if [ -f "$REPO_NAME/$SUBMODULE_GITFLOW" -a -f "$REPO_NAME/$SUBMODULE_SHFLAGS" ] ; then 60 | echo "Submodules look up to date" 61 | else 62 | echo "Updating submodules" 63 | lastpwd=$PWD 64 | cd "$REPO_NAME" 65 | git submodule init 66 | git submodule update 67 | cd "$lastpwd" 68 | fi 69 | install -v -d -m 0755 "$INSTALL_PREFIX" 70 | for exec_file in $EXEC_FILES ; do 71 | install -v -m 0755 "$REPO_NAME/$exec_file" "$INSTALL_PREFIX" 72 | echo "$REPO_NAME/$exec_file"; 73 | done 74 | for script_file in $SCRIPT_FILES ; do 75 | install -v -m 0644 "$REPO_NAME/$script_file" "$INSTALL_PREFIX" 76 | echo "$REPO_NAME/$script_file"; 77 | done 78 | exit 79 | ;; 80 | esac 81 | -------------------------------------------------------------------------------- /git-nflow: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # set this to workaround expr problems in shFlags on freebsd 4 | if uname -s | egrep -iq 'bsd'; then export EXPR_COMPAT=1; fi 5 | 6 | # enable debug mode 7 | if [ "$DEBUG" = "yes" ]; then 8 | set -x 9 | fi 10 | 11 | # The sed expression here replaces all backslashes by forward slashes. 12 | # This helps our Windows users, while not bothering our Unix users. 13 | export GITNFLOW_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") 14 | 15 | usage() { 16 | echo "usage: git nflow " 17 | echo 18 | echo "Available subcommands are:" 19 | echo " init Initialize a new git repo with support for the new branching model." 20 | echo " feature Manage your feature branches." 21 | echo " version Shows version information." 22 | echo 23 | echo "Try 'git nflow help' or 'git nflow -h' for details." 24 | } 25 | 26 | main() { 27 | if [ $# -lt 1 ]; then 28 | usage 29 | exit 1 30 | fi 31 | 32 | # load common functionality 33 | . "$GITNFLOW_DIR/gitnflow-gitflow-common" 34 | . "$GITNFLOW_DIR/gitnflow-common" 35 | 36 | # This environmental variable fixes non-POSIX getopt style argument 37 | # parsing, effectively breaking git-flow subcommand parsing on several 38 | # Linux platforms. 39 | export POSIXLY_CORRECT=1 40 | 41 | # use the shFlags project to parse the command line arguments 42 | . "$GITNFLOW_DIR/gitnflow-shFlags" 43 | FLAGS_PARENT="git nflow" 44 | 45 | # allow user to request git action logging 46 | DEFINE_boolean show_commands false 'show actions taken (git commands)' g 47 | 48 | # do actual parsing 49 | FLAGS "$@" || exit $? 50 | eval set -- "${FLAGS_ARGV}" 51 | 52 | # sanity checks 53 | SUBCOMMAND="$1"; shift 54 | 55 | if [ ! -e "$GITNFLOW_DIR/git-nflow-$SUBCOMMAND" ]; then 56 | usage 57 | exit 1 58 | fi 59 | 60 | # run command 61 | . "$GITNFLOW_DIR/git-nflow-$SUBCOMMAND" 62 | FLAGS_PARENT="git nflow $SUBCOMMAND" 63 | 64 | SUBACTION="default" 65 | #### if the first argument is '-h', run $SUBCOMMAND's help cmd 66 | if [ "$1" == "-h" ] ; then 67 | SUBACTION="help"; shift 68 | fi 69 | 70 | # test if the first argument is a flag (i.e. starts with '-') 71 | # in that case, we interpret this arg as a flag for the default 72 | # command 73 | if [ "$1" != "" ] && { ! echo "$1" | grep -q "^-"; } ; then 74 | SUBACTION="$1"; shift 75 | fi 76 | 77 | if ! type "cmd_$SUBACTION" >/dev/null 2>&1; then 78 | warn "Unknown subcommand: '$SUBACTION'" 79 | usage 80 | exit 1 81 | fi 82 | 83 | # run the specified action 84 | if [ $SUBACTION != "help" ] && [ $SUBCOMMAND != "init" ] ; then 85 | init 86 | fi 87 | cmd_$SUBACTION "$@" 88 | } 89 | 90 | main "$@" -------------------------------------------------------------------------------- /git-nflow-version: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | GITFLOW_VERSION=0.1.0 4 | 5 | usage() { 6 | echo "usage: git nflow version" 7 | } 8 | 9 | cmd_default() { 10 | echo "$GITFLOW_VERSION" 11 | } 12 | 13 | cmd_help() { 14 | usage 15 | exit 0 16 | } 17 | -------------------------------------------------------------------------------- /gitflow/.gitignore: -------------------------------------------------------------------------------- 1 | debian/files 2 | debian/*.substvars 3 | debian/*.debhelper.log 4 | debian/*/* 5 | -------------------------------------------------------------------------------- /gitflow/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "shFlags"] 2 | path = shFlags 3 | url = git://github.com/nvie/shFlags.git 4 | -------------------------------------------------------------------------------- /gitflow/AUTHORS: -------------------------------------------------------------------------------- 1 | Authors are (ordered by first commit date): 2 | 3 | - Vincent Driessen 4 | - Benedikt Böhm 5 | - Daniel Truemper 6 | - Jason L. Shiffer 7 | - Randy Merrill 8 | - Rick Osborne 9 | - Mark Derricutt 10 | - Nowell Strite 11 | - Felipe Talavera 12 | - Guillaume-Jean Herbiet 13 | - Joseph A. Levin 14 | - Jannis Leidel 15 | - Konstantin Tjuterev 16 | - Kiall Mac Innes 17 | - Jon Bernard 18 | - Olivier Mengué 19 | - Emre Berge Ergenekon 20 | - Eric Holmes 21 | - Vedang Manerikar 22 | - Myke Hines 23 | 24 | Portions derived from other open source works are clearly marked. 25 | -------------------------------------------------------------------------------- /gitflow/Changes.mdown: -------------------------------------------------------------------------------- 1 | 0.4.2: 2 | ----- 3 | Release date: **not yet** 4 | 5 | * `git flow init` now detects situations where origin already has gitflow 6 | branches set up, and behaves accordingly (thanks Emre Berge Ergenekon). 7 | 8 | * `git flow feature finish` can now be called without a feature branch 9 | name(prefix) argument and will finish the current branch, if on any. 10 | 11 | * `git flow feature pull` now has a `-r` flag, to support `pull --rebase` 12 | semantics (thanks Vedang Manerikar). 13 | 14 | * Various minor bug fixes related to internal argument passing. 15 | 16 | * Improved some documentation. 17 | 18 | * Better support for Windows and BSD users. 19 | 20 | * Add package installer for the Windows platform. 21 | 22 | 0.4.1: 23 | ----- 24 | Release date: **2011/02/04** 25 | 26 | * New option `-d` added to `git flow init`, to initialize with defaults without 27 | asking for input interactively. Ideal for creating git-flow enabled repos in 28 | custom scripts. 29 | 30 | * The parsing issues related to git-flow feature's flags are now dealt with on 31 | all known platforms. (Fixed #54, #62, #86, #97) 32 | 33 | * Escape queries for detecting branch/tag names. (Fixed #91) 34 | 35 | 36 | 0.4: 37 | --- 38 | Release date: **2010/10/18** 39 | 40 | * The flag parsing issues of git-flow subcommands are solved for most 41 | platforms. 42 | 43 | * `git flow {feature,hotfix,release} finish` now takes a `-k` flag, to keep the 44 | branch around after finishing. 45 | 46 | * `git flow release finish` takes a `-n` flag, to skip tagging. 47 | 48 | * For consistency, `git flow {release,hotfix}` now, too, have a `publish` and 49 | `track` subcommand, just like `feature`. 50 | 51 | * Various minor fixes. 52 | 53 | 54 | 0.3: 55 | ---- 56 | Release date: **2010/07/22** 57 | 58 | * New subcommands for `git flow feature`: 59 | - **checkout**: 60 | For easily checking out features by their short name. Even allows 61 | unique prefixes as arguments (see below). 62 | 63 | - **pull**: 64 | This subcommand allows you to painlessly work on a feature branch 65 | together with another peer. This is especially valuable for doing 66 | peer reviews of other people's code. For more detailed info, see the 67 | [commit log][1]. 68 | 69 | * Easier addressing of branch names by using name prefixes. 70 | For example, when using: 71 | 72 | git flow feature finish fo 73 | 74 | this automatically finishes the feature branch `foobar` if that's the only 75 | feature branch name starting with `fo`. 76 | 77 | * No force flag anymore for new feature branches 78 | `git flow feature start` lost its `-f` (force) flag. You now don't 79 | have to be in a clean repo anymore to start a new feature branch. This 80 | avoids the manual `git stash`, `git flow feature start`, `git stash 81 | pop` cycle. 82 | 83 | * You can use `git-flow` in stand-alone repo's now. 84 | This means it does not assume you have an `origin` repository. 85 | (Thanks [Mark][2].) 86 | 87 | * No commands fetch from `origin` by default anymore. 88 | There were some issues related to disabling this flag on some platforms. 89 | 90 | * Init guesses branch names you may want to use for `develop` and `master`. 91 | 92 | * Added super-easy installation script. (Thanks [Rick][3].) 93 | 94 | * Added BSD license. 95 | 96 | [1]: http://github.com/nvie/gitflow/commit/f68d405cc3a11e9df3671f567658a6ab6ed8e0a1 97 | [2]: http://github.com/talios 98 | [3]: http://github.com/rickosborne 99 | 100 | 101 | Older versions 102 | -------------- 103 | No change history is recorded for pre-0.3 releases. 104 | -------------------------------------------------------------------------------- /gitflow/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010 Vincent Driessen. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR 14 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 15 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 16 | SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 18 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 20 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 21 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those 25 | of the authors and should not be interpreted as representing official policies, 26 | either expressed or implied, of Vincent Driessen. 27 | -------------------------------------------------------------------------------- /gitflow/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Vincent Driessen. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, 8 | # this list of conditions and the following disclaimer. 9 | # 10 | # 2. Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR 15 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 | # EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | # 25 | # The views and conclusions contained in the software and documentation are 26 | # those of the authors and should not be interpreted as representing official 27 | # policies, either expressed or implied, of Vincent Driessen. 28 | # 29 | 30 | prefix=/usr/local 31 | 32 | # files that need mode 755 33 | EXEC_FILES=git-flow 34 | 35 | # files that need mode 644 36 | SCRIPT_FILES =git-flow-init 37 | SCRIPT_FILES+=git-flow-feature 38 | SCRIPT_FILES+=git-flow-hotfix 39 | SCRIPT_FILES+=git-flow-release 40 | SCRIPT_FILES+=git-flow-support 41 | SCRIPT_FILES+=git-flow-version 42 | SCRIPT_FILES+=gitflow-common 43 | SCRIPT_FILES+=gitflow-shFlags 44 | 45 | all: 46 | @echo "usage: make install" 47 | @echo " make uninstall" 48 | 49 | install: 50 | @test -f gitflow-shFlags || (echo "Run 'git submodule init && git submodule update' first." ; exit 1 ) 51 | install -d -m 0755 $(prefix)/bin 52 | install -m 0755 $(EXEC_FILES) $(prefix)/bin 53 | install -m 0644 $(SCRIPT_FILES) $(prefix)/bin 54 | 55 | uninstall: 56 | test -d $(prefix)/bin && \ 57 | cd $(prefix)/bin && \ 58 | rm -f $(EXEC_FILES) $(SCRIPT_FILES) 59 | -------------------------------------------------------------------------------- /gitflow/README.mdown: -------------------------------------------------------------------------------- 1 | git-flow 2 | ======== 3 | 4 | A collection of Git extensions to provide high-level repository operations 5 | for Vincent Driessen's [branching model](http://nvie.com/git-model "original 6 | blog post"). 7 | 8 | 9 | Getting started 10 | --------------- 11 | For the best introduction to get started with `git flow`, please read Jeff 12 | Kreeftmeijer's blog post: 13 | 14 | [http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/](http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/) 15 | 16 | Or have a look at one of these screen casts: 17 | 18 | * [How to use a scalable Git branching model called git-flow](http://buildamodule.com/video/change-management-and-version-control-deploying-releases-features-and-fixes-with-git-how-to-use-a-scalable-git-branching-model-called-gitflow) (by Build a Module) 19 | * [A short introduction to git-flow](http://vimeo.com/16018419) (by Mark Derricutt) 20 | * [On the path with git-flow](http://codesherpas.com/screencasts/on_the_path_gitflow.mov) (by Dave Bock) 21 | 22 | 23 | Installing git-flow 24 | ------------------- 25 | See the Wiki for up-to-date [Installation Instructions](https://github.com/nvie/gitflow/wiki/Installation). 26 | 27 | 28 | Integration with your shell 29 | --------------------------- 30 | For those who use the [Bash](http://www.gnu.org/software/bash/) or 31 | [ZSH](http://www.zsh.org) shell, please check out the excellent work on the 32 | [git-flow-completion](http://github.com/bobthecow/git-flow-completion) project 33 | by [bobthecow](http://github.com/bobthecow). It offers tab-completion for all 34 | git-flow subcommands and branch names. 35 | 36 | 37 | FAQ 38 | --- 39 | See the [FAQ](http://github.com/nvie/gitflow/wiki/FAQ) section of the project 40 | Wiki. 41 | 42 | 43 | Please help out 44 | --------------- 45 | This project is still under development. Feedback and suggestions are very 46 | welcome and I encourage you to use the [Issues 47 | list](http://github.com/nvie/gitflow/issues) on Github to provide that 48 | feedback. 49 | 50 | Feel free to fork this repo and to commit your additions. For a list of all 51 | contributors, please see the [AUTHORS](AUTHORS) file. 52 | 53 | Any questions, tips, or general discussion can be posted to our Google group: 54 | [http://groups.google.com/group/gitflow-users](http://groups.google.com/group/gitflow-users) 55 | 56 | Contributing 57 | ------------ 58 | Fork the repository. Then, run: 59 | 60 | git clone --recursive git@github.com:/gitflow.git 61 | cd gitflow 62 | git branch master origin/master 63 | git flow init -d 64 | git flow feature start 65 | 66 | Then, do work and commit your changes. **Hint**: ``export PATH=`pwd`:$PATH`` 67 | from within the gitflow directory makes sure you're using the version of 68 | gitflow you're currently developing. 69 | 70 | git flow feature publish 71 | 72 | When done, open a pull request to your feature branch. 73 | 74 | License terms 75 | ------------- 76 | git-flow is published under the liberal terms of the BSD License, see the 77 | [LICENSE](LICENSE) file. Although the BSD License does not require you to share 78 | any modifications you make to the source code, you are very much encouraged and 79 | invited to contribute back your modifications to the community, preferably 80 | in a Github fork, of course. 81 | 82 | 83 | ### Initialization 84 | 85 | To initialize a new repo with the basic branch structure, use: 86 | 87 | git flow init [-d] 88 | 89 | This will then interactively prompt you with some questions on which branches 90 | you would like to use as development and production branches, and how you 91 | would like your prefixes be named. You may simply press Return on any of 92 | those questions to accept the (sane) default suggestions. 93 | 94 | The ``-d`` flag will accept all defaults. 95 | 96 | 97 | ### Creating feature/release/hotfix/support branches 98 | 99 | * To list/start/finish feature branches, use: 100 | 101 | git flow feature 102 | git flow feature start [] 103 | git flow feature finish 104 | 105 | For feature branches, the `` arg must be a commit on `develop`. 106 | 107 | * To push/pull a feature branch to the remote repository, use: 108 | 109 | git flow feature publish 110 | git flow feature pull 111 | 112 | * To list/start/finish release branches, use: 113 | 114 | git flow release 115 | git flow release start [] 116 | git flow release finish 117 | 118 | For release branches, the `` arg must be a commit on `develop`. 119 | 120 | * To list/start/finish hotfix branches, use: 121 | 122 | git flow hotfix 123 | git flow hotfix start [] 124 | git flow hotfix finish 125 | 126 | For hotfix branches, the `` arg must be a commit on `master`. 127 | 128 | * To list/start support branches, use: 129 | 130 | git flow support 131 | git flow support start 132 | 133 | For support branches, the `` arg must be a commit on `master`. 134 | 135 | 136 | Showing your appreciation 137 | ========================= 138 | A few people already requested it, so now it's here: a Flattr button. 139 | 140 | Of course, the best way to show your appreciation for the original 141 | [blog post](http://nvie.com/posts/a-successful-git-branching-model/) or the git-flow tool itself remains 142 | contributing to the community. If you'd like to show your appreciation in 143 | another way, however, consider Flattr'ing me: 144 | 145 | [![Flattr this][2]][1] 146 | 147 | [1]: http://flattr.com/thing/53771/git-flow 148 | [2]: http://api.flattr.com/button/button-static-50x60.png 149 | -------------------------------------------------------------------------------- /gitflow/bump-version: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | usage() { 3 | echo "usage: bump-version " 4 | } 5 | 6 | if [ $# -ne 1 ]; then 7 | usage 8 | exit 1 9 | fi 10 | 11 | if ! sed 's/^GITFLOW_VERSION=.*$/GITFLOW_VERSION='$1'/g' git-flow-version > .git-flow-version.new; then 12 | echo "Could not replace GITFLOW_VERSION variable." >&2 13 | exit 2 14 | fi 15 | 16 | mv .git-flow-version.new git-flow-version 17 | git add git-flow-version 18 | git commit -m "Bumped version number to $1" git-flow-version 19 | -------------------------------------------------------------------------------- /gitflow/contrib/gitflow-installer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # git-flow make-less installer for *nix systems, by Rick Osborne 4 | # Based on the git-flow core Makefile: 5 | # http://github.com/nvie/gitflow/blob/master/Makefile 6 | 7 | # Licensed under the same restrictions as git-flow: 8 | # http://github.com/nvie/gitflow/blob/develop/LICENSE 9 | 10 | # Does this need to be smarter for each host OS? 11 | if [ -z "$INSTALL_PREFIX" ] ; then 12 | INSTALL_PREFIX="/usr/local/bin" 13 | fi 14 | 15 | if [ -z "$REPO_NAME" ] ; then 16 | REPO_NAME="gitflow" 17 | fi 18 | 19 | if [ -z "$REPO_HOME" ] ; then 20 | REPO_HOME="http://github.com/nvie/gitflow.git" 21 | fi 22 | 23 | EXEC_FILES="git-flow" 24 | SCRIPT_FILES="git-flow-init git-flow-feature git-flow-hotfix git-flow-release git-flow-support git-flow-version gitflow-common gitflow-shFlags" 25 | SUBMODULE_FILE="gitflow-shFlags" 26 | 27 | echo "### gitflow no-make installer ###" 28 | 29 | case "$1" in 30 | uninstall) 31 | echo "Uninstalling git-flow from $INSTALL_PREFIX" 32 | if [ -d "$INSTALL_PREFIX" ] ; then 33 | for script_file in $SCRIPT_FILES $EXEC_FILES ; do 34 | echo "rm -vf $INSTALL_PREFIX/$script_file" 35 | rm -vf "$INSTALL_PREFIX/$script_file" 36 | done 37 | else 38 | echo "The '$INSTALL_PREFIX' directory was not found." 39 | echo "Do you need to set INSTALL_PREFIX ?" 40 | fi 41 | exit 42 | ;; 43 | help) 44 | echo "Usage: [environment] gitflow-installer.sh [install|uninstall]" 45 | echo "Environment:" 46 | echo " INSTALL_PREFIX=$INSTALL_PREFIX" 47 | echo " REPO_HOME=$REPO_HOME" 48 | echo " REPO_NAME=$REPO_NAME" 49 | exit 50 | ;; 51 | *) 52 | echo "Installing git-flow to $INSTALL_PREFIX" 53 | if [ -d "$REPO_NAME" -a -d "$REPO_NAME/.git" ] ; then 54 | echo "Using existing repo: $REPO_NAME" 55 | else 56 | echo "Cloning repo from GitHub to $REPO_NAME" 57 | git clone "$REPO_HOME" "$REPO_NAME" 58 | fi 59 | if [ -f "$REPO_NAME/$SUBMODULE_FILE" ] ; then 60 | echo "Submodules look up to date" 61 | else 62 | echo "Updating submodules" 63 | lastcwd=$PWD 64 | cd "$REPO_NAME" 65 | git submodule init 66 | git submodule update 67 | cd "$lastcwd" 68 | fi 69 | install -v -d -m 0755 "$INSTALL_PREFIX" 70 | for exec_file in $EXEC_FILES ; do 71 | install -v -m 0755 "$REPO_NAME/$exec_file" "$INSTALL_PREFIX" 72 | done 73 | for script_file in $SCRIPT_FILES ; do 74 | install -v -m 0644 "$REPO_NAME/$script_file" "$INSTALL_PREFIX" 75 | done 76 | exit 77 | ;; 78 | esac 79 | -------------------------------------------------------------------------------- /gitflow/contrib/msysgit-install.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal 3 | if not "%~1"=="" set GIT_HOME=%~f1 4 | if "%GIT_HOME%"=="" call :FindGitHome "git.cmd" 5 | 6 | if exist "%GIT_HOME%" goto :GitHomeOK 7 | 8 | echo MsysGit installation directory not found.>&2 9 | echo Try to give the directory name on the command line:>&2 10 | echo %0 "%ProgramFiles%\Git" 11 | endlocal 12 | exit /B 1 13 | 14 | :GitHomeOK 15 | set ERR=0 16 | 17 | echo Installing gitflow into "%GIT_HOME%"... 18 | 19 | call :ChkGetopt getopt.exe || set ERR=1 20 | if %ERR%==1 goto :End 21 | echo getopt.exe... Found 22 | 23 | if not exist "%GIT_HOME%\bin\git-flow" goto :Install 24 | echo GitFlow is already installed.>&2 25 | set /p mychoice="Do you want to replace it [y/n]" 26 | if "%mychoice%"=="y" goto :DeleteOldFiles 27 | goto :Abort 28 | 29 | :DeleteOldFiles 30 | echo Deleting old files... 31 | for /F %%i in ("%GIT_HOME%\git-flow*" "%GIT_HOME%\gitflow-*") do if exist "%%~fi" del /F /Q "%%~fi" 32 | 33 | :Install 34 | echo Copying files... 35 | ::goto :EOF 36 | xcopy "%~dp0\..\git-flow" "%GIT_HOME%\bin" /Y /R /F 37 | if errorlevel 4 if not errorlevel 5 goto :AccessDenied 38 | if errorlevel 1 set ERR=1 39 | xcopy "%~dp0\..\git-flow*" "%GIT_HOME%\bin" /Y /R /F || set ERR=1 40 | xcopy "%~dp0\..\gitflow-*" "%GIT_HOME%\bin" /Y /R /F || set ERR=1 41 | xcopy "%~dp0\..\shFlags\src\shflags" "%GIT_HOME%\bin\gitflow-shFlags" /Y /R /F || set ERR=1 42 | 43 | if %ERR%==1 choice /T 30 /C Y /D Y /M "Some unexpected errors happened. Sorry, you'll have to fix them by yourself." 44 | 45 | :End 46 | endlocal & exit /B %ERR% 47 | goto :EOF 48 | 49 | :AccessDenied 50 | set ERR=1 51 | echo. 52 | echo You should run this script with "Full Administrator" rights:>&2 53 | echo - Right-click with Shift on the script from the Explorer>&2 54 | echo - Select "Run as administrator">&2 55 | choice /T 30 /C YN /D Y /N >nul 56 | goto :End 57 | 58 | :Abort 59 | echo Installation canceled.>&2 60 | set ERR=1 61 | goto :End 62 | 63 | :ChkGetopt 64 | :: %1 is getopt.exe 65 | if exist "%GIT_HOME%\bin\%1" goto :EOF 66 | if exist "%USERPROFILE%\bin\%1" goto :EOF 67 | if exist "%~f$PATH:1" goto :EOF 68 | echo %GIT_HOME%\bin\%1 not found.>&2 69 | echo You have to install this file manually. See the GitFlow README. 70 | exit /B 1 71 | 72 | :FindGitHome 73 | setlocal 74 | set GIT_CMD_DIR=%~dp$PATH:1 75 | if "%GIT_CMD_DIR%"=="" endlocal & goto :EOF 76 | endlocal & set GIT_HOME=%GIT_CMD_DIR:~0,-5% 77 | goto :EOF 78 | -------------------------------------------------------------------------------- /gitflow/git-flow: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # git-flow -- A collection of Git extensions to provide high-level 4 | # repository operations for Vincent Driessen's branching model. 5 | # 6 | # Original blog post presenting this model is found at: 7 | # http://nvie.com/git-model 8 | # 9 | # Feel free to contribute to this project at: 10 | # http://github.com/nvie/gitflow 11 | # 12 | # Copyright 2010 Vincent Driessen. All rights reserved. 13 | # 14 | # Redistribution and use in source and binary forms, with or without 15 | # modification, are permitted provided that the following conditions are met: 16 | # 17 | # 1. Redistributions of source code must retain the above copyright notice, 18 | # this list of conditions and the following disclaimer. 19 | # 20 | # 2. Redistributions in binary form must reproduce the above copyright 21 | # notice, this list of conditions and the following disclaimer in the 22 | # documentation and/or other materials provided with the distribution. 23 | # 24 | # THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR 25 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 27 | # EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 31 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 33 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | # 35 | # The views and conclusions contained in the software and documentation are 36 | # those of the authors and should not be interpreted as representing official 37 | # policies, either expressed or implied, of Vincent Driessen. 38 | # 39 | 40 | # set this to workaround expr problems in shFlags on freebsd 41 | if uname -s | egrep -iq 'bsd'; then export EXPR_COMPAT=1; fi 42 | 43 | # enable debug mode 44 | if [ "$DEBUG" = "yes" ]; then 45 | set -x 46 | fi 47 | 48 | # The sed expression here replaces all backslashes by forward slashes. 49 | # This helps our Windows users, while not bothering our Unix users. 50 | export GITFLOW_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") 51 | 52 | usage() { 53 | echo "usage: git flow " 54 | echo 55 | echo "Available subcommands are:" 56 | echo " init Initialize a new git repo with support for the branching model." 57 | echo " feature Manage your feature branches." 58 | echo " release Manage your release branches." 59 | echo " hotfix Manage your hotfix branches." 60 | echo " support Manage your support branches." 61 | echo " version Shows version information." 62 | echo 63 | echo "Try 'git flow help' for details." 64 | } 65 | 66 | main() { 67 | if [ $# -lt 1 ]; then 68 | usage 69 | exit 1 70 | fi 71 | 72 | # load common functionality 73 | . "$GITFLOW_DIR/gitflow-common" 74 | 75 | # This environmental variable fixes non-POSIX getopt style argument 76 | # parsing, effectively breaking git-flow subcommand parsing on several 77 | # Linux platforms. 78 | export POSIXLY_CORRECT=1 79 | 80 | # use the shFlags project to parse the command line arguments 81 | . "$GITFLOW_DIR/gitflow-shFlags" 82 | FLAGS_PARENT="git flow" 83 | 84 | # allow user to request git action logging 85 | DEFINE_boolean show_commands false 'show actions taken (git commands)' g 86 | 87 | # do actual parsing 88 | FLAGS "$@" || exit $? 89 | eval set -- "${FLAGS_ARGV}" 90 | 91 | # sanity checks 92 | SUBCOMMAND="$1"; shift 93 | 94 | if [ ! -e "$GITFLOW_DIR/git-flow-$SUBCOMMAND" ]; then 95 | usage 96 | exit 1 97 | fi 98 | 99 | # run command 100 | . "$GITFLOW_DIR/git-flow-$SUBCOMMAND" 101 | FLAGS_PARENT="git flow $SUBCOMMAND" 102 | 103 | # test if the first argument is a flag (i.e. starts with '-') 104 | # in that case, we interpret this arg as a flag for the default 105 | # command 106 | SUBACTION="default" 107 | if [ "$1" != "" ] && { ! echo "$1" | grep -q "^-"; } then 108 | SUBACTION="$1"; shift 109 | fi 110 | if ! type "cmd_$SUBACTION" >/dev/null 2>&1; then 111 | warn "Unknown subcommand: '$SUBACTION'" 112 | usage 113 | exit 1 114 | fi 115 | 116 | # run the specified action 117 | if [ $SUBACTION != "help" ] && [ $SUBCOMMAND != "init" ] ; then 118 | init 119 | fi 120 | cmd_$SUBACTION "$@" 121 | } 122 | 123 | main "$@" 124 | -------------------------------------------------------------------------------- /gitflow/git-flow-init: -------------------------------------------------------------------------------- 1 | # 2 | # git-flow -- A collection of Git extensions to provide high-level 3 | # repository operations for Vincent Driessen's branching model. 4 | # 5 | # Original blog post presenting this model is found at: 6 | # http://nvie.com/git-model 7 | # 8 | # Feel free to contribute to this project at: 9 | # http://github.com/nvie/gitflow 10 | # 11 | # Copyright 2010 Vincent Driessen. All rights reserved. 12 | # 13 | # Redistribution and use in source and binary forms, with or without 14 | # modification, are permitted provided that the following conditions are met: 15 | # 16 | # 1. Redistributions of source code must retain the above copyright notice, 17 | # this list of conditions and the following disclaimer. 18 | # 19 | # 2. Redistributions in binary form must reproduce the above copyright 20 | # notice, this list of conditions and the following disclaimer in the 21 | # documentation and/or other materials provided with the distribution. 22 | # 23 | # THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR 24 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 26 | # EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 30 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | # 34 | # The views and conclusions contained in the software and documentation are 35 | # those of the authors and should not be interpreted as representing official 36 | # policies, either expressed or implied, of Vincent Driessen. 37 | # 38 | 39 | usage() { 40 | echo "usage: git flow init [-fd]" 41 | } 42 | 43 | parse_args() { 44 | # parse options 45 | FLAGS "$@" || exit $? 46 | eval set -- "${FLAGS_ARGV}" 47 | } 48 | 49 | # Default entry when no SUBACTION is given 50 | cmd_default() { 51 | DEFINE_boolean force false 'force setting of gitflow branches, even if already configured' f 52 | DEFINE_boolean defaults false 'use default branch naming conventions' d 53 | parse_args "$@" 54 | 55 | if ! git rev-parse --git-dir >/dev/null 2>&1; then 56 | git_do init 57 | else 58 | # assure that we are not working in a repo with local changes 59 | git_repo_is_headless || require_clean_working_tree 60 | fi 61 | 62 | # running git flow init on an already initialized repo is fine 63 | if gitflow_is_initialized && ! flag force; then 64 | warn "Already initialized for gitflow." 65 | warn "To force reinitialization, use: git flow init -f" 66 | exit 0 67 | fi 68 | 69 | local branch_count 70 | local answer 71 | 72 | if flag defaults; then 73 | warn "Using default branch names." 74 | fi 75 | 76 | # add a master branch if no such branch exists yet 77 | local master_branch 78 | if gitflow_has_master_configured && ! flag force; then 79 | master_branch=$(git config --get gitflow.branch.master) 80 | else 81 | # Two cases are distinguished: 82 | # 1. A fresh git repo (without any branches) 83 | # We will create a new master/develop branch for the user 84 | # 2. Some branches do already exist 85 | # We will disallow creation of new master/develop branches and 86 | # rather allow to use existing branches for git-flow. 87 | local default_suggestion 88 | local should_check_existence 89 | branch_count=$(git_local_branches | wc -l) 90 | if [ "$branch_count" -eq 0 ]; then 91 | echo "No branches exist yet. Base branches must be created now." 92 | should_check_existence=NO 93 | default_suggestion=$(git config --get gitflow.branch.master || echo master) 94 | else 95 | echo 96 | echo "Which branch should be used for bringing forth production releases?" 97 | git_local_branches | sed 's/^.*$/ - &/g' 98 | 99 | should_check_existence=YES 100 | default_suggestion= 101 | for guess in $(git config --get gitflow.branch.master) \ 102 | 'production' 'main' 'master'; do 103 | if git_local_branch_exists "$guess"; then 104 | default_suggestion="$guess" 105 | break 106 | fi 107 | done 108 | fi 109 | 110 | printf "Branch name for production releases: [$default_suggestion] " 111 | if noflag defaults; then 112 | read answer 113 | else 114 | printf "\n" 115 | fi 116 | master_branch=${answer:-$default_suggestion} 117 | 118 | # check existence in case of an already existing repo 119 | if [ "$should_check_existence" = "YES" ]; then 120 | # if no local branch exists and a remote branch of the same 121 | # name exists, checkout that branch and use it for master 122 | if ! git_local_branch_exists "$master_branch" && \ 123 | git_remote_branch_exists "origin/$master_branch"; then 124 | git_do branch "$master_branch" "origin/$master_branch" >/dev/null 2>&1 125 | elif ! git_local_branch_exists "$master_branch"; then 126 | die "Local branch '$master_branch' does not exist." 127 | fi 128 | fi 129 | 130 | # store the name of the master branch 131 | git_do config gitflow.branch.master "$master_branch" 132 | fi 133 | 134 | # add a develop branch if no such branch exists yet 135 | local develop_branch 136 | if gitflow_has_develop_configured && ! flag force; then 137 | develop_branch=$(git config --get gitflow.branch.develop) 138 | else 139 | # Again, the same two cases as with the master selection are 140 | # considered (fresh repo or repo that contains branches) 141 | local default_suggestion 142 | local should_check_existence 143 | branch_count=$(git_local_branches | grep -v "^${master_branch}\$" | wc -l) 144 | if [ "$branch_count" -eq 0 ]; then 145 | should_check_existence=NO 146 | default_suggestion=$(git config --get gitflow.branch.develop || echo develop) 147 | else 148 | echo 149 | echo "Which branch should be used for integration of the \"next release\"?" 150 | git_local_branches | grep -v "^${master_branch}\$" | sed 's/^.*$/ - &/g' 151 | 152 | should_check_existence=YES 153 | default_suggestion= 154 | for guess in $(git config --get gitflow.branch.develop) \ 155 | 'develop' 'int' 'integration' 'master'; do 156 | if git_local_branch_exists "$guess" && [ "$guess" != "$master_branch" ]; then 157 | default_suggestion="$guess" 158 | break 159 | fi 160 | done 161 | 162 | if [ -z $default_suggestion ]; then 163 | should_check_existence=NO 164 | default_suggestion=$(git config --get gitflow.branch.develop || echo develop) 165 | fi 166 | 167 | fi 168 | 169 | printf "Branch name for \"next release\" development: [$default_suggestion] " 170 | if noflag defaults; then 171 | read answer 172 | else 173 | printf "\n" 174 | fi 175 | develop_branch=${answer:-$default_suggestion} 176 | 177 | if [ "$master_branch" = "$develop_branch" ]; then 178 | die "Production and integration branches should differ." 179 | fi 180 | 181 | # check existence in case of an already existing repo 182 | if [ "$should_check_existence" = "YES" ]; then 183 | git_local_branch_exists "$develop_branch" || \ 184 | die "Local branch '$develop_branch' does not exist." 185 | fi 186 | 187 | # store the name of the develop branch 188 | git_do config gitflow.branch.develop "$develop_branch" 189 | fi 190 | 191 | # Creation of HEAD 192 | # ---------------- 193 | # We create a HEAD now, if it does not exist yet (in a fresh repo). We need 194 | # it to be able to create new branches. 195 | local created_gitflow_branch=0 196 | if ! git rev-parse --quiet --verify HEAD >/dev/null 2>&1; then 197 | git_do symbolic-ref HEAD "refs/heads/$master_branch" 198 | git_do commit --allow-empty --quiet -m "Initial commit" 199 | created_gitflow_branch=1 200 | fi 201 | 202 | # Creation of master 203 | # ------------------ 204 | # At this point, there always is a master branch: either it existed already 205 | # (and was picked interactively as the production branch) or it has just 206 | # been created in a fresh repo 207 | 208 | # Creation of develop 209 | # ------------------- 210 | # The develop branch possibly does not exist yet. This is the case when, 211 | # in a git init'ed repo with one or more commits, master was picked as the 212 | # default production branch and develop was "created". We should create 213 | # the develop branch now in that case (we base it on master, of course) 214 | if ! git_local_branch_exists "$develop_branch"; then 215 | if git_remote_branch_exists "origin/$develop_branch"; then 216 | git_do branch "$develop_branch" "origin/$develop_branch" >/dev/null 2>&1 217 | else 218 | git_do branch --no-track "$develop_branch" "$master_branch" 219 | fi 220 | created_gitflow_branch=1 221 | fi 222 | 223 | # assert the gitflow repo has been correctly initialized 224 | gitflow_is_initialized 225 | 226 | # switch to develop branch if its newly created 227 | if [ $created_gitflow_branch -eq 1 ]; then 228 | git_do checkout -q "$develop_branch" 229 | fi 230 | 231 | # finally, ask the user for naming conventions (branch and tag prefixes) 232 | if flag force || \ 233 | ! git config --get gitflow.prefix.feature >/dev/null 2>&1 || 234 | ! git config --get gitflow.prefix.release >/dev/null 2>&1 || 235 | ! git config --get gitflow.prefix.hotfix >/dev/null 2>&1 || 236 | ! git config --get gitflow.prefix.support >/dev/null 2>&1 || 237 | ! git config --get gitflow.prefix.versiontag >/dev/null 2>&1; then 238 | echo 239 | echo "How to name your supporting branch prefixes?" 240 | fi 241 | 242 | local prefix 243 | 244 | # Feature branches 245 | if ! git config --get gitflow.prefix.feature >/dev/null 2>&1 || flag force; then 246 | default_suggestion=$(git config --get gitflow.prefix.feature || echo feature/) 247 | printf "Feature branches? [$default_suggestion] " 248 | if noflag defaults; then 249 | read answer 250 | else 251 | printf "\n" 252 | fi 253 | [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} 254 | git_do config gitflow.prefix.feature "$prefix" 255 | fi 256 | 257 | # Release branches 258 | if ! git config --get gitflow.prefix.release >/dev/null 2>&1 || flag force; then 259 | default_suggestion=$(git config --get gitflow.prefix.release || echo release/) 260 | printf "Release branches? [$default_suggestion] " 261 | if noflag defaults; then 262 | read answer 263 | else 264 | printf "\n" 265 | fi 266 | [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} 267 | git_do config gitflow.prefix.release "$prefix" 268 | fi 269 | 270 | 271 | # Hotfix branches 272 | if ! git config --get gitflow.prefix.hotfix >/dev/null 2>&1 || flag force; then 273 | default_suggestion=$(git config --get gitflow.prefix.hotfix || echo hotfix/) 274 | printf "Hotfix branches? [$default_suggestion] " 275 | if noflag defaults; then 276 | read answer 277 | else 278 | printf "\n" 279 | fi 280 | [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} 281 | git_do config gitflow.prefix.hotfix "$prefix" 282 | fi 283 | 284 | 285 | # Support branches 286 | if ! git config --get gitflow.prefix.support >/dev/null 2>&1 || flag force; then 287 | default_suggestion=$(git config --get gitflow.prefix.support || echo support/) 288 | printf "Support branches? [$default_suggestion] " 289 | if noflag defaults; then 290 | read answer 291 | else 292 | printf "\n" 293 | fi 294 | [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} 295 | git_do config gitflow.prefix.support "$prefix" 296 | fi 297 | 298 | 299 | # Version tag prefix 300 | if ! git config --get gitflow.prefix.versiontag >/dev/null 2>&1 || flag force; then 301 | default_suggestion=$(git config --get gitflow.prefix.versiontag || echo "") 302 | printf "Version tag prefix? [$default_suggestion] " 303 | if noflag defaults; then 304 | read answer 305 | else 306 | printf "\n" 307 | fi 308 | [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} 309 | git_do config gitflow.prefix.versiontag "$prefix" 310 | fi 311 | 312 | 313 | # TODO: what to do with origin? 314 | } 315 | 316 | cmd_help() { 317 | usage 318 | exit 0 319 | } 320 | -------------------------------------------------------------------------------- /gitflow/git-flow-support: -------------------------------------------------------------------------------- 1 | # 2 | # git-flow -- A collection of Git extensions to provide high-level 3 | # repository operations for Vincent Driessen's branching model. 4 | # 5 | # Original blog post presenting this model is found at: 6 | # http://nvie.com/git-model 7 | # 8 | # Feel free to contribute to this project at: 9 | # http://github.com/nvie/gitflow 10 | # 11 | # Copyright 2010 Vincent Driessen. All rights reserved. 12 | # 13 | # Redistribution and use in source and binary forms, with or without 14 | # modification, are permitted provided that the following conditions are met: 15 | # 16 | # 1. Redistributions of source code must retain the above copyright notice, 17 | # this list of conditions and the following disclaimer. 18 | # 19 | # 2. Redistributions in binary form must reproduce the above copyright 20 | # notice, this list of conditions and the following disclaimer in the 21 | # documentation and/or other materials provided with the distribution. 22 | # 23 | # THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR 24 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 26 | # EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 30 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | # 34 | # The views and conclusions contained in the software and documentation are 35 | # those of the authors and should not be interpreted as representing official 36 | # policies, either expressed or implied, of Vincent Driessen. 37 | # 38 | 39 | init() { 40 | require_git_repo 41 | require_gitflow_initialized 42 | gitflow_load_settings 43 | VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`") 44 | PREFIX=$(git config --get gitflow.prefix.support) 45 | } 46 | 47 | warn "note: The support subcommand is still very EXPERIMENTAL!" 48 | warn "note: DO NOT use it in a production situation." 49 | 50 | usage() { 51 | echo "usage: git flow support [list] [-v]" 52 | echo " git flow support start [-F] " 53 | } 54 | 55 | cmd_default() { 56 | cmd_list "$@" 57 | } 58 | 59 | cmd_list() { 60 | DEFINE_boolean verbose false 'verbose (more) output' v 61 | parse_args "$@" 62 | 63 | local support_branches 64 | local current_branch 65 | local short_names 66 | support_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX") 67 | if [ -z "$support_branches" ]; then 68 | warn "No support branches exist." 69 | warn "" 70 | warn "You can start a new support branch:" 71 | warn "" 72 | warn " git flow support start " 73 | warn "" 74 | exit 0 75 | fi 76 | current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g') 77 | short_names=$(echo "$support_branches" | sed "s ^$PREFIX g") 78 | 79 | # determine column width first 80 | local width=0 81 | local branch 82 | for branch in $short_names; do 83 | local len=${#branch} 84 | width=$(max $width $len) 85 | done 86 | width=$(($width+3)) 87 | 88 | local branch 89 | for branch in $short_names; do 90 | local fullname=$PREFIX$branch 91 | local base=$(git merge-base "$fullname" "$MASTER_BRANCH") 92 | local master_sha=$(git rev-parse "$MASTER_BRANCH") 93 | local branch_sha=$(git rev-parse "$fullname") 94 | if [ "$fullname" = "$current_branch" ]; then 95 | printf "* " 96 | else 97 | printf " " 98 | fi 99 | if flag verbose; then 100 | printf "%-${width}s" "$branch" 101 | if [ "$branch_sha" = "$master_sha" ]; then 102 | printf "(no commits yet)" 103 | else 104 | local tagname=$(git name-rev --tags --no-undefined --name-only "$base") 105 | local nicename 106 | if [ "$tagname" != "" ]; then 107 | nicename=$tagname 108 | else 109 | nicename=$(git rev-parse --short "$base") 110 | fi 111 | printf "(based on $nicename)" 112 | fi 113 | else 114 | printf "%s" "$branch" 115 | fi 116 | echo 117 | done 118 | } 119 | 120 | cmd_help() { 121 | usage 122 | exit 0 123 | } 124 | 125 | parse_args() { 126 | # parse options 127 | FLAGS "$@" || exit $? 128 | eval set -- "${FLAGS_ARGV}" 129 | 130 | # read arguments into global variables 131 | VERSION=$1 132 | BASE=$2 133 | BRANCH=$PREFIX$VERSION 134 | } 135 | 136 | require_version_arg() { 137 | if [ "$VERSION" = "" ]; then 138 | warn "Missing argument " 139 | usage 140 | exit 1 141 | fi 142 | } 143 | 144 | require_base_arg() { 145 | if [ "$BASE" = "" ]; then 146 | warn "Missing argument " 147 | usage 148 | exit 1 149 | fi 150 | } 151 | 152 | require_base_is_on_master() { 153 | if ! git branch --no-color --contains "$BASE" 2>/dev/null \ 154 | | sed 's/[* ] //g' \ 155 | | grep -q "^$MASTER_BRANCH\$"; then 156 | die "fatal: Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'." 157 | fi 158 | } 159 | 160 | cmd_start() { 161 | DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F 162 | parse_args "$@" 163 | require_version_arg 164 | require_base_arg 165 | require_base_is_on_master 166 | 167 | # sanity checks 168 | require_clean_working_tree 169 | 170 | # fetch remote changes 171 | if flag fetch; then 172 | git_do fetch -q "$ORIGIN" "$BASE" 173 | fi 174 | require_branch_absent "$BRANCH" 175 | 176 | # create branch 177 | git_do checkout -b "$BRANCH" "$BASE" 178 | 179 | echo 180 | echo "Summary of actions:" 181 | echo "- A new branch '$BRANCH' was created, based on '$BASE'" 182 | echo "- You are now on branch '$BRANCH'" 183 | echo 184 | } 185 | -------------------------------------------------------------------------------- /gitflow/git-flow-version: -------------------------------------------------------------------------------- 1 | # 2 | # git-flow -- A collection of Git extensions to provide high-level 3 | # repository operations for Vincent Driessen's branching model. 4 | # 5 | # Original blog post presenting this model is found at: 6 | # http://nvie.com/git-model 7 | # 8 | # Feel free to contribute to this project at: 9 | # http://github.com/nvie/gitflow 10 | # 11 | # Copyright 2010 Vincent Driessen. All rights reserved. 12 | # 13 | # Redistribution and use in source and binary forms, with or without 14 | # modification, are permitted provided that the following conditions are met: 15 | # 16 | # 1. Redistributions of source code must retain the above copyright notice, 17 | # this list of conditions and the following disclaimer. 18 | # 19 | # 2. Redistributions in binary form must reproduce the above copyright 20 | # notice, this list of conditions and the following disclaimer in the 21 | # documentation and/or other materials provided with the distribution. 22 | # 23 | # THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR 24 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 26 | # EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 30 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | # 34 | # The views and conclusions contained in the software and documentation are 35 | # those of the authors and should not be interpreted as representing official 36 | # policies, either expressed or implied, of Vincent Driessen. 37 | # 38 | 39 | GITFLOW_VERSION=0.4.2-pre 40 | 41 | usage() { 42 | echo "usage: git flow version" 43 | } 44 | 45 | cmd_default() { 46 | echo "$GITFLOW_VERSION" 47 | } 48 | 49 | cmd_help() { 50 | usage 51 | exit 0 52 | } 53 | -------------------------------------------------------------------------------- /gitflow/gitflow-common: -------------------------------------------------------------------------------- 1 | # 2 | # git-flow -- A collection of Git extensions to provide high-level 3 | # repository operations for Vincent Driessen's branching model. 4 | # 5 | # Original blog post presenting this model is found at: 6 | # http://nvie.com/git-model 7 | # 8 | # Feel free to contribute to this project at: 9 | # http://github.com/nvie/gitflow 10 | # 11 | # Copyright 2010 Vincent Driessen. All rights reserved. 12 | # 13 | # Redistribution and use in source and binary forms, with or without 14 | # modification, are permitted provided that the following conditions are met: 15 | # 16 | # 1. Redistributions of source code must retain the above copyright notice, 17 | # this list of conditions and the following disclaimer. 18 | # 19 | # 2. Redistributions in binary form must reproduce the above copyright 20 | # notice, this list of conditions and the following disclaimer in the 21 | # documentation and/or other materials provided with the distribution. 22 | # 23 | # THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR 24 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 26 | # EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 30 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | # 34 | # The views and conclusions contained in the software and documentation are 35 | # those of the authors and should not be interpreted as representing official 36 | # policies, either expressed or implied, of Vincent Driessen. 37 | # 38 | 39 | # 40 | # Common functionality 41 | # 42 | 43 | # shell output 44 | warn() { echo "$@" >&2; } 45 | die() { warn "$@"; exit 1; } 46 | 47 | escape() { 48 | echo "$1" | sed 's/\([\.\$\*]\)/\\\1/g' 49 | } 50 | 51 | # set logic 52 | has() { 53 | local item=$1; shift 54 | echo " $@ " | grep -q " $(escape $item) " 55 | } 56 | 57 | # basic math 58 | min() { [ "$1" -le "$2" ] && echo "$1" || echo "$2"; } 59 | max() { [ "$1" -ge "$2" ] && echo "$1" || echo "$2"; } 60 | 61 | # basic string matching 62 | startswith() { [ "$1" != "${1#$2}" ]; } 63 | endswith() { [ "$1" != "${1%$2}" ]; } 64 | 65 | # convenience functions for checking shFlags flags 66 | flag() { local FLAG; eval FLAG='$FLAGS_'$1; [ $FLAG -eq $FLAGS_TRUE ]; } 67 | noflag() { local FLAG; eval FLAG='$FLAGS_'$1; [ $FLAG -ne $FLAGS_TRUE ]; } 68 | 69 | # 70 | # Git specific common functionality 71 | # 72 | 73 | git_do() { 74 | # equivalent to git, used to indicate actions that make modifications 75 | if flag show_commands; then 76 | echo "git $@" >&2 77 | fi 78 | git "$@" 79 | } 80 | 81 | git_local_branches() { git branch --no-color | sed 's/^[* ] //'; } 82 | git_remote_branches() { git branch -r --no-color | sed 's/^[* ] //'; } 83 | git_all_branches() { ( git branch --no-color; git branch -r --no-color) | sed 's/^[* ] //'; } 84 | git_all_tags() { git tag; } 85 | 86 | git_current_branch() { 87 | git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g' 88 | } 89 | 90 | git_is_clean_working_tree() { 91 | if ! git diff --no-ext-diff --ignore-submodules --quiet --exit-code; then 92 | return 1 93 | elif ! git diff-index --cached --quiet --ignore-submodules HEAD --; then 94 | return 2 95 | else 96 | return 0 97 | fi 98 | } 99 | 100 | git_repo_is_headless() { 101 | ! git rev-parse --quiet --verify HEAD >/dev/null 2>&1 102 | } 103 | 104 | git_local_branch_exists() { 105 | has $1 $(git_local_branches) 106 | } 107 | 108 | git_remote_branch_exists() { 109 | has $1 $(git_remote_branches) 110 | } 111 | 112 | git_branch_exists() { 113 | has $1 $(git_all_branches) 114 | } 115 | 116 | git_tag_exists() { 117 | has $1 $(git_all_tags) 118 | } 119 | 120 | # 121 | # git_compare_branches() 122 | # 123 | # Tests whether branches and their "origin" counterparts have diverged and need 124 | # merging first. It returns error codes to provide more detail, like so: 125 | # 126 | # 0 Branch heads point to the same commit 127 | # 1 First given branch needs fast-forwarding 128 | # 2 Second given branch needs fast-forwarding 129 | # 3 Branch needs a real merge 130 | # 4 There is no merge base, i.e. the branches have no common ancestors 131 | # 132 | git_compare_branches() { 133 | local commit1=$(git rev-parse "$1") 134 | local commit2=$(git rev-parse "$2") 135 | if [ "$commit1" != "$commit2" ]; then 136 | local base=$(git merge-base "$commit1" "$commit2") 137 | if [ $? -ne 0 ]; then 138 | return 4 139 | elif [ "$commit1" = "$base" ]; then 140 | return 1 141 | elif [ "$commit2" = "$base" ]; then 142 | return 2 143 | else 144 | return 3 145 | fi 146 | else 147 | return 0 148 | fi 149 | } 150 | 151 | # 152 | # git_is_branch_merged_into() 153 | # 154 | # Checks whether branch $1 is succesfully merged into $2 155 | # 156 | git_is_branch_merged_into() { 157 | local subject=$1 158 | local base=$2 159 | local all_merges="$(git branch --no-color --contains $subject | sed 's/^[* ] //')" 160 | has $base $all_merges 161 | } 162 | 163 | # 164 | # gitflow specific common functionality 165 | # 166 | 167 | # check if this repo has been inited for gitflow 168 | gitflow_has_master_configured() { 169 | local master=$(git config --get gitflow.branch.master) 170 | [ "$master" != "" ] && git_local_branch_exists "$master" 171 | } 172 | 173 | gitflow_has_develop_configured() { 174 | local develop=$(git config --get gitflow.branch.develop) 175 | [ "$develop" != "" ] && git_local_branch_exists "$develop" 176 | } 177 | 178 | gitflow_has_prefixes_configured() { 179 | git config --get gitflow.prefix.feature >/dev/null 2>&1 && \ 180 | git config --get gitflow.prefix.release >/dev/null 2>&1 && \ 181 | git config --get gitflow.prefix.hotfix >/dev/null 2>&1 && \ 182 | git config --get gitflow.prefix.support >/dev/null 2>&1 && \ 183 | git config --get gitflow.prefix.versiontag >/dev/null 2>&1 184 | } 185 | 186 | gitflow_is_initialized() { 187 | gitflow_has_master_configured && \ 188 | gitflow_has_develop_configured && \ 189 | [ "$(git config --get gitflow.branch.master)" != \ 190 | "$(git config --get gitflow.branch.develop)" ] && \ 191 | gitflow_has_prefixes_configured 192 | } 193 | 194 | # loading settings that can be overridden using git config 195 | gitflow_load_settings() { 196 | export DOT_GIT_DIR=$(git rev-parse --git-dir 2>/dev/null) 197 | export MASTER_BRANCH=$(git config --get gitflow.branch.master) 198 | export DEVELOP_BRANCH=$(git config --get gitflow.branch.develop) 199 | export ORIGIN=$(git config --get gitflow.origin || echo origin) 200 | } 201 | 202 | # 203 | # gitflow_resolve_nameprefix 204 | # 205 | # Inputs: 206 | # $1 = name prefix to resolve 207 | # $2 = branch prefix to use 208 | # 209 | # Searches branch names from git_local_branches() to look for a unique 210 | # branch name whose name starts with the given name prefix. 211 | # 212 | # There are multiple exit codes possible: 213 | # 0: The unambiguous full name of the branch is written to stdout 214 | # (success) 215 | # 1: No match is found. 216 | # 2: Multiple matches found. These matches are written to stderr 217 | # 218 | gitflow_resolve_nameprefix() { 219 | local name=$1 220 | local prefix=$2 221 | local matches 222 | local num_matches 223 | 224 | # first, check if there is a perfect match 225 | if git_local_branch_exists "$prefix$name"; then 226 | echo "$name" 227 | return 0 228 | fi 229 | 230 | matches=$(echo "$(git_local_branches)" | grep "^$(escape "$prefix$name")") 231 | num_matches=$(echo "$matches" | wc -l) 232 | if [ -z "$matches" ]; then 233 | # no prefix match, so take it literally 234 | warn "No branch matches prefix '$name'" 235 | return 1 236 | else 237 | if [ $num_matches -eq 1 ]; then 238 | echo "${matches#$prefix}" 239 | return 0 240 | else 241 | # multiple matches, cannot decide 242 | warn "Multiple branches match prefix '$name':" 243 | for match in $matches; do 244 | warn "- $match" 245 | done 246 | return 2 247 | fi 248 | fi 249 | } 250 | 251 | # 252 | # Assertions for use in git-flow subcommands 253 | # 254 | 255 | require_git_repo() { 256 | if ! git rev-parse --git-dir >/dev/null 2>&1; then 257 | die "fatal: Not a git repository" 258 | fi 259 | } 260 | 261 | require_gitflow_initialized() { 262 | if ! gitflow_is_initialized; then 263 | die "fatal: Not a gitflow-enabled repo yet. Please run \"git flow init\" first." 264 | fi 265 | } 266 | 267 | require_clean_working_tree() { 268 | git_is_clean_working_tree 269 | local result=$? 270 | if [ $result -eq 1 ]; then 271 | die "fatal: Working tree contains unstaged changes. Aborting." 272 | fi 273 | if [ $result -eq 2 ]; then 274 | die "fatal: Index contains uncommited changes. Aborting." 275 | fi 276 | } 277 | 278 | require_local_branch() { 279 | if ! git_local_branch_exists $1; then 280 | die "fatal: Local branch '$1' does not exist and is required." 281 | fi 282 | } 283 | 284 | require_remote_branch() { 285 | if ! has $1 $(git_remote_branches); then 286 | die "Remote branch '$1' does not exist and is required." 287 | fi 288 | } 289 | 290 | require_branch() { 291 | if ! has $1 $(git_all_branches); then 292 | die "Branch '$1' does not exist and is required." 293 | fi 294 | } 295 | 296 | require_branch_absent() { 297 | if has $1 $(git_all_branches); then 298 | die "Branch '$1' already exists. Pick another name." 299 | fi 300 | } 301 | 302 | require_tag_absent() { 303 | for tag in $(git_all_tags); do 304 | if [ "$1" = "$tag" ]; then 305 | die "Tag '$1' already exists. Pick another name." 306 | fi 307 | done 308 | } 309 | 310 | require_branches_equal() { 311 | require_local_branch "$1" 312 | require_remote_branch "$2" 313 | git_compare_branches "$1" "$2" 314 | local status=$? 315 | if [ $status -gt 0 ]; then 316 | warn "Branches '$1' and '$2' have diverged." 317 | if [ $status -eq 1 ]; then 318 | die "And branch '$1' may be fast-forwarded." 319 | elif [ $status -eq 2 ]; then 320 | # Warn here, since there is no harm in being ahead 321 | warn "And local branch '$1' is ahead of '$2'." 322 | else 323 | die "Branches need merging first." 324 | fi 325 | fi 326 | } 327 | -------------------------------------------------------------------------------- /gitflow/gitflow-shFlags: -------------------------------------------------------------------------------- 1 | shFlags/src/shflags -------------------------------------------------------------------------------- /gitnflow-common: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | #### common 5 | 6 | git_do() { 7 | # equivalent to git, used to indicate actions that make modifications 8 | if flag show_commands; then 9 | echo "gitnflow do: git $@" >&2 10 | fi 11 | git "$@" 12 | } 13 | 14 | #### args has repetition 15 | #### true: has false:not has 16 | has_repetition() { 17 | local num1=$( 18 | for i in $* ; do 19 | echo "$i"; 20 | done | wc -l 21 | ) 22 | 23 | local num2=$( 24 | for i in $* ; do 25 | echo "$i"; 26 | done | sort -u | wc -l 27 | ) 28 | [ $num1 != $num2 ] 29 | } 30 | 31 | 32 | # 33 | # gitnflow specific common functionality 34 | # 35 | 36 | # check if this repo has been inited for gitnflow 37 | gitnflow_has_develop_configured() { 38 | local develop=$(git config --get gitnflow.branch.develop) 39 | [ "$develop" != "" ] && git_local_branch_exists "$develop" 40 | } 41 | 42 | gitnflow_has_test_configured() { 43 | local test=$(git config --get gitnflow.branch.test) 44 | [ "$test" != "" ] && git_local_branch_exists "$test" 45 | } 46 | 47 | gitnflow_has_preview_configured() { 48 | local preview=$(git config --get gitnflow.branch.preview) 49 | [ "$preview" != "" ] && git_local_branch_exists "$preview" 50 | } 51 | 52 | gitnflow_has_master_configured() { 53 | local master=$(git config --get gitnflow.branch.master) 54 | [ "$master" != "" ] && git_local_branch_exists "$master" 55 | } 56 | 57 | gitnflow_has_remote_configured() { 58 | local remote=$(git config --get gitnflow.remote) 59 | [ "$remote" != "" ] 60 | } 61 | 62 | gitnflow_has_prefixes_configured() { 63 | git config --get gitnflow.prefix.feature >/dev/null 2>&1 64 | } 65 | 66 | gitnflow_is_initialized() { 67 | local master=$(git config --get gitnflow.branch.master) 68 | local develop=$(git config --get gitnflow.branch.develop) 69 | local test=$(git config --get gitnflow.branch.test) 70 | local preview=$(git config --get gitnflow.branch.preview) 71 | 72 | gitnflow_has_master_configured && \ 73 | gitnflow_has_develop_configured && \ 74 | gitnflow_has_test_configured && \ 75 | gitnflow_has_preview_configured && \ 76 | gitnflow_has_remote_configured && \ 77 | ! has_repetition "$master" "$develop" "$test" "$preview" && \ 78 | gitnflow_has_prefixes_configured 79 | } 80 | 81 | # loading settings that can be overridden using git config 82 | gitnflow_load_settings() { 83 | export DOT_GIT_DIR=$(git rev-parse --git-dir 2>/dev/null) 84 | export DEVELOP_BRANCH=$(git config --get gitnflow.branch.develop) 85 | export TEST_BRANCH=$(git config --get gitnflow.branch.test) 86 | export PREVIEW_BRANCH=$(git config --get gitnflow.branch.preview) 87 | export MASTER_BRANCH=$(git config --get gitnflow.branch.master) 88 | export REMOTE=$(git config --get gitnflow.remote) 89 | } 90 | 91 | require_gitnflow_initialized() { 92 | if ! gitnflow_is_initialized; then 93 | die "fatal: Not a gitnflow-enabled repo yet. Please run \"git nflow init\" first." 94 | fi 95 | } 96 | 97 | -------------------------------------------------------------------------------- /gitnflow-gitflow-common: -------------------------------------------------------------------------------- 1 | gitflow/gitflow-common -------------------------------------------------------------------------------- /gitnflow-shFlags: -------------------------------------------------------------------------------- 1 | shflags/shflags -------------------------------------------------------------------------------- /shflags/.githooks/generic: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # A generic git hook proxy. 4 | # https://git-scm.com/docs/githooks 5 | 6 | run() { 7 | hook=$1 8 | file=$2 9 | 10 | n=$(echo "${file}" |sed "s/^.*${hook}\.//") 11 | echo "running ${n} ${hook}" 12 | ${file} 13 | } 14 | 15 | die() { 16 | hook=$1 17 | echo "${hook} hook did not succeed" >&2 18 | exit 1 19 | } 20 | 21 | # Redirect output to stderr. 22 | exec 1>&2 23 | 24 | githooks='.githooks' 25 | basename=$(basename "$0") 26 | 27 | for f in $(cd ${githooks} && echo *); do 28 | case "${f}" in 29 | ${basename}.*) 30 | run ${basename} "${githooks}/${f}" || die "${f}" 31 | ;; 32 | esac 33 | done 34 | -------------------------------------------------------------------------------- /shflags/.githooks/pre-commit.shellcheck: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Git hook to run ShellCheck. 4 | # 5 | # ShellCheck 6 | 7 | # Treat unset variables as an error when performing parameter expansion. 8 | set -u 9 | 10 | TRUE=0 11 | FALSE=1 12 | 13 | die() { 14 | echo "$@" >&2 15 | exit 1 16 | } 17 | 18 | if ! command -v shellcheck >/dev/null; then 19 | echo 'unable to locate shellcheck' >&2 20 | return 0 21 | fi 22 | 23 | success=${TRUE} 24 | for f in $(git diff --cached --name-only); do 25 | # Check for file deletion. 26 | if [ ! -r "${f}" ]; then 27 | continue 28 | fi 29 | 30 | cmd=':' 31 | case "${f}" in 32 | shflags|shflags_test_helpers) cmd="shellcheck -s sh ${f}" ;; 33 | *.sh) cmd="shellcheck ${f}" ;; 34 | esac 35 | if ! ${cmd}; then 36 | success=${FALSE} 37 | echo "shellcheck error for '${f}'" >&2 38 | fi 39 | done 40 | 41 | exit ${success} 42 | -------------------------------------------------------------------------------- /shflags/.gitignore: -------------------------------------------------------------------------------- 1 | # Hidden files generated by OS X. 2 | ._* 3 | -------------------------------------------------------------------------------- /shflags/.travis.yml: -------------------------------------------------------------------------------- 1 | language: bash 2 | 3 | env: 4 | - SHUNIT_COLOR='always' 5 | 6 | script: 7 | # Execute the unit tests. 8 | - ./test_runner 9 | 10 | addons: 11 | apt: 12 | packages: 13 | - ksh 14 | - mksh 15 | - zsh 16 | 17 | matrix: 18 | include: 19 | - os: linux 20 | dist: bionic # Ubuntu Bionic 18.04 (EoL Apr 2028). 21 | - os: linux 22 | dist: xenial # Ubuntu Xenial 16.04 (EoL Apr 2024). 23 | - os: linux 24 | dist: trusty # Ubuntu Trusty 14.04 (EoL Apr 2022). 25 | - os: osx 26 | - os: linux 27 | script: 28 | # Run the source through ShellCheck (http://www.shellcheck.net). 29 | - shellcheck *_test.sh 30 | - shellcheck -s sh shflags shflags_test_helpers 31 | 32 | branches: 33 | only: 34 | - master 35 | - 1.0.x 36 | # Tags, e.g. v.1.2.3. 37 | - /^v\d+\.\d+(\.\d+)?(-\S*)?$/ 38 | -------------------------------------------------------------------------------- /shflags/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at kate.ward@forestent.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /shflags/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Coding Standards 2 | 3 | shFlags is more than just a simple 20 line shell script. It is a significant library of shell code that at first glance might not seam easy to understand. To improve code readability and usability, these guidelines are followed to help make the code more understandable for anyone who wants to read or modify it. 4 | 5 | [TOC] 6 | 7 | ## Function declaration 8 | 9 | Declare functions using the following form: 10 | 11 | ```sh 12 | doSomething() { 13 | echo 'done!' 14 | } 15 | ``` 16 | 17 | One-line functions are allowed if they are for a single command. 18 | 19 | ```sh 20 | doSomething() { echo 'done!'; } 21 | ``` 22 | 23 | ## Function documentation 24 | 25 | Each function should be preceded by a header that provides the following: 26 | 27 | 1. A one-sentence summary of what the function does. 28 | 29 | 1. (optional) A longer description of what the function does, and perhaps some special information that helps convey its usage better. 30 | 31 | 1. Args: a one-line summary of each argument of the form: 32 | 33 | `name: type: description` 34 | 35 | 1. Output: a one-line summary of the output provided. Only output to STDOUT must be documented, unless the output to STDERR is of significance (i.e. not just an error message). The output should be of the form: 36 | 37 | `type: description` 38 | 39 | 1. Returns: a one-line summary of the value returned. Returns in shell are always integers, but if the output is a true/false for success (i.e. a boolean), it should be noted. The output should be of the form: 40 | 41 | `type: description` 42 | 43 | Here is a sample header: 44 | 45 | ``` 46 | # Return valid getopt options using currently defined list of long options. 47 | # 48 | # This function builds a proper getopt option string for short (and long) 49 | # options, using the current list of long options for reference. 50 | # 51 | # Args: 52 | # _flags_optStr: integer: option string type (__FLAGS_OPTSTR_*) 53 | # Output: 54 | # string: generated option string for getopt 55 | # Returns: 56 | # boolean: success of operation (always returns True) 57 | ``` 58 | 59 | ## Variable and function names 60 | 61 | All shFlags specific constants, variables, and functions will be prefixed appropriately with `flags`. This is to distinguish usage in the shFlags code from users own scripts so that the shell name space remains predictable to users. The exceptions here are the standard `assertEquals`, etc., functions. 62 | 63 | All non built-in constants and variables will be surrounded with squiggle brackets, e.g. `${flags_someVariable}` to improve code readability. 64 | 65 | Due to some shells not supporting local variables in functions, care in the naming and use of variables, both public and private, is very important. Accidental overriding of the variables can occur easily if care is not taken as all variables are technically global variables in some shells. 66 | 67 | Type | Sample 68 | -------------------------------- | --------------------- 69 | global public constant | `FLAGS_TRUE` 70 | global private constant | `__FLAGS_SHELL_FLAGS` 71 | global public variable | `flags_variable` 72 | global private variable | `__flags_variable` 73 | global macro | `_FLAGS_SOME_MACRO_` 74 | public function | `flags_function` 75 | public function, local variable | `flags_variable_` 76 | private function | `_flags_function` 77 | private function, local variable | `_flags_variable_` 78 | 79 | Where it makes sense to improve readability, variables can have the first letter of the second and later words capitalized. For example, the local variable name for the help string length is `flags_helpStrLen_`. 80 | 81 | There are three special-case global public variables used. They are used due to overcome the limitations of shell scoping or to prevent forking. The three variables are: 82 | 83 | - `flags_error` 84 | - `flags_output` 85 | - `flags_return` 86 | 87 | ## Local variable cleanup 88 | 89 | As many shells do not support local variables, no support for cleanup of variables is present either. As such, all variables local to a function must be cleared up with the `unset` built-in command at the end of each function. 90 | 91 | ## Indentation 92 | 93 | Code block indentation is two (2) spaces, and tabs may not be used. 94 | 95 | ```sh 96 | if [ -z 'some string' ]; then 97 | someFunction 98 | fi 99 | ``` 100 | 101 | Lines of code have no line limit, although the general preference is to wrap lines at reasonable boundaries (e.g., between if/then/else clauses). When long lines are wrapped using the backslash character '\', subsequent lines should be indented with four (4) spaces so as to differentiate from the standard spacing of two characters, and tabs may not be used. 102 | 103 | ```sh 104 | for x in some set of very long set of arguments that make for a very long \ 105 | that extends much too long for one line 106 | do 107 | echo ${x} 108 | done 109 | ``` 110 | 111 | When a conditional expression is written using the built-in `[` command, and that line must be wrapped, place the control `||` or `&&` operators on the same line as the expression where possible, with the list to be executed on its own line. 112 | 113 | ```sh 114 | [ -n 'some really long expression' -a -n 'some other long expr' ] && \ 115 | echo 'that was actually true!' 116 | ``` 117 | -------------------------------------------------------------------------------- /shflags/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /shflags/README.md: -------------------------------------------------------------------------------- 1 | # shFlags README 2 | 3 | shFlags is a port of the Google [gflags](http://gflags.github.io/gflags/) library for Unix shell. The code is written in a way to be as portable as possible to work across a wide array of Unix variants. It is also tested with [shUnit2](https://github.com/kward/shunit2) to maintain code quality. 4 | 5 | If you'd like to use shFlags, feel free to read the documentation. 6 | https://github.com/kward/shflags/wiki/Documentation12x 7 | 8 | [![Travis CI][travis-ci-png]][travis-ci] 9 | 10 | [travis-ci-png]: https://travis-ci.org/kward/shflags.png?branch=master 11 | [travis-ci]: https://travis-ci.org/kward/shflags 12 | -------------------------------------------------------------------------------- /shflags/doc/CHANGES-1.0.md: -------------------------------------------------------------------------------- 1 | # Changes in shFlags 2 | 3 | ## Changes with 1.0.3 4 | 5 | MAJOR CHANGE! `FLAGS_ARGC` is now obsolete, and is replaced by `FLAGS_ARGV`. See 6 | below for more info. 7 | 8 | Fixed issue# 7 where long flags defined with '=' (e.g. `--abc=123`) made it 9 | impossible for the user to know how many non-flag command-line arguments were 10 | available because the value returned by `FLAGS_ARGC` was wrong. The `FLAGS_ARGC` 11 | value is now obsolete, but will be maintained for backwards compatibility. The 12 | new method of getting the non-flag arguments is by executing `eval set -- 13 | "${FLAGS_ARGV}"` after the `FLAGS` call. The arguments will then be available 14 | using the standard shell $#, $@, $*, $1, etc. variables. 15 | 16 | Due to above fix for issue# 7, there is now proper support for mixing flags with 17 | non-flag arguments on the command-line. Previously, all non-flag arguments had 18 | to be at the end of the command-line. 19 | 20 | Renamed `_flags_standardGetopt()` and `_flags_enhancedGetopt()` functions to 21 | `_flags_getoptStandard()` and `_flags_getoptEnhanced()`. 22 | 23 | Took out the setting and restoration of the '-u' shell flag to treat unset 24 | variables as an error. No point in having it in this library as it is verified 25 | in the unit tests, and provides basically no benefit. 26 | 27 | Fixed bug under Solaris where the generated help was adding extra 'x' 28 | characters. 29 | 30 | Added checks for reserved flag variables (e.g. `FLAGS_TRUE`). 31 | 32 | Fixed some unset variable bugs. 33 | 34 | Now report the actual `getopt` error if there is one. 35 | 36 | All tests now properly enable skipping based on whether a standard or enhanced 37 | `getopt` is found. 38 | 39 | Added the OS version to OS release for Solaris. 40 | 41 | Fixed `flags_reset()` so it unsets the default value environment vars. 42 | 43 | ## Changes with 1.0.2 44 | 45 | FLAGS_PARENT no longer transforms into a constant so that it can be defined at 46 | run time in scripts. 47 | 48 | Added warning about short flags being unsupported when there are problems 49 | parsing the options with `getopt`. 50 | 51 | Add default values to end of description strings. 52 | 53 | Fixed bug that returned an error instead of success when recalling the default 54 | values for empty strings. 55 | 56 | Added warning when a duplicate flag definition is attempted. 57 | 58 | Improved `assert[Warn|Error]Msg()` test helper grepping. 59 | 60 | Replaced shell_versions.sh with a new versions library and created 61 | `gen_test_results.sh` to make releases easier. 62 | 63 | Copied the coding standards from shUnit2, but haven't fully implemented them in 64 | shFlags yet. 65 | 66 | Issue# 1: When a user defines their own `--help` flag, no more warning is thrown 67 | when `FLAGS()` is called stating that the help flag already defined. 68 | 69 | Issue# 2: Passing the `--nohelp` option no longer gives help output. 70 | 71 | Issue# 3: Added support for screen width detection. 72 | 73 | ## Changes with 1.0.1 74 | 75 | Fixed bug where the help output added '[no]' to all flag names 76 | 77 | Added additional example files that are referenced by the documentation. 78 | 79 | Improved `zsh` version and option checking. 80 | 81 | Upgraded shUnit2 to 2.1.4 82 | 83 | Added unit testing for the help output. 84 | 85 | When including a library (e.g. shflags) in a script, zsh 3.0.8 doesn't actually 86 | execute the code in-line, but later. As such, variables that are defined in the 87 | library cannot be used until functions are called from the main code. This 88 | required the 'help' flag definition to be moved inside the FLAGS command. 89 | 90 | ## Changes with 1.0.0 91 | 92 | This is the first official release, so everything is new. 93 | -------------------------------------------------------------------------------- /shflags/doc/CHANGES-1.2.md: -------------------------------------------------------------------------------- 1 | # Changes in shFlags 2 | 3 | ## Changes with 1.2.3 4 | 5 | Upgraded shUnit2 to 2.1.7. 6 | 7 | Fixed the examples to work again with the new code structure. 8 | 9 | Removed `gen_test_report.sh` as it isn't used anymore. 10 | 11 | Minor fix for `_flags_underscoreName()` to insure POSIX compliance. 12 | 13 | Cleanup of pre-GitHub cruft. 14 | 15 | Fixed bug in `_flags_columns()` where `stty size` sometimes gave unexpected 16 | output, causing the function to not work. 17 | 18 | Replaced `test_runner` with upstream from https://github.com/kward/shlib. 19 | 20 | ## Changes with 1.2.2 21 | 22 | Ran all scripts through [ShellCheck](http://www.shellcheck.net/). 23 | 24 | Replaced `shflags_test.sh` with `test_runner` from 25 | https://github.com/kward/shlib. 26 | 27 | Fixed issue #45. Empty help string causes `shflags_test_issue_28.sh` to fail. 28 | 29 | Continuous integration testing setup with [Travis 30 | CI](https://travis-ci.org/kward/shflags). 31 | 32 | Restructured code to be more GitHub like. 33 | 34 | ## Changes with 1.2.1 35 | 36 | Fixed issue #43. Added support for BusyBox `ash` shell. 37 | 38 | Fixed issues #26, #27. Re-factored `_flags_itemInList()` to use built-ins. 39 | 40 | Fixed issue #31. Documented newline support in FLAGS_HELP. 41 | 42 | Fixed issue #28. DEFINE_boolean misbehaves when help-string is empty. 43 | 44 | Fixed issue #25. Fix some typos. 45 | 46 | ## Changes with 1.2.0 47 | 48 | Changed from the LGPL v2.1 license to the Apache v2.0 license so that others can 49 | include the library or make changes without needing to release the modified 50 | source code as well. 51 | 52 | Moved documentation to Markdown. 53 | 54 | Migrated the code to GitHub as http://code.google.com/ is turning down. 55 | 56 | Fixed issue #10. Usage of `expr` under FreeBSD 7.2 (FreeNAS 0.7.1) and FreeBSD 57 | 8.0 that was causing many unit tests to fail. 58 | 59 | Fixed issue where booleans were sometimes mis-configured to require additional 60 | values like other flags. 61 | 62 | Changed `_flags_fatal()` to exit with `FLAGS_ERROR` immediately. 63 | 64 | Fixed issue #11. When help is requested, the help flag is no longer prefixed 65 | with '[no]'. 66 | 67 | Upgraded shUnit2 to 2.1.6. 68 | 69 | Fixed issue #12. Requesting help shouldn't be considered an error. 70 | 71 | Added the ability to override the use of the OS default `getopt` command by 72 | defining the `FLAGS_GETOPT_CMD` variable. 73 | 74 | Updated `gen_test_results.sh` and versions from shUnit2 source. 75 | 76 | Fixed issues# 13, 14. Added support for dashes '-' in long flag names. The 77 | defined flag will still be declared with underscores '\_' due to shell 78 | limitations, so only one of a dashed flag name or an underscored flag name are 79 | allowed, not both. (Backslash on \_ to prevent Markdown formatting.) 80 | 81 | Issue #20. Updated LGPL v2.1 license from 82 | http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. 83 | 84 | Issue #15. Use `gexpr` instead of `expr` on BSD variants. 85 | 86 | Minor tweaks to make run on FreeBSD 9.1. 87 | 88 | Fixed issue in `shflags_test_public.sh` where screens >80 columns were causing a 89 | test to fail. 90 | 91 | Issue #22. Fixed broken testGetFlagInfo() test. 92 | 93 | Created alternate `validFloat()` and `validInt()` functions that use shell 94 | built-ins where possible to increase performance and reduce the usage of the 95 | `expr` command. 96 | 97 | Added separate built-in and `expr` functions for doing math. 98 | 99 | ## Changes with 1.0.3 100 | 101 | MAJOR CHANGE! `FLAGS_ARGC` is now obsolete, and is replaced by `FLAGS_ARGV`. See 102 | below for more info. 103 | 104 | Fixed issue# 7 where long flags defined with '=' (e.g. `--abc=123`) made it 105 | impossible for the user to know how many non-flag command-line arguments were 106 | available because the value returned by `FLAGS_ARGC` was wrong. The `FLAGS_ARGC` 107 | value is now obsolete, but will be maintained for backwards compatibility. The 108 | new method of getting the non-flag arguments is by executing `eval set -- 109 | "${FLAGS_ARGV}"` after the `FLAGS` call. The arguments will then be available 110 | using the standard shell $#, $@, $\*, $1, etc. variables. (Backslash on \* to 111 | prevent Markdown formatting.) 112 | 113 | Due to above fix for issue# 7, there is now proper support for mixing flags with 114 | non-flag arguments on the command-line. Previously, all non-flag arguments had 115 | to be at the end of the command-line. 116 | 117 | Renamed `_flags_standardGetopt()` and `_flags_enhancedGetopt()` functions to 118 | `_flags_getoptStandard()` and `_flags_getoptEnhanced()`. 119 | 120 | Took out the setting and restoration of the '-u' shell flag to treat unset 121 | variables as an error. No point in having it in this library as it is verified 122 | in the unit tests, and provides basically no benefit. 123 | 124 | Fixed bug under Solaris where the generated help was adding extra 'x' 125 | characters. 126 | 127 | Added checks for reserved flag variables (e.g. `FLAGS_TRUE`). 128 | 129 | Fixed some unset variable bugs. 130 | 131 | Now report the actual `getopt` error if there is one. 132 | 133 | All tests now properly enable skipping based on whether a standard or enhanced 134 | `getopt` is found. 135 | 136 | Added the OS version to OS release for Solaris. 137 | 138 | Fixed `flags_reset()` so it unsets the default value environment vars. 139 | 140 | ## Changes with 1.0.2 141 | 142 | ${FLAGS_PARENT} no longer transforms into a constant so that it can be defined 143 | at run time in scripts. 144 | 145 | Added warning about short flags being unsupported when there are problems 146 | parsing the options with `getopt`. 147 | 148 | Add default values to end of description strings. 149 | 150 | Fixed bug that returned an error instead of success when recalling the default 151 | values for empty strings. 152 | 153 | Added warning when a duplicate flag definition is attempted. 154 | 155 | Improved `assert[Warn|Error]Msg()` test helper grepping. 156 | 157 | Replaced shell_versions.sh with a new versions library and created 158 | `gen_test_results.sh` to make releases easier. 159 | 160 | Copied the coding standards from shUnit2, but haven't fully implemented them in 161 | shFlags yet. 162 | 163 | Issue# 1: When a user defines their own `--help` flag, no more warning is thrown 164 | when `FLAGS()` is called stating that the help flag already defined. 165 | 166 | Issue# 2: Passing the `--nohelp` option no longer gives help output. 167 | 168 | Issue# 3: Added support for screen width detection. 169 | 170 | ## Changes with 1.0.1 171 | 172 | Fixed bug where the help output added '[no]' to all flag names 173 | 174 | Added additional example files that are referenced by the documentation. 175 | 176 | Improved `zsh` version and option checking. 177 | 178 | Upgraded shUnit2 to 2.1.4 179 | 180 | Added unit testing for the help output. 181 | 182 | When including a library (e.g. shflags) in a script, zsh 3.0.8 doesn't actually 183 | execute the code in-line, but later. As such, variables that are defined in the 184 | library cannot be used until functions are called from the main code. This 185 | required the 'help' flag definition to be moved inside the FLAGS command. 186 | 187 | ## Changes with 1.0.0 188 | 189 | This is the first official release, so everything is new. 190 | -------------------------------------------------------------------------------- /shflags/doc/CHANGES-1.3.md: -------------------------------------------------------------------------------- 1 | # Changes in shFlags 2 | 3 | ## 1.3.x development series 4 | 5 | ### Changes with 1.3.0 6 | 7 | *A new series was started due to the major changes required for 'set -e' support.* 8 | 9 | Upgraded shUnit2 to 2.1.9pre, which includes 'set -e' support. 10 | 11 | Fixed #9. shFlags now works properly with 'set -e' enabled. 12 | 13 | Fixed #50. The `FLAGS_ARGC` variable is no longer is no longer exported. The variable was marked obsolete in 1.0.3, and it is finally being removed. 14 | 15 | --- 16 | 17 | ## 1.2.x stable series 18 | 19 | ### Changes with 1.2.3 20 | 21 | Upgraded shUnit2 to 2.1.7. 22 | 23 | Fixed the examples to work again with the new code structure. 24 | 25 | Removed `gen_test_report.sh` as it isn't used anymore. 26 | 27 | Minor fix for `_flags_underscoreName()` to insure POSIX compliance. 28 | 29 | Cleanup of pre-GitHub cruft. 30 | 31 | Fixed bug in `_flags_columns()` where `stty size` sometimes gave unexpected 32 | output, causing the function to not work. 33 | 34 | Replaced `test_runner` with upstream from https://github.com/kward/shlib. 35 | 36 | ### Changes with 1.2.2 37 | 38 | Ran all scripts through [ShellCheck](http://www.shellcheck.net/). 39 | 40 | Replaced `shflags_test.sh` with `test_runner` from https://github.com/kward/shlib. 41 | 42 | Fixed issue #45. Empty help string causes `shflags_test_issue_28.sh` to fail. 43 | 44 | Continuous integration testing setup with [Travis CI](https://travis-ci.org/kward/shflags). 45 | 46 | Restructured code to be more GitHub like. 47 | 48 | ### Changes with 1.2.1 49 | 50 | Fixed issue #43. Added support for BusyBox `ash` shell. 51 | 52 | Fixed issues #26, #27. Re-factored `_flags_itemInList()` to use built-ins. 53 | 54 | Fixed issue #31. Documented newline support in `FLAGS_HELP`. 55 | 56 | Fixed issue #28. `DEFINE_boolean` misbehaves when help-string is empty. 57 | 58 | Fixed issue #25. Fix some typos. 59 | 60 | ### Changes with 1.2.0 61 | 62 | Changed from the LGPL v2.1 license to the Apache v2.0 license so that others can include the library or make changes without needing to release the modified source code as well. 63 | 64 | Moved documentation to Markdown. 65 | 66 | Migrated the code to GitHub as http://code.google.com/ is turning down. 67 | 68 | Fixed issue #10. Usage of `expr` under FreeBSD 7.2 (FreeNAS 0.7.1) and FreeBSD 8.0 that was causing many unit tests to fail. 69 | 70 | Fixed issue where booleans were sometimes mis-configured to require additional values like other flags. 71 | 72 | Changed `_flags_fatal()` to exit with `FLAGS_ERROR` immediately. 73 | 74 | Fixed issue #11. When help is requested, the help flag is no longer prefixed with '[no]'. 75 | 76 | Upgraded shUnit2 to 2.1.6. 77 | 78 | Fixed issue #12. Requesting help shouldn't be considered an error. 79 | 80 | Added the ability to override the use of the OS default `getopt` command by defining the `FLAGS_GETOPT_CMD` variable. 81 | 82 | Updated `gen_test_results.sh` and versions from shUnit2 source. 83 | 84 | Fixed issues #13, #14. Added support for dashes '-' in long flag names. The defined flag will still be declared with underscores '\_' due to shell limitations, so only one of a dashed flag name or an underscored flag name are allowed, not both. (Backslash on _ to prevent Markdown formatting.) 85 | 86 | Issue #20. Updated LGPL v2.1 license from http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. 87 | 88 | Issue #15. Use `gexpr` instead of `expr` on BSD variants. 89 | 90 | Minor tweaks to make run on FreeBSD 9.1. 91 | 92 | Fixed issue in `shflags_test_public.sh` where screens >80 columns were causing a test to fail. 93 | 94 | Issue #22. Fixed broken `testGetFlagInfo()` test. 95 | 96 | Created alternate `validFloat()` and `validInt()` functions that use shell built-ins where possible to increase performance and reduce the usage of the `expr` command. 97 | 98 | Added separate built-in and `expr` functions for doing math. 99 | 100 | --- 101 | 102 | ## 1.0.x stable series 103 | 104 | ### Changes with 1.0.3 105 | 106 | MAJOR CHANGE! `FLAGS_ARGC` is now obsolete, and is replaced by `FLAGS_ARGV`. See below for more info. 107 | 108 | Fixed issue# 7 where long flags defined with '=' (e.g. `--abc=123`) made it impossible for the user to know how many non-flag command-line arguments were available because the value returned by `FLAGS_ARGC` was wrong. The `FLAGS_ARGC` value is now obsolete, but will be maintained for backwards compatibility. The new method of getting the non-flag arguments is by executing `eval set -- "${FLAGS_ARGV}"` after the `FLAGS` call. The arguments will then be available using the standard shell $#, $@, $\*, $1, etc. variables. (Backslash on \* to prevent Markdown formatting.) 109 | 110 | Due to above fix for issue# 7, there is now proper support for mixing flags with non-flag arguments on the command-line. Previously, all non-flag arguments had to be at the end of the command-line. 111 | 112 | Renamed `_flags_standardGetopt()` and `_flags_enhancedGetopt()` functions to `_flags_getoptStandard()` and `_flags_getoptEnhanced()`. 113 | 114 | Took out the setting and restoration of the '-u' shell flag to treat unset variables as an error. No point in having it in this library as it is verified in the unit tests, and provides basically no benefit. 115 | 116 | Fixed bug under Solaris where the generated help was adding extra 'x' characters. 117 | 118 | Added checks for reserved flag variables (e.g. `FLAGS_TRUE`). 119 | 120 | Fixed some unset variable bugs. 121 | 122 | Now report the actual `getopt` error if there is one. 123 | 124 | All tests now properly enable skipping based on whether a standard or enhanced `getopt` is found. 125 | 126 | Added the OS version to OS release for Solaris. 127 | 128 | Fixed `flags_reset()` so it unsets the default value environment vars. 129 | 130 | ### Changes with 1.0.2 131 | 132 | `${FLAGS_PARENT}` no longer transforms into a constant so that it can be defined at run time in scripts. 133 | 134 | Added warning about short flags being unsupported when there are problems 135 | parsing the options with `getopt`. 136 | 137 | Add default values to end of description strings. 138 | 139 | Fixed bug that returned an error instead of success when recalling the default values for empty strings. 140 | 141 | Added warning when a duplicate flag definition is attempted. 142 | 143 | Improved `assert[Warn|Error]Msg()` test helper grepping. 144 | 145 | Replaced shell_versions.sh with a new versions library and created `gen_test_results.sh` to make releases easier. 146 | 147 | Copied the coding standards from shUnit2, but haven't fully implemented them in shFlags yet. 148 | 149 | Issue# 1: When a user defines their own `--help` flag, no more warning is thrown when `FLAGS()` is called stating that the help flag already defined. 150 | 151 | Issue# 2: Passing the `--nohelp` option no longer gives help output. 152 | 153 | Issue# 3: Added support for screen width detection. 154 | 155 | ### Changes with 1.0.1 156 | 157 | Fixed bug where the help output added '[no]' to all flag names 158 | 159 | Added additional example files that are referenced by the documentation. 160 | 161 | Improved `zsh` version and option checking. 162 | 163 | Upgraded shUnit2 to 2.1.4 164 | 165 | Added unit testing for the help output. 166 | 167 | When including a library (e.g. shflags) in a script, zsh 3.0.8 doesn't actually execute the code in-line, but later. As such, variables that are defined in the library cannot be used until functions are called from the main code. This required the 'help' flag definition to be moved inside the `FLAGS` command. 168 | 169 | ### Changes with 1.0.0 170 | 171 | This is the first official release, so everything is new. 172 | -------------------------------------------------------------------------------- /shflags/doc/LICENSE.shunit2: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /shflags/doc/RELEASE_NOTES-1.0.0.txt: -------------------------------------------------------------------------------- 1 | ------------------------------ 2 | shFlags.sh 1.0.0 Release Notes 3 | ------------------------------ 4 | 5 | Preface 6 | ------- 7 | Copyright 2008 Kate Ward. All Rights Reserved. 8 | Released under the LGPL (GNU Lesser General Public License) 9 | 10 | Author: Kate Ward (kate.ward@forestent.com) 11 | 12 | This document covers any known issues and workarounds for the stated release of 13 | shFlags. 14 | 15 | General info 16 | ------------ 17 | 18 | This is the first official release of shFlags. The project is modeled after the 19 | gflags code released by Google on http://code.google.com/p/google-gflags/. Many 20 | thanks for the code they have provided. 21 | 22 | As this is the first release, there are bound to be issues. Feel free 23 | 24 | Disclamer 25 | --------- 26 | 27 | The unit tests 28 | -------------- 29 | 30 | shFlags is designed to work on as many environments as possible, but not all 31 | environments are created equal. As such, not all of the unit tests will succeed 32 | on every platform. The unit tests are therefore designed to fail, indicating to 33 | the tester that the supported functionality is not present, but an additional 34 | test is present to verify that shFlags properly caught the limitation and 35 | presented the user with an appropriate error message. 36 | 37 | shFlags tries to support both the standard and enhanced versions of ``getopt``. 38 | As each responds differently, and not everything is supported on the standard 39 | version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when 40 | the standard version of ``getopt`` is detected. The reason being that there is 41 | no point testing for functionality that is positively known not to exist. A 42 | tally of skipped tests will be kept for later reference. 43 | 44 | Standard vs Enhanced getopt 45 | --------------------------- 46 | 47 | Here is a matrix of the supported features of the various getopt variants. 48 | 49 | +-------------------------+---+---+ 50 | |Feature |std|enh| 51 | +=========================+===+===+ 52 | |short option names | Y | Y | 53 | |long option names | N | Y | 54 | |spaces in string options | N | Y | 55 | +-------------------------+---+---+ 56 | 57 | Known Issues 58 | ------------ 59 | 60 | The getopt version provided by default with all versions of Solaris (up to and 61 | including Solaris 10) is the standard version. As such, only short flags are 62 | supported. 63 | 64 | The getopt version provided by default with all versions of Mac OS X (up to and 65 | including 10.5) is the standard version. As such, only short flags are 66 | supported. 67 | 68 | Workarounds 69 | ----------- 70 | 71 | The zsh shell requires the 'shwordsplit' option to be set, and the special 72 | FLAGS_PARENT variable must be defined. 73 | -------------------------------------------------------------------------------- /shflags/doc/RELEASE_NOTES-1.0.1.txt: -------------------------------------------------------------------------------- 1 | ------------------------------ 2 | shFlags.sh 1.0.1 Release Notes 3 | ------------------------------ 4 | 5 | Preface 6 | ------- 7 | Copyright 2008 Kate Ward. All Rights Reserved. 8 | Released under the LGPL (GNU Lesser General Public License) 9 | 10 | Author: Kate Ward (kate.ward@forestent.com) 11 | 12 | This document covers any known issues and workarounds for the stated release of 13 | shFlags. 14 | 15 | General info 16 | ------------ 17 | 18 | This is a minor bugfix release of shFlags. It mainly fixes poor output of the 19 | automated help system, but it also includes a couple more examples that are 20 | referenced by the documentation. 21 | 22 | Please see the CHANGES-1.0.txt file for a complete list of changes. 23 | 24 | Disclamer 25 | --------- 26 | 27 | The unit tests 28 | -------------- 29 | 30 | shFlags is designed to work on as many environments as possible, but not all 31 | environments are created equal. As such, not all of the unit tests will succeed 32 | on every platform. The unit tests are therefore designed to fail, indicating to 33 | the tester that the supported functionality is not present, but an additional 34 | test is present to verify that shFlags properly caught the limitation and 35 | presented the user with an appropriate error message. 36 | 37 | shFlags tries to support both the standard and enhanced versions of ``getopt``. 38 | As each responds differently, and not everything is supported on the standard 39 | version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when 40 | the standard version of ``getopt`` is detected. The reason being that there is 41 | no point testing for functionality that is positively known not to exist. A 42 | tally of skipped tests will be kept for later reference. 43 | 44 | Standard vs Enhanced getopt 45 | --------------------------- 46 | 47 | Here is a matrix of the supported features of the various getopt variants. 48 | 49 | +-------------------------+---+---+ 50 | |Feature |std|enh| 51 | +=========================+===+===+ 52 | |short option names | Y | Y | 53 | |long option names | N | Y | 54 | |spaces in string options | N | Y | 55 | +-------------------------+---+---+ 56 | 57 | Known Issues 58 | ------------ 59 | 60 | The getopt version provided by default with all versions of Mac OS X (up to and 61 | including 10.5) is the standard version. As such, only short flags are 62 | supported. 63 | 64 | The getopt version provided by default with all versions of Solaris (up to and 65 | including Solaris 10) is the standard version. As such, only short flags are 66 | supported. 67 | 68 | Workarounds 69 | ----------- 70 | 71 | The zsh shell requires the 'shwordsplit' option to be set, and the special 72 | FLAGS_PARENT variable must be defined. 73 | -------------------------------------------------------------------------------- /shflags/doc/RELEASE_NOTES-1.0.2.txt: -------------------------------------------------------------------------------- 1 | ------------------------------ 2 | shFlags.sh 1.0.1 Release Notes 3 | ------------------------------ 4 | 5 | Preface 6 | ------- 7 | Copyright 2008 Kate Ward. All Rights Reserved. 8 | Released under the LGPL (GNU Lesser General Public License) 9 | 10 | Author: Kate Ward (kate.ward@forestent.com) 11 | 12 | This document covers any known issues and workarounds for the stated release of 13 | shFlags. 14 | 15 | General info 16 | ------------ 17 | 18 | This is both a minor bug fix release, and a minor new feature release of 19 | shFlags. It adds several warning messages, fixes three issues, and now displays 20 | the default value behind the help string when help is requested. Additionally, 21 | the coding standards have been modified slightly and officially documented. 22 | They were taken from the standards used by shUnit2 (the unit testing framework 23 | used for the unit testing). 24 | 25 | Please see the CHANGES-1.0.txt file for a complete list of changes. 26 | 27 | The unit tests 28 | -------------- 29 | 30 | shFlags is designed to work on as many environments as possible, but not all 31 | environments are created equal. As such, not all of the unit tests will succeed 32 | on every platform. The unit tests are therefore designed to fail, indicating to 33 | the tester that the supported functionality is not present, but an additional 34 | test is present to verify that shFlags properly caught the limitation and 35 | presented the user with an appropriate error message. 36 | 37 | shFlags tries to support both the standard and enhanced versions of **getopt**. 38 | As each responds differently, and not everything is supported on the standard 39 | version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when 40 | the standard version of **getopt** is detected. The reason being that there is 41 | no point testing for functionality that is positively known not to exist. A 42 | tally of skipped tests will be kept for later reference. 43 | 44 | To see the test results for the various OSes tested, please visit 45 | http://forestent.com/projects/shflags/testresults/. 46 | 47 | Standard vs Enhanced getopt 48 | --------------------------- 49 | 50 | Here is a matrix of the supported features of the various **getopt** variants. 51 | 52 | +-------------------------+---+---+ 53 | |Feature |std|enh| 54 | +=========================+===+===+ 55 | |short option names | Y | Y | 56 | |long option names | N | Y | 57 | |spaces in string options | N | Y | 58 | +-------------------------+---+---+ 59 | 60 | Known Issues 61 | ------------ 62 | 63 | The **getopt** version provided by default with all versions of Mac OS X (up to 64 | and including 10.5.5) is the standard version. As such, only short flags are 65 | supported. 66 | 67 | The **getopt** version provided by default with all versions of Solaris (up to 68 | and including Solaris 10 and OpenSolaris) is the standard version. As such, 69 | only short flags are supported. 70 | 71 | Workarounds 72 | ----------- 73 | 74 | The Zsh shell requires the ``shwordsplit`` option to be set, and the special 75 | ``FLAGS_PARENT`` variable must be defined. 76 | 77 | 78 | .. vim:fileencoding=latin1:ft=rst:spell:tw=80 79 | -------------------------------------------------------------------------------- /shflags/doc/RELEASE_NOTES-1.0.3.txt: -------------------------------------------------------------------------------- 1 | ------------------------------ 2 | shFlags.sh 1.0.3 Release Notes 3 | ------------------------------ 4 | 5 | Preface 6 | ======= 7 | Copyright 2008-2009 Kate Ward. All Rights Reserved. 8 | Released under the LGPL (GNU Lesser General Public License) 9 | Author: kate.ward@forestent.com (Kate Ward) 10 | 11 | This document covers any known issues and workarounds for the stated release of 12 | shFlags. 13 | 14 | Release info 15 | ============ 16 | 17 | This is a major bug fix release. The biggest fix is in how non-flag arguments are 18 | made available to the script. 19 | 20 | Major changes 21 | ------------- 22 | 23 | The use of the ``FLAGS_ARGC`` variable is now obsolete. It will be maintained 24 | for backwards compatibility with old scripts, but its value is known to be 25 | wrong when flag and non-flag arguments are mixed together on the command-line. 26 | 27 | To gain access to the non-flag arguments, replace the following snippet of code 28 | in your scripts with the updated version. 29 | 30 | old :: 31 | shift ${FLAGS_ARGC} 32 | 33 | new :: 34 | eval set -- "${FLAGS_ARGV}" 35 | 36 | Please see the CHANGES-1.0.txt file for a complete list of changes. 37 | 38 | Obsolete items 39 | -------------- 40 | 41 | Bug fixes 42 | --------- 43 | 44 | Issue# 7 Flags set with '=' result in off-by-one shifting error 45 | 46 | General info 47 | ============ 48 | 49 | The unit tests 50 | -------------- 51 | 52 | shFlags is designed to work on as many environments as possible, but not all 53 | environments are created equal. As such, not all of the unit tests will succeed 54 | on every platform. The unit tests are therefore designed to fail, indicating to 55 | the tester that the supported functionality is not present, but an additional 56 | test is present to verify that shFlags properly caught the limitation and 57 | presented the user with an appropriate error message. 58 | 59 | shFlags tries to support both the standard and enhanced versions of ``getopt``. 60 | As each responds differently, and not everything is supported on the standard 61 | version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when 62 | the standard version of ``getopt`` is detected. The reason being that there is 63 | no point testing for functionality that is positively known not to exist. A 64 | tally of skipped tests will be kept for later reference. 65 | 66 | Standard vs Enhanced getopt 67 | --------------------------- 68 | 69 | Here is a matrix of the supported features of the various **getopt** variants. 70 | 71 | +=========================================+=====+=====+ 72 | | Feature | std | enh | 73 | +-----------------------------------------+-----+-----+ 74 | | short option names | Y | Y | 75 | | long option names | N | Y | 76 | | spaces in string options | N | Y | 77 | | intermixing of flag and non-flag values | N | Y | 78 | +=========================================+=====+=====+ 79 | 80 | Known Issues 81 | ------------ 82 | 83 | The **getopt** version provided by default with all versions of Mac OS X (up to 84 | and including 10.5.6) and Solaris (up to and including Solaris 10 and 85 | OpenSolaris) is the standard version. 86 | 87 | Workarounds 88 | ----------- 89 | 90 | The Zsh shell requires the ``shwordsplit`` option to be set and the special 91 | ``FLAGS_PARENT`` variable must be defined. See ``src/shflags_test_helpers`` to 92 | see how the unit tests do this. 93 | 94 | .. vim:fileencoding=latin1:ft=rst:spell:tw=80 95 | -------------------------------------------------------------------------------- /shflags/doc/RELEASE_NOTES-1.2.0.md: -------------------------------------------------------------------------------- 1 | # shFlags 1.2.0 Release Notes 2 | https://github.com/kward/shflags 3 | 4 | Preface 5 | ======= 6 | 7 | This document covers any known issues and workarounds for the stated release of 8 | shFlags. 9 | 10 | Release info 11 | ============ 12 | 13 | This is a minor bug fix release. 14 | 15 | Please see the `CHANGES-1.2.md` file for a complete list of changes. 16 | 17 | Major changes 18 | ------------- 19 | 20 | Changed from the LGPL v2.1 license to the Apache v2.0 license so that others 21 | can include the library or make changes without needing to release the modified 22 | source code as well. 23 | 24 | Obsolete items 25 | -------------- 26 | 27 | None 28 | 29 | Bug fixes 30 | --------- 31 | 32 | Issue #10 - Changed the internal usage of the `expn` command to fix issues 33 | under FreeBSD. 34 | 35 | General info 36 | ============ 37 | 38 | The unit tests 39 | -------------- 40 | 41 | shFlags is designed to work on as many environments as possible, but not all 42 | environments are created equal. As such, not all of the unit tests will succeed 43 | on every platform. The unit tests are therefore designed to fail, indicating to 44 | the tester that the supported functionality is not present, but an additional 45 | test is present to verify that shFlags properly caught the limitation and 46 | presented the user with an appropriate error message. 47 | 48 | shFlags tries to support both the standard and enhanced versions of `getopt`. 49 | As each responds differently, and not everything is supported on the standard 50 | version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when 51 | the standard version of `getopt` is detected. The reason being that there is 52 | no point testing for functionality that is positively known not to exist. A 53 | tally of skipped tests will be kept for later reference. 54 | 55 | Standard vs Enhanced getopt 56 | --------------------------- 57 | 58 | Here is a matrix of the supported features of the various `getopt` variants. 59 | 60 | | Feature | std | enh | 61 | |-----------------------------------------|-----|-----| 62 | | short option names | Y | Y | 63 | | long option names | N | Y | 64 | | spaces in string options | N | Y | 65 | | intermixing of flag and non-flag values | N | Y | 66 | 67 | Known Issues 68 | ------------ 69 | 70 | The `getopt` version provided by default with all versions of Mac OS X (up to 71 | and including 10.10.2) and Solaris (up to and including Solaris 10 and 72 | OpenSolaris) is the standard version. 73 | 74 | Workarounds 75 | ----------- 76 | The Zsh shell requires the `shwordsplit` option to be set and the special 77 | `FLAGS_PARENT` variable must be defined. See `src/shflags_test_helpers` to 78 | see how the unit tests do this. 79 | -------------------------------------------------------------------------------- /shflags/doc/RELEASE_NOTES-1.2.1.md: -------------------------------------------------------------------------------- 1 | # shFlags 1.2.1 Release Notes 2 | 3 | https://github.com/kward/shflags 4 | 5 | ## Preface 6 | 7 | This document covers any known issues and workarounds for the stated release of 8 | shFlags. 9 | 10 | 11 | ## Release info 12 | 13 | This is a minor bug fix release. 14 | 15 | Please see the `CHANGES-1.2.md` file for a complete list of changes. 16 | 17 | ### Notable changes 18 | 19 | Support for the BusyBox `ash` shell was added. 20 | 21 | ### Notable bug fixes 22 | 23 | Fixed issue #28. DEFINE_boolean misbehaves when help-string is empty. 24 | 25 | 26 | ## General info 27 | 28 | ### The unit tests 29 | 30 | shFlags is designed to work on as many environments as possible, but not all 31 | environments are created equal. As such, not all of the unit tests will succeed 32 | on every platform. The unit tests are therefore designed to fail, indicating to 33 | the tester that the supported functionality is not present, but an additional 34 | test is present to verify that shFlags properly caught the limitation and 35 | presented the user with an appropriate error message. 36 | 37 | shFlags tries to support both the standard and enhanced versions of `getopt`. 38 | As each responds differently, and not everything is supported on the standard 39 | version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when 40 | the standard version of `getopt` is detected. The reason being that there is 41 | no point testing for functionality that is positively known not to exist. A 42 | tally of skipped tests will be kept for later reference. 43 | 44 | ### Standard vs Enhanced getopt 45 | 46 | Here is a matrix of the supported features of the various `getopt` variants. 47 | 48 | | Feature | std | enh | 49 | |-----------------------------------------|-----|-----| 50 | | short option names | Y | Y | 51 | | long option names | N | Y | 52 | | spaces in string options | N | Y | 53 | | intermixing of flag and non-flag values | N | Y | 54 | 55 | 56 | ## Known Issues 57 | 58 | The `getopt` version provided by default with all versions of Mac OS X (up to 59 | and including 10.10.2) and Solaris (up to and including Solaris 10 and 60 | OpenSolaris) is the standard version. 61 | 62 | ## Workarounds 63 | 64 | The Zsh shell requires the `shwordsplit` option to be set and the special 65 | `FLAGS_PARENT` variable must be defined. See `src/shflags_test_helpers` to 66 | see how the unit tests do this. 67 | -------------------------------------------------------------------------------- /shflags/doc/RELEASE_NOTES-1.2.2.md: -------------------------------------------------------------------------------- 1 | # shFlags 1.2.2 Release Notes 2 | 3 | https://github.com/kward/shflags 4 | 5 | ## Preface 6 | 7 | This document covers any known issues and workarounds for the stated release of 8 | shFlags. 9 | 10 | ## Release info 11 | 12 | This is a minor bug fix release. 13 | 14 | Please see the `CHANGES-1.2.md` file for a complete list of changes. 15 | 16 | ### Notable changes 17 | 18 | Continuous integration testing setup with [Travis CI][travis-ci]. This helps 19 | keep the code in a working state by executing the unit tests on every submit. 20 | 21 | [travis-ci]: https://travis-ci.org/kward/shflags 22 | 23 | All code run through [ShellCheck](http://www.shellcheck.net/). This is an 24 | excellent shell linter, and brings consistency to the coding patterns used. 25 | 26 | The code was restructured to be more GitHub friendly. It should make the code 27 | more appealing to a wider audience. 28 | 29 | ### Notable bug fixes 30 | 31 | Fixed issue #45. Empty help string causes `shflags_test_issue_28.sh` to fail. 32 | 33 | ## General info 34 | 35 | ### The unit tests 36 | 37 | shFlags is designed to work on as many environments as possible, but not all 38 | environments are created equal. As such, not all of the unit tests will succeed 39 | on every platform. The unit tests are therefore designed to fail, indicating to 40 | the tester that the supported functionality is not present, but an additional 41 | test is present to verify that shFlags properly caught the limitation and 42 | presented the user with an appropriate error message. 43 | 44 | shFlags tries to support both the standard and enhanced versions of `getopt`. As 45 | each responds differently, and not everything is supported on the standard 46 | version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when 47 | the standard version of `getopt` is detected. The reason being that there is no 48 | point testing for functionality that is positively known not to exist. A tally 49 | of skipped tests will be kept for later reference. 50 | 51 | ### Standard vs Enhanced getopt 52 | 53 | Here is a matrix of the supported features of the various `getopt` variants. 54 | 55 | Feature | std | enh 56 | --------------------------------------- | --- | --- 57 | short option names | Y | Y 58 | long option names | N | Y 59 | spaces in string options | N | Y 60 | intermixing of flag and non-flag values | N | Y 61 | 62 | ## Known Issues 63 | 64 | The `getopt` version provided by default with all versions of Mac OS X (up to 65 | and including 10.13.0) and Solaris (up to and including Solaris 10 and 66 | OpenSolaris) is the standard version. 67 | 68 | ## Workarounds 69 | 70 | The Zsh shell requires the `shwordsplit` option to be set and the special 71 | `FLAGS_PARENT` variable must be defined. See `src/shflags_test_helpers` to see 72 | how the unit tests do this. 73 | -------------------------------------------------------------------------------- /shflags/doc/RELEASE_NOTES-1.2.3.md: -------------------------------------------------------------------------------- 1 | # shFlags 1.2.3 Release Notes 2 | 3 | https://github.com/kward/shflags 4 | 5 | ## Preface 6 | 7 | This document covers any known issues and workarounds for the stated release of 8 | shFlags. 9 | 10 | ## Release info 11 | 12 | This is a minor bug fix and cleanup release. 13 | 14 | There were several minor changes thanks to feedback from a major code review by 15 | [James Youngman](https://www.linkedin.com/in/jamesyoungman/). Thank you! 16 | 17 | Please see the `CHANGES-1.2.md` file for a complete list of changes. 18 | 19 | ### Notable changes 20 | 21 | None. 22 | 23 | ### Notable bug fixes 24 | 25 | Fixed the examples to work again with the new code structure. These broke when 26 | the code was refactored for GitHub. 27 | 28 | ## General info 29 | 30 | ### The unit tests 31 | 32 | shFlags is designed to work on as many environments as possible, but not all 33 | environments are created equal. As such, not all of the unit tests will succeed 34 | on every platform. The unit tests are therefore designed to fail, indicating to 35 | the tester that the supported functionality is not present, but an additional 36 | test is present to verify that shFlags properly caught the limitation and 37 | presented the user with an appropriate error message. 38 | 39 | shFlags tries to support both the standard and enhanced versions of `getopt`. As 40 | each responds differently, and not everything is supported on the standard 41 | version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when 42 | the standard version of `getopt` is detected. The reason being that there is no 43 | point testing for functionality that is positively known not to exist. A tally 44 | of skipped tests will be kept for later reference. 45 | 46 | ### Standard vs Enhanced getopt 47 | 48 | Here is a matrix of the supported features of the various `getopt` variants. 49 | 50 | Feature | std | enh 51 | --------------------------------------- | --- | --- 52 | short option names | Y | Y 53 | long option names | N | Y 54 | spaces in string options | N | Y 55 | intermixing of flag and non-flag values | N | Y 56 | 57 | ## Known Issues 58 | 59 | The `getopt` version provided by default with all versions of Mac OS X (up to 60 | and including 10.13.0) and Solaris (up to and including Solaris 10 and 61 | OpenSolaris) is the standard version. 62 | 63 | ## Workarounds 64 | 65 | The Zsh shell requires the `shwordsplit` option to be set and the special 66 | `FLAGS_PARENT` variable must be defined. See `src/shflags_test_helpers` to see 67 | how the unit tests do this. 68 | -------------------------------------------------------------------------------- /shflags/doc/TODO.txt: -------------------------------------------------------------------------------- 1 | improve zsh, automatically ... (pulled from configure) 2 | 3 | if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then 4 | emulate sh 5 | NULLCMD=: 6 | # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which 7 | # is contrary to our usage. Disable this feature. 8 | alias -g '${1+"$@"}'='"$@"' 9 | setopt NO_GLOB_SUBST 10 | else 11 | -------------------------------------------------------------------------------- /shflags/examples/debug_output.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This script does the very simple job of echoing some text. If a '-d' (or 4 | # '--debug') flag is given, additinal "debug" output is enabled. 5 | # 6 | # This script demonstrates the use of a boolean flag to enable custom 7 | # functionality in a script. 8 | # 9 | # Try running these: 10 | # $ ./debug_output.sh speak 11 | # $ ./debug_output.sh sing 12 | # $ ./debug_output.sh --debug sing 13 | 14 | # Source shflags. 15 | . ../shflags 16 | 17 | # Define flags. 18 | DEFINE_boolean 'debug' false 'enable debug mode' 'd' 19 | FLAGS_HELP=`cat <&2 28 | } 29 | 30 | die() { [ $# -gt 0 ] && echo "error: $@" >&2 31 | flags_help 32 | exit 1 33 | } 34 | 35 | # Parse the command-line. 36 | FLAGS "$@" || exit 1 37 | eval set -- "${FLAGS_ARGV}" 38 | 39 | command=$1 40 | case ${command} in 41 | '') die ;; 42 | 43 | speak) 44 | debug "I'm getting ready to say something..." 45 | echo 'The answer to the question "What is the meaning of life?" is "42".' 46 | ;; 47 | 48 | sing) 49 | debug "I'm getting ready to sing something..." 50 | echo 'I love to sing! La diddy da dum!' 51 | ;; 52 | 53 | *) die "unrecognized command (${command})" ;; 54 | esac 55 | -------------------------------------------------------------------------------- /shflags/examples/hello_world.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This is the proverbial 'Hello, world!' script to demonstrate the most basic 4 | # functionality of shFlags. 5 | # 6 | # This script demonstrates accepts a single command-line flag of '-n' (or 7 | # '--name'). If a name is given, it is output, otherwise the default of 'world' 8 | # is output. 9 | 10 | # Source shflags. 11 | . ../shflags 12 | 13 | # Define a 'name' command-line string flag. 14 | DEFINE_string 'name' 'world' 'name to say hello to' 'n' 15 | 16 | # Parse the command-line. 17 | FLAGS "$@" || exit 1 18 | eval set -- "${FLAGS_ARGV}" 19 | 20 | echo "Hello, ${FLAGS_name}!" 21 | -------------------------------------------------------------------------------- /shflags/examples/write_date.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This script takes a filename as input and writes the current date to the 4 | # file. If the file already exists, it will not be overwritten unless the '-f' 5 | # (or '--force') flag is given. 6 | # 7 | # This script demonstrates several types of shFlags functionality. 8 | # - declaration of the FLAGS_HELP variable to customize the help output 9 | # - direct calling of the flags_help() function for script controlled usage 10 | # output 11 | # - handling of non-flag type command-line arguments that follow the flags 12 | # 13 | # Try the following: 14 | # $ ./write_date.sh now.out 15 | # $ cat now.out 16 | # 17 | # $ ./write_date.sh now.out 18 | # $ cat now.out 19 | # 20 | # $ ./write_date.sh -f now.out 21 | # $ cat now.out 22 | 23 | # Source shFlags. 24 | . ../shflags 25 | 26 | # Configure shFlags. 27 | DEFINE_boolean 'force' false 'force overwriting' 'f' 28 | FLAGS_HELP="USAGE: $0 [flags] filename" 29 | 30 | die() { 31 | [ $# -gt 0 ] && echo "error: $@" 32 | flags_help 33 | exit 1 34 | } 35 | 36 | # Parse the command-line. 37 | FLAGS "$@" || exit 1 38 | eval set -- "${FLAGS_ARGV}" 39 | 40 | # Check for filename on command-line. 41 | [ $# -gt 0 ] || die 'filename missing.' 42 | filename=$1 43 | 44 | # Redirect STDOUT to the file ($1). This seemingly complicated method using exec 45 | # is used so that a potential race condition between checking for the presence 46 | # of the file and writing to the file is mitigated. 47 | if [ ${FLAGS_force} -eq ${FLAGS_FALSE} ] ; then 48 | [ ! -f "${filename}" ] || die "file \"${filename}\" already exists." 49 | # Set noclobber, redirect STDOUT to the file, first saving STDOUT to fd 4. 50 | set -C 51 | exec 4>&1 >"${filename}" # This fails if the file exists. 52 | else 53 | # Forcefully overwrite (clobber) the file. 54 | exec 4>&1 >|"${filename}" 55 | fi 56 | 57 | # What time is it? 58 | date 59 | 60 | # Restore STDOUT from file descriptor 4, and close fd 4. 61 | exec 1>&4 4>&- 62 | 63 | echo "The current date was written to \"${filename}\"." 64 | -------------------------------------------------------------------------------- /shflags/init_githooks.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # Initialize the local git hooks this repository. 4 | # https://git-scm.com/docs/githooks 5 | 6 | topLevel=$(git rev-parse --show-toplevel) 7 | if ! cd "${topLevel}"; then 8 | echo "filed to cd into topLevel directory '${topLevel}'" 9 | exit 1 10 | fi 11 | 12 | hooksDir="${topLevel}/.githooks" 13 | if ! hooksPath=$(git config core.hooksPath); then 14 | hooksPath="${topLevel}/.git/hooks" 15 | fi 16 | 17 | src="${hooksDir}/generic" 18 | echo "linking hooks..." 19 | for hook in \ 20 | applypatch-msg \ 21 | pre-applypatch \ 22 | post-applypatch \ 23 | pre-commit \ 24 | pre-merge-commit \ 25 | prepare-commit-msg \ 26 | commit-msg \ 27 | post-commit \ 28 | pre-rebase \ 29 | post-checkout \ 30 | post-merge \ 31 | pre-push \ 32 | pre-receive \ 33 | update \ 34 | post-receive \ 35 | post-update \ 36 | push-to-checkout \ 37 | pre-auto-gc \ 38 | post-rewrite \ 39 | sendemail-validate \ 40 | fsmonitor-watchman \ 41 | p4-pre-submit \ 42 | post-index-change 43 | do 44 | echo " ${hook}" 45 | dest="${hooksPath}/${hook}" 46 | ln -sf "${src}" "${dest}" 47 | done 48 | -------------------------------------------------------------------------------- /shflags/lib/versions: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # Versions determines the versions of all installed shells. 5 | # 6 | # Copyright 2008-2020 Kate Ward. All Rights Reserved. 7 | # Released under the Apache 2.0 License. 8 | # 9 | # Author: kate.ward@forestent.com (Kate Ward) 10 | # https://github.com/kward/shlib 11 | # 12 | # This library provides reusable functions that determine actual names and 13 | # versions of installed shells and the OS. The library can also be run as a 14 | # script if set executable. 15 | # 16 | # Disable checks that aren't fully portable (POSIX != portable). 17 | # shellcheck disable=SC2006 18 | 19 | ARGV0=`basename "$0"` 20 | LSB_RELEASE='/etc/lsb-release' 21 | VERSIONS_SHELLS='ash /bin/bash /bin/dash /bin/ksh /bin/mksh /bin/pdksh /bin/zsh /usr/xpg4/bin/sh /bin/sh /sbin/sh' 22 | 23 | true; TRUE=$? 24 | false; FALSE=$? 25 | ERROR=2 26 | 27 | UNAME_R=`uname -r` 28 | UNAME_S=`uname -s` 29 | 30 | __versions_haveStrings=${ERROR} 31 | 32 | versions_osName() { 33 | os_name_='unrecognized' 34 | os_system_=${UNAME_S} 35 | os_release_=${UNAME_R} 36 | case ${os_system_} in 37 | CYGWIN_NT-*) os_name_='Cygwin' ;; 38 | Darwin) 39 | os_name_=`/usr/bin/sw_vers -productName` 40 | os_version_=`versions_osVersion` 41 | case ${os_version_} in 42 | 10.4|10.4.[0-9]*) os_name_='Mac OS X Tiger' ;; 43 | 10.5|10.5.[0-9]*) os_name_='Mac OS X Leopard' ;; 44 | 10.6|10.6.[0-9]*) os_name_='Mac OS X Snow Leopard' ;; 45 | 10.7|10.7.[0-9]*) os_name_='Mac OS X Lion' ;; 46 | 10.8|10.8.[0-9]*) os_name_='Mac OS X Mountain Lion' ;; 47 | 10.9|10.9.[0-9]*) os_name_='Mac OS X Mavericks' ;; 48 | 10.10|10.10.[0-9]*) os_name_='Mac OS X Yosemite' ;; 49 | 10.11|10.11.[0-9]*) os_name_='Mac OS X El Capitan' ;; 50 | 10.12|10.12.[0-9]*) os_name_='macOS Sierra' ;; 51 | 10.13|10.13.[0-9]*) os_name_='macOS High Sierra' ;; 52 | 10.14|10.14.[0-9]*) os_name_='macOS Mojave' ;; 53 | 10.15|10.15.[0-9]*) os_name_='macOS Catalina' ;; 54 | *) os_name_='macOS' ;; 55 | esac 56 | ;; 57 | FreeBSD) os_name_='FreeBSD' ;; 58 | Linux) os_name_='Linux' ;; 59 | SunOS) 60 | os_name_='SunOS' 61 | if [ -r '/etc/release' ]; then 62 | if grep 'OpenSolaris' /etc/release >/dev/null; then 63 | os_name_='OpenSolaris' 64 | else 65 | os_name_='Solaris' 66 | fi 67 | fi 68 | ;; 69 | esac 70 | 71 | echo ${os_name_} 72 | unset os_name_ os_system_ os_release_ os_version_ 73 | } 74 | 75 | versions_osVersion() { 76 | os_version_='unrecognized' 77 | os_system_=${UNAME_S} 78 | os_release_=${UNAME_R} 79 | case ${os_system_} in 80 | CYGWIN_NT-*) 81 | os_version_=`expr "${os_release_}" : '\([0-9]*\.[0-9]\.[0-9]*\).*'` 82 | ;; 83 | Darwin) 84 | os_version_=`/usr/bin/sw_vers -productVersion` 85 | ;; 86 | FreeBSD) 87 | os_version_=`expr "${os_release_}" : '\([0-9]*\.[0-9]*\)-.*'` 88 | ;; 89 | Linux) 90 | if [ -r '/etc/os-release' ]; then 91 | os_version_=`awk -F= '$1~/PRETTY_NAME/{print $2}' /etc/os-release \ 92 | |sed 's/"//g'` 93 | elif [ -r '/etc/redhat-release' ]; then 94 | os_version_=`cat /etc/redhat-release` 95 | elif [ -r '/etc/SuSE-release' ]; then 96 | os_version_=`head -n 1 /etc/SuSE-release` 97 | elif [ -r "${LSB_RELEASE}" ]; then 98 | if grep -q 'DISTRIB_ID=Ubuntu' "${LSB_RELEASE}"; then 99 | # shellcheck disable=SC2002 100 | os_version_=`cat "${LSB_RELEASE}" \ 101 | |awk -F= '$1~/DISTRIB_DESCRIPTION/{print $2}' \ 102 | |sed 's/"//g;s/ /-/g'` 103 | fi 104 | fi 105 | ;; 106 | SunOS) 107 | if [ -r '/etc/release' ]; then 108 | if grep 'OpenSolaris' /etc/release >/dev/null; then # OpenSolaris 109 | os_version_=`grep 'OpenSolaris' /etc/release |awk '{print $2"("$3")"}'` 110 | else # Solaris 111 | major_=`echo "${os_release_}" |sed 's/[0-9]*\.\([0-9]*\)/\1/'` 112 | minor_=`grep Solaris /etc/release |sed 's/[^u]*\(u[0-9]*\).*/\1/'` 113 | os_version_="${major_}${minor_}" 114 | fi 115 | fi 116 | ;; 117 | esac 118 | 119 | echo "${os_version_}" 120 | unset os_release_ os_system_ os_version_ major_ minor_ 121 | } 122 | 123 | versions_shellVersion() { 124 | shell_=$1 125 | 126 | shell_present_=${FALSE} 127 | case "${shell_}" in 128 | ash) [ -x '/bin/busybox' ] && shell_present_=${TRUE} ;; 129 | *) [ -x "${shell_}" ] && shell_present_=${TRUE} ;; 130 | esac 131 | if [ ${shell_present_} -eq ${FALSE} ]; then 132 | echo 'not installed' 133 | return ${FALSE} 134 | fi 135 | 136 | version_='' 137 | case ${shell_} in 138 | # SunOS shells. 139 | /sbin/sh) ;; 140 | /usr/xpg4/bin/sh) version_=`versions_shell_xpg4 "${shell_}"` ;; 141 | 142 | # Generic shell. 143 | */sh) 144 | # This could be one of any number of shells. Try until one fits. 145 | version_='' 146 | [ -z "${version_}" ] && version_=`versions_shell_bash "${shell_}"` 147 | # dash cannot be self determined yet 148 | [ -z "${version_}" ] && version_=`versions_shell_ksh "${shell_}"` 149 | # pdksh is covered in versions_shell_ksh() 150 | [ -z "${version_}" ] && version_=`versions_shell_xpg4 "${shell_}"` 151 | [ -z "${version_}" ] && version_=`versions_shell_zsh "${shell_}"` 152 | ;; 153 | 154 | # Specific shells. 155 | ash) version_=`versions_shell_ash "${shell_}"` ;; 156 | # bash - Bourne Again SHell (https://www.gnu.org/software/bash/) 157 | */bash) version_=`versions_shell_bash "${shell_}"` ;; 158 | */dash) version_=`versions_shell_dash` ;; 159 | # ksh - KornShell (http://www.kornshell.com/) 160 | */ksh) version_=`versions_shell_ksh "${shell_}"` ;; 161 | # mksh - MirBSD Korn Shell (http://www.mirbsd.org/mksh.htm) 162 | */mksh) version_=`versions_shell_ksh "${shell_}"` ;; 163 | # pdksh - Public Domain Korn Shell (http://web.cs.mun.ca/~michael/pdksh/) 164 | */pdksh) version_=`versions_shell_pdksh "${shell_}"` ;; 165 | # zsh (https://www.zsh.org/) 166 | */zsh) version_=`versions_shell_zsh "${shell_}"` ;; 167 | 168 | # Unrecognized shell. 169 | *) version_='invalid' 170 | esac 171 | 172 | echo "${version_:-unknown}" 173 | unset shell_ version_ 174 | } 175 | 176 | # The ash shell is included in BusyBox. 177 | versions_shell_ash() { 178 | busybox --help |head -1 |sed 's/BusyBox v\([0-9.]*\) .*/\1/' 179 | } 180 | 181 | versions_shell_bash() { 182 | $1 --version : 2>&1 |grep 'GNU bash' |sed 's/.*version \([^ ]*\).*/\1/' 183 | } 184 | 185 | # Assuming Ubuntu Linux until somebody comes up with a better test. The 186 | # following test will return an empty string if dash is not installed. 187 | versions_shell_dash() { 188 | eval dpkg >/dev/null 2>&1 189 | [ $? -eq 127 ] && return # Return if dpkg not found. 190 | 191 | dpkg -l |grep ' dash ' |awk '{print $3}' 192 | } 193 | 194 | versions_shell_ksh() { 195 | versions_shell_=$1 196 | versions_version_='' 197 | 198 | # Try a few different ways to figure out the version. 199 | versions_version_=`${versions_shell_} --version : 2>&1` 200 | # shellcheck disable=SC2181 201 | if [ $? -eq 0 ]; then 202 | versions_version_=`echo "${versions_version_}" \ 203 | |sed 's/.*\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\).*/\1/'` 204 | else 205 | versions_version_='' 206 | fi 207 | if [ -z "${versions_version_}" ]; then 208 | # shellcheck disable=SC2016 209 | versions_version_=`${versions_shell_} -c 'echo ${KSH_VERSION}'` 210 | fi 211 | if [ -z "${versions_version_}" ]; then 212 | _versions_have_strings 213 | versions_version_=`strings "${versions_shell_}" 2>&1 \ 214 | |grep Version \ 215 | |sed 's/^.*Version \(.*\)$/\1/;s/ s+ \$$//;s/ /-/g'` 216 | fi 217 | if [ -z "${versions_version_}" ]; then 218 | versions_version_=`versions_shell_pdksh "${versions_shell_}"` 219 | fi 220 | 221 | echo "${versions_version_}" 222 | unset versions_shell_ versions_version_ 223 | } 224 | 225 | # mksh - MirBSD Korn Shell (http://www.mirbsd.org/mksh.htm) 226 | # mksh is a successor to pdksh (Public Domain Korn Shell). 227 | versions_shell_mksh() { 228 | versions_shell_ksh 229 | } 230 | 231 | # pdksh - Public Domain Korn Shell 232 | # pdksh is an obsolete shell, which was replaced by mksh (among others). 233 | versions_shell_pdksh() { 234 | _versions_have_strings 235 | strings "$1" 2>&1 \ 236 | |grep 'PD KSH' \ 237 | |sed -e 's/.*PD KSH \(.*\)/\1/;s/ /-/g' 238 | } 239 | 240 | versions_shell_xpg4() { 241 | _versions_have_strings 242 | strings "$1" 2>&1 \ 243 | |grep 'Version' \ 244 | |sed -e 's/^@(#)Version //' 245 | } 246 | 247 | versions_shell_zsh() { 248 | versions_shell_=$1 249 | 250 | # Try a few different ways to figure out the version. 251 | # shellcheck disable=SC2016 252 | versions_version_=`echo 'echo ${ZSH_VERSION}' |${versions_shell_}` 253 | if [ -z "${versions_version_}" ]; then 254 | versions_version_=`${versions_shell_} --version : 2>&1` 255 | # shellcheck disable=SC2181 256 | if [ $? -eq 0 ]; then 257 | versions_version_=`echo "${versions_version_}" |awk '{print $2}'` 258 | else 259 | versions_version_='' 260 | fi 261 | fi 262 | 263 | echo "${versions_version_}" 264 | unset versions_shell_ versions_version_ 265 | } 266 | 267 | # Determine if the 'strings' binary installed. 268 | _versions_have_strings() { 269 | [ ${__versions_haveStrings} -ne ${ERROR} ] && return 270 | if eval strings /dev/null >/dev/null 2>&1; then 271 | __versions_haveStrings=${TRUE} 272 | return 273 | fi 274 | 275 | echo 'WARN: strings not installed. try installing binutils?' >&2 276 | __versions_haveStrings=${FALSE} 277 | } 278 | 279 | versions_main() { 280 | # Treat unset variables as an error. 281 | set -u 282 | 283 | os_name=`versions_osName` 284 | os_version=`versions_osVersion` 285 | echo "os: ${os_name} version: ${os_version}" 286 | 287 | for shell in ${VERSIONS_SHELLS}; do 288 | shell_version=`versions_shellVersion "${shell}"` 289 | echo "shell: ${shell} version: ${shell_version}" 290 | done 291 | } 292 | 293 | if [ "${ARGV0}" = 'versions' ]; then 294 | versions_main "$@" 295 | fi 296 | -------------------------------------------------------------------------------- /shflags/shflags_defines_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # shFlags unit test for the flag definition methods 5 | # 6 | # Copyright 2008-2020 Kate Ward. All Rights Reserved. 7 | # Released under the Apache 2.0 license. 8 | # 9 | # Author: kate.ward@forestent.com (Kate Ward) 10 | # https://github.com/kward/shflags 11 | # 12 | ### ShellCheck (http://www.shellcheck.net/) 13 | # Disable source following. 14 | # shellcheck disable=SC1090,SC1091 15 | 16 | # Exit immediately if a simple command exits with a non-zero status. 17 | set -e 18 | 19 | # Treat unset variables as an error when performing parameter expansion. 20 | set -u 21 | 22 | # These variables will be overridden by the test helpers. 23 | stdoutF="${TMPDIR:-/tmp}/STDOUT" 24 | stderrF="${TMPDIR:-/tmp}/STDERR" 25 | 26 | # Load test helpers. 27 | . ./shflags_test_helpers 28 | 29 | testFlagsDefine() { 30 | # No arguments. 31 | if _flags_define >"${stdoutF}" 2>"${stderrF}" 32 | then :; else 33 | assertEquals '_flags_define() with no arguments should error' "${FLAGS_ERROR}" $? 34 | fi 35 | assertErrorMsg '' 'no arguments' 36 | 37 | # One argument. 38 | if _flags_define arg1 >"${stdoutF}" 2>"${stderrF}" 39 | then :; else 40 | assertEquals '_flags_define() call with one argument should error' "${FLAGS_ERROR}" $? 41 | fi 42 | assertErrorMsg '' 'one argument' 43 | 44 | # Two arguments. 45 | if _flags_define arg1 arg2 >"${stdoutF}" 2>"${stderrF}" 46 | then :; else 47 | assertEquals '_flags_define() call with two arguments should error' "${FLAGS_ERROR}" $? 48 | fi 49 | assertErrorMsg '' 'two arguments' 50 | 51 | # Three arguments. 52 | if _flags_define arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" 53 | then :; else 54 | assertEquals '_flags_define() call with three arguments should error' "${FLAGS_ERROR}" $? 55 | fi 56 | assertErrorMsg '' 'three arguments' 57 | 58 | # Multiple definition. Assumes working boolean definition (tested elsewhere). 59 | if ! _flags_define "${__FLAGS_TYPE_BOOLEAN}" multiDefBool true 'multi def #1' m; then 60 | fail "didn't expect _flags_define for 'multi def #1' to fail" 61 | fi 62 | if _flags_define "${__FLAGS_TYPE_BOOLEAN}" multiDefBool false 'multi def #2' m >"${stdoutF}" 2>"${stderrF}" 63 | then :; else 64 | assertEquals '_flags_define() with existing flag name should fail' "${FLAGS_FALSE}" $? 65 | fi 66 | assertTrue '_flags_define() should not overwrite previously defined default.' "${FLAGS_multiDefBool:-}" 67 | assertWarnMsg '' 'existing flag' 68 | 69 | # Duplicate dashed and underscored definition. 70 | if ! _flags_define "${__FLAGS_TYPE_STRING}" long-name 'foo' 'dashed name' l; then 71 | fail "didn't expect _flags_define() for 'dashed name' to fail" 72 | fi 73 | if _flags_define "${__FLAGS_TYPE_STRING}" long_name 'bar' 'underscored name' l >"${stdoutF}" 2>"${stderrF}" 74 | then :; else 75 | assertEquals '_flags_define() with duplicate dashed and underscored definition should fail' "${FLAGS_FALSE}" $? 76 | fi 77 | # shellcheck disable=SC2154 78 | assertEquals '_flags_define() should not overwrite previously defined default.' "${FLAGS_long_name}" 'foo' 79 | assertWarnMsg '' 'already exists' 80 | 81 | # TODO(kward): test requirement of enhanced getopt. 82 | 83 | # Invalid type. 84 | if _flags_define invalid arg2 arg3 arg4 i >"${stdoutF}" 2>"${stderrF}" 85 | then :; else 86 | assertEquals '_flags_define() with "invalid" type should have failed.' "${FLAGS_ERROR}" $? 87 | fi 88 | assertErrorMsg 'unrecognized flag type' 'invalid type' 89 | } 90 | 91 | testBoolean() { 92 | while read -r desc ok default want; do 93 | flags_reset 94 | 95 | if DEFINE_boolean boolVal "${default}" 'my boolean' b >"${stdoutF}" 2>"${stderrF}" 96 | then 97 | assertEquals "${desc}: incorrect FLAGS_boolVal value" "${FLAGS_boolVal:-}" "${want}" 98 | else 99 | got=$? 100 | if [ "${ok}" -eq "${FLAGS_TRUE}" ]; then 101 | assertEquals "${desc}: DEFINE_boolean() failed unexpectedly" "${want}" "${got}" 102 | else 103 | assertEquals "${desc}: DEFINE_boolean() expected different return value" "${want}" "${got}" 104 | assertErrorMsg 105 | fi 106 | fi 107 | done <"${stdoutF}" 2>"${stderrF}" 137 | then 138 | fail "${desc}: expected DEFINE_float() to fail" 139 | else 140 | assertEquals "${desc}: DEFINE_float() expected error" "${FLAGS_ERROR}" $? 141 | assertErrorMsg 142 | fi 143 | done 144 | } 145 | 146 | testInteger() { 147 | # Valid defaults. 148 | for default in ${TH_INT_VALID}; do 149 | flags_reset 150 | desc="valid_int_val='${default}'" 151 | if DEFINE_integer intVal "${default}" 'valid integer' i 152 | then 153 | got="${FLAGS_intVal:-}" want="${default}" 154 | assertEquals "${desc}: incorrect FLAGS_intVal value" "${want}" "${got}" 155 | else 156 | assertEquals "${desc}: DEFINE_integer() failed unexpectedly." "${FLAGS_TRUE}" $? 157 | fi 158 | done 159 | 160 | # Invalid defaults. 161 | for default in ${TH_INT_INVALID}; do 162 | flags_reset 163 | desc="invalid_int_val='${default}'" 164 | if DEFINE_integer intVal "${default}" 'invalid integer' i >"${stdoutF}" 2>"${stderrF}" 165 | then 166 | fail "${desc}: expected DEFINE_integer() to fail" 167 | else 168 | assertEquals "${desc}: DEFINE_integer() expected error." "${FLAGS_ERROR}" $? 169 | assertErrorMsg 170 | fi 171 | done 172 | } 173 | 174 | testString() { 175 | # Valid defaults. 176 | for default in ${TH_BOOL_VALID} ${TH_FLOAT_VALID} ${TH_INT_VALID} 'also valid' '' 177 | do 178 | flags_reset 179 | desc="valid_string_val='${default}'" 180 | if DEFINE_string strVal "${default}" "string: ${default}" s 181 | then 182 | got="${FLAGS_strVal:-}" want="${default}" 183 | assertEquals "${desc}: incorrect FLAGS_strVal value" "${want}" "${got}" 184 | else 185 | assertEquals "${desc}: DEFINE_string() failed unexpectedly." "${FLAGS_TRUE}" $? 186 | fi 187 | done 188 | 189 | # There are no known invalid defaults. 190 | } 191 | 192 | testShortNameLength() { 193 | # Make sure short names are no longer than a single character. 194 | : 195 | } 196 | 197 | testFlagNameIsReserved() { 198 | if DEFINE_string TRUE '' 'true is a reserved flag name' t >"${stdoutF}" 2>"${stderrF}" 199 | then 200 | fail "expected DEFINE with reserved flag name to fail" 201 | else 202 | assertEquals "expected error from DEFINE with reserved flag" "${FLAGS_ERROR}" $? 203 | assertErrorMsg 'flag name (TRUE) is reserved' 204 | fi 205 | } 206 | 207 | oneTimeSetUp() { 208 | th_oneTimeSetUp 209 | } 210 | 211 | tearDown() { 212 | flags_reset 213 | } 214 | 215 | # Load and run shUnit2. 216 | # shellcheck disable=SC2034 217 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 218 | . "${TH_SHUNIT}" 219 | -------------------------------------------------------------------------------- /shflags/shflags_parsing_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # shFlags unit test for the flag definition methods 5 | # 6 | # Copyright 2008-2020 Kate Ward. All Rights Reserved. 7 | # Released under the Apache 2.0 license. 8 | # 9 | # Author: kate.ward@forestent.com (Kate Ward) 10 | # https://github.com/kward/shflags 11 | # 12 | ### ShellCheck (http://www.shellcheck.net/) 13 | # Disable source following. 14 | # shellcheck disable=SC1090,SC1091 15 | 16 | # TODO(kward): assert on FLAGS errors 17 | # TODO(kward): testNonStandardIFS() 18 | 19 | # These variables will be overridden by the test helpers. 20 | stdoutF="${TMPDIR:-/tmp}/STDOUT" 21 | stderrF="${TMPDIR:-/tmp}/STDERR" 22 | 23 | # Load test helpers. 24 | . ./shflags_test_helpers 25 | 26 | testGetoptStandard() { 27 | if ! _flags_getoptStandard '-b' >"${stdoutF}" 2>"${stderrF}"; then 28 | fail "error parsing -b flag" 29 | _showTestOutput 30 | fi 31 | 32 | if _flags_getoptStandard '-x' >"${stdoutF}" 2>"${stderrF}"; then 33 | fail "expected error parsing invalid -x flag" 34 | _showTestOutput 35 | fi 36 | } 37 | 38 | testGetoptEnhanced() { 39 | if ! flags_getoptIsEnh; then 40 | return 41 | fi 42 | 43 | if ! _flags_getoptEnhanced '-b' >"${stdoutF}" 2>"${stderrF}"; then 44 | fail "error parsing -b flag" 45 | _showTestOutput 46 | fi 47 | if ! _flags_getoptEnhanced '--bool' >"${stdoutF}" 2>"${stderrF}"; then 48 | fail "error parsing --bool flag" 49 | _showTestOutput 50 | fi 51 | 52 | if _flags_getoptEnhanced '-x' >"${stdoutF}" 2>"${stderrF}"; then 53 | fail "expected error parsing invalid -x flag" 54 | _showTestOutput 55 | fi 56 | if _flags_getoptEnhanced '--xyz' >"${stdoutF}" 2>"${stderrF}"; then 57 | fail "expected error parsing invalid --xyz flag" 58 | _showTestOutput 59 | fi 60 | } 61 | 62 | testValidBoolsShort() { 63 | desc='bool_true_arg' 64 | if FLAGS -b >"${stdoutF}" 2>"${stderrF}"; then 65 | assertTrue "${desc}: expected true value" "${FLAGS_bool:-}" 66 | else 67 | fail "${desc}: FLAGS returned a non-zero result ($?)" 68 | fi 69 | th_showOutput 70 | 71 | desc='bool2_defined' 72 | DEFINE_boolean bool2 true '2nd boolean' B 73 | if FLAGS >"${stdoutF}" 2>"${stderrF}"; then 74 | assertTrue "${desc}: expected true value" "${FLAGS_bool2:-}" 75 | else 76 | fail "${desc}: FLAGS returned a non-zero result ($?)" 77 | fi 78 | th_showOutput 79 | 80 | desc='bool_false_arg' 81 | if FLAGS -B >"${stdoutF}" 2>"${stderrF}"; then 82 | assertFalse "${desc}: expected false value" "${FLAGS_bool2:-}" 83 | else 84 | fail "${desc}: FLAGS returned a non-zero result ($?)" 85 | fi 86 | th_showOutput 87 | } 88 | 89 | # TODO(kate): separate into multiple functions to reflect correct usage 90 | testValidBoolsLong() { 91 | flags_getoptIsEnh 92 | [ $? -eq "${FLAGS_FALSE}" ] && return 93 | 94 | # Note: the default value of bool is 'false'. 95 | 96 | # Leave flag false. 97 | FLAGS --nobool >"${stdoutF}" 2>"${stderrF}" 98 | r3turn=$? 99 | assertTrue "FLAGS returned a non-zero result (${r3turn})" ${r3turn} 100 | assertFalse '--noXX flag resulted in true value.' "${FLAGS_bool:-}" 101 | assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" 102 | th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" 103 | 104 | # Flip flag true. 105 | FLAGS --bool >"${stdoutF}" 2>"${stderrF}" 106 | r3turn=$? 107 | assertTrue "FLAGS returned a non-zero result (${r3turn})" ${r3turn} 108 | assertTrue '--XX flag resulted in false value.' "${FLAGS_bool:-}" 109 | assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" 110 | th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" 111 | 112 | # Flip flag back false. 113 | FLAGS --nobool >"${stdoutF}" 2>"${stderrF}" 114 | r3turn=$? 115 | assertTrue "FLAGS returned a non-zero result (${r3turn})" ${r3turn} 116 | assertFalse '--noXX flag resulted in true value.' "${FLAGS_bool:-}" 117 | assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" 118 | th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" 119 | } 120 | 121 | testFloats() { 122 | _testFloats '-f' 123 | if flags_getoptIsEnh; then 124 | _testFloats '--float' 125 | fi 126 | } 127 | 128 | _testFloats() { 129 | flag=$1 130 | 131 | for value in ${TH_FLOAT_VALID}; do 132 | if FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"; then 133 | # shellcheck disable=SC2154 134 | assertEquals "${flag}: incorrect value" "${value}" "${FLAGS_float}" 135 | else 136 | fail "${flag}: unexpected non-zero result ($?)" 137 | th_showOutput 138 | fi 139 | done 140 | 141 | for value in ${TH_FLOAT_INVALID}; do 142 | # Wrap FLAGS in () to catch errors. 143 | if (FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"); then 144 | fail "${flag}: expected a non-zero result" 145 | th_showOutput 146 | else 147 | assertEquals "${flag}: expected an error" $? "${FLAGS_ERROR}" 148 | fi 149 | done 150 | } 151 | 152 | testIntegers() { 153 | _testIntegers '-i' 154 | if flags_getoptIsEnh; then 155 | _testIntegers '--int' 156 | fi 157 | } 158 | 159 | _testIntegers() { 160 | flag=$1 161 | 162 | for value in ${TH_INT_VALID}; do 163 | if FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"; then 164 | # shellcheck disable=SC2154 165 | assertEquals "${flag}: incorrect value" "${value}" "${FLAGS_int}" 166 | else 167 | fail "${flag}: unexpected non-zero result ($?)" 168 | th_showOutput 169 | fi 170 | done 171 | 172 | for value in ${TH_INT_INVALID}; do 173 | # Wrap FLAGS in () to catch errors. 174 | if (FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"); then 175 | fail "${flag}: expected a non-zero result" 176 | th_showOutput 177 | else 178 | assertEquals "${flag}: expected an error" $? "${FLAGS_ERROR}" 179 | fi 180 | done 181 | } 182 | 183 | testStrings() { 184 | _testStrings 'std_single_word' -s single_word 185 | if flags_getoptIsEnh; then 186 | _testStrings 'enh_single_word' --str single_word 187 | _testStrings 'enh_multi_word' --str 'string with spaces' 188 | fi 189 | } 190 | 191 | _testStrings() { 192 | desc=$1 193 | flag=$2 194 | value=$3 195 | 196 | if FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"; then 197 | # shellcheck disable=SC2154 198 | assertEquals "${desc}: incorrect value" "${value}" "${FLAGS_str}" 199 | else 200 | fail "${desc}: unexpected non-zero result ($?)" 201 | # Validate that an error is thrown for unsupported getopt uses. 202 | assertFatalMsg '.* spaces in options' 203 | th_showOutput 204 | fi 205 | } 206 | 207 | testMultipleFlags() { 208 | _testMultipleFlags '-b' '-i' '-f' '-s' 209 | flags_getoptIsEnh 210 | [ $? -eq "${FLAGS_FALSE}" ] && return 211 | _testMultipleFlags '--bool' '--int' '--float' '--str' 212 | } 213 | 214 | _testMultipleFlags() { 215 | boolFlag=$1 216 | intFlag=$2 217 | floatFlag=$3 218 | strFlag=$4 219 | 220 | FLAGS \ 221 | "${boolFlag}" \ 222 | "${intFlag}" 567 \ 223 | "${floatFlag}" 123.45678 \ 224 | "${strFlag}" 'some_string' \ 225 | >"${stdoutF}" 2>"${stderrF}" 226 | r3turn=$? 227 | assertTrue "use of multiple flags returned a non-zero result" ${r3turn} 228 | assertTrue 'boolean test failed.' "${FLAGS_bool}" 229 | assertNotSame 'float test failed.' 0 "${FLAGS_float}" 230 | assertNotSame 'integer test failed.' 0 "${FLAGS_int}" 231 | assertNotSame 'string test failed.' '' "${FLAGS_str}" 232 | assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" 233 | th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" 234 | } 235 | 236 | _testNonFlagArgs() { 237 | argc=$1 238 | shift 239 | 240 | FLAGS "$@" >"${stdoutF}" 2>"${stderrF}" 241 | r3turn=$? 242 | assertTrue 'parse returned non-zero value.' ${r3turn} 243 | th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" 244 | 245 | eval set -- "${FLAGS_ARGV}" 246 | assertEquals 'wrong count of argv arguments returned.' "${argc}" $# 247 | } 248 | 249 | testSingleNonFlagArg() { _testNonFlagArgs 1 argOne; } 250 | testMultipleNonFlagArgs() { _testNonFlagArgs 3 argOne argTwo arg3; } 251 | 252 | testMultipleNonFlagStringArgsWithSpaces() { 253 | if flags_getoptIsEnh; then 254 | _testNonFlagArgs 3 argOne 'arg two' arg3 255 | fi 256 | } 257 | 258 | testFlagsWithEquals() { 259 | if ! flags_getoptIsEnh; then 260 | return 261 | fi 262 | 263 | FLAGS --str='str_flag' 'non_flag' >"${stdoutF}" 2>"${stderrF}" 264 | assertTrue 'FLAGS returned a non-zero result' $? 265 | assertEquals 'string flag not set properly' 'str_flag' "${FLAGS_str}" 266 | th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" 267 | 268 | eval set -- "${FLAGS_ARGV}" 269 | assertEquals 'wrong count of argv arguments returned.' 1 $# 270 | } 271 | 272 | testComplicatedCommandLineStandard() { 273 | flags_getoptIsEnh 274 | [ $? -eq "${FLAGS_TRUE}" ] && return 275 | 276 | # Note: standard getopt stops parsing after first non-flag argument, which 277 | # results in the remaining flags being treated as arguments instead. 278 | FLAGS -i 1 non_flag_1 -s 'two' non_flag_2 -f 3 non_flag_3 \ 279 | >"${stdoutF}" 2>"${stderrF}" 280 | r3turn=$? 281 | assertTrue 'FLAGS returned a non-zero result' ${r3turn} 282 | assertEquals 'failed int test' 1 "${FLAGS_int}" 283 | th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" 284 | 285 | eval set -- "${FLAGS_ARGV}" 286 | assertEquals 'incorrect number of argv values' 7 $# 287 | } 288 | 289 | testComplicatedCommandLineEnhanced() { 290 | flags_getoptIsEnh 291 | [ $? -eq "${FLAGS_FALSE}" ] && return 292 | 293 | FLAGS -i 1 non_flag_1 --str='two' non_flag_2 --float 3 'non flag 3' \ 294 | >"${stdoutF}" 2>"${stderrF}" 295 | r3turn=$? 296 | assertTrue 'FLAGS returned a non-zero result' ${r3turn} 297 | assertEquals 'failed int test' 1 "${FLAGS_int}" 298 | assertEquals 'failed str test' 'two' "${FLAGS_str}" 299 | assertEquals 'failed float test' 3 "${FLAGS_float}" 300 | th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" 301 | 302 | eval set -- "${FLAGS_ARGV}" 303 | assertEquals 'incorrect number of argv values' 3 $# 304 | } 305 | 306 | oneTimeSetUp() { 307 | th_oneTimeSetUp 308 | 309 | if flags_getoptIsStd; then 310 | th_warn 'Standard version of getopt found. Enhanced tests will be skipped.' 311 | else 312 | th_warn 'Enhanced version of getopt found. Standard tests will be skipped.' 313 | fi 314 | } 315 | 316 | setUp() { 317 | DEFINE_boolean bool false 'boolean test' 'b' 318 | DEFINE_float float 0.0 'float test' 'f' 319 | DEFINE_integer int 0 'integer test' 'i' 320 | DEFINE_string str '' 'string test' 's' 321 | } 322 | 323 | tearDown() { 324 | flags_reset 325 | } 326 | 327 | # showTestOutput for the most recently run test. 328 | _showTestOutput() { th_showOutput "${SHUNIT_FALSE}" "${stdoutF}" "${stderrF}"; } 329 | 330 | # Load and run shUnit2. 331 | # shellcheck disable=SC2034 332 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 333 | . "${TH_SHUNIT}" 334 | -------------------------------------------------------------------------------- /shflags/shflags_private_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # shFlags unit tests for the internal functions. 5 | # 6 | # Copyright 2008-2020 Kate Ward. All Rights Reserved. 7 | # Released under the Apache 2.0 license. 8 | # 9 | # Author: kate.ward@forestent.com (Kate Ward) 10 | # https://github.com/kward/shflags 11 | # 12 | ### ShellCheck (http://www.shellcheck.net/) 13 | # Disable source following. 14 | # shellcheck disable=SC1090,SC1091 15 | # expr may be antiquated, but it is the only solution in some cases. 16 | # shellcheck disable=SC2003 17 | # $() are not fully portable (POSIX != portable). 18 | # shellcheck disable=SC2006 19 | 20 | # These variables will be overridden by the test helpers. 21 | stdoutF="${TMPDIR:-/tmp}/STDOUT" 22 | stderrF="${TMPDIR:-/tmp}/STDERR" 23 | 24 | # Load test helpers. 25 | . ./shflags_test_helpers 26 | 27 | testColumns() { 28 | cols=`_flags_columns` 29 | value=`expr "${cols}" : '\([0-9]*\)'` 30 | assertNotNull "unexpected screen width (${cols})" "${value}" 31 | } 32 | 33 | testGetoptVers() { 34 | # shellcheck disable=SC2162 35 | while read desc mock want; do 36 | assertEquals "${desc}" "$(_flags_getopt_vers "${mock}")" "${want}" 37 | done <"${stderrF}"`"; then 98 | fail "${desc}: expected invalid flag request to fail" 99 | th_showOutput 100 | else 101 | assertEquals "${desc}: expected an error" "${FLAGS_ERROR}" $? 102 | assertErrorMsg "missing flag info variable" 103 | fi 104 | } 105 | 106 | testItemInList() { 107 | list='this is a test' 108 | # shellcheck disable=SC2162 109 | while read desc item want; do 110 | if [ "${want}" -eq "${FLAGS_TRUE}" ]; then 111 | continue 112 | fi 113 | got=${FLAGS_TRUE} 114 | if ! _flags_itemInList "${item}" "${list}"; then 115 | got=${FLAGS_FALSE} 116 | fi 117 | assertEquals "${desc}: itemInList(${item})" "${want}" "${got}" 118 | done </dev/null 2>&1; then 256 | got=${FLAGS_FALSE} 257 | fi 258 | assertFalse 'missing math succeeded' "${got}" 259 | } 260 | 261 | testMathBuiltin() { 262 | _flags_useBuiltin || startSkipping 263 | _testMath 264 | } 265 | 266 | testMathExpr() { 267 | ( 268 | _flags_useBuiltin() { return "${FLAGS_FALSE}"; } 269 | _testMath 270 | ) 271 | } 272 | 273 | _testStrlen() { 274 | len=`_flags_strlen` 275 | assertTrue 'missing argument failed' $? 276 | assertEquals 'missing argument' 0 "${len}" 277 | 278 | len=`_flags_strlen ''` 279 | assertTrue 'empty argument failed' $? 280 | assertEquals 'empty argument' 0 "${len}" 281 | 282 | len=`_flags_strlen abc123` 283 | assertTrue 'single-word failed' $? 284 | assertEquals 'single-word' 6 "${len}" 285 | 286 | len=`_flags_strlen 'This is a test'` 287 | assertTrue 'multi-word failed' $? 288 | assertEquals 'multi-word' 14 "${len}" 289 | } 290 | 291 | testStrlenBuiltin() { 292 | _flags_useBuiltin || startSkipping 293 | _testStrlen 294 | } 295 | 296 | testStrlenExpr() { 297 | ( 298 | _flags_useBuiltin() { return "${FLAGS_FALSE}"; } 299 | _testStrlen 300 | ) 301 | } 302 | 303 | oneTimeSetUp() { 304 | th_oneTimeSetUp 305 | 306 | _flags_useBuiltin || \ 307 | th_warn 'Shell built-ins not supported. Some tests will be skipped.' 308 | } 309 | 310 | tearDown() { 311 | flags_reset 312 | } 313 | 314 | # Load and run shUnit2. 315 | # shellcheck disable=SC2034 316 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 317 | . "${TH_SHUNIT}" 318 | -------------------------------------------------------------------------------- /shflags/shflags_public_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # shFlags unit test for the public functions. 5 | # 6 | # Copyright 2008-2020 Kate Ward. All Rights Reserved. 7 | # Released under the Apache 2.0 license. 8 | # 9 | # Author: kate.ward@forestent.com (Kate Ward) 10 | # https://github.com/kward/shflags 11 | # 12 | ### ShellCheck (http://www.shellcheck.net/) 13 | # Disable source following. 14 | # shellcheck disable=SC1090,SC1091 15 | # $() are not fully portable (POSIX != portable). 16 | # shellcheck disable=SC2006 17 | 18 | # These variables will be overridden by the test helpers. 19 | expectedF="${TMPDIR:-/tmp}/expected" 20 | returnF="${TMPDIR:-/tmp}/return" 21 | stdoutF="${TMPDIR:-/tmp}/STDOUT" 22 | stderrF="${TMPDIR:-/tmp}/STDERR" 23 | 24 | # Load test helpers. 25 | . ./shflags_test_helpers 26 | 27 | testHelp() { 28 | _testHelp '-h' 29 | _testHelp '--help' 30 | } 31 | 32 | _testHelp() { 33 | if ! flags_getoptIsEnh; then 34 | return 35 | fi 36 | 37 | flag=$1 38 | 39 | # Test default help output. 40 | th_clearReturn 41 | ( 42 | FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" 43 | echo $? >"${returnF}" 44 | ) 45 | assertFalse \ 46 | 'short help request should have returned a false exit code.' \ 47 | "$(th_queryReturn)" 48 | (grep 'show this help' "${stderrF}" >/dev/null) 49 | r3turn=$? 50 | assertTrue \ 51 | 'short request for help should have produced some help output.' \ 52 | ${r3turn} 53 | [ ${r3turn} -ne "${FLAGS_TRUE}" ] && th_showOutput 54 | 55 | # Test proper output when FLAGS_HELP set. 56 | ( 57 | FLAGS_HELP='this is a test' 58 | FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" 59 | ) 60 | (grep 'this is a test' "${stderrF}" >/dev/null) 61 | r3turn=$? 62 | assertTrue 'setting FLAGS_HELP did not produce expected result' ${r3turn} 63 | [ ${r3turn} -ne "${FLAGS_TRUE}" ] && th_showOutput 64 | 65 | # Test that "'" chars work in help string. 66 | ( 67 | # shellcheck disable=SC2034 68 | DEFINE_boolean b false "help string containing a ' char" b 69 | FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" 70 | ) 71 | (grep "help string containing a ' char" "${stderrF}" >/dev/null) 72 | r3turn=$? 73 | assertTrue "help strings containing apostrophes don't work" ${r3turn} 74 | [ ${r3turn} -ne "${FLAGS_TRUE}" ] && th_showOutput 75 | 76 | return "${SHUNIT_TRUE}" 77 | } 78 | 79 | mock_flags_columns() { 80 | echo 80 81 | } 82 | 83 | testStandardHelpOutput() { 84 | if ! flags_getoptIsStd; then 85 | startSkipping 86 | fi 87 | 88 | DEFINE_boolean test_bool false 'test boolean' b 89 | DEFINE_integer test_int 0 'test integer' i 90 | DEFINE_string test_str '' 'test string' s 91 | DEFINE_string long_desc 'blah' \ 92 | 'testing of a long description to force wrap of default value' D 93 | DEFINE_string long_default \ 94 | 'this_is_a_long_default_value_to_force_alternate_indentation' \ 95 | 'testing of long default value' F 96 | 97 | # Test for https://github.com/kward/shflags/issues/28. 98 | DEFINE_boolean 'force' false '' f 99 | 100 | help='USAGE: standard [flags] args' 101 | 102 | cat >"${expectedF}" <"${stdoutF}" 2>"${stderrF}"; then 120 | rtrn=$? 121 | else 122 | rtrn=$? 123 | fi 124 | echo "${rtrn}" >"${returnF}" 125 | ) 126 | assertFalse 'a call for help should return a non-zero exit code.' "$(th_queryReturn)" 127 | 128 | if ! diff "${expectedF}" "${stderrF}" >/dev/null; then 129 | fail 'unexpected help output' 130 | th_showOutput 131 | fi 132 | } 133 | 134 | testEnhancedHelpOutput() { 135 | if ! flags_getoptIsEnh; then 136 | startSkipping 137 | fi 138 | 139 | # shellcheck disable=SC2034 140 | DEFINE_boolean test_bool false 'test boolean' b 141 | # shellcheck disable=SC2034 142 | DEFINE_integer test_int 0 'test integer' i 143 | # shellcheck disable=SC2034 144 | DEFINE_string test_str '' 'test string' s 145 | # shellcheck disable=SC2034 146 | DEFINE_string long_desc 'blah' \ 147 | 'testing of a long description to force wrap of default value' D 148 | # shellcheck disable=SC2034 149 | DEFINE_string long_default \ 150 | 'this_is_a_long_default_value_to_force_alternate_indentation' \ 151 | 'testing of long default value' F 152 | 153 | # Test for https://github.com/kward/shflags/issues/28. 154 | DEFINE_boolean 'force' false '' f 155 | 156 | help='USAGE: enhanced [flags] args' 157 | 158 | cat >"${expectedF}" <"${stdoutF}" 2>"${stderrF}"; then 177 | rtrn=$? 178 | else 179 | rtrn=$? 180 | fi 181 | echo "${rtrn}" >"${returnF}" 182 | ) 183 | assertFalse 'a call for help should return a non-zero exit code.' "$(th_queryReturn)" 184 | 185 | if ! diff "${expectedF}" "${stderrF}" >/dev/null; then 186 | fail 'unexpected help output' 187 | th_showOutput 188 | fi 189 | } 190 | 191 | testNoHelp() { 192 | if ! flags_getoptIsEnh; then 193 | startSkipping 194 | fi 195 | 196 | ( FLAGS --nohelp >"${stdoutF}" 2>"${stderrF}" ) 197 | r3turn=$? 198 | assertTrue "FLAGS returned a non-zero result (${r3turn})" ${r3turn} 199 | assertFalse 'expected no output to STDOUT' "[ -s '${stdoutF}' ]" 200 | assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" 201 | } 202 | 203 | testLoggingLevel() { 204 | # Check that the default logging level is set properly. 205 | got=`flags_loggingLevel` want=${__FLAGS_LEVEL_DEFAULT} 206 | assertTrue "Unexpected default logging level = ${got}, want ${want}" "[ ${got} -eq ${want} ]" 207 | 208 | # Override the logging level, and check again. 209 | flags_setLoggingLevel "${FLAGS_LEVEL_FATAL}" 210 | flags_setLoggingLevel "${FLAGS_LEVEL_INFO}" 211 | got=`flags_loggingLevel` want=${FLAGS_LEVEL_INFO} 212 | assertTrue "Unexpected configured logging level = ${got}, want ${want}" "[ ${got} -eq ${want} ]" 213 | } 214 | 215 | # According to https://github.com/kward/shflags/issues/28 216 | # 217 | # DEFINE_boolean misbehaves when help-string is empty 218 | testIssue28() { 219 | # shellcheck disable=SC2034 220 | DEFINE_boolean 'force' false '' f 221 | 222 | testHelp && return 223 | } 224 | 225 | oneTimeSetUp() { 226 | th_oneTimeSetUp 227 | 228 | if flags_getoptIsStd; then 229 | th_warn 'Standard version of getopt found. Enhanced tests will be skipped.' 230 | return 231 | fi 232 | th_warn 'Enhanced version of getopt found. Standard tests will be skipped.' 233 | } 234 | 235 | setUp() { 236 | flags_reset 237 | } 238 | 239 | # Load and run shUnit2. 240 | # shellcheck disable=SC2034 241 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 242 | . "${TH_SHUNIT}" 243 | -------------------------------------------------------------------------------- /shflags/shflags_test_helpers: -------------------------------------------------------------------------------- 1 | # vim:et:ft=sh:sts=2:sw=2 2 | # 3 | # shFlags unit test common functions 4 | # 5 | # Copyright 2008-2018 Kate Ward. All Rights Reserved. 6 | # Released under the Apache 2.0 license. 7 | # 8 | # Author: kate.ward@forestent.com (Kate Ward) 9 | # https://github.com/kward/shflags 10 | # 11 | ### ShellCheck (http://www.shellcheck.net/) 12 | # Disable source following. 13 | # shellcheck disable=SC1090,SC1091 14 | # $() are not fully portable (POSIX != portable). 15 | # shellcheck disable=SC2006 16 | # Arrays are not available in all shells. 17 | # shellcheck disable=SC2089 18 | # Exporting variables shouldn't impact their contents. 19 | # shellcheck disable=SC2090 20 | # Disagree with [ p ] && [ q ] vs [ p -a -q ] recommendation. 21 | # shellcheck disable=SC2166 22 | 23 | # Exit immediately if a simple command exits with a non-zero status. 24 | set -e 25 | 26 | # Treat unset variables as an error when performing parameter expansion. 27 | set -u 28 | 29 | # Set shwordsplit for zsh. 30 | [ -n "${ZSH_VERSION:-}" ] && setopt shwordsplit 31 | 32 | # Message functions. 33 | th_trace() { echo "test:TRACE $*" >&2; } 34 | th_debug() { echo "test:DEBUG $*" >&2; } 35 | th_info() { echo "test:INFO $*" >&2; } 36 | th_warn() { echo "test:WARN $*" >&2; } 37 | th_error() { echo "test:ERROR $*" >&2; } 38 | th_fatal() { echo "test:FATAL $*" >&2; exit 1; } 39 | 40 | # Path to shFlags library. Can be overridden by setting SHFLAGS_INC. 41 | TH_SHFLAGS=${SHFLAGS_INC:-./shflags}; export TH_SHFLAGS 42 | 43 | # Path to shUnit2 library. Can be overridden by setting SHUNIT_INC. 44 | TH_SHUNIT=${SHUNIT_INC:-lib/shunit2}; export TH_SHUNIT 45 | 46 | TH_BOOL_VALID='true t 0 false f 1'; export TH_BOOL_VALID 47 | TH_BOOL_INVALID='123 123.0 invalid'; export TH_BOOL_INVALID 48 | TH_FLOAT_VALID='-1234.0 -1.0 -.123 0.0 0. .123 1.0 1234.0' 49 | export TH_FLOAT_VALID 50 | TH_FLOAT_INVALID='true false 1.2.3 -1.2.3 ""'; export TH_FLOAT_INVALID 51 | TH_INT_VALID='-1234 -1 0 1 1234'; export TH_INT_VALID 52 | TH_INT_INVALID='true false -1.0 -.123 0.0 .123 1.0 ""'; export TH_INT_INVALID 53 | 54 | # 55 | # Test helper functions. 56 | # 57 | 58 | th_oneTimeSetUp() { 59 | # Load shFlags. 60 | # shellcheck disable=SC2034 61 | [ -n "${ZSH_VERSION:-}" ] && FLAGS_PARENT=$0 62 | . "${TH_SHFLAGS}" 63 | 64 | # These files will be cleaned up automatically by shUnit2. 65 | tmpDir=${SHUNIT_TMPDIR}; export tmpDir 66 | stdoutF="${tmpDir}/stdout" && touch "${stdoutF}" 67 | stderrF="${tmpDir}/stderr" && touch "${stderrF}" 68 | returnF="${tmpDir}/return" && touch "${returnF}" 69 | expectedF="${tmpDir}/expected" && touch "${expectedF}" 70 | } 71 | 72 | th_showOutput() { 73 | if isSkipping; then 74 | return 75 | fi 76 | 77 | _th_return="${1:-${returnF}}" 78 | _th_stdout="${2:-${stdoutF}}" 79 | _th_stderr="${3:-${stderrF}}" 80 | 81 | if [ "${_th_return}" != "${FLAGS_TRUE}" ]; then 82 | # shellcheck disable=SC2166 83 | if [ -n "${_th_stdout}" -a -s "${_th_stdout}" ]; then 84 | echo '>>> STDOUT' >&2 85 | cat "${_th_stdout}" >&2 86 | echo '<<< STDOUT' >&2 87 | fi 88 | # shellcheck disable=SC2166 89 | if [ -n "${_th_stderr}" -a -s "${_th_stderr}" ]; then 90 | echo '>>> STDERR' >&2 91 | cat "${_th_stderr}" >&2 92 | echo '<<< STDERR' >&2 93 | fi 94 | fi 95 | 96 | unset _th_rtrn _th_stdout _th_stderr 97 | } 98 | 99 | # Some shells, zsh on Solaris in particular, return immediately from a sub-shell 100 | # when a non-zero return value is encountered. To properly catch these values, 101 | # they are either written to disk, or recognized as an error the file is empty. 102 | th_clearReturn() { cp /dev/null "${returnF}"; } 103 | th_queryReturn() { 104 | if [ -s "${returnF}" ]; then 105 | cat "${returnF}" 106 | return $? 107 | fi 108 | echo "${SHUNIT_ERROR}" 109 | return "${SHUNIT_ERROR}" 110 | } 111 | 112 | assertWarnMsg() { _th_assertMsg 'WARN' "${1:-}" "${2:-}"; } 113 | assertErrorMsg() { _th_assertMsg 'ERROR' "${1:-}" "${2:-}"; } 114 | assertFatalMsg() { _th_assertMsg 'FATAL' "${1:-}" "${2:-}"; } 115 | 116 | _th_assertMsg() { 117 | _th_alert_type_=$1 118 | _th_alert_msg_=$2 119 | _th_msg_=$3 120 | 121 | case ${_th_alert_type_} in 122 | WARN) _th_alert_str_='a warning' ;; 123 | ERROR) _th_alert_str_='an error' ;; 124 | FATAL) _th_alert_str_='a fatal' ;; 125 | esac 126 | if [ -z "${_th_alert_msg_}" ]; then 127 | _th_alert_msg_='.*' 128 | fi 129 | if [ -n "${_th_msg_}" ]; then 130 | _th_msg_="(${_th_msg_}) " 131 | fi 132 | 133 | (grep -- "^flags:${_th_alert_type_} ${_th_alert_msg_}" "${stderrF}" >/dev/null) 134 | assertEquals "FLAGS ${_th_msg_}failure did not generate ${_th_alert_str_} message" "${FLAGS_TRUE}" $? 135 | 136 | unset _th_alert_type_ _th_alert_msg_ _th_alert_str_ _th_msg_ 137 | } 138 | -------------------------------------------------------------------------------- /shflags/test_runner: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # Unit test suite runner. 5 | # 6 | # Copyright 2008-2020 Kate Ward. All Rights Reserved. 7 | # Released under the Apache 2.0 license. 8 | # 9 | # Author: kate.ward@forestent.com (Kate Ward) 10 | # https://github.com/kward/shlib 11 | # 12 | # This script runs all the unit tests that can be found, and generates a nice 13 | # report of the tests. 14 | # 15 | ### Sample usage: 16 | # 17 | # Run all tests for all shells. 18 | # $ ./test_runner 19 | # 20 | # Run all tests for single shell. 21 | # $ ./test_runner -s /bin/bash 22 | # 23 | # Run single test for all shells. 24 | # $ ./test_runner -t shunit_asserts_test.sh 25 | # 26 | # Run single test for single shell. 27 | # $ ./test_runner -s /bin/bash -t shunit_asserts_test.sh 28 | # 29 | ### ShellCheck (http://www.shellcheck.net/) 30 | # Disable source following. 31 | # shellcheck disable=SC1090,SC1091 32 | # expr may be antiquated, but it is the only solution in some cases. 33 | # shellcheck disable=SC2003 34 | # $() are not fully portable (POSIX != portable). 35 | # shellcheck disable=SC2006 36 | 37 | # Return if test_runner already loaded. 38 | [ -z "${RUNNER_LOADED:-}" ] || return 0 39 | RUNNER_LOADED=0 40 | 41 | RUNNER_ARGV0=`basename "$0"` 42 | RUNNER_SHELLS='/bin/sh ash /bin/bash /bin/dash /bin/ksh /bin/mksh /bin/zsh' 43 | RUNNER_TEST_SUFFIX='_test.sh' 44 | true; RUNNER_TRUE=$? 45 | false; RUNNER_FALSE=$? 46 | 47 | runner_warn() { echo "runner:WARN $*" >&2; } 48 | runner_error() { echo "runner:ERROR $*" >&2; } 49 | runner_fatal() { echo "runner:FATAL $*" >&2; exit 1; } 50 | 51 | runner_usage() { 52 | echo "usage: ${RUNNER_ARGV0} [-e key=val ...] [-s shell(s)] [-t test(s)]" 53 | } 54 | 55 | _runner_tests() { echo ./*${RUNNER_TEST_SUFFIX} |sed 's#\./##g'; } 56 | _runner_testName() { 57 | # shellcheck disable=SC1117 58 | _runner_testName_=`expr "${1:-}" : "\(.*\)${RUNNER_TEST_SUFFIX}"` 59 | if [ -n "${_runner_testName_}" ]; then 60 | echo "${_runner_testName_}" 61 | else 62 | echo 'unknown' 63 | fi 64 | unset _runner_testName_ 65 | } 66 | 67 | main() { 68 | # Find and load versions library. 69 | for _runner_dir_ in . ${LIB_DIR:-lib}; do 70 | if [ -r "${_runner_dir_}/versions" ]; then 71 | _runner_lib_dir_="${_runner_dir_}" 72 | break 73 | fi 74 | done 75 | [ -n "${_runner_lib_dir_}" ] || runner_fatal 'Unable to find versions library.' 76 | . "${_runner_lib_dir_}/versions" || runner_fatal 'Unable to load versions library.' 77 | unset _runner_dir_ _runner_lib_dir_ 78 | 79 | # Process command line flags. 80 | env='' 81 | while getopts 'e:hs:t:' opt; do 82 | case ${opt} in 83 | e) # set an environment variable 84 | key=`expr "${OPTARG}" : '\([^=]*\)='` 85 | val=`expr "${OPTARG}" : '[^=]*=\(.*\)'` 86 | # shellcheck disable=SC2166 87 | if [ -z "${key}" -o -z "${val}" ]; then 88 | runner_usage 89 | exit 1 90 | fi 91 | eval "${key}='${val}'" 92 | eval "export ${key}" 93 | env="${env:+${env} }${key}" 94 | ;; 95 | h) runner_usage; exit 0 ;; # help output 96 | s) shells=${OPTARG} ;; # list of shells to run 97 | t) tests=${OPTARG} ;; # list of tests to run 98 | *) runner_usage; exit 1 ;; 99 | esac 100 | done 101 | shift "`expr ${OPTIND} - 1`" 102 | 103 | # Fill shells and/or tests. 104 | shells=${shells:-${RUNNER_SHELLS}} 105 | [ -z "${tests}" ] && tests=`_runner_tests` 106 | 107 | # Error checking. 108 | if [ -z "${tests}" ]; then 109 | runner_error 'no tests found to run; exiting' 110 | exit 1 111 | fi 112 | 113 | cat <&1; ) 177 | shell_passing=$? 178 | if [ "${shell_passing}" -ne "${RUNNER_TRUE}" ]; then 179 | runner_warn "${shell_bin} not passing" 180 | fi 181 | test "${runner_passing_}" -eq ${RUNNER_TRUE} -a ${shell_passing} -eq ${RUNNER_TRUE} 182 | runner_passing_=$? 183 | done 184 | done 185 | return ${runner_passing_} 186 | } 187 | 188 | # Execute main() if this is run in standalone mode (i.e. not from a unit test). 189 | if [ -z "${SHUNIT_VERSION}" ]; then 190 | main "$@" 191 | fi 192 | --------------------------------------------------------------------------------