Commit 399c8a3b authored by cmosh's avatar cmosh

Merge branch 'release/npm'

npm
parents 07d11995 ee951439
# This is the top-most .editorconfig file; do not search in parent directories.
root = true
[*]
end_of_line = LF
insert_final_newline = true
trim_trailing_whitespace = true
[Changes.mdown]
indent_style = space
indent_size = 2
[*.mdown]
trim_trailing_whitespace = false
[{Makefile, makefile, GNUmakefile}]
indent_style = tab
indent_size = 4
debian/files
debian/*.substvars
debian/*.debhelper.log
debian/*/*
.timelog
.seconds
.seconds-feature-workingtime
.timelog-feature-workingtime
.seconds-feature-sdsa
.timelog-feature-sdsa
.seconds-feature-finish_fix
.timelog-feature-finish_fix
.seconds-feature-finish_fix
.timelog-feature-finish_fix
.seconds-feature-finish_fix
.timelog-feature-finish_fix
.seconds-feature-interrupt
.timelog-feature-interrupt
.seconds-feature-interrupt_final_test
.timelog-feature-interrupt_final_test
.breaktime-feature-interrupt_final_test
.seconds-feature-interrupt_final_test
.timelog-feature-interrupt_final_test
.breaktime-feature-interrupt_final_test
.seconds-feature-interrupt_final_test
.timelog-feature-interrupt_final_test
.breaktime-feature-interrupt_final_test
.seconds-feature-shortcuts
.timelog-feature-shortcuts
.breaktime-feature-shortcuts
.seconds-feature-test
.timelog-feature-test
.breaktime-feature-test
node_modules/*
\ No newline at end of file
[submodule "shFlags"]
path = shFlags
url = git://github.com/nvie/shFlags.git
#
# This list is used by git-shortlog to fix a few botched names in the
# git-flow repo, either because the author's full name was messed up and/or
# not always written the same way, making contributions from the same person
# appearing not to be so.
#
Eric Holmes <eric@ejholmes.net>
Eric J. Holmes <eric@ejholmes.net>
Stefan Näwe <stefan.naewe@atlas-elektronik.com>
Stefan Näwe <stefan.naewe+github@googlemail.com>
Authors are (ordered by first commit date):
git-flow AVH Authors
- Vincent Driessen
- Benedikt Böhm
- Daniel Truemper
- Jason L. Shiffer
- Randy Merrill
- Rick Osborne
- Mark Derricutt
- Nowell Strite
- Felipe Talavera
- Guillaume-Jean Herbiet
- Joseph A. Levin
- Jannis Leidel
- Konstantin Tjuterev
- Kiall Mac Innes
- Jon Bernard
- Olivier Mengué
- Emre Berge Ergenekon
- Eric Holmes
- Vedang Manerikar
- Myke Hines
This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
(Changes.mdown) and logs, available at
http://github.com/petervanderdoes/gitflow.
Portions derived from other open source works are clearly marked.
Peter van der Does
Vincent Driessen
Daniel Dehennin
Benedikt Böhm
Leonid Komarovsky
Felipe Talavera
Randy Merrill
Kevin Woo
Daniel Truemper
Eric J. Holmes
Fred Condo
Alexandre Dutra
Ben Loveridge
Florian Gamböck
Gergely Nagy
JP Toto
Kiall Mac Innes
Lorin Hochstein
Olivier Mengué
Stefan Näwe
Adam Gibbins
Alexander Groß
Alexander Norström
Alexander Zeitler
Brian St. Pierre
Cararus Eugeniu
Chad Walker
Craig Fowler
Emre Berge Ergenekon
Gregor A. Cieslak
Gruen Christian-Rolf (Kiki)
Guillaume-Jean Herbiet
James Moran
Jannis Leidel
Jason L. Shiffer
Jean Jordaan
Jelte Fennema
Joe Ebmeier
John Sivak
Jon Bernard
Joseph A. Levin
Joshua P. Tilles
Juan Rial
Justin Penney
Konstantin Tjuterev
Kridsada Thanabulpong
Leonardo Giordani
Mark Borcherding
Mark Derricutt
Mateusz Kaczmarek
Matias Hernan Lauriti
Nowell Strite
Opher Vishnia
Peter Schröder
Stefan Schüßler
Steffen Jaeckel
Steve Streeting
Tacit Sawk
Vedang Manerikar
eddie cianci
gmallard
raybec
Portions of the project are derived from other open source works are clearly
marked.
This file is auto generated, any changes will be lost.
0.4.2:
-----
Release date: **not yet**
[petervanderdoes]: https://github.com/petervanderdoes "Peter van der Does on github"
[bloveridge]: https://github.com/bloveridge "Ben Loveridge on github"
[memleak]: https://github.com/memleak/
[sinbad]: https://github.com/sinbad
[bloomonkey]: https://github.com/bloomonkey
[mallamanis]: https://github.com/mallamanis
[kperi]: https://github.com/kperi
[gvangool]: https://github.com/gvangool
[baby-gnu]: https://github.com/baby-gnu
[pcragone]: https://github.com/pcragone
[mykehsd]: https://github.com/mykehsd
[jeromebaum]: https://github.com/jeromebaum
[adutra]: https://github.com/adutra
[floga]: https://github.com/FloGa
[merelyapseudonym]: https://github.com/MerelyAPseudonym
[shpoont]: https://github.com/shpoont
[cyberbob]: https://github.com/cyberbob
[shpoont]: https://github.com/shpoont
[jsivak]: https://github.com/jsivak
[OpherV]: https://github.com/OpherV
[craigfowler]: https://github.com/craigfowler
[havvg]: https://github.com/havvg
[algernon]: https://github.com/algernon
[jebmeier]: https://github.com/jebmeier
[aleno]: https://github.com/aleno
[sirn]: https://github.com/sirn
[jpenney78]: https://github.com/jpenney78
# Changelog
#### 1.11.0-dev.1
* Preparation for new development cycle.
#### 1.10.2
[Peter van der Does][petervanderdoes]
* Bugfix: Error finishing a release.
#### 1.10.1
[Peter van der Does][petervanderdoes]
* Bugfix: flag short name (p) already defined
#### 1.10.0
[Peter van der Does][petervanderdoes]
* Update github links.
* Add explanation of AVH.
* Add ability when finishing a release to push or not push the branches and/or tag involved.
* The finishing of a release branch based on a branch other than develop fails with errors.
* Add --push flag for feature finish. This gives the ability to push the base branch after the finish.
* When finishing a release have the ability to fast-forward the master branch, if possible.
This is controlled by the flag --ff-master.
* Add new flag -T, --tagname to override the tag name when finishing a release or hotfix.
* Allow multiple hotfix branches by setting the config allowmultihotfix to true.
The command to set it is
[Kridsada Thanabulpong][sirn]
* Fix infinite loop during Darwin link resolving.
[Justin Penney][jpenney78]
* Add detection for BusyBox getopt.
#### 1.9.1
[Peter van der Does][petervanderdoes]
* Bugfix: git-flow directories are not set correctly
#### 1.9.0
[Peter van der Does][petervanderdoes]
* Add bugfix command.
* Repositories with spaces in path cause the pre * post hook to fail.
* Error using git flow log.
* Using defaults with init fails with existing repository.
* Allow multiple hotfix branches.
By setting the config gitflow.multi-hotfix to true, you can have multiple
hotfix branches. Example: git config --set gitflow.multi-hotfix true
* Can't delete branch if the base branch is not the develop branch.
* Add squash and squash-info flag to hotfix finish.
* Problem when the repository directory has multiple spaces.
[Gergely Nagy][algernon]
* Remove bash code.
[Joe Ebmeier][jebmeier]
* Fix issue in case CDPATH is being used.
In the case of CDPATH being used, it is possible DOT_GIT_DIR variable
is incorrect.
[Alexander Norström][aleno]
* Fix issue when a prefix is chosen that doesn't end in a slash
#### 1.8.0
[Peter van der Does][petervanderdoes]
* Add rebase action to release, hotfix and support.
* Shortcut for rebase commands.
Introduce the following new command:
* git flow rebase
This command will perform the action on the branch that's currently active.
* Use the base branch when doing a git flow feature diff.
When doing a diff on the feature branch use the base branch which this
feature originated from. It will show the committed changes.
* Problem when certain variables are set before executing git-flow.
When certain variables are set in the shell environment it causes problems.
* Warning for commands to be deprecated.
The command "feature checkout/co" will be deprecated per version 2.0.0
The command "feature pull" will be deprecated per version 2.0.0
* Using fetch flag fails sometimes.
* Hooks and filters are not executed when you are in a subdirectory of the
repository and the hooks directory is set to the suggested value during
initialization.
[Craig Fowler][craigfowler]
* 'export' fails in 'gitflow_load_settings()'
[Toni Uebernickel][havvg]
* Add log command
#### 1.7.0
[Peter van der Does][petervanderdoes]
* Refactor the gitflow override flag functions.
* Shortcut for finish, delete, and publish commands.
Introduce the following new commands:
* git flow finish
* git flow delete
* git flow publish
These commands will perform the action on the branch that's currently active.
* No branch is needed for the following function:
* git flow feature publish/finish/delete
* git flow release publish/finish/delete
* git flow hotfix publish/finish/delete
* Remove base configuration when deleting a feature/hotfix/release branch.
* Help text for certain commands is wrong.
* Bugfix: Invalid function call.
* Bugfix: No make installer fails
* Support branches are no longer marked as experimental.
[John Sivak][jsivak]
* Fix sanity check for release track command.
[Opher Vishnia][OpherV]
* Fix feature pull.
The pull request fails when there's no local branch with the same name as the
remote branch.
[Leonid Komarovsky][shpoont]
* Option for global hooks and filters directory.
This is only for hooks and filters related to git-flow, not the standard git
hooks.
#### 1.6.1
[Peter van der Does][petervanderdoes]
* Migration of gitflow_config fails for posix sh.
* Error messages when .gitflow_export doesn't exists.
#### 1.6.0
[Peter van der Does][petervanderdoes]
* Add ability to short-circuit the version filters.
An exit of 127 will short-circuit the process.
* Output when finishing a branch is wrong.
[Mateusz Kaczmarek][cyberbob]
* Fix sanity check for feature track command.
[Leonid Komarovsky][shpoont]
* Move configuration from ~/.gitflow_export to default git config.
* Move base configuration from it's own configuration file to the default local git config file.
* Improve formatting of the help.
#### 1.5.3
[Peter van der Does][petervanderdoes]
* Bugfix: Error about deleting branch when using squash option.
When using the squash option for release/feature finish, the release/feature
branch is not deleted.
#### 1.5.2
[Peter van der Does][petervanderdoes]
* Add filter for tag message .
If a tag message is given, the message can be modified using the filters:
- filter-flow-hotfix-finish-tag-message
- filter-flow-release-finish-tag-message
- filter-flow-release-branch-tag-message
* Bugfix: Typo in documentation.
[Florian Gamböck][floga]
* Bugfix: Fix variable name in hotfix
[Leonid Komarovsky][shpoont]
* git flow rebase will rebase against its base branch instead of develop.
* Add flag --preserve-merges for feature rebase or feature finish.
#### 1.5.1
[Peter van der Does][petervanderdoes]
* Fix some of the flag override environment variable names.
[Joshua P. Tilles][merelyapseudonym]
* Add default flag for flag showcommands.
[Florian Gamböck][floga]
* Bugfix: Fix variable non-zero test
Due to missing quotation marks, the -n test won't work properly, leading to
always returning true and overriding variables with nothing.
#### 1.5.0
[Peter van der Does][petervanderdoes]
* Add the ability to set defaults for flag.
You can now set defaults for flags by setting environment variables.
* Add flag no-ff to feature finish.
This gives the ability to never fast-forward a merge, even when it's only
one commit.
* Bugfix: Error in a long flag name for release finish
* Function in gitflow-shFlags refactored to make it faster.
* Add flag --squash-info to release/feature finish.
When you use the flag --squash while finishing a release or feature branch,
the logs don't make it clear which branch you merged. The new flag will add
an extra comment to the commit message, stating which branch was used for the
merge.
* Bugfix: The contrib gitflow-installer.sh shows wrong installation instructions.
#### 1.4.2
* Bugfix: Update from upstream for shFlags
#### 1.4.1
* Bugfix: Missed quotation mark
#### 1.4.0
[Peter van der Does][petervanderdoes]
* Remember the base.
With the commands feature/hotfix/release start you can give a base from which
the new branch will be created. Upon finishing this branch it will
automatically merge the branch back into the base as given during the start.
If no base is given the normal functionality will be followed.
With the hotfix and release, if a base is given and it's not the
DEVELOP_BRANCH, the branch will *NOT* be merged back into the $DEVELOP_BRANCH
upon finishing this branch.
* New config command.
git flow config base. This can be used to set and get the base for
feature/hotfix/release branches so it can be used when finishing these
branches.
* Get the correct working directory when the git-flow file is a symbolic link.
* Don't check/compare hotfix and base branch when branch is merged already.
* Remove export POSIXLY_CORRECT.
Setting this environment variable can mess things up when git-flow is used in
combination with other shell scripts.
* Update gitflow-shFlags from upstream.
Besides other improvements this update eliminates the use of external system
calls on a majority of systems which in theory leads to a speed increase of
about 20%.
* Use GNU getopt on BSD systems.
BSD getopt doesn't support long options in commands but the GNU getopt does.
[Alexandre Dutra][adutra]
* Git refuses to delete local branch with "-d" if it is tracking a remote one.
* Can't always delete current release/hotfix local branch on finish
Situation can occur you are on the local branch the script wants to delete, if
you are you can't delete that branch. We'll switch to the base branch when
you are deleting the branch you currently are on.
#### 1.3.1
* Bugix: git flow config list results in error.
#### 1.3.0
[Peter van der Does][petervanderdoes]
* Make name in feature publish optional.
Instead of always having to add the branch when doing a git flow feature
publish, the name should be optional.
When a name isn't given, the current branch, if it's a feature branch,
will be published.
* Add option to select configuration file usage
As with the regular git config, git flow init now has the
option --file, --global, --system and --local. --local is default.
* Add a new command.
New command git flow config is added.
With this command you can see your current git flow configuration and you
can also set the options.
* Environment settings for git-flow only.
With git you can set environment variables to change behavior, like
GIT_MERGE_AUTOEDIT for example.
You can add these exports to the file ~/.gitflow_export if you only want
to set the environment variable for git-flow.
* Bugfix: Missing command hotfix track.
The command git flow hotfix track is not implemented.
#### 1.2.1
[Peter van der Does][petervanderdoes]
* Bugfix: The --showcommands was on by default. It should be off by default.
#### 1.2.0
[Peter van der Does][petervanderdoes]
* Improve the help output of the commands.
* Fix problem with init function on BSD systems.
* Add initialize function to git flow version.
* Add parameter --showcommands to all commands.
This will show the git commands performed while executing the command. Thanks
to [Jerome Baum][jeromebaum] for the original implementation.
[Daniel Dehennin][baby-gnu]
* Display where user is on finish.
Some commands did not display the branch you are on after the command
finished.
* When finishing a hotfix/release and it's to be tagged, the tag must not exist.
#### 1.1.0
[Peter van der Does][petervanderdoes]
* Bugfix: feature finish does double merge when using squash option.
* Add the ability to keep/delete local/remote branches on finish.
When finishing a release/hotfix/feature you now can keep/delete the
local/remote release/hotfix/feature branch.
* New command: git flow release branch
With this command you can directly release a given branch. There is no need
to start a new release and finish it. You can not use this command on the
git-flow branches feature/hotfix/release/support.
* Do not display object fetch summary if flag was not set.
Thanks to [Daniel Dehennin][baby-gnu].
* Bugfix: Checking if branch exists will fail for remote branches.
* Make die output consistent for each die case.
* Bugfix: When running git flow init an error message pops up.
* Show correct help for subactions.
When requesting help with -h for the subactions, the help would show the
incorrect command line.
* Support reading the tag message from a file in release/hotfix finish.
Add the option -f,--messagefile to release and hotfix finish. Thanks to
[Steve Streeting][sinbad] for the original coding.
* Bugfix: git_current_branch fails for git prior 1.7.10.
git symbolic-ref does not have the --short option prior to version 1.7.10.
Bug found by [Daniel Dehennin][baby-gnu].
* Clean up code.
Remove all porcelain commands.
Refactor code.
* Improve the back-merge functionality.
Adds an command line option (-b), which the user can utilize if the user
doesn't want to back-merge but rather merge the release branch into
develop.
* Add the sub-action delete to sub-commands feature, release and hotfix.
The sub-commands feature, release and hotfix now have a new sub-action,
delete. With that action you can delete the branches, locally and remote.
The action has two options, -f and -r. With -f you can force the deletion,
even when the to be deleted branch was not merged yet. With -r the remote
branch will also be deleted.
[Daniel Dehennin][baby-gnu]
* Bugfix: release/feature/hotfix start -F fails.
Usage of positional parameters requires to eval ${FLAGS_ARGV}. The "eval set"
in function call does not propagate to the caller.
* Accept tags as base for hotfix/release/support start.
Commit pointed by tags are reachable with ^0\[1\].
* Check for parameter existence for branch and tag existence helpers.
* Do not finish hotfixes if they have no commits.
A hotfix branch must have some commits and be ahead of master.
* Bugfix: When running git flow version an error message pops up.
* Reorder fetch and sanity checks.
When a user requests a fetch for git flow {feature|hotfix|support} start, do
this before some sanity checks to avoid any conflict in branch names
and/or version.
* Fix flag test in cmd_delete().
[Myke Hines][mykehsd]
* Feature and Release squashing options.
This allows a -S option to both feature and releasing finishing actions so
that developers can squash commits into one large one.
[Peter Ragone][pcragone]
* Add init to git-flow-{feature,release,hotfix,support}.
Fixes the relatively minor issue where 'git flow subcommand help'
gives "Not a gitflow-enabled repo yet".
* Special thanks to the following individual:
[Gert Van Gool][gvangool]
#### 1.0-avh
[Peter van der Does][petervanderdoes]
* Remove trailing whitespace.
* Updated from latest develop branch from nvie.
Some features were still missing.
* Remove the submodule shFlags.
Instead of the submodule we'll just use the file.
* When finishing a release or hotfix, use tag for back-merging if available.
When a release or hotfix branch is tagged, the tag is never merged into the
develop branch, it is preferable to have the tag in the develop branch as
well, for use with git describe for example.
* Update license info.
* Bugfix: Typo when pulling existing feature from remote.Thanks to [John Harrison][bloomonkey], [Miltos][mallamanis], [Kostas][kperi] and [memleak][memleak].
* Wrong variable names in the bare-bones.
The wrong variable name is set, this can lead to confusing on what's
passed to the script,
[Steve Streeting][sinbad]
* Fixes the suggested name for the integration branch.
When git init -d is executed on a repo with multiple branches, the
suggested name for the integration branch could possibly be the same name
that was already selected for the production release branch.
If no suggested name is determined the suggested name remains empty which
leads to all sorts of other problems.
#### 0.4.2-avh1
[Peter van der Does][petervanderdoes]
* Start of the git flow AVH release.
* Adds support for the version filter in the commands `git flow release start`
and `git flow hotfix start`
* Adds support for hooks in various commands.
[Ben Loveridge][bloveridge]
* Fix usage of shFlags on FreeBSD
#### 0.4.2
Release date: not yet
* `git flow init` now detects situations where origin already has gitflow
branches set up, and behaves accordingly (thanks Emre Berge Ergenekon).
......@@ -19,8 +451,7 @@ Release date: **not yet**
* Add package installer for the Windows platform.
0.4.1:
-----
#### 0.4.1
Release date: **2011/02/04**
* New option `-d` added to `git flow init`, to initialize with defaults without
......@@ -33,8 +464,7 @@ Release date: **2011/02/04**
* Escape queries for detecting branch/tag names. (Fixed #91)
0.4:
---
#### 0.4
Release date: **2010/10/18**
* The flag parsing issues of git-flow subcommands are solved for most
......@@ -51,8 +481,7 @@ Release date: **2010/10/18**
* Various minor fixes.
0.3:
----
#### 0.3
Release date: **2010/07/22**
* New subcommands for `git flow feature`:
......@@ -97,7 +526,9 @@ Release date: **2010/07/22**
[2]: http://github.com/talios
[3]: http://github.com/rickosborne
Older versions
--------------
#####Older versions
No change history is recorded for pre-0.3 releases.
#### Glossary
* RFC: Request For Change. This indicates a new or improved function requested
by one or more users.
This software is forked of the original git-flow, see License #2.
License #1 is added to reflect the changes made.
gitflow-shFlags is released under LGPL, see License #3
************************************************************
LICENSE #1:
Copyright (c) 2012-2015 Peter van der Does
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************
LICENSE #2:
Copyright 2010 Vincent Driessen. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
......@@ -24,3 +58,509 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Vincent Driessen.
************************************************************
LICENSE #3:
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
\ No newline at end of file
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of Vincent Driessen.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
prefix=/usr/local
datarootdir=$(prefix)/share
docdir=$(datarootdir)/doc/gitflow
# files that need mode 755
EXEC_FILES=git-flow
# files that need mode 644
SCRIPT_FILES =git-flow-init
SCRIPT_FILES+=git-flow-feature
SCRIPT_FILES+=git-flow-bugfix
SCRIPT_FILES+=git-flow-hotfix
SCRIPT_FILES+=git-flow-release
SCRIPT_FILES+=git-flow-support
SCRIPT_FILES+=git-flow-version
SCRIPT_FILES+=git-flow-log
SCRIPT_FILES+=git-flow-config
SCRIPT_FILES+=gitflow-common
SCRIPT_FILES+=gitflow-shFlags
# Hook files
HOOK_FILES=$(wildcard hooks/*)
all:
@echo "usage: make install"
@echo " make uninstall"
install:
@test -f gitflow-shFlags || (echo "Run 'git submodule init && git submodule update' first." ; exit 1 )
install -d -m 0755 $(prefix)/bin
install -d -m 0755 $(docdir)/hooks
install -m 0755 $(EXEC_FILES) $(prefix)/bin
install -m 0644 $(SCRIPT_FILES) $(prefix)/bin
install -m 0644 $(HOOK_FILES) $(docdir)/hooks
uninstall:
test -d $(prefix)/bin && \
cd $(prefix)/bin && \
rm -f $(EXEC_FILES) $(SCRIPT_FILES)
test -d $(docdir) && \
rm -rf $(docdir)
# git-flow (AVH Edition)
A collection of Git extensions to provide high-level repository operations
for Vincent Driessen's [branching model](http://nvie.com/git-model "original
blog post"). This fork adds functionality not added to the original branch.
## Getting started
For the best introduction to get started with `git flow`, please read Jeff
Kreeftmeijer's blog post:
[http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/](http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/)
Or have a look at one of these screen casts:
* [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)
* [A short introduction to git-flow](http://vimeo.com/16018419) (by Mark Derricutt)
* [On the path with git-flow](https://vimeo.com/codesherpas/on-the-path-gitflow) (by Dave Bock)
A quick cheatsheet was made by Daniel Kummer:
[http://danielkummer.github.io/git-flow-cheatsheet/](http://danielkummer.github.io/git-flow-cheatsheet/)
## Installing git-flow
See the Wiki for up-to-date [Installation Instructions](https://github.com/petervanderdoes/gitflow-avh/wiki/Installation).
## Integration with your shell
For those who use the [Bash](http://www.gnu.org/software/bash/) or [ZSH](http://www.zsh.org)
shell, you can use my [fork of git-flow-completion](https://github.com/petervanderdoes/git-flow-completion)
which includes several additions for git-flow (AVH Edition), or you can use the
original [git-flow-completion](http://github.com/bobthecow/git-flow-completion)
project by [bobthecow](http://github.com/bobthecow). Both offer tab-completion
for git-flow subcommands and branch names with my fork including tab-completion
for the commands not found in the original git-flow.
## FAQ
* See the [FAQ](http://github.com/petervanderdoes/gitflow-avh/wiki/FAQ) section
of the project Wiki.
* Version Numbering Scheme.
Starting with version 1.0, the project uses the following scheme:
\<MAJOR\>.\<MINOR\>.\<REVISION\>\
* AVH is the acronym of "A VirtualHome"
## Please help out
This project is under constant development. Feedback and suggestions are very
welcome and I encourage you to use the [Issues
list](http://github.com/petervanderdoes/gitflow-avh/issues) on Github to provide that
feedback.
Feel free to fork this repository and to commit your additions. For a list of
all contributors, please see the [AUTHORS](AUTHORS) file.
Any questions, tips, or general discussion can be posted to the Google group:
[http://groups.google.com/group/gitflow-users](http://groups.google.com/group/gitflow-users)
This is the original group set up to support the nvie branch, but I am monitoring
the list as well for any questions related to my version.
When you do post a question on the list please indicate which version you are,
using the complete version number.
## Contributing
Fork the repository. Then, run:
```shell
git clone -b master git@github.com:<username>/gitflow-avh.git
cd gitflow-avh
```
The `-b master` switch has to be added since the fork operation automatically
clones the `develop` branch of the official gitflow repository and cloning it
results in a local repository with just a `develop` branch.
If you do not have gitflow installed yet install it by running `make && make install`.
After that initialize the local gitflow repository with gitflow itself:
```shell
git flow init -d
git flow feature start <your feature>
```
Then, do work and commit your changes.
```shell
git flow feature publish <your feature>
```
When done, open a pull request to your feature branch.
## License terms
git-flow is published under the FreeBSD License, see the
[LICENSE](LICENSE) file. Although the FreeBSD License does not require you to
share any modifications you make to the source code, you are very much
encouraged and invited to contribute back your modifications to the community,
preferably in a Github fork, of course.
## git flow usage
### Initialization
To initialize a new repo with the basic branch structure, use:
git flow init [-d]
This will then interactively prompt you with some questions on which branches
you would like to use as development and production branches, and how you
would like your prefixes be named. You may simply press Return on any of
those questions to accept the (sane) default suggestions.
The ``-d`` flag will accept all defaults.
![Screencast git flow init](http://i.imgur.com/lFQbY5V.gif)
### Creating feature/release/hotfix/support branches
* To list/start/finish/delete feature branches, use:
git flow feature
git flow feature start <name> [<base>]
git flow feature finish <name>
git flow feature delete <name>
For feature branches, the `<base>` arg must be a branch, when omitted it defaults to the develop branch.
* To push/pull a feature branch to the remote repository, use:
git flow feature publish <name>
git flow feature track <name>
* To list/start/finish/delete release branches, use:
git flow release
git flow release start <release> [<base>]
git flow release finish <release>
git flow release delete <release>
For release branches, the `<base>` arg must be a branch, when omitted it defaults to the develop branch.
* To list/start/finish/delete hotfix branches, use:
git flow hotfix
git flow hotfix start <release> [<base>]
git flow hotfix finish <release>
git flow hotfix delete <release>
For hotfix branches, the `<base>` arg must be a branch, when omitted it defaults to the production branch.
* To list/start support branches, use:
git flow support
git flow support start <release> <base>
For support branches, the `<base>` arg must be a branch, when omitted it defaults to the production branch.
### Share features with others
You can easily publish a feature you are working on. The reason can be to allow other programmers to work on it or to access it from another machine. The publish/track feature of gitflow simplify the creation of a remote branch and its tracking.
When you want to publish a feature just use:
git flow feature publish <name>
or, if you already are into the `feature/<name>` branch, just issue:
git flow feature publish
Now if you execute `git branch -avv` you will see that your branch `feature/<name>` tracks `[origin/feature/<name>]`. To track the same remote branch in another clone of the same repository use:
git flow feature track <name>
This will create a local feature `feature/<name>` that tracks the same remote branch as the original one, that is `origin/feature/<name>`.
When one developer (depending on your work flow) finishes working on the feature he or she can issue `git flow feature finish <name>` and this will automatically delete the remote branch. All other developers shall then run:
git flow feature delete <name>
to get rid of the local feature that tracks a remote branch that no more exist.
### Using Hooks and Filters
For a wide variety of commands hooks or filters can be called before and after
the command.
The files should be placed in .git/hooks
In the directory hooks you can find examples of all the hooks available.
## Showing your appreciation
Of course, the best way to show your appreciation for the git-flow tool itself
remains contributing to the community. If you'd like to show your appreciation
in another way, however, consider donating through PayPal:
[![PayPal][2]][1]
[1]: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=S85FXJ9EBHAF2&lc=US&item_name=gitflow&item_number=gitflow&no_note=0&cn=Add%20special%20instructions%20to%20the%20seller&no_shipping=1&rm=1&return=https%3a%2f%2fgithub%2ecom%2fpetervanderdoes%2fgitflow&cancel_return=https%3a%2f%2fgithub%2ecom%2fpetervanderdoes%2fgitflow&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted
[2]: https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif
git-flow
========
# git-flow (Dreidev Edition)
A collection of Git extensions to provide high-level repository operations
for Vincent Driessen's [branching model](http://nvie.com/git-model "original
blog post").
blog post"). This fork adds functionality not added to the original branch.
Getting started
---------------
## Getting started
For the best introduction to get started with `git flow`, please read Jeff
Kreeftmeijer's blog post:
......@@ -17,68 +16,56 @@ Or have a look at one of these screen casts:
* [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)
* [A short introduction to git-flow](http://vimeo.com/16018419) (by Mark Derricutt)
* [On the path with git-flow](http://codesherpas.com/screencasts/on_the_path_gitflow.mov) (by Dave Bock)
* [On the path with git-flow](https://vimeo.com/codesherpas/on-the-path-gitflow) (by Dave Bock)
Installing git-flow
-------------------
See the Wiki for up-to-date [Installation Instructions](https://github.com/nvie/gitflow/wiki/Installation).
A quick cheatsheet was made by Daniel Kummer:
[http://danielkummer.github.io/git-flow-cheatsheet/](http://danielkummer.github.io/git-flow-cheatsheet/)
Integration with your shell
---------------------------
For those who use the [Bash](http://www.gnu.org/software/bash/) or
[ZSH](http://www.zsh.org) shell, please check out the excellent work on the
[git-flow-completion](http://github.com/bobthecow/git-flow-completion) project
by [bobthecow](http://github.com/bobthecow). It offers tab-completion for all
git-flow subcommands and branch names.
## Installing git-flow
npm -i gitflow (Mac and Linux users only)
FAQ
---
See the [FAQ](http://github.com/nvie/gitflow/wiki/FAQ) section of the project
Wiki.
## Contributing
Fork the repository. Then, run:
Please help out
---------------
This project is still under development. Feedback and suggestions are very
welcome and I encourage you to use the [Issues
list](http://github.com/nvie/gitflow/issues) on Github to provide that
feedback.
```shell
git clone -b master git@github.com:<username>/gitflow.git
cd gitflow
```
Feel free to fork this repo and to commit your additions. For a list of all
contributors, please see the [AUTHORS](AUTHORS) file.
The `-b master` switch has to be added since the fork operation automatically
clones the `develop` branch of the official gitflow repository and cloning it
results in a local repository with just a `develop` branch.
Any questions, tips, or general discussion can be posted to our Google group:
[http://groups.google.com/group/gitflow-users](http://groups.google.com/group/gitflow-users)
If you do not have gitflow installed yet install it by running `make && make install`.
Contributing
------------
Fork the repository. Then, run:
After that initialize the local gitflow repository with gitflow itself:
git clone --recursive git@github.com:<username>/gitflow.git
cd gitflow
git branch master origin/master
git flow init -d
git flow feature start <your feature>
```shell
git flow init -d
git flow feature start <your feature>
```
Then, do work and commit your changes. **Hint**: ``export PATH=`pwd`:$PATH``
from within the gitflow directory makes sure you're using the version of
gitflow you're currently developing.
Then, do work and commit your changes.
git flow feature publish <your feature>
```shell
git flow feature publish <your feature>
```
When done, open a pull request to your feature branch.
License terms
-------------
git-flow is published under the liberal terms of the BSD License, see the
[LICENSE](LICENSE) file. Although the BSD License does not require you to share
any modifications you make to the source code, you are very much encouraged and
invited to contribute back your modifications to the community, preferably
in a Github fork, of course.
## License terms
git-flow is published under the FreeBSD License, see the
[LICENSE](LICENSE) file. Although the FreeBSD License does not require you to
share any modifications you make to the source code, you are very much
encouraged and invited to contribute back your modifications to the community,
preferably in a Github fork, of course.
## git flow usage
### Initialization
......@@ -93,56 +80,89 @@ those questions to accept the (sane) default suggestions.
The ``-d`` flag will accept all defaults.
![Screencast git flow init](http://i.imgur.com/lFQbY5V.gif)
### Creating feature/release/hotfix/support branches
* To list/start/finish feature branches, use:
* To list/start/finish/delete feature branches, use:
git flow feature
git flow feature start <name> [<base>]
git flow feature finish <name>
* Note, if installed via npm the 'git' can be dropped from every command.
For feature branches, the `<base>` arg must be a commit on `develop`.
git flow feature (flow)
git flow feature start <name> [<base>] (flow feature start/flow start/git start)
git flow feature pause (flow feature pause/flow pause/git pause)
git flow feature interrupt (flow feature interrupt/flow interrupt/git interrupt)
git flow feature resume <name> (flow feature resume/flow resume/git resume)
git flow feature finish <name> (flow feature finish/flow finish/git finish)
git flow feature delete <name> (flow feature delete/flow delete/git delete)
For feature branches, the `<base>` arg must be a branch, when omitted it defaults to the develop branch.
* To push/pull a feature branch to the remote repository, use:
git flow feature publish <name>
git flow feature pull <remote> <name>
git flow feature publish <name> (flow feature publish/flow publish/git publish)
git flow feature review <name> (flow feature resume/flow review/git review)
git flow feature track <name> (flow feature resume/flow review/git review)
* To list/start/finish/delete release branches, use:
* To list/start/finish release branches, use:
* Note, if installed via npm the 'git' can be dropped from every command.
git flow release
git flow release start <release> [<base>]
git flow release finish <release>
git flow release delete <release>
For release branches, the `<base>` arg must be a commit on `develop`.
For release branches, the `<base>` arg must be a branch, when omitted it defaults to the develop branch.
* To list/start/finish hotfix branches, use:
* To list/start/finish/delete hotfix branches, use:
git flow hotfix
git flow hotfix start <release> [<base>]
git flow hotfix finish <release>
git flow hotfix delete <release>
For hotfix branches, the `<base>` arg must be a commit on `master`.
For hotfix branches, the `<base>` arg must be a branch, when omitted it defaults to the production branch.
* To list/start support branches, use:
git flow support
git flow support start <release> <base>
For support branches, the `<base>` arg must be a commit on `master`.
For support branches, the `<base>` arg must be a branch, when omitted it defaults to the production branch.
### Share features with others
You can easily publish a feature you are working on. The reason can be to allow other programmers to work on it or to access it from another machine. The publish/track feature of gitflow simplify the creation of a remote branch and its tracking.
When you want to publish a feature just use:
git flow feature publish <name>
or, if you already are into the `feature/<name>` branch, just issue:
git flow feature publish
Now if you execute `git branch -avv` you will see that your branch `feature/<name>` tracks `[origin/feature/<name>]`. To track the same remote branch in another clone of the same repository use:
git flow feature track <name>
This will create a local feature `feature/<name>` that tracks the same remote branch as the original one, that is `origin/feature/<name>`.
When one developer (depending on your work flow) finishes working on the feature he or she can issue `git flow feature finish <name>` and this will automatically delete the remote branch. All other developers shall then run:
git flow feature delete <name>
to get rid of the local feature that tracks a remote branch that no more exist.
Showing your appreciation
=========================
A few people already requested it, so now it's here: a Flattr button.
### Using Hooks and Filters
Of course, the best way to show your appreciation for the original
[blog post](http://nvie.com/posts/a-successful-git-branching-model/) or the git-flow tool itself remains
contributing to the community. If you'd like to show your appreciation in
another way, however, consider Flattr'ing me:
For a wide variety of commands hooks or filters can be called before and after
the command.
The files should be placed in .git/hooks
In the directory hooks you can find examples of all the hooks available.
[![Flattr this][2]][1]
## Showing your appreciation
[1]: http://flattr.com/thing/53771/git-flow
[2]: http://api.flattr.com/button/button-static-50x60.png
Of course, the best way to show your appreciation for the git-flow tool itself
remains contributing to the community.
\ No newline at end of file
#!/bin/sh
usage() {
echo "usage: bump-version <version-id>"
}
if [ $# -ne 1 ]; then
usage
exit 1
fi
if ! sed 's/^GITFLOW_VERSION=.*$/GITFLOW_VERSION='$1'/g' git-flow-version > .git-flow-version.new; then
echo "Could not replace GITFLOW_VERSION variable." >&2
exit 2
fi
mv .git-flow-version.new git-flow-version
git add git-flow-version
git commit -m "Bumped version number to $1" git-flow-version
......@@ -2,14 +2,25 @@
# git-flow make-less installer for *nix systems, by Rick Osborne
# Based on the git-flow core Makefile:
# http://github.com/nvie/gitflow/blob/master/Makefile
# http://github.com/petervanderdoes/gitflow-avh/blob/master/Makefile
# Licensed under the same restrictions as git-flow:
# http://github.com/nvie/gitflow/blob/develop/LICENSE
# http://github.com/petervanderdoes/gitflow-avh/blob/develop/LICENSE
# Updated for the fork at petervanderdoes
usage() {
echo "Usage: [environment] gitflow-installer.sh [install|uninstall] [stable|develop]"
echo "Environment:"
echo " PREFIX=$PREFIX"
echo " REPO_HOME=$REPO_HOME"
echo " REPO_NAME=$REPO_NAME"
exit 1
}
# Does this need to be smarter for each host OS?
if [ -z "$INSTALL_PREFIX" ] ; then
INSTALL_PREFIX="/usr/local/bin"
if [ -z "$PREFIX" ] ; then
PREFIX="/usr/local"
fi
if [ -z "$REPO_NAME" ] ; then
......@@ -17,62 +28,85 @@ if [ -z "$REPO_NAME" ] ; then
fi
if [ -z "$REPO_HOME" ] ; then
REPO_HOME="http://github.com/nvie/gitflow.git"
REPO_HOME="https://github.com/dreidev/gitflow.git"
fi
EXEC_PREFIX="$PREFIX"
BINDIR="$EXEC_PREFIX/bin"
DATAROOTDIR="$PREFIX/share"
DOCDIR="$DATAROOTDIR/doc/gitflow"
EXEC_FILES="git-flow"
SCRIPT_FILES="git-flow-init git-flow-feature git-flow-hotfix git-flow-release git-flow-support git-flow-version gitflow-common gitflow-shFlags"
SUBMODULE_FILE="gitflow-shFlags"
SCRIPT_FILES="git-flow-init git-flow-feature git-flow-bugfix git-flow-hotfix git-flow-release git-flow-support git-flow-version gitflow-common gitflow-shFlags git-flow-config"
HOOK_FILES="$REPO_NAME/hooks/*"
echo "### gitflow no-make installer ###"
echo "### git-flow no-make installer ###"
case "$1" in
uninstall)
echo "Uninstalling git-flow from $INSTALL_PREFIX"
if [ -d "$INSTALL_PREFIX" ] ; then
uninstall)
echo "Uninstalling git-flow from $PREFIX"
if [ -d "$BINDIR" ] ; then
for script_file in $SCRIPT_FILES $EXEC_FILES ; do
echo "rm -vf $INSTALL_PREFIX/$script_file"
rm -vf "$INSTALL_PREFIX/$script_file"
echo "rm -vf $BINDIR/$script_file"
rm -vf "$BINDIR/$script_file"
done
rm -rf "$DOCDIR"
else
echo "The '$INSTALL_PREFIX' directory was not found."
echo "Do you need to set INSTALL_PREFIX ?"
echo "The '$BINDIR' directory was not found."
fi
exit
;;
help)
echo "Usage: [environment] gitflow-installer.sh [install|uninstall]"
echo "Environment:"
echo " INSTALL_PREFIX=$INSTALL_PREFIX"
echo " REPO_HOME=$REPO_HOME"
echo " REPO_NAME=$REPO_NAME"
help)
usage
exit
;;
*)
echo "Installing git-flow to $INSTALL_PREFIX"
install)
if [ -z $2 ]; then
usage
exit
fi
echo "Installing git-flow to $BINDIR"
if [ -d "$REPO_NAME" -a -d "$REPO_NAME/.git" ] ; then
echo "Using existing repo: $REPO_NAME"
else
echo "Cloning repo from GitHub to $REPO_NAME"
git clone "$REPO_HOME" "$REPO_NAME"
fi
if [ -f "$REPO_NAME/$SUBMODULE_FILE" ] ; then
echo "Submodules look up to date"
else
echo "Updating submodules"
lastcwd=$PWD
cd "$REPO_NAME"
git submodule init
git submodule update
cd "$lastcwd"
fi
install -v -d -m 0755 "$INSTALL_PREFIX"
git pull
cd "$OLDPWD"
case "$2" in
stable)
cd "$REPO_NAME"
git checkout master
cd "$OLDPWD"
;;
develop)
cd "$REPO_NAME"
git checkout develop
cd "$OLDPWD"
;;
*)
usage
exit
;;
esac
install -v -d -m 0755 "$PREFIX/bin"
install -v -d -m 0755 "$DOCDIR/hooks"
for exec_file in $EXEC_FILES ; do
install -v -m 0755 "$REPO_NAME/$exec_file" "$INSTALL_PREFIX"
install -v -m 0755 "$REPO_NAME/$exec_file" "$BINDIR"
done
for script_file in $SCRIPT_FILES ; do
install -v -m 0644 "$REPO_NAME/$script_file" "$INSTALL_PREFIX"
install -v -m 0644 "$REPO_NAME/$script_file" "$BINDIR"
done
for hook_file in $HOOK_FILES ; do
install -v -m 0644 "$hook_file" "$DOCDIR/hooks"
done
exit
;;
*)
usage
exit
;;
esac
......@@ -38,7 +38,6 @@ if errorlevel 4 if not errorlevel 5 goto :AccessDenied
if errorlevel 1 set ERR=1
xcopy "%~dp0\..\git-flow*" "%GIT_HOME%\bin" /Y /R /F || set ERR=1
xcopy "%~dp0\..\gitflow-*" "%GIT_HOME%\bin" /Y /R /F || set ERR=1
xcopy "%~dp0\..\shFlags\src\shflags" "%GIT_HOME%\bin\gitflow-shFlags" /Y /R /F || set ERR=1
if %ERR%==1 choice /T 30 /C Y /D Y /M "Some unexpected errors happened. Sorry, you'll have to fix them by yourself."
......@@ -63,7 +62,6 @@ goto :End
:ChkGetopt
:: %1 is getopt.exe
if exist "%GIT_HOME%\bin\%1" goto :EOF
if exist "%USERPROFILE%\bin\%1" goto :EOF
if exist "%~f$PATH:1" goto :EOF
echo %GIT_HOME%\bin\%1 not found.>&2
echo You have to install this file manually. See the GitFlow README.
......
......@@ -3,51 +3,90 @@
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# Original blog post presenting this model is found at:
# http://nvie.com/git-model
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/nvie/gitflow
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of Vincent Driessen.
#
# set this to workaround expr problems in shFlags on freebsd
if uname -s | egrep -iq 'bsd'; then export EXPR_COMPAT=1; fi
# enable debug mode
if [ "$DEBUG" = "yes" ]; then
set -x
fi
# The sed expression here replaces all backslashes by forward slashes.
# This helps our Windows users, while not bothering our Unix users.
export GITFLOW_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
# Setup the GITFLOW_DIR for different operating systems.
# This is mostly to make sure that we get the correct directory when the
# git-flow file is a symbolic link
case $(uname -s) in
Linux)
export GITFLOW_DIR=$(dirname "$(readlink -e "$0")")
;;
FreeBSD|OpenBSD|NetBSD)
export FLAGS_GETOPT_CMD='/usr/local/bin/getopt'
export GITFLOW_DIR=$(dirname "$(realpath "$0")")
;;
Darwin)
PRG="$0"
while [ -h "$PRG" ]; do
link=$(readlink "$PRG")
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="$(dirname "$PRG")/$link"
fi
done
export GITFLOW_DIR=$(dirname "$PRG")
;;
*MINGW*)
export GITFLOW_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
pwd () {
builtin pwd -W
}
;;
*)
# The sed expression here replaces all backslashes by forward slashes.
# This helps our Windows users, while not bothering our Unix users.)
export GITFLOW_DIR=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
;;
esac
# Extra environment settings
if [ -f ~/.gitflow_export ]; then
if grep -E 'GITFLOW_FLAG_(SHOWCOMMANDS|INIT|FEATURE|HOTFIX|RELEASE|SUPPORT)' ~/.gitflow_export > /dev/null; then
echo "Using environment variables for \"showcommands\", \"init\", \"feature\", \"hotfix\", \"release\" and \"support\" in ~/.gitflow_export has deprecated, use git config instead."
echo ""
exit 1;
else
. ~/.gitflow_export
fi
fi
usage() {
echo "usage: git flow <subcommand>"
......@@ -55,10 +94,13 @@ usage() {
echo "Available subcommands are:"
echo " init Initialize a new git repo with support for the branching model."
echo " feature Manage your feature branches."
echo " bugfix Manage your bugfix branches."
echo " release Manage your release branches."
echo " hotfix Manage your hotfix branches."
echo " support Manage your support branches."
echo " version Shows version information."
echo " config Manage your git-flow configuration."
echo " log Show log deviating from base branch."
echo
echo "Try 'git flow <subcommand> help' for details."
}
......@@ -69,55 +111,99 @@ main() {
exit 1
fi
# load common functionality
. "$GITFLOW_DIR/gitflow-common"
# This environmental variable fixes non-POSIX getopt style argument
# parsing, effectively breaking git-flow subcommand parsing on several
# Linux platforms.
export POSIXLY_CORRECT=1
# use the shFlags project to parse the command line arguments
# Use the shFlags project to parse the command line arguments
. "$GITFLOW_DIR/gitflow-shFlags"
FLAGS_PARENT="git flow"
# allow user to request git action logging
DEFINE_boolean show_commands false 'show actions taken (git commands)' g
# Load common functionality
. "$GITFLOW_DIR/gitflow-common"
# do actual parsing
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# allow user to request git action logging
DEFINE_boolean 'showcommands' false 'Show actions taken (git commands)'
# but if the user prefers that the logging is always on,
# use the environmental variables.
gitflow_override_flag_boolean 'showcommands' 'showcommands'
# sanity checks
# Sanity checks
SUBCOMMAND="$1"; shift
if [ "${SUBCOMMAND}" = "finish" ] || [ "${SUBCOMMAND}" = "delete" ] || [ "${SUBCOMMAND}" = "publish" ] || [ "${SUBCOMMAND}" = "rebase" ]; then
_current_branch=$(git_current_branch)
if gitflow_is_prefixed_branch "${_current_branch}"; then
if startswith "${_current_branch}" $(git config --get gitflow.prefix.feature); then
SUBACTION="${SUBCOMMAND}"
SUBCOMMAND="feature"
_prefix=$(git config --get gitflow.prefix.feature)
_short_branch_name=$(echo ${_current_branch#*${_prefix}})
else
if startswith "${_current_branch}" $(git config --get gitflow.prefix.bugfix); then
SUBACTION="${SUBCOMMAND}"
SUBCOMMAND="bugfix"
_prefix=$(git config --get gitflow.prefix.bugfix)
_short_branch_name=$(echo ${_current_branch#*${_prefix}})
else
if startswith "${_current_branch}" $(git config --get gitflow.prefix.hotfix); then
SUBACTION="${SUBCOMMAND}"
SUBCOMMAND="hotfix"
_prefix=$(git config --get gitflow.prefix.hotfix)
_short_branch_name=$(echo ${_current_branch#*${_prefix}})
else
if startswith "${_current_branch}" $(git config --get gitflow.prefix.release); then
SUBACTION="${SUBCOMMAND}"
SUBCOMMAND="release"
_prefix=$(git config --get gitflow.prefix.release)
_short_branch_name=$(echo ${_current_branch#*${_prefix}})
fi
fi
fi
fi
fi
fi
if [ ! -e "$GITFLOW_DIR/git-flow-$SUBCOMMAND" ]; then
usage
exit 1
fi
# run command
# Run command
. "$GITFLOW_DIR/git-flow-$SUBCOMMAND"
FLAGS_PARENT="git flow $SUBCOMMAND"
# test if the first argument is a flag (i.e. starts with '-')
# in that case, we interpret this arg as a flag for the default
# command
if [ -z "${SUBACTION}" ]; then
# If the first argument is a flag, it starts with '-', we interpret this
# argument as a flag for the default command.
if startswith "$1" "-"; then
SUBACTION="default"
if [ "$1" != "" ] && { ! echo "$1" | grep -q "^-"; } then
SUBACTION="$1"; shift
elif [ -z "$1" ]; then
SUBACTION="default"
else
SUBACTION="$1"
shift
# Do not allow direct calls to subactions with an underscore.
if $(contains "$SUBACTION" "_"); then
warn "Unknown subcommand: '$SUBACTION'"
usage
exit 1
fi
# Replace the dash with an underscore as bash doesn't allow a dash
# in the function name.
SUBACTION=$(echo "$SUBACTION" |tr '-' '_')
fi
fi
if ! type "cmd_$SUBACTION" >/dev/null 2>&1; then
warn "Unknown subcommand: '$SUBACTION'"
usage
exit 1
fi
# run the specified action
if [ $SUBACTION != "help" ] && [ $SUBCOMMAND != "init" ] ; then
init
# Run the specified action
if [ $SUBACTION != "help" ] && [ $SUBCOMMAND != "init" ]; then
initialize
fi
if [ $SUBACTION != 'default' ]; then
FLAGS_PARENT="git flow $SUBCOMMAND $SUBACTION"
fi
cmd_$SUBACTION "$@"
}
cmd_$SUBACTION "$@" "${_short_branch_name}"
}
main "$@"
#
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
initialize() {
require_git_repo
require_gitflow_initialized
git config --get gitflow.prefix.bugfix >/dev/null 2>&1 || die "Bugfix prefix not set. Please run 'git flow init'."
gitflow_load_settings
PREFIX=$(git config --get gitflow.prefix.bugfix)
}
usage() {
OPTIONS_SPEC="\
git flow bugfix [list]
git flow bugfix start
git flow bugfix finish
git flow bugfix publish
git flow bugfix track
git flow bugfix diff
git flow bugfix rebase
git flow bugfix checkout
git flow bugfix pull
git flow bugfix delete
Manage your bugfix branches.
For more specific help type the command followed by --help
--
"
flags_help
}
cmd_default() {
cmd_list "$@"
}
cmd_list() {
OPTIONS_SPEC="\
git flow bugfix [list] [-h] [-v]
Lists all the existing bugfix branches in the local repository.
--
h,help! Show this help
v,verbose Verbose (more) output
"
local bugfix_branches current_branch width branch len
local base develop_sha branch_sha
# Define flags
DEFINE_boolean 'verbose' false 'verbose (more) output' v
# Parse argun=ments
parse_args "$@"
bugfix_branches=$(git_local_branches_prefixed "$PREFIX")
if [ -z "$bugfix_branches" ]; then
warn "No bugfix branches exist."
warn ""
warn "You can start a new bugfix branch:"
warn ""
warn " git flow bugfix start <name> [<base>]"
warn ""
exit 0
fi
current_branch=$(git_current_branch)
# Determine column width first
width=0
for branch in $bugfix_branches; do
len=${#branch}
width=$(max $width $len)
done
width=$(($width+3-${#PREFIX}))
for branch in $bugfix_branches; do
base=$(git merge-base "$branch" "$DEVELOP_BRANCH")
develop_sha=$(git rev-parse "$DEVELOP_BRANCH")
branch_sha=$(git rev-parse "$branch")
if [ "$branch" = "$current_branch" ]; then
printf "* "
else
printf " "
fi
if flag verbose; then
printf "%-${width}s" "${branch#$PREFIX}"
if [ "$branch_sha" = "$develop_sha" ]; then
printf "(no commits yet)"
elif [ "$base" = "$branch_sha" ]; then
printf "(is behind develop, may ff)"
elif [ "$base" = "$develop_sha" ]; then
printf "(based on latest develop)"
else
printf "(may be rebased)"
fi
else
printf "%s" "${branch#$PREFIX}"
fi
echo
done
}
cmd_help() {
usage
exit 0
}
# Parse arguments and set common variables
parse_args() {
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# read arguments into global variables
if [ -z $1 ]; then
NAME=''
else
NAME=$1
fi
BRANCH=$PREFIX$NAME
}
parse_remote_name() {
# Parse arguments
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# read arguments into global variables
if [ -z $1 ]; then
REMOTE=''
else
REMOTE=$1
fi
if [ -z $2 ]; then
NAME=''
else
NAME=$2
fi
BRANCH=$PREFIX$NAME
}
cmd_start() {
OPTIONS_SPEC="\
git flow bugfix start [-h] [-F] <name> [<base>]
Start new bugfix <name>, optionally basing it on <base> instead of <develop>
--
h,help! Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from origin before performing local operation
"
local base
# Define flags
DEFINE_boolean 'fetch' false 'fetch from origin before performing local operation' F
# Override defaults with values from config
gitflow_override_flag_boolean "bugfix.start.fetch" "fetch"
# Parse arguments
parse_args "$@"
eval set -- "${FLAGS_ARGV}"
base=${2:-$DEVELOP_BRANCH}
require_base_is_local_branch "$base"
gitflow_require_name_arg
gitflow_config_set_base_branch $base $BRANCH
# Update the local repo with remote changes, if asked
if flag fetch; then
git_fetch_branch "$ORIGIN" "$base"
fi
# Sanity checks
require_branch_absent "$BRANCH"
# If the origin branch counterpart exists, assert that the local branch
# isn't behind it (to avoid unnecessary rebasing)
if git_remote_branch_exists "$ORIGIN/$base"; then
require_branches_equal "$base" "$ORIGIN/$base"
fi
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH" "$base"
# create branch
git_do checkout -b "$BRANCH" "$base" || die "Could not create bugfix branch '$BRANCH'."
run_post_hook "$NAME" "$ORIGIN" "$BRANCH" "$base"
echo
echo "Summary of actions:"
echo "- A new branch '$BRANCH' was created, based on '$base'"
echo "- You are now on branch '$(git_current_branch)'"
echo ""
echo "Now, start committing on your bugfix. When done, use:"
echo ""
echo " git flow bugfix finish $NAME"
echo
}
cmd_finish() {
OPTIONS_SPEC="\
git flow bugfix finish [-h] [-F] [-r] [-p] [-k] [-D] [-S] [--no-ff] <name|nameprefix>
Finish bugfix <name>
--
h,help! Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from origin before performing finish
r,[no]rebase Rebase before merging
p,[no]preserve-merges Preserve merges while rebasing
k,[no]keep Keep branch after performing finish
keepremote! Keep the remote branch
keeplocal! Keep the local branch
D,[no]force_delete Force delete bugfix branch after finish
S,[no]squash Squash bugfix during merge
no-ff! Never fast-forward during the merge
"
local finish_base
# Define flags
DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean 'rebase' false "rebase before merging" r
DEFINE_boolean 'preserve-merges' false 'try to recreate merges while rebasing' p
DEFINE_boolean 'keep' false "keep branch after performing finish" k
DEFINE_boolean 'keepremote' false "keep the remote branch"
DEFINE_boolean 'keeplocal' false "keep the local branch"
DEFINE_boolean 'force_delete' false "force delete bugfix branch after finish" D
DEFINE_boolean 'squash' false "squash bugfix during merge" S
DEFINE_boolean 'squash-info' false "add branch info during squash"
DEFINE_boolean 'no-ff!' false "Don't fast-forward ever during merge "
# Override defaults with values from config
gitflow_override_flag_boolean "bugfix.finish.fetch" "fetch"
gitflow_override_flag_boolean "bugfix.finish.rebase" "rebase"
gitflow_override_flag_boolean "bugfix.finish.preserve-merges" "preserve_merges"
gitflow_override_flag_boolean "bugfix.finish.keep" "keep"
gitflow_override_flag_boolean "bugfix.finish.keepremote" "keepremote"
gitflow_override_flag_boolean "bugfix.finish.keeplocal" "keeplocal"
gitflow_override_flag_boolean "bugfix.finish.force-delete" "force_delete"
gitflow_override_flag_boolean "bugfix.finish.squash" "squash"
gitflow_override_flag_boolean "bugfix.finish.squash-info" "squash_info"
gitflow_override_flag_boolean "bugfix.finish.no-ff" "no_ff"
# Parse arguments
parse_args "$@"
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
# Keeping both branches implies the --keep flag to be true.
if flag keepremote && flag keeplocal; then
FLAGS_keep=$FLAGS_TRUE
fi
# Sanity checks
require_branch "$BRANCH"
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't finish the bugfix branch '$BRANCH'."
# Detect if we're restoring from a merge conflict
if [ -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE" ]; then
#
# TODO: detect that we're working on the correct branch here!
# The user need not necessarily have given the same $NAME twice here
# (although he/she should).
#
# TODO: git_is_clean_working_tree() should provide an alternative
# exit code for "unmerged changes in working tree", which we should
# actually be testing for here
if git_is_clean_working_tree; then
finish_base=$(cat "$DOT_GIT_DIR/.gitflow/MERGE_BASE")
# Since the working tree is now clean, either the user did a
# successful merge manually, or the merge was cancelled.
# We detect this using git_is_branch_merged_into()
if git_is_branch_merged_into "$BRANCH" "$finish_base"; then
rm -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
helper_finish_cleanup
exit 0
else
# If the user cancelled the merge and decided to wait until
# later,that's fine. But we have to acknowledge this by
# removing the MERGE_BASE file and continuing normal execution
# of the finish
rm -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
fi
else
echo
echo "Merge conflicts not resolved yet, use:"
echo " git mergetool"
echo " git commit"
echo
echo "You can then complete the finish by running it again:"
echo " git flow bugfix finish $NAME"
echo
exit 1
fi
fi
# Sanity checks
require_clean_working_tree
# We always fetch the Branch from Origin
# This is done to avoid possible commits on the remote that are not
# merged into the local branch
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_fetch_branch "$ORIGIN" "$BRANCH"
fi
# Update local branches with remote branches
if flag fetch; then
git_fetch_branch "$ORIGIN" "$BASE_BRANCH"
fi
# Check if the local branches have all the commits from the remote branches
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
fi
if git_remote_branch_exists "$ORIGIN/$BASE_BRANCH"; then
require_branches_equal "$BASE_BRANCH" "$ORIGIN/$BASE_BRANCH"
fi
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH"
# If the user wants to rebase, do that first
if flag rebase; then
local _rebase_opts=""
if flag preserve_merges; then
_rebase_opts="$_rebase_opts -p"
fi
if flag showcommands; then
_rebase_opts="$_rebase_opts --showcommands"
fi
if ! git flow bugfix rebase $_rebase_opts "$NAME"; then
warn "Finish was aborted due to conflicts during rebase."
warn "Please finish the rebase manually now."
warn "When finished, re-run:"
warn " git flow bugfix finish '$NAME' '$BASE_BRANCH'"
exit 1
fi
fi
# Merge into BASE
git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
if noflag squash; then
if flag no_ff; then
git_do merge --no-ff "$BRANCH"
else
if [ "$(git rev-list -n2 "$BASE_BRANCH..$BRANCH" | wc -l)" -eq 1 ]; then
git_do merge --ff "$BRANCH"
else
git_do merge --no-ff "$BRANCH"
fi
fi
else
git_do merge --squash "$BRANCH"
flag squash_info && gitflow_create_squash_message "Merged bugfix branch '$BRANCH'" "$BASE_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG"
git_do commit
fi
if [ $? -ne 0 ]; then
# Oops.. we have a merge conflict!
# Write the given $BASE_BRANCH to a temporary file as we will
# be needing it later.
mkdir -p "$DOT_GIT_DIR/.gitflow"
echo "$BASE_BRANCH" > "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
echo
echo "There were merge conflicts. To resolve the merge conflict manually, use:"
echo " git mergetool"
echo " git commit"
echo
echo "You can then complete the finish by running it again:"
echo " git flow bugfix finish $NAME"
echo
exit 1
fi
run_post_hook "$NAME" "$ORIGIN" "$BRANCH"
# When no merge conflict is detected, just clean up the bugfix branch
gitflow_config_remove_base_branch "$BRANCH"
helper_finish_cleanup
}
helper_finish_cleanup() {
local keepmsg remotebranchdeleted localbranchdeleted
# Sanity checks
require_branch "$BRANCH"
require_clean_working_tree
remotebranchdeleted=$FLAGS_FALSE
localbranchdeleted=$FLAGS_FALSE
if noflag keep; then
# Always delete remote first
if noflag keepremote;then
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_remote_branch_delete "$BRANCH" && remotebranchdeleted=$FLAGS_TRUE
fi
fi
# Delete local after remote to avoid warnings
if noflag keeplocal; then
if [ "$BRANCH" = "$(git_current_branch)" ]; then
git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
fi
if flag force_delete; then
git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
else
if noflag squash; then
git_do branch -d "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
else
git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
fi
fi
fi
# no more branches: we can safely remove config section
if ! git_remote_branch_exists "$ORIGIN/$BRANCH" -a ! git_local_branch_exists "$BRANCH"; then
gitflow_config_remove_base_section "$BRANCH"
fi
fi
echo
echo "Summary of actions:"
echo "- The bugfix branch '$BRANCH' was merged into '$BASE_BRANCH'"
#echo "- Merge conflicts were resolved" # TODO: Add this line when it's supported
if noflag keep; then
if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg="has been locally deleted"
else
keepmsg="is still locally available"
fi
if [ $remotebranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg=$keepmsg"; it has been remotely deleted from '$ORIGIN'"
elif git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
else
keepmsg="is still locally available"
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
fi
echo "- bugfix branch '$BRANCH' "$keepmsg
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_publish() {
OPTIONS_SPEC="\
git flow bugfix publish [-h] [<name>]
Publish bugfix branch <name> on $ORIGIN.
When <name> is omitted the current branch is used, but only if it's a bugfix branch.
--
h,help! Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
# Sanity checks
require_clean_working_tree
require_branch "$BRANCH"
git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
require_branch_absent "$ORIGIN/$BRANCH"
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH"
# Create remote branch with remote tracking
git_do push -u "$ORIGIN" "$BRANCH:$BRANCH"
git_do fetch -q "$ORIGIN" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'."
run_post_hook "$NAME" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- The remote branch '$BRANCH' was created or updated"
echo "- The local branch '$BRANCH' was configured to track the remote branch"
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_track() {
OPTIONS_SPEC="\
git flow bugfix track [-h] <name>
Start tracking bugfix <name> that is shared on $ORIGIN
--
h,help! Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
gitflow_require_name_arg
# Sanity checks
require_clean_working_tree
require_local_branch_absent "$BRANCH"
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH"
git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
git_remote_branch_exists "$ORIGIN/$BRANCH"
# Create tracking branch
git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH" || die "Could not create '$BRANCH'."
run_post_hook "$NAME" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote tracking branch '$BRANCH' was created"
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_diff() {
OPTIONS_SPEC="\
git flow bugfix diff [-h] [<name|nameprefix>]
Show all changes in <name> that are not in the base
--
h,help! Show this help
showcommands! Show git commands while executing them
"
local base
# Parse arguments
parse_args "$@"
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
base=$(gitflow_config_get_base_branch $BRANCH)
base=${base:-$DEVELOP_BRANCH}
git_do diff "$base..$BRANCH"
}
cmd_checkout() {
OPTIONS_SPEC="\
git flow bugfix checkout [-h] [<name|nameprefix>]
Switch to bugfix branch <name>
--
h,help! Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
NAME=$(gitflow_resolve_nameprefix "$NAME" "$PREFIX")
if [ $? -eq 0 ]; then
BRANCH=$PREFIX$NAME
git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'."
fi
}
cmd_co() {
# Alias for checkout
cmd_checkout "$@"
}
cmd_rebase() {
OPTIONS_SPEC="\
git flow bugfix rebase [-h] [-i] [-p] [<name|nameprefix>]
Rebase <name> on <base_branch>
--
h,help! Show this help
showcommands! Show git commands while executing them
i,[no]interactive Do an interactive rebase
p,[no]preserve-merges Preserve merges
"
local opts
# Define flags
DEFINE_boolean 'interactive' false 'do an interactive rebase' i
DEFINE_boolean 'preserve-merges' false 'try to recreate merges' p
# Override defaults with values from config
gitflow_override_flag_boolean "bugfix.rebase.interactive" "interactive"
gitflow_override_flag_boolean "bugfix.rebase.preserve-merges" "preserve_merges"
# Parse arguments
parse_args "$@"
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
warn "Will try to rebase '$NAME' which is based on '$BASE_BRANCH'..."
require_clean_working_tree
require_branch "$BRANCH"
git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't rebase the bugfix branch '$BRANCH'."
git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'."
if flag interactive; then
opts="$opts -i"
fi
if flag preserve_merges; then
opts="$opts -p"
fi
git_do rebase $opts "$BASE_BRANCH"
}
avoid_accidental_cross_branch_action() {
local current_branch
current_branch=$(git_current_branch)
if [ "$BRANCH" != "$current_branch" ]; then
warn "Trying to pull from '$BRANCH' while currently on branch '$current_branch'."
warn "To avoid unintended merges, git-flow aborted."
return 1
fi
return 0
}
cmd_pull() {
OPTIONS_SPEC="\
git flow bugfix pull [-h] <remote> [<name>]
Pull bugfix <name> from <remote>
--
h,help! Show this help
showcommands! Show git commands while executing them
"
local current_branch
# Define flags
DEFINE_boolean 'rebase' false "pull with rebase" r
warn "The command 'git flow bugfix pull' will be deprecated per version 2.0.0. Use 'git flow bugfix track' instead."
# Parse arguments
parse_remote_name "$@"
if [ -z "$REMOTE" ]; then
die "Name a remote explicitly."
fi
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
# To avoid accidentally merging different bugfix branches into each other,
# die if the current bugfix branch differs from the requested $NAME
# argument.
current_branch=$(git_current_branch)
if startswith "$current_branch" "$PREFIX"; then
# We are on a local bugfix branch already, so $BRANCH must be equal to
# the current branch
avoid_accidental_cross_branch_action || die
fi
require_clean_working_tree
run_pre_hook "$NAME" "$REMOTE" "$BRANCH"
if git_local_branch_exists "$BRANCH"; then
# Again, avoid accidental merges
avoid_accidental_cross_branch_action || die
# We already have a local branch called like this, so simply pull the
# remote changes in
if flag rebase; then
if ! git_do pull --rebase -q "$REMOTE" "$BRANCH"; then
warn "Pull was aborted. There might be conflicts during rebase or '$REMOTE' might be inaccessible."
exit 1
fi
else
git_do pull -q "$REMOTE" "$BRANCH" || die "Failed to pull from remote '$REMOTE'."
fi
echo "Pulled $REMOTE's changes into $BRANCH."
else
# Setup the local branch clone for the first time
git_do fetch -q "$REMOTE" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$REMOTE'." # Stores in FETCH_HEAD
git_do branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed."
git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'."
echo "Created local branch $BRANCH based on $REMOTE's $BRANCH."
fi
run_post_hook "$NAME" "$REMOTE" "$BRANCH"
}
cmd_delete() {
OPTIONS_SPEC="\
git flow bugfix delete [-h] [-f] [-r] <name>
Delete a given bugfix branch
--
h,help! Show this help
showcommands! Show git commands while executing them
f,[no]force Force deletion
r,[no]remote Delete remote branch
"
local current_branch
# Define flags
DEFINE_boolean 'force' false "force deletion" f
DEFINE_boolean 'remote' false "delete remote branch" r
# Override defaults with values from config
gitflow_override_flag_boolean "bugfix.delete.force" "force"
gitflow_override_flag_boolean "bugfix.delete.remote" "remote"
# Parse arguments
parse_args "$@"
gitflow_require_name_arg
# Sanity checks
require_branch "$BRANCH"
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH"
current_branch=$(git_current_branch)
# We can't delete a branch we are on, switch to the develop branch.
if [ "$BRANCH" = "$current_branch" ]; then
require_clean_working_tree
if git_local_branch_exists "$BASE_BRANCH"; then
git_do checkout "$BASE_BRANCH"
else
git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
fi
fi
if git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
git_do branch -d "$BRANCH" || die "Could not delete the $BRANCH."
if flag remote; then
git_do push "$ORIGIN" :"$BRANCH" || die "Could not delete the remote $BRANCH in $ORIGIN."
fi
else
if flag force; then
git_do branch -D "$BRANCH" || die "Could not delete the $BRANCH."
if flag remote; then
git_do push "$ORIGIN" :"$BRANCH" || die "Could not delete the remote $BRANCH in $ORIGIN."
fi
else
die "bugfix branch '$BRANCH' has been not been merged yet. Use -f to force the deletion."
fi
fi
gitflow_config_remove_base_section "$BRANCH"
run_post_hook "$NAME" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- bugfix branch '$BRANCH' has been deleted."
flag remote && echo "- bugfix branch '$BRANCH' in '$ORIGIN' has been deleted."
echo "- You are now on branch '$(git_current_branch)'"
echo
}
#
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
initialize() {
require_git_repo
require_gitflow_initialized
gitflow_load_settings
}
usage() {
OPTIONS_SPEC="\
git flow config [list]
git flow config set
git flow config base
Manage the git-flow configuration.
For more specific help type the command followed by --help
--
"
flags_help
}
parse_args() {
# Parse options
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
OPTION=$(echo $1|tr '[:upper:]' '[:lower:]')
if [ "$FLAGS_file" != "" ]; then
gitflow_config_option="--file '$FLAGS_file'"
elif flag local; then
gitflow_config_option="--local"
elif flag global; then
gitflow_config_option="--global"
elif flag system; then
gitflow_config_option="--system"
else
gitflow_config_option=""
fi
}
# Default entry when no SUBACTION is given
cmd_default() {
cmd_list "$@"
}
cmd_list() {
OPTIONS_SPEC="\
git flow config [list]
Show the git-flow configurations
--
h,help! Show this help
Use config file location
local! Use repository config file
global! Use global config file
system! Use system config file
file= Use given config file
"
local output
# Define flags
DEFINE_boolean 'local' false 'use repository config file'
DEFINE_boolean 'global' false 'use global config file'
DEFINE_boolean 'system' false 'use system config file'
DEFINE_string 'file' "" 'use given config file'
# Parse arguments
parse_args "$@"
output=$(git config $gitflow_config_option --get gitflow.branch.master)
echo "Branch name for production releases: $output "
output=$(git config $gitflow_config_option --get gitflow.branch.develop)
echo "Branch name for \"next release\" development: $output "
output=$(git config $gitflow_config_option --get gitflow.prefix.feature)
echo "Feature branch prefix: $output "
output=$(git config $gitflow_config_option --get gitflow.prefix.bugfix)
echo "Bugfix branch prefix: $output "
output=$(git config $gitflow_config_option --get gitflow.prefix.release)
echo "Release branch prefix: $output "
output=$(git config $gitflow_config_option --get gitflow.prefix.hotfix)
echo "Hotfix branch prefix: $output "
output=$(git config $gitflow_config_option --get gitflow.prefix.support)
echo "Support branch prefix: $output "
output=$(git config $gitflow_config_option --get gitflow.prefix.versiontag)
echo "Version tag prefix: $output "
}
cmd_set() {
OPTIONS_SPEC="\
git flow config set <option> <value>
Set the git-flow configuration option to the given value
--
h,help! Show this help
local! Use repository config file
global! Use global config file
system! Use system config file
file= Use given config file
"
local value cfg_option txt
# Define flags
DEFINE_boolean 'local' false 'use repository config file'
DEFINE_boolean 'global' false 'use global config file'
DEFINE_boolean 'system' false 'use system config file'
DEFINE_string 'file' "" 'use given config file'
# Parse arguments
parse_args "$@"
eval set -- "${FLAGS_ARGV}"
value=$2
case $OPTION in
master)
cfg_option="gitflow.branch.master"
txt="Branch name for production releases"
;;
develop)
cfg_option="gitflow.branch.develop"
txt="Branch name for \"next release\" development"
;;
feature)
cfg_option="gitflow.prefix.feature"
txt="Feature branch prefix"
;;
bugfix)
cfg_option="gitflow.prefix.bugfix"
txt="Bugfix branch prefix"
;;
hotfix)
cfg_option="gitflow.prefix.hotfix"
txt="Hotfix branch prefix"
;;
release)
cfg_option="gitflow.prefix.release"
txt="Release branch prefix"
;;
support)
cfg_option="gitflow.prefix.support"
txt="Support branch prefix"
;;
versiontagprefix)
cfg_option="gitflow.prefix.versiontag"
txt="Version tag prefix"
;;
allowmultihotfix)
cfg_option="gitflow.multi-hotfix"
txt="Allow multiple hotfix branches"
;;
*)
die_help "Invalid option given."
;;
esac
[ -n "$value" ] || die_help "No value given"
if [ $OPTION = "master" ]; then
develop_branch=$(git config --get gitflow.branch.develop)
if [ "$value" = $develop_branch ]; then
die "Production and \"next release\" branch should differ."
fi
if ! git_local_branch_exists "$value" && git_remote_branch_exists "origin/$value"; then
git_do branch "$value" "origin/$value" >/dev/null 2>&1
elif ! git_local_branch_exists "$value"; then
die "Local branch '$value' does not exist."
fi
fi
if [ $OPTION = "develop" ]; then
master_branch=$(git config --get gitflow.branch.master)
if [ "$value" = $master_branch ]; then
die "Production and \"next release\" branch should differ."
fi
if ! git_local_branch_exists "$value" && git_remote_branch_exists "origin/$value"; then
git_do branch "$value" "origin/$value" >/dev/null 2>&1
elif ! git_local_branch_exists "$value"; then
die "Local branch '$value' does not exist."
fi
fi
if [ $OPTION = "allowmultihotfix" ]; then
check_boolean "${value}"
case $? in
${FLAGS_ERROR})
die "Invalid value for option 'allowmultihotfix'. Valid values are 'true' or 'false'"
;;
*)
;;
esac
fi
git_do config $gitflow_config_option $cfg_option "$value"
case $? in
0)
;;
3)
die "The config file is invalid."
;;
4)
die "Can not write to the config file."
;;
*)
die "Unknown return code [$?]. Please file an issue about this error."
;;
esac
echo
echo "Summary of actions:"
if [ "$FLAGS_file" != "" ]; then
echo "- Using configuration file '$FLAGS_file'"
elif flag local; then
echo "- Using repository specific configuration file."
elif flag global; then
echo "- Using user-specific configuration file."
elif flag system; then
echo "- Using system-wide configuration file."
else
echo "- Using repository specific configuration file."
fi
echo "- $txt set to $value"
echo
}
cmd_base () {
OPTIONS_SPEC="\
git flow config base [<options>] <branch> [<base>]
Set the given <base> for the given <branch>
--
h,help! Show this help
get Get the base for the given branch (default behavior).
set Set the given base for the given branch.
"
DEFINE_boolean 'get' true 'Get the base for the given branch (default behavior).'
DEFINE_boolean 'set' false 'Set the given base for the given branch.'
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
if flag 'set'; then
[ -z "$1" ] && die_help 'No branch given'
[ -z "$2" ] && die_help 'No base given'
__set_base "$@"
else
[ -z "$1" ] && die_help 'No branch given'
__get_base "$@"
fi
}
cmd_help() {
usage
exit 0
}
# Private functions
__set_base () {
require_branch "$1"
git_branch_exists "$2" || die_help "Given base doesn't exists or is not a branch."
gitflow_config_set_base_branch "$2" "$1"
}
__get_base () {
local base
base=$(gitflow_config_get_base_branch "$1")
echo
if [ -z "$base" ]; then
echo "Base branch not set for branch '"$1"'"
else
echo "Base branch for branch '"$1"' set to '"$base"'"
fi
}
#@IgnoreInspection BashAddShebang
#
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# Original blog post presenting this model is found at:
# http://nvie.com/git-model
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/nvie/gitflow
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of Vincent Driessen.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
init() {
initialize() {
require_git_repo
require_gitflow_initialized
git config --get gitflow.prefix.feature >/dev/null 2>&1 || die "Feature prefix not set. Please run 'git flow init'."
gitflow_load_settings
parse_args "$@"
PREFIX=$(git config --get gitflow.prefix.feature)
}
usage() {
echo "usage: git flow feature [list] [-v] s"
echo " git flow feature start [-F] <name> [<base>]"
echo " git flow feature finish [-rFkDS] [<name|nameprefix>]"
echo " git flow feature publish <name>"
echo " git flow feature track <name>"
echo " git flow feature diff [<name|nameprefix>]"
echo " git flow feature rebase [-i] [<name|nameprefix>]"
echo " git flow feature checkout [<name|nameprefix>]"
echo " git flow feature pull [-r] <remote> [<name>]"
echo " git flow feature pause <name>"
OPTIONS_SPEC="\
git flow feature [list]
git flow feature start
git flow feature finish
git flow feature pause
git flow feature interrupt
git flow feature resume
git flow feature review
git flow feature finish
git flow feature publish
git flow feature track
git flow feature diff
git flow feature rebase
git flow feature checkout
git flow feature pull
git flow feature delete
Manage your feature branches.
For more specific help type the command followed by --help
--
"
flags_help
}
cmd_default() {
......@@ -63,13 +75,24 @@ cmd_default() {
}
cmd_list() {
DEFINE_boolean verbose false 'verbose (more) output' v
OPTIONS_SPEC="\
git flow feature [list] [-h] [-v]
Lists all the existing feature branches in the local repository.
--
h,help! Show this help
v,verbose Verbose (more) output
"
local feature_branches current_branch width branch len
local base develop_sha branch_sha
# Define flags
DEFINE_boolean 'verbose' false 'verbose (more) output' v
# Parse argun=ments
parse_args "$@"
local feature_branches
local current_branch
local short_names
feature_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
feature_branches=$(git_local_branches_prefixed "$PREFIX")
if [ -z "$feature_branches" ]; then
warn "No feature branches exist."
warn ""
......@@ -79,31 +102,27 @@ cmd_list() {
warn ""
exit 0
fi
current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
short_names=$(echo "$feature_branches" | sed "s ^$PREFIX g")
current_branch=$(git_current_branch)
# determine column width first
local width=0
local branch
for branch in $short_names; do
local len=${#branch}
# Determine column width first
width=0
for branch in $feature_branches; do
len=${#branch}
width=$(max $width $len)
done
width=$(($width+3))
local branch
for branch in $short_names; do
local fullname=$PREFIX$branch
local base=$(git merge-base "$fullname" "$DEVELOP_BRANCH")
local develop_sha=$(git rev-parse "$DEVELOP_BRANCH")
local branch_sha=$(git rev-parse "$fullname")
if [ "$fullname" = "$current_branch" ]; then
width=$(($width+3-${#PREFIX}))
for branch in $feature_branches; do
base=$(git merge-base "$branch" "$DEVELOP_BRANCH")
develop_sha=$(git rev-parse "$DEVELOP_BRANCH")
branch_sha=$(git rev-parse "$branch")
if [ "$branch" = "$current_branch" ]; then
printf "* "
else
printf " "
fi
if flag verbose; then
printf "%-${width}s" "$branch"
printf "%-${width}s" "${branch#$PREFIX}"
if [ "$branch_sha" = "$develop_sha" ]; then
printf "(no commits yet)"
elif [ "$base" = "$branch_sha" ]; then
......@@ -114,7 +133,7 @@ cmd_list() {
printf "(may be rebased)"
fi
else
printf "%s" "$branch"
printf "%s" "${branch#$PREFIX}"
fi
echo
done
......@@ -125,101 +144,88 @@ cmd_help() {
exit 0
}
require_name_arg() {
if [ "$NAME" = "" ]; then
warn "Missing argument <name>"
usage
exit 1
fi
}
expand_nameprefix_arg() {
require_name_arg
local expanded_name
local exitcode
expanded_name=$(gitflow_resolve_nameprefix "$NAME" "$PREFIX")
exitcode=$?
case $exitcode in
0) NAME=$expanded_name
BRANCH=$PREFIX$NAME
;;
*) exit 1 ;;
esac
}
use_current_feature_branch_name() {
local current_branch=$(git_current_branch)
if startswith "$current_branch" "$PREFIX"; then
BRANCH=$current_branch
NAME=${BRANCH#$PREFIX}
else
warn "The current HEAD is no feature branch."
warn "Please specify a <name> argument."
exit 1
fi
}
expand_nameprefix_arg_or_current() {
if [ "$NAME" != "" ]; then
expand_nameprefix_arg
require_branch "$PREFIX$NAME"
else
use_current_feature_branch_name
fi
}
name_or_current() {
if [ -z "$NAME" ]; then
use_current_feature_branch_name
fi
}
# Parse arguments and set common variables
parse_args() {
# parse options
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# read arguments into global variables
if [ -z $1 ]; then
NAME=''
else
NAME=$1
fi
BRANCH=$PREFIX$NAME
}
parse_remote_name() {
# parse options
# Parse arguments
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# read arguments into global variables
if [ -z $1 ]; then
REMOTE=''
else
REMOTE=$1
fi
if [ -z $2 ]; then
NAME=''
else
NAME=$2
fi
BRANCH=$PREFIX$NAME
}
cmd_start() {
DEFINE_boolean fetch false 'fetch from origin before performing local operation' F
OPTIONS_SPEC="\
git flow feature start [-h] [-F] <name> [<base>]
Start new feature <name>, optionally basing it on <base> instead of <develop>
--
h,help! Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from origin before performing local operation
"
local base
# Define flags
DEFINE_boolean 'fetch' false 'fetch from origin before performing local operation' F
# Override defaults with values from config
gitflow_override_flag_boolean "feature.start.fetch" "fetch"
# Parse arguments
parse_args "$@"
BASE=${2:-$DEVELOP_BRANCH}
require_name_arg
eval set -- "${FLAGS_ARGV}"
base=${2:-$DEVELOP_BRANCH}
# sanity checks
require_branch_absent "$BRANCH"
require_base_is_local_branch "$base"
gitflow_require_name_arg
gitflow_config_set_base_branch $base $BRANCH
# update the local repo with remote changes, if asked
# Update the local repo with remote changes, if asked
if flag fetch; then
git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
git_fetch_branch "$ORIGIN" "$base"
fi
# if the origin branch counterpart exists, assert that the local branch
# Sanity checks
require_branch_absent "$BRANCH"
# If the origin branch counterpart exists, assert that the local branch
# isn't behind it (to avoid unnecessary rebasing)
if git_branch_exists "$ORIGIN/$DEVELOP_BRANCH"; then
require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
if git_remote_branch_exists "$ORIGIN/$base"; then
require_branches_equal "$base" "$ORIGIN/$base"
fi
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH" "$base"
# create branch
if ! git_do checkout -b "$BRANCH" "$BASE"; then
die "Could not create feature branch '$BRANCH'"
fi
git_do checkout -b "$BRANCH" "$base" || die "Could not create feature branch '$BRANCH'."
run_post_hook "$NAME" "$ORIGIN" "$BRANCH" "$base"
echo "How long do you think this feature will take in hours (e.g 1.5)?"
read TIME_REQUIRED
......@@ -237,8 +243,8 @@ cmd_start() {
echo
echo "Summary of actions:"
echo "- A new branch '$BRANCH' was created, based on '$BASE'"
echo "- You are now on branch '$BRANCH'"
echo "- A new branch '$BRANCH' was created, based on '$base'"
echo "- You are now on branch '$(git_current_branch)'"
echo ""
echo "Now, start committing on your feature. When done, use:"
echo ""
......@@ -247,18 +253,73 @@ cmd_start() {
}
cmd_finish() {
DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean rebase false "rebase instead of merge" r
DEFINE_boolean keep false "keep branch after performing finish" k
DEFINE_boolean force_delete false "force delete feature branch after finish" D
DEFINE_boolean squash false "squash feature during merge" S
OPTIONS_SPEC="\
git flow feature finish [-h] [-F] [-r] [-p] [-k] [-D] [-S] [--no-ff] <name|nameprefix>
Finish feature <name>
--
h,help! Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from origin before performing finish
r,[no]rebase Rebase before merging
p,[no]preserve-merges Preserve merges while rebasing
[no]push Push to origin after performing finish
k,[no]keep Keep branch after performing finish
keepremote! Keep the remote branch
keeplocal! Keep the local branch
D,[no]force_delete Force delete feature branch after finish
S,[no]squash Squash feature during merge
no-ff! Never fast-forward during the merge
"
local finish_base
# Define flags
DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean 'rebase' false "rebase before merging" r
DEFINE_boolean 'preserve-merges' false 'try to recreate merges while rebasing' p
DEFINE_boolean 'push' false "push to $ORIGIN after performing finish"
DEFINE_boolean 'keep' false "keep branch after performing finish" k
DEFINE_boolean 'keepremote' false "keep the remote branch"
DEFINE_boolean 'keeplocal' false "keep the local branch"
DEFINE_boolean 'force_delete' false "force delete feature branch after finish" D
DEFINE_boolean 'squash' false "squash feature during merge" S
DEFINE_boolean 'squash-info' false "add branch info during squash"
DEFINE_boolean 'no-ff!' false "Don't fast-forward ever during merge "
# Override defaults with values from config
gitflow_override_flag_boolean "feature.finish.fetch" "fetch"
gitflow_override_flag_boolean "feature.finish.rebase" "rebase"
gitflow_override_flag_boolean "feature.finish.preserve-merges" "preserve_merges"
gitflow_override_flag_boolean "feature.finish.push" "push"
gitflow_override_flag_boolean "feature.finish.keep" "keep"
gitflow_override_flag_boolean "feature.finish.keepremote" "keepremote"
gitflow_override_flag_boolean "feature.finish.keeplocal" "keeplocal"
gitflow_override_flag_boolean "feature.finish.force-delete" "force_delete"
gitflow_override_flag_boolean "feature.finish.squash" "squash"
gitflow_override_flag_boolean "feature.finish.squash-info" "squash_info"
gitflow_override_flag_boolean "feature.finish.no-ff" "no_ff"
# Parse arguments
parse_args "$@"
expand_nameprefix_arg_or_current
# sanity checks
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
# Keeping both branches implies the --keep flag to be true.
if flag keepremote && flag keeplocal; then
FLAGS_keep=$FLAGS_TRUE
fi
# Sanity checks
require_branch "$BRANCH"
# detect if we're restoring from a merge conflict
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't finish the feature branch '$BRANCH'."
# Detect if we're restoring from a merge conflict
if [ -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE" ]; then
#
# TODO: detect that we're working on the correct branch here!
......@@ -268,21 +329,22 @@ cmd_finish() {
# TODO: git_is_clean_working_tree() should provide an alternative
# exit code for "unmerged changes in working tree", which we should
# actually be testing for
# actually be testing for here
if git_is_clean_working_tree; then
FINISH_BASE=$(cat "$DOT_GIT_DIR/.gitflow/MERGE_BASE")
finish_base=$(cat "$DOT_GIT_DIR/.gitflow/MERGE_BASE")
# Since the working tree is now clean, either the user did a
# succesfull merge manually, or the merge was cancelled.
# successful merge manually, or the merge was cancelled.
# We detect this using git_is_branch_merged_into()
if git_is_branch_merged_into "$BRANCH" "$FINISH_BASE"; then
if git_is_branch_merged_into "$BRANCH" "$finish_base"; then
rm -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
helper_finish_cleanup
exit 0
else
# If the user cancelled the merge and decided to wait until later,
# that's fine. But we have to acknowledge this by removing the
# MERGE_BASE file and continuing normal execution of the finish
# If the user cancelled the merge and decided to wait until
# later,that's fine. But we have to acknowledge this by
# removing the MERGE_BASE file and continuing normal execution
# of the finish
rm -f "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
fi
else
......@@ -298,54 +360,74 @@ cmd_finish() {
fi
fi
# sanity checks
# Sanity checks
require_clean_working_tree
# update local repo with remote changes first, if asked
if has "$ORIGIN/$BRANCH" $(git_remote_branches); then
if flag fetch; then
git_do fetch -q "$ORIGIN" "$BRANCH"
git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
# We always fetch the Branch from Origin
# This is done to avoid possible commits on the remote that are not
# merged into the local branch
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_fetch_branch "$ORIGIN" "$BRANCH"
fi
# Update local branches with remote branches
if flag fetch; then
git_fetch_branch "$ORIGIN" "$BASE_BRANCH"
fi
if has "$ORIGIN/$BRANCH" $(git_remote_branches); then
# Check if the local branches have all the commits from the remote branches
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
fi
if has "$ORIGIN/$DEVELOP_BRANCH" $(git_remote_branches); then
require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
if git_remote_branch_exists "$ORIGIN/$BASE_BRANCH"; then
require_branches_equal "$BASE_BRANCH" "$ORIGIN/$BASE_BRANCH"
fi
# if the user wants to rebase, do that first
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH"
# If the user wants to rebase, do that first
if flag rebase; then
if ! git flow feature rebase "$NAME" "$DEVELOP_BRANCH"; then
local _rebase_opts=""
if flag preserve_merges; then
_rebase_opts="$_rebase_opts -p"
fi
if flag showcommands; then
_rebase_opts="$_rebase_opts --showcommands"
fi
if ! git flow feature rebase $_rebase_opts "$NAME"; then
warn "Finish was aborted due to conflicts during rebase."
warn "Please finish the rebase manually now."
warn "When finished, re-run:"
warn " git flow feature finish '$NAME' '$DEVELOP_BRANCH'"
warn " git flow feature finish '$NAME' '$BASE_BRANCH'"
exit 1
fi
fi
# merge into BASE
git_do checkout "$DEVELOP_BRANCH"
if [ "$(git rev-list -n2 "$DEVELOP_BRANCH..$BRANCH" | wc -l)" -eq 1 ]; then
# Merge into BASE
git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
if noflag squash; then
if flag no_ff; then
git_do merge --no-ff "$BRANCH"
else
if [ "$(git rev-list -n2 "$BASE_BRANCH..$BRANCH" | wc -l)" -eq 1 ]; then
git_do merge --ff "$BRANCH"
else
if noflag squash; then
git_do merge --no-ff "$BRANCH"
fi
fi
else
git_do merge --squash "$BRANCH"
flag squash_info && gitflow_create_squash_message "Merged feature branch '$BRANCH'" "$BASE_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG"
git_do commit
git_do merge "$BRANCH"
fi
fi
if [ $? -ne 0 ]; then
# oops.. we have a merge conflict!
# write the given $DEVELOP_BRANCH to a temporary file (we need it later)
# Oops.. we have a merge conflict!
# Write the given $BASE_BRANCH to a temporary file as we will
# be needing it later.
mkdir -p "$DOT_GIT_DIR/.gitflow"
echo "$DEVELOP_BRANCH" > "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
echo "$BASE_BRANCH" > "$DOT_GIT_DIR/.gitflow/MERGE_BASE"
echo
echo "There were merge conflicts. To resolve the merge conflict manually, use:"
echo " git mergetool"
......@@ -357,6 +439,11 @@ cmd_finish() {
exit 1
fi
run_post_hook "$NAME" "$ORIGIN" "$BRANCH"
# When no merge conflict is detected, just clean up the feature branch
gitflow_config_remove_base_branch "$BRANCH"
echo $(date +%s) >> "./.git/.gitflow/.timelog-feature-$NAME"
LAST_TIME=$(tail -1 .git/.gitflow/.timelog-feature-$NAME | head -1)
......@@ -381,232 +468,198 @@ cmd_finish() {
git commit --allow-empty -m "--Flow message(finish) --$BRANCH was completed on $(date), total time taken:$FINALTIME expectde time was $TIME_EXPECTED hour(s), Time spent on breaks was $TOTAL_TIME_OFF"
# when no merge conflict is detected, just clean up the feature branch
helper_finish_cleanup
}
helper_finish_cleanup() {
# sanity checks
local keepmsg remotebranchdeleted localbranchdeleted
# Sanity checks
require_branch "$BRANCH"
require_clean_working_tree
# delete branch
if flag fetch; then
git_do push "$ORIGIN" ":refs/heads/$BRANCH"
fi
remotebranchdeleted=$FLAGS_FALSE
localbranchdeleted=$FLAGS_FALSE
if noflag keep; then
# Always delete remote first
if noflag keepremote;then
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_remote_branch_delete "$BRANCH" && remotebranchdeleted=$FLAGS_TRUE
fi
fi
# Delete local after remote to avoid warnings
if noflag keeplocal; then
if [ "$BRANCH" = "$(git_current_branch)" ]; then
git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
fi
if flag force_delete; then
git_do branch -D "$BRANCH"
git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
else
if noflag squash; then
git_do branch -d "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
else
git_do branch -d "$BRANCH"
git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
fi
fi
fi
# no more branches: we can safely remove config section
if ! git_remote_branch_exists "$ORIGIN/$BRANCH" -a ! git_local_branch_exists "$BRANCH"; then
gitflow_config_remove_base_section "$BRANCH"
fi
fi
if flag push; then
git_do push "$ORIGIN" "$BASE_BRANCH" || die "Could not push branch '$BASE_BRANCH' to remote '$ORIGIN'."
fi
echo
echo "Summary of actions:"
echo "- The feature branch '$BRANCH' was merged into '$DEVELOP_BRANCH'"
echo "- The feature branch '$BRANCH' was merged into '$BASE_BRANCH'"
#echo "- Merge conflicts were resolved" # TODO: Add this line when it's supported
if flag keep; then
echo "- Feature branch '$BRANCH' is still available"
if noflag keep; then
if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg="has been locally deleted"
else
echo "- Feature branch '$BRANCH' has been removed"
keepmsg="is still locally available"
fi
echo "- You are now on branch '$DEVELOP_BRANCH'"
if [ $remotebranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg=$keepmsg"; it has been remotely deleted from '$ORIGIN'"
elif git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
else
keepmsg="is still locally available"
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
fi
echo "- Feature branch '$BRANCH' "$keepmsg
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_publish() {
OPTIONS_SPEC="\
git flow feature publish [-h] [<name>]
Publish feature branch <name> on $ORIGIN.
When <name> is omitted the current branch is used, but only if it's a feature branch.
--
h,help! Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
expand_nameprefix_arg
# sanity checks
require_clean_working_tree
require_branch "$BRANCH"
git_do fetch -q "$ORIGIN"
require_branch_absent "$ORIGIN/$BRANCH"
# create remote branch
git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
git_do fetch -q "$ORIGIN"
# configure remote tracking
git_do config "branch.$BRANCH.remote" "$ORIGIN"
git_do config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
git_do checkout "$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote branch '$BRANCH' was created"
echo "- The local branch '$BRANCH' was configured to track the remote branch"
echo "- You are now on branch '$BRANCH'"
echo
}
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
cmd_review() {
parse_args "$@"
expand_nameprefix_arg
# sanity checks
# Sanity checks
require_clean_working_tree
require_branch "$BRANCH"
git_do fetch -q "$ORIGIN"
# require_branch_absent "$ORIGIN/$BRANCH"
# create remote branch
git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
git_do fetch -q "$ORIGIN"
# configure remote tracking
git_do config "branch.$BRANCH.remote" "$ORIGIN"
git_do config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
git_do checkout "$BRANCH"
echo $(date +%s) >> "./.git/.gitflow/.timelog-feature-$NAME"
LAST_TIME=$(tail -1 .git/.gitflow/.timelog-feature-$NAME | head -1)
PREV_TIME=$(tail -2 .git/.gitflow/.timelog-feature-$NAME | head -1)
TIME_USED=$((LAST_TIME-PREV_TIME))
echo "$TIME_USED" >> "./.git/.gitflow/.seconds-feature-$NAME"
if [ -f ./.git/.gitflow/.breaktime-feature-$NAME ];
then
TOTAL_BREAK_TIME=$(awk '{ sum += $1 } END { print sum }' ./.git/.gitflow/.breaktime-feature-$NAME)
else
TOTAL_BREAK_TIME=0
fi
TOTAL_TIME=$(awk '{ sum += $1 } END { print sum }' ./.git/.gitflow/.seconds-feature-$NAME)
TIME_EXPECTED=$(head -n 1 ./.git/.gitflow/.timelog-feature-$NAME)
FINALTIME=$((TOTAL_TIME/86400))" days "$(date -d "1970-01-01 + $TOTAL_TIME seconds" "+%H hours %M minutes %S seconds")
TOTAL_TIME_OFF=$((TOTAL_BREAK_TIME/86400))" days "$(date -d "1970-01-01 + $TOTAL_BREAK_TIME seconds" "+%H hours %M minutes %S seconds")
git commit --allow-empty -m "--Flow message(finish) --$BRANCH was completed on $(date), total time taken:$FINALTIME expected time was $TIME_EXPECTED hour(s), Time spent on breaks was $TOTAL_TIME_OFF"
GIT_URL=$(git config --get remote.origin.url)
GIT_URL_WITHOUT_SUFFIX="${GIT_URL%.*}"
REPO="$(basename "${GIT_URL_WITHOUT_SUFFIX}")"
URL_WITH_OWNER="$(dirname "${GIT_URL_WITHOUT_SUFFIX})")"
OWNER=$(basename $(echo $URL_WITH_OWNER | tr ":" /))
DEVELOPMENT_BRANCH=$(git config --get gitflow.branch.develop)
if [ -f ./.git/.gitflow/.github_token ];
then
GITHUB_USERNAME=$(tail -1 ./.git/.gitflow/.github_username | head -1)
GITHUB_TOKEN=$(tail -1 ./.git/.gitflow/.github_token | head -1)
GITHUB_REQUEST=$(curl -X POST --write-out %{http_code} --silent --output /dev/null -H "Content-Type: application/json" \
-H "Cache-Control: no-cache" \
--user $GITHUB_USERNAME:$GITHUB_TOKEN \
-d '{
"title":"'"$GITHUB_USERNAME"' submitted '"$BRANCH"' branch for review",
"head":"'"$BRANCH"'",
"base":"'"$DEVELOPMENT_BRANCH"'",
"body":"'"$GITHUB_USERNAME"' is asking for code review. Total time taken:'"$FINALTIME"' expected time was '"$TIME_EXPECTED"' hour(s), Time spent on breaks was '"$TOTAL_TIME_OFF"' -- message by gitflow",
"maintainer_can_modify": true
}' \
"https://api.github.com/repos/$OWNER/$REPO/pulls")
if [ "$GITHUB_REQUEST" -gt 300 ]
then
echo "Failed to create pull request"
else
echo "Pull request created on github please inform the code reviewer by mentioning them in the comments"
fi
fi
if [ -f ./.git/.gitflow/.gitlab_token ];
then
GITLAB_TOKEN=$(tail -1 ./.git/.gitflow/.gitlab_token | head -1)
USER_NAME=$(git config --get --global user.name)
GITLAB_REQUEST=$(curl -X POST --write-out %{http_code} --silent --output /dev/null -H "PRIVATE-TOKEN: $GITLAB_TOKEN" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -H "Postman-Token: 209ed2f2-a7bd-ab33-a432-1d884669976b" -d '{
"target_branch": "'"$DEVELOPMENT_BRANCH"'",
"source_branch": "'"$BRANCH"'",
"title": "'"$BRANCH Merge Request by $USER_NAME"'",
"body":"'"$USER_NAME"' is asking for code review. Total time taken:'"$FINALTIME"' expected time was '"$TIME_EXPECTED"' hour(s), Time spent on breaks was '"$TOTAL_TIME_OFF"' -- message by gitflow"
}' "https://gitlab.com/api/v3/projects/$OWNER%2F$REPO/merge_requests")
git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
require_branch_absent "$ORIGIN/$BRANCH"
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH"
# Create remote branch with remote tracking
git_do push -u "$ORIGIN" "$BRANCH:$BRANCH"
git_do fetch -q "$ORIGIN" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'."
if [ "$GITLAB_REQUEST" -gt 300 ]
then
echo "Failed to create merge request"
else
echo "Merge request created on gitlab please inform the code reviewer by mentioning them in the comments"
fi
fi
git pause
git checkout $DEVELOPMENT_BRANCH
git pull
run_post_hook "$NAME" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote branch '$BRANCH' was created"
echo "- The remote branch '$BRANCH' was created or updated"
echo "- The local branch '$BRANCH' was configured to track the remote branch"
echo "- You are now on branch '$DEVELOPMENT_BRANCH'"
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_track() {
OPTIONS_SPEC="\
git flow feature track [-h] <name>
Start tracking feature <name> that is shared on $ORIGIN
--
h,help! Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
require_name_arg
# sanity checks
gitflow_require_name_arg
# Sanity checks
require_clean_working_tree
require_branch_absent "$BRANCH"
git_do fetch -q "$ORIGIN"
require_branch "$ORIGIN/$BRANCH"
require_local_branch_absent "$BRANCH"
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH"
# create tracking branch
git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH"
git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
git_remote_branch_exists "$ORIGIN/$BRANCH"
# Create tracking branch
git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH" || die "Could not create '$BRANCH'."
run_post_hook "$NAME" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote tracking branch '$BRANCH' was created"
echo "- You are now on branch '$BRANCH'"
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_diff() {
OPTIONS_SPEC="\
git flow feature diff [-h] [<name|nameprefix>]
Show all changes in <name> that are not in the base
--
h,help! Show this help
showcommands! Show git commands while executing them
"
local base
# Parse arguments
parse_args "$@"
if [ "$NAME" != "" ]; then
expand_nameprefix_arg
BASE=$(git merge-base "$DEVELOP_BRANCH" "$BRANCH")
git diff "$BASE..$BRANCH"
else
if ! git_current_branch | grep -q "^$PREFIX"; then
die "Not on a feature branch. Name one explicitly."
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
BASE=$(git merge-base "$DEVELOP_BRANCH" HEAD)
git diff "$BASE"
fi
base=$(gitflow_config_get_base_branch $BRANCH)
base=${base:-$DEVELOP_BRANCH}
git_do diff "$base..$BRANCH"
}
cmd_checkout() {
OPTIONS_SPEC="\
git flow feature checkout [-h] [<name|nameprefix>]
Switch to feature branch <name>
--
h,help! Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
if [ "$NAME" != "" ]; then
expand_nameprefix_arg
git_do checkout "$BRANCH"
else
die "Name a feature branch explicitly."
NAME=$(gitflow_resolve_nameprefix "$NAME" "$PREFIX")
if [ $? -eq 0 ]; then
BRANCH=$PREFIX$NAME
git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'."
fi
}
......@@ -616,23 +669,58 @@ cmd_co() {
}
cmd_rebase() {
DEFINE_boolean interactive false 'do an interactive rebase' i
OPTIONS_SPEC="\
git flow feature rebase [-h] [-i] [-p] [<name|nameprefix>]
Rebase <name> on <base_branch>
--
h,help! Show this help
showcommands! Show git commands while executing them
i,[no]interactive Do an interactive rebase
p,[no]preserve-merges Preserve merges
"
local opts
# Define flags
DEFINE_boolean 'interactive' false 'do an interactive rebase' i
DEFINE_boolean 'preserve-merges' false 'try to recreate merges' p
# Override defaults with values from config
gitflow_override_flag_boolean "feature.rebase.interactive" "interactive"
gitflow_override_flag_boolean "feature.rebase.preserve-merges" "preserve_merges"
# Parse arguments
parse_args "$@"
expand_nameprefix_arg_or_current
warn "Will try to rebase '$NAME'..."
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
warn "Will try to rebase '$NAME' which is based on '$BASE_BRANCH'..."
require_clean_working_tree
require_branch "$BRANCH"
git_do checkout -q "$BRANCH"
local OPTS=
git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't rebase the feature branch '$BRANCH'."
git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'."
if flag interactive; then
OPTS="$OPTS -i"
opts="$opts -i"
fi
git_do rebase $OPTS "$DEVELOP_BRANCH"
if flag preserve_merges; then
opts="$opts -p"
fi
git_do rebase $opts "$BASE_BRANCH"
}
avoid_accidental_cross_branch_action() {
local current_branch=$(git_current_branch)
local current_branch
current_branch=$(git_current_branch)
if [ "$BRANCH" != "$current_branch" ]; then
warn "Trying to pull from '$BRANCH' while currently on branch '$current_branch'."
warn "To avoid unintended merges, git-flow aborted."
......@@ -642,32 +730,52 @@ avoid_accidental_cross_branch_action() {
}
cmd_pull() {
#DEFINE_string prefix false 'alternative remote feature branch name prefix' p
DEFINE_boolean rebase false "pull with rebase" r
OPTIONS_SPEC="\
git flow feature pull [-h] <remote> [<name>]
Pull feature <name> from <remote>
--
h,help! Show this help
showcommands! Show git commands while executing them
"
local current_branch
# Define flags
DEFINE_boolean 'rebase' false "pull with rebase" r
warn "The command 'git flow feature pull' will be deprecated per version 2.0.0. Use 'git flow feature track' instead."
# Parse arguments
parse_remote_name "$@"
if [ -z "$REMOTE" ]; then
die "Name a remote explicitly."
fi
name_or_current
# Use current branch if no name is given
if [ "$NAME" = "" ]; then
gitflow_use_current_branch_name
fi
# To avoid accidentally merging different feature branches into each other,
# die if the current feature branch differs from the requested $NAME
# argument.
local current_branch=$(git_current_branch)
current_branch=$(git_current_branch)
if startswith "$current_branch" "$PREFIX"; then
# we are on a local feature branch already, so $BRANCH must be equal to
# We are on a local feature branch already, so $BRANCH must be equal to
# the current branch
avoid_accidental_cross_branch_action || die
fi
require_clean_working_tree
if git_branch_exists "$BRANCH"; then
run_pre_hook "$NAME" "$REMOTE" "$BRANCH"
if git_local_branch_exists "$BRANCH"; then
# Again, avoid accidental merges
avoid_accidental_cross_branch_action || die
# we already have a local branch called like this, so simply pull the
# We already have a local branch called like this, so simply pull the
# remote changes in
if flag rebase; then
if ! git_do pull --rebase -q "$REMOTE" "$BRANCH"; then
......@@ -680,16 +788,99 @@ cmd_pull() {
echo "Pulled $REMOTE's changes into $BRANCH."
else
# setup the local branch clone for the first time
git_do fetch -q "$REMOTE" "$BRANCH" || die "Fetch failed." # stores in FETCH_HEAD
# Setup the local branch clone for the first time
git_do fetch -q "$REMOTE" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$REMOTE'." # Stores in FETCH_HEAD
git_do branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed."
git_do checkout -q "$BRANCH" || die "Checking out new local branch failed."
git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'."
echo "Created local branch $BRANCH based on $REMOTE's $BRANCH."
fi
run_post_hook "$NAME" "$REMOTE" "$BRANCH"
}
cmd_delete() {
OPTIONS_SPEC="\
git flow feature delete [-h] [-f] [-r] <name>
Delete a given feature branch
--
h,help! Show this help
showcommands! Show git commands while executing them
f,[no]force Force deletion
r,[no]remote Delete remote branch
"
local current_branch
# Define flags
DEFINE_boolean 'force' false "force deletion" f
DEFINE_boolean 'remote' false "delete remote branch" r
# Override defaults with values from config
gitflow_override_flag_boolean "feature.delete.force" "force"
gitflow_override_flag_boolean "feature.delete.remote" "remote"
# Parse arguments
parse_args "$@"
gitflow_require_name_arg
# Sanity checks
require_branch "$BRANCH"
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
run_pre_hook "$NAME" "$ORIGIN" "$BRANCH"
current_branch=$(git_current_branch)
# We can't delete a branch we are on, switch to the develop branch.
if [ "$BRANCH" = "$current_branch" ]; then
require_clean_working_tree
if git_local_branch_exists "$BASE_BRANCH"; then
git_do checkout "$BASE_BRANCH"
else
git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
fi
fi
if git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
git_do branch -d "$BRANCH" || die "Could not delete the $BRANCH."
if flag remote; then
git_do push "$ORIGIN" :"$BRANCH" || die "Could not delete the remote $BRANCH in $ORIGIN."
fi
else
if flag force; then
git_do branch -D "$BRANCH" || die "Could not delete the $BRANCH."
if flag remote; then
git_do push "$ORIGIN" :"$BRANCH" || die "Could not delete the remote $BRANCH in $ORIGIN."
fi
else
die "Feature branch '$BRANCH' has been not been merged yet. Use -f to force the deletion."
fi
fi
gitflow_config_remove_base_section "$BRANCH"
run_post_hook "$NAME" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- Feature branch '$BRANCH' has been deleted."
flag remote && echo "- Feature branch '$BRANCH' in '$ORIGIN' has been deleted."
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_pause() {
OPTIONS_SPEC="\
git flow feature pause [-h]
Use this to pause the timer at any time for a coffee.
----
h,help! Show this help
"
parse_args "$@"
local current_branch
......@@ -740,6 +931,15 @@ cmd_pause() {
cmd_interrupt() {
OPTIONS_SPEC="\
git flow feature interrupt [-h]
Use this to pause the timer. Resuming the feature will ask you for a reason
----
h,help! Show this help
"
parse_args "$@"
local current_branch
......@@ -787,6 +987,13 @@ cmd_interrupt() {
cmd_resume() {
OPTIONS_SPEC="\
git flow feature resume [-h] <name>
Allows you to continue working on a feature after using pause or interrupt
----
h,help! Show this help
"
parse_args "$@"
require_name_arg
......@@ -839,3 +1046,127 @@ cmd_resume() {
echo
}
cmd_review() {
OPTIONS_SPEC="\
git flow feature review [-h] <name>
Publishes a feature and submits a pull request if gitlab/github is configured
--
h,help! Show this help
"
parse_args "$@"
expand_nameprefix_arg
# sanity checks
require_clean_working_tree
require_branch "$BRANCH"
git_do fetch -q "$ORIGIN"
# require_branch_absent "$ORIGIN/$BRANCH"
# create remote branch
git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
git_do fetch -q "$ORIGIN"
# configure remote tracking
git_do config "branch.$BRANCH.remote" "$ORIGIN"
git_do config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
git_do checkout "$BRANCH"
echo $(date +%s) >> "./.git/.gitflow/.timelog-feature-$NAME"
LAST_TIME=$(tail -1 .git/.gitflow/.timelog-feature-$NAME | head -1)
PREV_TIME=$(tail -2 .git/.gitflow/.timelog-feature-$NAME | head -1)
TIME_USED=$((LAST_TIME-PREV_TIME))
echo "$TIME_USED" >> "./.git/.gitflow/.seconds-feature-$NAME"
if [ -f ./.git/.gitflow/.breaktime-feature-$NAME ];
then
TOTAL_BREAK_TIME=$(awk '{ sum += $1 } END { print sum }' ./.git/.gitflow/.breaktime-feature-$NAME)
else
TOTAL_BREAK_TIME=0
fi
TOTAL_TIME=$(awk '{ sum += $1 } END { print sum }' ./.git/.gitflow/.seconds-feature-$NAME)
TIME_EXPECTED=$(head -n 1 ./.git/.gitflow/.timelog-feature-$NAME)
FINALTIME=$((TOTAL_TIME/86400))" days "$(date -d "1970-01-01 + $TOTAL_TIME seconds" "+%H hours %M minutes %S seconds")
TOTAL_TIME_OFF=$((TOTAL_BREAK_TIME/86400))" days "$(date -d "1970-01-01 + $TOTAL_BREAK_TIME seconds" "+%H hours %M minutes %S seconds")
git commit --allow-empty -m "--Flow message(finish) --$BRANCH was completed on $(date), total time taken:$FINALTIME expected time was $TIME_EXPECTED hour(s), Time spent on breaks was $TOTAL_TIME_OFF"
GIT_URL=$(git config --get remote.origin.url)
GIT_URL_WITHOUT_SUFFIX="${GIT_URL%.*}"
REPO="$(basename "${GIT_URL_WITHOUT_SUFFIX}")"
URL_WITH_OWNER="$(dirname "${GIT_URL_WITHOUT_SUFFIX})")"
OWNER=$(basename $(echo $URL_WITH_OWNER | tr ":" /))
DEVELOPMENT_BRANCH=$(git config --get gitflow.branch.develop)
if [ -f ./.git/.gitflow/.github_token ];
then
GITHUB_USERNAME=$(tail -1 ./.git/.gitflow/.github_username | head -1)
GITHUB_TOKEN=$(tail -1 ./.git/.gitflow/.github_token | head -1)
GITHUB_REQUEST=$(curl -X POST --write-out %{http_code} --silent --output /dev/null -H "Content-Type: application/json" \
-H "Cache-Control: no-cache" \
--user $GITHUB_USERNAME:$GITHUB_TOKEN \
-d '{
"title":"'"$GITHUB_USERNAME"' submitted '"$BRANCH"' branch for review",
"head":"'"$BRANCH"'",
"base":"'"$DEVELOPMENT_BRANCH"'",
"body":"'"$GITHUB_USERNAME"' is asking for code review. Total time taken:'"$FINALTIME"' expected time was '"$TIME_EXPECTED"' hour(s), Time spent on breaks was '"$TOTAL_TIME_OFF"' -- message by gitflow",
"maintainer_can_modify": true
}' \
"https://api.github.com/repos/$OWNER/$REPO/pulls")
if [ "$GITHUB_REQUEST" -gt 300 ]
then
echo "Failed to create pull request"
else
echo "Pull request created on github please inform the code reviewer by mentioning them in the comments"
fi
fi
if [ -f ./.git/.gitflow/.gitlab_token ];
then
GITLAB_TOKEN=$(tail -1 ./.git/.gitflow/.gitlab_token | head -1)
USER_NAME=$(git config --get --global user.name)
GITLAB_REQUEST=$(curl -X POST --write-out %{http_code} --silent --output /dev/null -H "PRIVATE-TOKEN: $GITLAB_TOKEN" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -H "Postman-Token: 209ed2f2-a7bd-ab33-a432-1d884669976b" -d '{
"target_branch": "'"$DEVELOPMENT_BRANCH"'",
"source_branch": "'"$BRANCH"'",
"title": "'"$BRANCH Merge Request by $USER_NAME"'",
"body":"'"$USER_NAME"' is asking for code review. Total time taken:'"$FINALTIME"' expected time was '"$TIME_EXPECTED"' hour(s), Time spent on breaks was '"$TOTAL_TIME_OFF"' -- message by gitflow"
}' "https://gitlab.com/api/v3/projects/$OWNER%2F$REPO/merge_requests")
if [ "$GITLAB_REQUEST" -gt 300 ]
then
echo "Failed to create merge request"
else
echo "Merge request created on gitlab please inform the code reviewer by mentioning them in the comments"
fi
fi
git pause
git checkout $DEVELOPMENT_BRANCH
git pull
echo
echo "Summary of actions:"
echo "- A new remote branch '$BRANCH' was created"
echo "- The local branch '$BRANCH' was configured to track the remote branch"
echo "- You are now on branch '$DEVELOPMENT_BRANCH'"
echo
}
\ No newline at end of file
......@@ -2,54 +2,62 @@
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# Original blog post presenting this model is found at:
# http://nvie.com/git-model
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/nvie/gitflow
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of Vincent Driessen.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
init() {
initialize() {
require_git_repo
require_gitflow_initialized
git config --get gitflow.prefix.hotfix >/dev/null 2>&1 || die "Hotfix prefix not set. Please run 'git flow init'."
gitflow_load_settings
VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`")
VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
PREFIX=$(git config --get gitflow.prefix.hotfix)
}
usage() {
echo "usage: git flow hotfix [list] [-v]"
echo " git flow hotfix start [-F] <version> [<base>]"
echo " git flow hotfix finish [-Fsumpk] <version>"
echo " git flow hotfix publish <version>"
echo " git flow hotfix track <version>"
OPTIONS_SPEC="\
git flow hotfix [list]
git flow hotfix start
git flow hotfix finish
git flow hotfix publish
git flow hotfix delete
Manage your hotfix branches.
For more specific help type the command followed by --help
--
"
flags_help
}
cmd_default() {
......@@ -57,13 +65,24 @@ cmd_default() {
}
cmd_list() {
DEFINE_boolean verbose false 'verbose (more) output' v
OPTIONS_SPEC="\
git flow hotfix [list] [-h] [-v]
Lists all local hotfix branches
--
h,help! Show this help
v,verbose! Verbose (more) output
"
local hotfix_branches current_branch width branch len
local base master_sha branch_sha
# Define flags
DEFINE_boolean 'verbose' false 'verbose (more) output' v
# Parse arguments
parse_args "$@"
local hotfix_branches
local current_branch
local short_names
hotfix_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
hotfix_branches=$(git_local_branches_prefixed "$PREFIX")
if [ -z "$hotfix_branches" ]; then
warn "No hotfix branches exist."
warn ""
......@@ -73,31 +92,27 @@ cmd_list() {
warn ""
exit 0
fi
current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
short_names=$(echo "$hotfix_branches" | sed "s ^$PREFIX g")
current_branch=$(git_current_branch)
# determine column width first
local width=0
local branch
for branch in $short_names; do
local len=${#branch}
# Determine column width first
width=0
for branch in $hotfix_branches; do
len=${#branch}
width=$(max $width $len)
done
width=$(($width+3))
local branch
for branch in $short_names; do
local fullname=$PREFIX$branch
local base=$(git merge-base "$fullname" "$MASTER_BRANCH")
local master_sha=$(git rev-parse "$MASTER_BRANCH")
local branch_sha=$(git rev-parse "$fullname")
if [ "$fullname" = "$current_branch" ]; then
width=$(($width+3-${#PREFIX}))
for branch in $hotfix_branches; do
base=$(git merge-base "$branch" "$MASTER_BRANCH")
master_sha=$(git rev-parse "$MASTER_BRANCH")
branch_sha=$(git rev-parse "$branch")
if [ "$branch" = "$current_branch" ]; then
printf "* "
else
printf " "
fi
if flag verbose; then
printf "%-${width}s" "$branch"
printf "%-${width}s" "${branch#$PREFIX}"
if [ "$branch_sha" = "$master_sha" ]; then
printf "(no commits yet)"
else
......@@ -111,7 +126,7 @@ cmd_list() {
printf "(based on $nicename)"
fi
else
printf "%s" "$branch"
printf "%s" "${branch#$PREFIX}"
fi
echo
done
......@@ -122,70 +137,99 @@ cmd_help() {
exit 0
}
# Parse arguments and set common variables
parse_args() {
# parse options
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# read arguments into global variables
# Read arguments into global variables
if [ -z $1 ]; then
VERSION=''
else
VERSION=$1
fi
BRANCH=$PREFIX$VERSION
}
require_version_arg() {
if [ "$VERSION" = "" ]; then
warn "Missing argument <version>"
usage
exit 1
fi
}
require_no_existing_hotfix_branches() {
local hotfix_branches first_branch
require_base_is_on_master() {
if ! git branch --no-color --contains "$BASE" 2>/dev/null \
| sed 's/[* ] //g' \
| grep -q "^$MASTER_BRANCH\$"; then
die "fatal: Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'."
fi
}
hotfix_branches=$(git_local_branches_prefixed "$PREFIX")
first_branch=$(echo ${hotfix_branches} | head -n1)
require_no_existing_hotfix_branches() {
local hotfix_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
local first_branch=$(echo ${hotfix_branches} | head -n1)
first_branch=${first_branch#$PREFIX}
[ -z "$hotfix_branches" ] || \
die "There is an existing hotfix branch ($first_branch). Finish that one first."
[ -z "$hotfix_branches" ] || die "There is an existing hotfix branch '$first_branch'. Finish that one first."
}
cmd_start() {
DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
OPTIONS_SPEC="\
git flow hotfix start [-h] [-F] <version> [<base>]
Start new hotfix branch named <version>, optionally base it on <base> instead of the <master> branch
--
h,help! Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from origin before performing local operation
"
local base
# Define flags
DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
# Override defaults with values from config
gitflow_override_flag_boolean "hotfix.start.fetch" "fetch"
# Parse arguments
parse_args "$@"
BASE=${2:-$MASTER_BRANCH}
require_version_arg
require_base_is_on_master
require_no_existing_hotfix_branches
eval set -- "${FLAGS_ARGV}"
base=${2:-$MASTER_BRANCH}
# sanity checks
# No need to continue if not clean
require_base_is_local_branch "$base"
require_clean_working_tree
require_branch_absent "$BRANCH"
require_tag_absent "$VERSION_PREFIX$VERSION"
gitflow_config_set_base_branch $base $BRANCH
# Update the local repo with remote changes, if asked
if flag fetch; then
git_do fetch -q "$ORIGIN" "$MASTER_BRANCH"
git_fetch_branch "$ORIGIN" "$base"
fi
# Run filter on the version
VERSION=$(run_filter_hook hotfix-start-version $VERSION)
if [ $? -eq 127 ]; then
die $VERSION
fi
# As VERSION might have changed reset BRANCH with new VERSION
BRANCH=$PREFIX$VERSION
gitflow_require_version_arg
if ! $(git config --bool --get gitflow.multi-hotfix 2>&1); then
require_no_existing_hotfix_branches
fi
if has "$ORIGIN/$MASTER_BRANCH" $(git_remote_branches); then
require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
# Sanity checks
require_branch_absent "$BRANCH"
require_tag_absent "$VERSION_PREFIX$VERSION"
if git_remote_branch_exists "$ORIGIN/$base"; then
require_branches_equal "$base" "$ORIGIN/$base"
fi
# create branch
git_do checkout -b "$BRANCH" "$BASE"
run_pre_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH" "$base"
# Create branch
git_do checkout -b "$BRANCH" "$base" || die "Could not create hotfix branch '$BRANCH'."
run_post_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH" "$base"
echo
echo "Summary of actions:"
echo "- A new branch '$BRANCH' was created, based on '$BASE'"
echo "- You are now on branch '$BRANCH'"
echo "- A new branch '$BRANCH' was created, based on '$base'"
echo "- You are now on branch '$(git_current_branch)'"
echo
echo "Follow-up actions:"
echo "- Bump the version number now!"
echo "- Start committing your hot fixes"
echo "- Bump the version number now!"
echo "- When done, run:"
echo
echo " git flow hotfix finish '$VERSION'"
......@@ -193,43 +237,114 @@ cmd_start() {
}
cmd_publish() {
OPTIONS_SPEC="\
git flow hotfix publish [-h] <version>
Start sharing hotfix <name> on $ORIGIN
--
h,help! Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
require_version_arg
# sanity checks
# Use current branch if no version is given
if [ "$VERSION" = "" ]; then
gitflow_use_current_branch_version
fi
# Sanity checks
require_clean_working_tree
require_branch "$BRANCH"
git_do fetch -q "$ORIGIN"
git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
require_branch_absent "$ORIGIN/$BRANCH"
# create remote branch
git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
git_do fetch -q "$ORIGIN"
run_pre_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH"
# Create remote branch with remote tracking
git_do push -u "$ORIGIN" "$BRANCH:$BRANCH"
git_do fetch -q "$ORIGIN" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'."
# configure remote tracking
git config "branch.$BRANCH.remote" "$ORIGIN"
git config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
git_do checkout "$BRANCH"
run_post_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote branch '$BRANCH' was created"
echo "- The remote branch '$BRANCH' was created or updated"
echo "- The local branch '$BRANCH' was configured to track the remote branch"
echo "- You are now on branch '$BRANCH'"
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_rebase() {
OPTIONS_SPEC="\
git flow hotfix rebase [-h] [-i] [-p] [<name|nameprefix>]
Rebase <name> on <base_branch>
--
h,help! Show this help
showcommands! Show git commands while executing them
i,[no]interactive Do an interactive rebase
p,[no]preserve-merges Preserve merges
"
local opts
# Define flags
DEFINE_boolean 'interactive' false 'do an interactive rebase' i
DEFINE_boolean 'preserve-merges' false 'try to recreate merges' p
# Override defaults with values from config
gitflow_override_flag_boolean "hotfix.rebase.interactive" "interactive"
gitflow_override_flag_boolean "hotfix.rebase.preserve-merges" "preserve_merges"
# Parse arguments
parse_args "$@"
# Use current branch if no version is given
if [ "$VERSION" = "" ]; then
gitflow_use_current_branch_version
fi
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
warn "Will try to rebase '$NAME' which is based on '$BASE_BRANCH'..."
require_clean_working_tree
require_branch "$BRANCH"
git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't rebase the hotfixe branch '$BRANCH'."
git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'."
if flag interactive; then
opts="$opts -i"
fi
if flag preserve_merges; then
opts="$opts -p"
fi
git_do rebase $opts "$BASE_BRANCH"
}
cmd_track() {
OPTIONS_SPEC="\
git flow hotfix track [-h] <version>
Create a tracking hotfix branch from $ORIGIN
--
h,help! Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
require_version_arg
# sanity checks
gitflow_require_version_arg
# Sanity checks
require_clean_working_tree
require_branch_absent "$BRANCH"
git_do fetch -q "$ORIGIN"
require_branch "$ORIGIN/$BRANCH"
# create tracking branch
# Create tracking branch
git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH"
echo
......@@ -240,110 +355,372 @@ cmd_track() {
}
cmd_finish() {
DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean sign false "sign the release tag cryptographically" s
DEFINE_string signingkey "" "use the given GPG-key for the digital signature (implies -s)" u
DEFINE_string message "" "use the given tag message" m
DEFINE_string messagefile "" "use the contents of the given file as tag message" f
DEFINE_boolean push false "push to $ORIGIN after performing finish" p
DEFINE_boolean keep false "keep branch after performing finish" k
DEFINE_boolean notag false "don't tag this release" n
OPTIONS_SPEC="\
git flow hotfix finish [-h] [-F] [-s] [-u] [-m | -f ] [-p] [-k] [-n] [-b] [-S] <version>
Finish hotfix branch <version>
--
h,help! Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from origin before performing finish
s,[no]sign Sign the release tag cryptographically
u,[no]signingkey Use the given GPG-key for the digital signature (implies -s)
m,[no]message Use the given tag message
f,[no]messagefile= Use the contents of the given file as tag message
p,[no]push Push to origin after performing finish
k,[no]keep Keep branch after performing finish
[no]keepremote Keep the remote branch
[no]keeplocal Keep the local branch
D,[no]force_delete Force delete hotfix branch after finish
n,[no]notag Don't tag this hotfix
b,[no]nobackmerge Don't back-merge master, or tag if applicable, in develop
S,[no]squash Squash hotfix during merge
T,tagname! Use given tag name
"
local opts commit keepmsg remotebranchdeleted localbranchdeleted
# Define flags
DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean 'sign' false "sign the release tag cryptographically" s
DEFINE_string 'signingkey' "" "use the given GPG-key for the digital signature (implies -s)" u
DEFINE_string 'message' "" "use the given tag message" m
DEFINE_string 'messagefile' "" "use the contents of the given file as tag message" f
DEFINE_boolean 'push' false "push to $ORIGIN after performing finish" p
DEFINE_boolean 'keep' false "keep branch after performing finish" k
DEFINE_boolean 'keepremote' false "keep the remote branch"
DEFINE_boolean 'keeplocal' false "keep the local branch"
DEFINE_boolean 'force_delete' false "force delete hotfix branch after finish" D
DEFINE_boolean 'notag' false "don't tag this hotfix" n
DEFINE_boolean 'nobackmerge' false "don't back-merge $MASTER_BRANCH, or tag if applicable, in $DEVELOP_BRANCH " b
DEFINE_boolean 'squash' false "squash release during merge" S
DEFINE_boolean 'squash-info' false "add branch info during squash"
DEFINE_string 'tagname' "" "use the given tag name" T
# Override defaults with values from config
gitflow_override_flag_boolean "hotfix.finish.fetch" "fetch"
gitflow_override_flag_boolean "hotfix.finish.sign" "sign"
gitflow_override_flag_boolean "hotfix.finish.push" "push"
gitflow_override_flag_boolean "hotfix.finish.keep" "keep"
gitflow_override_flag_boolean "hotfix.finish.keepremote" "keepremote"
gitflow_override_flag_boolean "hotfix.finish.keeplocal" "keeplocal"
gitflow_override_flag_boolean "hotfix.finish.force-delete" "force_delete"
gitflow_override_flag_boolean "hotfix.finish.notag" "notag"
gitflow_override_flag_boolean "hotfix.finish.nobackmerge" "nobackmerge"
gitflow_override_flag_boolean "hotfix.finish.squash" "squash"
gitflow_override_flag_boolean "hotfix.finish.squash-info" "squash_info"
gitflow_override_flag_string "hotfix.finish.signingkey" "signingkey"
gitflow_override_flag_string "hotfix.finish.message" "message"
gitflow_override_flag_string "hotfix.finish.messagefile" "messagefile"
# Parse arguments
parse_args "$@"
require_version_arg
# handle flags that imply other flags
# Use current branch if no version is given
if [ "$VERSION" = "" ]; then
gitflow_use_current_branch_version
fi
# Use branch name if no tag name is given
if [ "$FLAGS_tagname" != "" ]; then
TAGNAME=$FLAGS_tagname
else
TAGNAME=$VERSION
fi
remotebranchdeleted=$FLAGS_FALSE
localbranchdeleted=$FLAGS_FALSE
# Handle flags that imply other flags
if [ "$FLAGS_signingkey" != "" ]; then
FLAGS_sign=$FLAGS_TRUE
fi
# sanity checks
# Keeping both branches implies the --keep flag to be true.
if flag keepremote && flag keeplocal; then
FLAGS_keep=$FLAGS_TRUE
fi
# Sanity checks
require_branch "$BRANCH"
require_clean_working_tree
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$MASTER_BRANCH}
git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't finish the hotfix branch '$BRANCH'."
# We always fetch the Branch from Origin
# This is done to avoid possible commits on the remote that are not
# merged into the local branch
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_fetch_branch "$ORIGIN" "$BRANCH"
fi
# Update local branches with remote branches
if flag fetch; then
git_do fetch -q "$ORIGIN" "$MASTER_BRANCH" || \
die "Could not fetch $MASTER_BRANCH from $ORIGIN."
git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH" || \
die "Could not fetch $DEVELOP_BRANCH from $ORIGIN."
git_fetch_branch "$ORIGIN" "$BASE_BRANCH"
[ "$BASE_BRANCH" = "$MASTER_BRANCH" ] && git_fetch_branch "$ORIGIN" "$DEVELOP_BRANCH"
fi
if has "$ORIGIN/$MASTER_BRANCH" $(git_remote_branches); then
require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
# Check if the local branches have all the commits from the remote branches
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
fi
if has "$ORIGIN/$DEVELOP_BRANCH" $(git_remote_branches); then
if git_remote_branch_exists "$ORIGIN/$BASE_BRANCH"; then
require_branches_equal "$BASE_BRANCH" "$ORIGIN/$BASE_BRANCH"
fi
if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
if git_remote_branch_exists "$ORIGIN/$DEVELOP_BRANCH"; then
require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
fi
fi
# try to merge into master
# in case a previous attempt to finish this release branch has failed,
# but the merge into master was successful, we skip it now
if ! git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH"; then
git_do checkout "$MASTER_BRANCH" || \
die "Could not check out $MASTER_BRANCH."
git_do merge --no-ff "$BRANCH" || \
die "There were merge conflicts."
# TODO: What do we do now?
# If the branch is already merged there is no need to check the hotfix branch
# This can happen when the merge in develop fails and we rerun the finish.
if ! git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
# Check if the hotfix branch:
# - has commits: No reason to finish a hotfix without commits
# - Is ahead of the BASE: If it's not a good idea to merge
# - Can be merged: If there's no common ancestor we can't merge the hotfix
git_compare_refs "$BRANCH" "$BASE_BRANCH"
case $? in
0)
die "You need some commits in the hotfix branch '$BRANCH'"
;;
1)
die "The hotfix branch '$BRANCH' is not ahead of branch '$BASE_BRANCH'"
;;
4)
die "The hotfix branch '$BRANCH' has no common ancestor with branch '$BASE_BRANCH'"
;;
*)
;;
esac
fi
if noflag notag; then
# We ask for a tag, be sure it does not exists or
# points to the latest hotfix commit
if git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
git_compare_refs "$BRANCH" "$VERSION_PREFIX$TAGNAME"^2 2>/dev/null
[ $? -eq 0 ] || die "Tag already exists and does not point to hotfix branch '$BRANCH'"
fi
fi
run_pre_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"
# Try to merge into BASE.
# In case a previous attempt to finish this release branch has failed,
# but the merge into BASE was successful, we skip it now
if ! git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
if noflag squash; then
git_do merge --no-ff "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
else
git_do merge --squash "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
flag squash_info && gitflow_create_squash_message "Merged hotfix branch '$BRANCH'" "$BASE_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG"
git_do commit
fi
fi
if noflag notag; then
# try to tag the release
# in case a previous attempt to finish this release branch has failed,
# Try to tag the release.
# In case a previous attempt to finish this release branch has failed,
# but the tag was set successful, we skip it now
local tagname=$VERSION_PREFIX$VERSION
if ! git_tag_exists "$tagname"; then
local opts="-a"
if ! git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
if [ "$FLAGS_message" != "" ] && [ "$FLAGS_messagefile" != "" ]; then
die "Use either -m,--message or -f,--messagefile. Can not use both options at the same time"
fi
opts="-a"
flag sign && opts="$opts -s"
[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
[ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'"
if [ "$FLAGS_message" != "" ]; then
# Run filter on the tag message
FLAGS_message=$(run_filter_hook hotfix-finish-tag-message "${FLAGS_message}" "$VERSION_PREFIX$TAGNAME")
opts="$opts -m '$FLAGS_message'"
fi
[ "$FLAGS_messagefile" != "" ] && opts="$opts -F '$FLAGS_messagefile'"
eval git_do tag $opts "$VERSION_PREFIX$VERSION" "$BRANCH" || \
die "Tagging failed. Please run finish again to retry."
eval git_do tag $opts "$VERSION_PREFIX$TAGNAME" || die "Tagging failed. Please run finish again to retry."
fi
fi
if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
# By default we back-merge the $MASTER_BRANCH unless the user explicitly
# stated not to do a back-merge, in that case we use the $BRANCH.
if noflag nobackmerge; then
MERGE_BRANCH="$BASE_BRANCH"
else
MERGE_BRANCH="$BRANCH"
fi
# try to merge into develop
# in case a previous attempt to finish this release branch has failed,
# Try to merge into develop.
# In case a previous attempt to finish this release branch has failed,
# but the merge into develop was successful, we skip it now
if ! git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH"; then
git_do checkout "$DEVELOP_BRANCH" || \
die "Could not check out $DEVELOP_BRANCH."
# TODO: Actually, accounting for 'git describe' pays, so we should
# ideally git merge --no-ff $tagname here, instead!
git_do merge --no-ff "$BRANCH" || \
die "There were merge conflicts."
if ! git_is_branch_merged_into "$MERGE_BRANCH" "$DEVELOP_BRANCH"; then
git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
if noflag nobackmerge; then
# Accounting for 'git describe', if a release is tagged
# we use the tag commit instead of the branch.
if noflag notag; then
commit="$VERSION_PREFIX$TAGNAME"
else
commit="$BASE_BRANCH"
fi
else
commit="$BRANCH"
fi
git_do merge --no-ff "$commit" || die "There were merge conflicts."
# TODO: What do we do now?
fi
fi
# delete branch
run_post_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"
# Delete branch
if noflag keep; then
git_do branch -d "$BRANCH"
# Always delete remote first
if noflag keepremote;then
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_remote_branch_delete "$BRANCH" && remotebranchdeleted=$FLAGS_TRUE
fi
fi
# Delete local after remote to avoid warnings
if noflag keeplocal; then
if [ "$BRANCH" = "$(git_current_branch)" ]; then
git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
fi
if flag force_delete; then
git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
else
git_do branch -d "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
fi
fi
# no more branches: we can safely remove config section
if ! git_remote_branch_exists "$ORIGIN/$BRANCH" -a ! git_local_branch_exists "$BRANCH"; then
gitflow_config_remove_base_section "$BRANCH"
fi
fi
if flag push; then
git_do push "$ORIGIN" "$DEVELOP_BRANCH" || \
die "Could not push to $DEVELOP_BRANCH from $ORIGIN."
git_do push "$ORIGIN" "$MASTER_BRANCH" || \
die "Could not push to $MASTER_BRANCH from $ORIGIN."
if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
git_do push "$ORIGIN" "$DEVELOP_BRANCH" || die "Could not push branch '$DEVELOP_BRANCH' to remote '$ORIGIN'."
fi
git_do push "$ORIGIN" "$BASE_BRANCH" || die "Could not push branch '$BASE_BRANCH' to remote '$ORIGIN'."
if noflag notag; then
git_do push --tags "$ORIGIN" || \
die "Could not push tags to $ORIGIN."
git_do push --tags "$ORIGIN" || die "Could not push tags to remote '$ORIGIN'."
fi
fi
echo
echo "Summary of actions:"
if flag fetch; then
echo "- Latest objects have been fetched from '$ORIGIN'"
echo "- Hotfix branch has been merged into '$MASTER_BRANCH'"
fi
echo "- Hotfix branch '$BRANCH' has been merged into '$BASE_BRANCH'"
if noflag notag; then
echo "- The hotfix was tagged '$VERSION_PREFIX$VERSION'"
echo "- The hotfix was tagged '$VERSION_PREFIX$TAGNAME'"
fi
if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
[ "$commit" = "$BASE_BRANCH" ] && echo "- Master branch '$BASE_BRANCH' has been back-merged into '$DEVELOP_BRANCH'"
[ "$commit" = "$VERSION_PREFIX$TAGNAME" ] && echo "- Hotfix tag '$VERSION_PREFIX$TAGNAME' has been back-merged into '$DEVELOP_BRANCH'"
[ "$commit" = "$BRANCH" ] && echo "- Hotfix branch '$BRANCH' has been merged into '$DEVELOP_BRANCH'"
fi
echo "- Hotfix branch has been back-merged into '$DEVELOP_BRANCH'"
if flag keep; then
echo "- Hotfix branch '$BRANCH' is still available"
if noflag keep; then
if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg="has been locally deleted"
else
echo "- Hotfix branch '$BRANCH' has been deleted"
keepmsg="is still locally available"
fi
if [ $remotebranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg=$keepmsg"; it has been remotely deleted from '$ORIGIN'"
elif git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
else
keepmsg="is still locally available"
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
fi
echo "- Hotfix branch '$BRANCH' "$keepmsg
if flag push; then
echo "- '$DEVELOP_BRANCH', '$MASTER_BRANCH' and tags have been pushed to '$ORIGIN'"
if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
echo "- '$DEVELOP_BRANCH', '$BASE_BRANCH' and tags have been pushed to '$ORIGIN'"
else
echo "- '$BASE_BRANCH' and tags have been pushed to '$ORIGIN'"
fi
fi
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_delete() {
OPTIONS_SPEC="\
git flow hotfix delete [-h] [-f] [-r] <name>
Delete the given hotfix branch
--
h,help! Show this help
showcommands! Show git commands while executing them
f,[no]force Force deletion
r,[no]remote Delete remote branch
"
local current_branch
# Define flags
DEFINE_boolean 'force' false "force deletion" f
DEFINE_boolean 'remote' false "delete remote branch" r
# Override defaults with values from config
gitflow_override_flag_boolean "hotfix.delete.force" "force"
gitflow_override_flag_boolean "hotfix.finish.remote" "remote"
# Parse arguments
parse_args "$@"
gitflow_require_version_arg
# Sanity checks
require_branch "$BRANCH"
run_pre_hook "$VERSION" "$ORIGIN" "$BRANCH"
current_branch=$(git_current_branch)
# We can't delete a branch we are on, switch to the master branch.
if [ "$BRANCH" = "$current_branch" ]; then
require_clean_working_tree
git_do checkout "$MASTER_BRANCH" || die "Could not check out branch '$MASTER_BRANCH'."
fi
if ( git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH" && git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH" ); then
git_do branch -d "$BRANCH" || die "Could not delete the $BRANCH."
if flag remote; then
git_do push "$ORIGIN" :"$BRANCH" || die "Could not delete the remote $BRANCH in $ORIGIN."
fi
else
if flag force; then
git_do branch -D "$BRANCH" || die "Could not delete the $BRANCH."
if flag remote; then
git_do push "$ORIGIN" :"$BRANCH" || die "Could not delete the remote $BRANCH in $ORIGIN."
fi
else
die "Hotfix branch '$BRANCH' has been not been merged in branch '$MASTER_BRANCH' and/or branch '$DEVELOP_BRANCH'. Use -f to force the deletion."
fi
fi
gitflow_config_remove_base_section "$BRANCH"
run_post_hook "$VERSION" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- Hotfix branch '$BRANCH' has been deleted."
flag remote && echo "- Hotfix branch '$BRANCH' in '$ORIGIN' has been deleted."
echo "- You are now on branch '$(git_current_branch)'"
echo
}
......@@ -2,81 +2,156 @@
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# Original blog post presenting this model is found at:
# http://nvie.com/git-model
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/nvie/gitflow
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of Vincent Driessen.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
usage() {
echo "usage: git flow init [-fd]"
OPTIONS_SPEC="\
git flow init
Initialize a new git repo with support for the branching model.
----
git flow init gitlab
Allow flow to automatically create merge requests on your behalf on gitlab
----
A personal access token is needed, create one at https://gitlab.com/profile/personal_access_tokens
git flow init github
Allow flow to automatically create pull requests on your behalf on github
----
Your username and a personal access token are need, create one at https://github.com/settings/tokens
----
For more specific help type the command followed by --help
--
"
flags_help
}
# Parse arguments and set common variables
parse_args() {
# parse options
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
}
# Default entry when no SUBACTION is given
cmd_default() {
DEFINE_boolean force false 'force setting of gitflow branches, even if already configured' f
DEFINE_boolean defaults false 'use default branch naming conventions' d
OPTIONS_SPEC="\
git flow init [-h] [-d] [-f]
Setup a git repository for git flow usage. Can also be used to start a git repository.
--
h,help! Show this help
showcommands! Show git commands while executing them
d,[no]defaults Use default branch naming conventions
f,[no]force Force setting of gitflow branches, even if already configured
Use config file location
local! use repository config file
global! use global config file
system! use system config file
file= use given config file
"
git config alias.start 'flow feature start'
git config alias.finish 'flow feature finish'
git config alias.fin 'flow feature finish'
git config alias.stop 'flow feature finish'
git config alias.resume 'flow feature resume'
git config alias.res 'flow feature resume'
git config alias.interrupt 'flow feature interrupt'
git config alias.int 'flow feature interrupt'
git config alias.pause 'flow feature pause'
git config alias.p 'flow feature pause'
git config alias.hotfix 'flow hotfix'
git config alias.hotfix 'flow hotfix'
git config alias.support 'flow support'
git config alias.release 'flow release'
local gitflow_config_option should_check_existence branchcount guess
local master_branch develop_branch default_suggestion answer prefix
# Define flags
DEFINE_boolean 'force' false 'force setting of gitflow branches, even if already configured' f
DEFINE_boolean 'defaults' false 'use default branch naming conventions' d
DEFINE_boolean 'local' false 'use repository config file'
DEFINE_boolean 'global' false 'use global config file'
DEFINE_boolean 'system' false 'use system config file'
DEFINE_string 'file' "" 'use given config file'
# Override defaults with values from config
gitflow_override_flag_boolean "init.defaults" "defaults"
# Parse arguments
parse_args "$@"
if [ "$FLAGS_file" != "" ]; then
gitflow_config_option="--file '$FLAGS_file''"
elif flag local; then
gitflow_config_option="--local"
elif flag global; then
gitflow_config_option="--global"
elif flag system; then
gitflow_config_option="--system"
else
gitflow_config_option=""
fi
if ! git rev-parse --git-dir >/dev/null 2>&1; then
git_do init
else
# assure that we are not working in a repo with local changes
# Assure that we are not working in a repo with local changes
git_repo_is_headless || require_clean_working_tree
fi
# running git flow init on an already initialized repo is fine
# Running git flow init on an already initialized repo is fine
if gitflow_is_initialized && ! flag force; then
warn "Already initialized for gitflow."
warn "To force reinitialization, use: git flow init -f"
exit 0
fi
local branch_count
local answer
if flag defaults; then
warn "Using default branch names."
fi
# add a master branch if no such branch exists yet
local master_branch
# Add a master branch if no such branch exists yet
if gitflow_has_master_configured && ! flag force; then
master_branch=$(git config --get gitflow.branch.master)
else
......@@ -86,8 +161,6 @@ cmd_default() {
# 2. Some branches do already exist
# We will disallow creation of new master/develop branches and
# rather allow to use existing branches for git-flow.
local default_suggestion
local should_check_existence
branch_count=$(git_local_branches | wc -l)
if [ "$branch_count" -eq 0 ]; then
echo "No branches exist yet. Base branches must be created now."
......@@ -100,13 +173,18 @@ cmd_default() {
should_check_existence=YES
default_suggestion=
for guess in $(git config --get gitflow.branch.master) \
'production' 'main' 'master'; do
for guess in $(git config --get gitflow.branch.master) 'production' 'main' 'master'; do
if git_local_branch_exists "$guess"; then
default_suggestion="$guess"
break
fi
done
fi
if [ -z $default_suggestion ] && flag defaults; then
should_check_existence=YES
default_suggestion=$(git config --get gitflow.branch.master || echo master)
fi
printf "Branch name for production releases: [$default_suggestion] "
......@@ -117,31 +195,27 @@ cmd_default() {
fi
master_branch=${answer:-$default_suggestion}
# check existence in case of an already existing repo
# Check existence in case of an already existing repo
if [ "$should_check_existence" = "YES" ]; then
# if no local branch exists and a remote branch of the same
# If no local branch exists and a remote branch of the same
# name exists, checkout that branch and use it for master
if ! git_local_branch_exists "$master_branch" && \
git_remote_branch_exists "origin/$master_branch"; then
if ! git_local_branch_exists "$master_branch" && git_remote_branch_exists "origin/$master_branch"; then
git_do branch "$master_branch" "origin/$master_branch" >/dev/null 2>&1
elif ! git_local_branch_exists "$master_branch"; then
die "Local branch '$master_branch' does not exist."
fi
fi
# store the name of the master branch
git_do config gitflow.branch.master "$master_branch"
# Store the name of the master branch
git_do config $gitflow_config_option gitflow.branch.master "$master_branch"
fi
# add a develop branch if no such branch exists yet
local develop_branch
# Add a develop branch if no such branch exists yet
if gitflow_has_develop_configured && ! flag force; then
develop_branch=$(git config --get gitflow.branch.develop)
else
# Again, the same two cases as with the master selection are
# considered (fresh repo or repo that contains branches)
local default_suggestion
local should_check_existence
branch_count=$(git_local_branches | grep -v "^${master_branch}\$" | wc -l)
if [ "$branch_count" -eq 0 ]; then
should_check_existence=NO
......@@ -153,19 +227,17 @@ cmd_default() {
should_check_existence=YES
default_suggestion=
for guess in $(git config --get gitflow.branch.develop) \
'develop' 'int' 'integration' 'master'; do
for guess in $(git config --get gitflow.branch.develop) 'develop' 'int' 'integration' 'master'; do
if git_local_branch_exists "$guess" && [ "$guess" != "$master_branch" ]; then
default_suggestion="$guess"
break
fi
done
if [ -z $default_suggestion ]; then
should_check_existence=NO
default_suggestion=$(git config --get gitflow.branch.develop || echo develop)
fi
if [ -z $default_suggestion ] && flag defaults; then
should_check_existence=YES
default_suggestion=$(git config --get gitflow.branch.develop || echo develop)
fi
printf "Branch name for \"next release\" development: [$default_suggestion] "
......@@ -180,14 +252,13 @@ cmd_default() {
die "Production and integration branches should differ."
fi
# check existence in case of an already existing repo
# Check existence in case of an already existing repo
if [ "$should_check_existence" = "YES" ]; then
git_local_branch_exists "$develop_branch" || \
die "Local branch '$develop_branch' does not exist."
git_local_branch_exists "$develop_branch" || die "Local branch '$develop_branch' does not exist."
fi
# store the name of the develop branch
git_do config gitflow.branch.develop "$develop_branch"
# Store the name of the develop branch
git_do config $gitflow_config_option gitflow.branch.develop "$develop_branch"
fi
# Creation of HEAD
......@@ -222,17 +293,18 @@ cmd_default() {
created_gitflow_branch=1
fi
# assert the gitflow repo has been correctly initialized
# Assert the git-flow repo has been correctly initialized
gitflow_is_initialized
# switch to develop branch if its newly created
# Switch to develop branch if its newly created
if [ $created_gitflow_branch -eq 1 ]; then
git_do checkout -q "$develop_branch"
git_do checkout -q "$develop_branch" || die "Could not check out branch '$develop_branch'."
fi
# finally, ask the user for naming conventions (branch and tag prefixes)
# Ask the user for naming conventions (branch and tag prefixes )
if flag force || \
! git config --get gitflow.prefix.feature >/dev/null 2>&1 ||
! git config --get gitflow.prefix.bugfix >/dev/null 2>&1 ||
! git config --get gitflow.prefix.release >/dev/null 2>&1 ||
! git config --get gitflow.prefix.hotfix >/dev/null 2>&1 ||
! git config --get gitflow.prefix.support >/dev/null 2>&1 ||
......@@ -241,19 +313,6 @@ cmd_default() {
echo "How to name your supporting branch prefixes?"
fi
git config --global alias.start 'flow feature start'
git config --global alias.finish 'flow feature finish'
git config --global alias.fin 'flow feature finish'
git config --global alias.stop 'flow feature finish'
git config --global alias.resume 'flow feature resume'
git config --global alias.res 'flow feature resume'
git config --global alias.interrupt 'flow feature interrupt'
git config --global alias.int 'flow feature interrupt'
git config --global alias.pause 'flow feature pause'
git config --global alias.p 'flow feature pause'
local prefix
# Feature branches
if ! git config --get gitflow.prefix.feature >/dev/null 2>&1 || flag force; then
default_suggestion=$(git config --get gitflow.prefix.feature || echo feature/)
......@@ -264,7 +323,20 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
git_do config gitflow.prefix.feature "$prefix"
git_do config $gitflow_config_option gitflow.prefix.feature "$prefix"
fi
# Bugfix branches
if ! git config --get gitflow.prefix.bugfix >/dev/null 2>&1 || flag force; then
default_suggestion=$(git config --get gitflow.prefix.bugfix || echo bugfix/)
printf "Bugfix branches? [$default_suggestion] "
if noflag defaults; then
read answer
else
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
git_do config $gitflow_config_option gitflow.prefix.bugfix "$prefix"
fi
# Release branches
......@@ -277,10 +349,9 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
git_do config gitflow.prefix.release "$prefix"
git_do config $gitflow_config_option gitflow.prefix.release "$prefix"
fi
# Hotfix branches
if ! git config --get gitflow.prefix.hotfix >/dev/null 2>&1 || flag force; then
default_suggestion=$(git config --get gitflow.prefix.hotfix || echo hotfix/)
......@@ -291,10 +362,9 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
git_do config gitflow.prefix.hotfix "$prefix"
git_do config $gitflow_config_option gitflow.prefix.hotfix "$prefix"
fi
# Support branches
if ! git config --get gitflow.prefix.support >/dev/null 2>&1 || flag force; then
default_suggestion=$(git config --get gitflow.prefix.support || echo support/)
......@@ -305,10 +375,9 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
git_do config gitflow.prefix.support "$prefix"
git_do config $gitflow_config_option gitflow.prefix.support "$prefix"
fi
# Version tag prefix
if ! git config --get gitflow.prefix.versiontag >/dev/null 2>&1 || flag force; then
default_suggestion=$(git config --get gitflow.prefix.versiontag || echo "")
......@@ -319,8 +388,24 @@ cmd_default() {
printf "\n"
fi
[ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion}
git_do config gitflow.prefix.versiontag "$prefix"
git_do config $gitflow_config_option gitflow.prefix.versiontag "$prefix"
fi
# Paths
if ! git config --get gitflow.path.hooks >/dev/null 2>&1 || flag force; then
DOT_GIT_DIR=$(git rev-parse --git-dir)
DOT_GIT_DIR=$(cd "$DOT_GIT_DIR" >/dev/null 2>&1 && pwd)
default_suggestion=$(git config --get gitflow.path.hooks || echo "$DOT_GIT_DIR"/hooks)
printf "Hooks and filters directory? [$default_suggestion] "
if noflag defaults; then
read answer
else
printf "\n"
fi
[ "$answer" = "-" ] && hooks_dir= || hooks_dir=${answer:-$default_suggestion}
git_do config $gitflow_config_option gitflow.path.hooks "$hooks_dir"
fi
mkdir -p "./.git/.gitflow"
git checkout --orphan flopharn
git rm * --quiet --ignore-unmatch
......@@ -339,13 +424,40 @@ cmd_default() {
configure_gitlab_api
fi
# TODO: what to do with origin?
}
cmd_help() {
usage
exit 0
}
cmd_github() {
OPTIONS_SPEC="\
git flow init github
Allow flow to automatically create pull requests on your behalf on github
----
Your username and a personal access token are need, create one at https://github.com/settings/tokens
"
parse_args "$@"
configure_github_api
}
cmd_gitlab() {
OPTIONS_SPEC="\
git flow init gitlab
Allow flow to automatically create merge requests on your behalf on gitlab
----
A personal access token is needed, create one at https://gitlab.com/profile/personal_access_tokens
"
parse_args "$@"
configure_gitlab_api
}
......@@ -401,13 +513,3 @@ configure_gitlab_api() {
esac
}
\ No newline at end of file
cmd_help() {
usage
exit 0
}
#
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
initialize() {
require_git_repo
require_gitflow_initialized
gitflow_load_settings
}
usage() {
OPTIONS_SPEC="\
git flow log
shows current branch log compared to develop
'git help log' for arguments
--
"
flags_help
}
# Parse arguments and set common variables
parse_args() {
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
}
cmd_default() {
cmd_list "$@"
}
cmd_list() {
OPTIONS_SPEC="\
git flow feature log [<options>]
Show log on <feature> branch since the fork of <develop> branch
Options come from git log
--
h,help! Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
# get base branch from current branch
local base=$(gitflow_config_get_base_branch $(git_current_branch))
# no base branch found, comparing against $master
if [ -z $base ]; then
base=$MASTER_BRANCH
fi
# Get the log
echo "Comparing against \"$base\" branch\n"
git_do log "$@""$base.."
}
cmd_help() {
usage
exit 0
}
......@@ -2,54 +2,427 @@
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# Original blog post presenting this model is found at:
# http://nvie.com/git-model
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/nvie/gitflow
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of Vincent Driessen.
# Function used by finish command to actually finish the release branch
# Called when the base of the release is the $DEVELOP_BRANCH
#
_finish_from_develop() {
local opts merge_branch commit keepmsg remotebranchdeleted localbranchdeleted compare_refs_result merge_result
remotebranchdeleted=$FLAGS_FALSE
localbranchdeleted=$FLAGS_FALSE
# Update local branches with remote branches
if flag fetch; then
git_fetch_branch "$ORIGIN" "$MASTER_BRANCH"
git_fetch_branch "$ORIGIN" "$DEVELOP_BRANCH"
fi
# Check if the local branches have all the commits from the remote branches
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
fi
if git_remote_branch_exists "$ORIGIN/$MASTER_BRANCH"; then
if flag ff_master; then
git_compare_refs "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
compare_refs_result=$?
if [ $compare_refs_result -gt 0 ]; then
warn "Branches '"$MASTER_BRANCH"' and '"$ORIGIN/$MASTER_BRANCH"' have diverged."
if [ $compare_refs_result -eq 1 ]; then
warn "Fast forwarding '"$MASTER_BRANCH"'."
git_do checkout "$MASTER_BRANCH" || die "Could not check out branch '$MASTER_BRANCH'."
git_do merge --ff-only "$ORIGIN/$MASTER_BRANCH" >/dev/null 2>&1
merge_result=$?
git_do checkout "$BRANCH"
if [ $merge_result -gt 0 ]; then
die "'"$MASTER_BRANCH"' can not be fast forwarded."
fi
elif [ $compare_refs_result -eq 2 ]; then
# Warn here, since there is no harm in being ahead
warn "And local branch '$1' is ahead of '$2'."
else
die "Branches need merging first."
fi
fi
else
require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
fi
fi
if git_remote_branch_exists "$ORIGIN/$DEVELOP_BRANCH"; then
require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
fi
if noflag notag; then
# We ask for a tag, be sure it does not exists or
# points to the latest hotfix commit
if git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
git_compare_refs "$BRANCH" "$VERSION_PREFIX$TAGNAME"^2 2>/dev/null
[ $? -eq 0 ] || die "Tag already exists and does not point to release branch '$BRANCH'"
fi
fi
run_pre_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"
# Try to merge into master.
# In case a previous attempt to finish this release branch has failed,
# but the merge into master was successful, we skip it now
if ! git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH"; then
git_do checkout "$MASTER_BRANCH" || die "Could not check out branch '$MASTER_BRANCH'."
if noflag squash; then
git_do merge --no-ff "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
else
git_do merge --squash "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
flag squash_info && gitflow_create_squash_message "Merged release branch '$BRANCH'" "$MASTER_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG"
git_do commit
fi
fi
if noflag notag; then
# Try to tag the release.
# In case a previous attempt to finish this release branch has failed,
# but the tag was set successful, we skip it now
if ! git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
git_do checkout "$MASTER_BRANCH" || die "Could not check out branch '$MASTER_BRANCH'."
if [ "$FLAGS_message" != "" ] && [ "$FLAGS_messagefile" != "" ]; then
die "Use either -m,--message or -f,--messagefile. Can not use both options at the same time"
fi
opts="-a"
flag sign && opts="$opts -s"
[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
if [ "$FLAGS_message" != "" ]; then
# Run filter on the tag message
FLAGS_message=$(run_filter_hook release-finish-tag-message "${FLAGS_message}" "$VERSION_PREFIX$TAGNAME")
opts="$opts -m '$FLAGS_message'"
fi
[ "$FLAGS_messagefile" != "" ] && opts="$opts -F '$FLAGS_messagefile'"
eval git_do tag $opts "$VERSION_PREFIX$TAGNAME" || die "Tagging failed. Please run finish again to retry."
fi
fi
# By default we backmerge the $MASTER_BRANCH unless the user explicitly
# stated not to do a back merge, in that case we use the $BRANCH.
if noflag nobackmerge; then
merge_branch="$MASTER_BRANCH"
else
merge_branch="$BRANCH"
fi
# Try to merge into develop.
# In case a previous attempt to finish this release branch has failed,
# but the merge into develop was successful, we skip it now
if ! git_is_branch_merged_into "$merge_branch" "$DEVELOP_BRANCH"; then
git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
if noflag nobackmerge; then
# Accounting for 'git describe', if a release is tagged
# we use the tag commit instead of the branch.
if noflag notag; then
commit="$VERSION_PREFIX$TAGNAME"
else
commit="$MASTER_BRANCH"
fi
git_do merge --no-ff "$commit" || die "There were merge conflicts." # TODO: What do we do now?
else
commit="$BRANCH"
if noflag squash; then
git_do merge --no-ff "$commit" || die "There were merge conflicts." # TODO: What do we do now?
else
git_do merge --squash "$commit" || die "There were merge conflicts." # TODO: What do we do now?
flag squash_info && gitflow_create_squash_message "Merged release branch '$BRANCH'" "$DEVELOP_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG"
git_do commit
fi
fi
fi
run_post_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"
# Delete branch
if noflag keep; then
if [ "$BRANCH" = "$(git_current_branch)" ]; then
git_do checkout "$MASTER_BRANCH" || die "Could not check out branch '$MASTER_BRANCH'."
fi
# Always delete remote first
if noflag keepremote;then
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_remote_branch_delete "$BRANCH" && remotebranchdeleted=$FLAGS_TRUE
fi
fi
# Delete local after remote to avoid warnings
if noflag keeplocal; then
if flag force_delete; then
git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
else
if noflag squash; then
git_do branch -d "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
else
git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
fi
fi
fi
# no more branches: we can safely remove config section
if ! git_remote_branch_exists "$ORIGIN/$BRANCH" -a ! git_local_branch_exists "$BRANCH"; then
gitflow_config_remove_base_section "$BRANCH"
fi
fi
init() {
if flag push; then
if flag pushdevelop; then
git_do push "$ORIGIN" "$DEVELOP_BRANCH" || die "Could not push branch '$DEVELOP_BRANCH' to remote '$ORIGIN'."
fi
if flag pushproduction; then
git_do push "$ORIGIN" "$MASTER_BRANCH" || die "Could not push branch '$MASTER_BRANCH' to remote '$ORIGIN'."
fi
if noflag notag && flag pushtag; then
git_do push --tags "$ORIGIN" || die "Could not push tags to remote '$ORIGIN'."
fi
fi
echo
echo "Summary of actions:"
if flag fetch; then
echo "- Latest objects have been fetched from '$ORIGIN'"
fi
echo "- Release branch '$BRANCH' has been merged into '$MASTER_BRANCH'"
if noflag notag; then
echo "- The release was tagged '$VERSION_PREFIX$TAGNAME'"
fi
[ "$commit" = "$MASTER_BRANCH" ] && echo "- Master branch '$MASTER_BRANCH' has been back-merged into '$DEVELOP_BRANCH'"
[ "$commit" = "$VERSION_PREFIX$TAGNAME" ] && echo "- Release tag '$VERSION_PREFIX$TAGNAME' has been back-merged into '$DEVELOP_BRANCH'"
[ "$commit" = "$BRANCH" ] && echo "- Release branch '$BRANCH' has been merged into '$DEVELOP_BRANCH'"
if noflag keep; then
if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg="has been locally deleted"
else
keepmsg="is still locally available"
fi
if [ $remotebranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg=$keepmsg"; it has been remotely deleted from '$ORIGIN'"
elif git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
else
keepmsg="is still locally available"
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
fi
echo "- Release branch '$BRANCH' "$keepmsg
if flag push; then
echo "- '$DEVELOP_BRANCH', '$MASTER_BRANCH' and tags have been pushed to '$ORIGIN'"
fi
echo "- You are now on branch '$(git_current_branch)'"
echo
}
#
# Function used by finish command to actually finish the release branch
# Called when the base of the release is NOT the $DEVELOP_BRANCH
#
_finish_base() {
local opts merge_branch commit keepmsg localbranchdeleted remotebranchdeleted
remotebranchdeleted=$FLAGS_FALSE
localbranchdeleted=$FLAGS_FALSE
# Update local branches with remote branches
if flag fetch; then
git_fetch_branch "$ORIGIN" "$BASE_BRANCH"
fi
# Check if the local branches have all the commits from the remote branches
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
fi
if git_remote_branch_exists "$ORIGIN/$BASE_BRANCH"; then
require_branches_equal "$BASE_BRANCH" "$ORIGIN/$BASE_BRANCH"
fi
if noflag notag; then
# We ask for a tag, be sure it does not exists or
# points to the latest hotfix commit
if git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
git_compare_refs "$BRANCH" "$VERSION_PREFIX$TAGNAME"^2 2>/dev/null
[ $? -eq 0 ] || die "Tag already exists and does not point to release branch '$BRANCH'"
fi
fi
run_pre_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"
# Try to merge into base branch.
# In case a previous attempt to finish this release branch has failed,
# but the merge into develop was successful, we skip it now
if ! git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
if noflag squash; then
git_do merge --no-ff "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
else
git_do merge --squash "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
flag squash_info && gitflow_create_squash_message "Merged release branch '$BRANCH'" "$BASE_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG"
git_do commit
fi
fi
if noflag notag; then
# Try to tag the release.
# In case a previous attempt to finish this release branch has failed,
# but the tag was set successful, we skip it now
if ! git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
if [ "$FLAGS_message" != "" ] && [ "$FLAGS_messagefile" != "" ]; then
die "Use either -m,--message or -f,--messagefile. Can not use both options at the same time"
fi
opts="-a"
flag sign && opts="$opts -s"
[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
if [ "$FLAGS_message" != "" ]; then
# Run filter on the tag message
FLAGS_message=$(run_filter_hook release-finish-tag-message "${FLAGS_message}" "$VERSION_PREFIX$TAGNAME")
opts="$opts -m '$FLAGS_message'"
fi
[ "$FLAGS_messagefile" != "" ] && opts="$opts -F '$FLAGS_messagefile'"
eval git_do tag $opts "$VERSION_PREFIX$TAGNAME" || die "Tagging failed. Please run finish again to retry."
fi
fi
run_post_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"
# Delete branch
if noflag keep; then
# Always delete remote first
if noflag keepremote;then
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_remote_branch_delete "$BRANCH" && remotebranchdeleted=$FLAGS_TRUE
fi
fi
# Delete local after remote to avoid warnings
if noflag keeplocal; then
if [ "$BRANCH" = "$(git_current_branch)" ]; then
git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
fi
if flag force_delete; then
git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
else
git_do branch -d "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
fi
fi
# no more branches: we can safely remove config section
if ! git_remote_branch_exists "$ORIGIN/$BRANCH" -a ! git_local_branch_exists "$BRANCH"; then
gitflow_config_remove_base_section "$BRANCH"
fi
fi
if flag push; then
if flag pushdevelop; then
git_do push "$ORIGIN" "$BASE_BRANCH" || die "Could not push branch '$BASE_BRANCH' to remote '$ORIGIN'."
fi
if noflag notag && flag pushtag; then
git_do push --tags "$ORIGIN" || die "Could not push tags to remote '$ORIGIN'."
fi
fi
echo
echo "Summary of actions:"
if flag fetch; then
echo "- Latest objects have been fetched from '$ORIGIN'"
fi
if noflag notag; then
echo "- The release was tagged '$VERSION_PREFIX$TAGNAME'"
fi
[ "$commit" = "$VERSION_PREFIX$TAGNAME" ] && echo "- Release tag '$VERSION_PREFIX$TAGNAME' has been merged into '$BASE_BRANCH'"
[ "$commit" = "$BRANCH" ] && echo "- Release branch '$BRANCH' has been merged into '$BASE_BRANCH'"
if noflag keep; then
if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg="has been locally deleted"
else
keepmsg="is still locally available"
fi
if [ $remotebranchdeleted -eq $FLAGS_TRUE ]; then
keepmsg=$keepmsg"; it has been remotely deleted from '$ORIGIN'"
elif git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
else
keepmsg="is still locally available"
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
fi
fi
echo "- Release branch '$BRANCH' "$keepmsg
if flag push; then
echo "- '$BASE_BRANCH' and tags have been pushed to '$ORIGIN'"
fi
echo "- You are now on branch '$(git_current_branch)'"
echo
}
initialize() {
require_git_repo
require_gitflow_initialized
git config --get gitflow.prefix.release >/dev/null 2>&1 || die "Release prefix not set. Please run 'git flow init'."
gitflow_load_settings
VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`")
VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
PREFIX=$(git config --get gitflow.prefix.release)
}
usage() {
echo "usage: git flow release [list] [-v]"
echo " git flow release start [-F] <version> [<base>]"
echo " git flow release finish [-FsumpkS] <version>"
echo " git flow release publish <name>"
echo " git flow release track <name>"
OPTIONS_SPEC="\
git flow release [list]
git flow release start
git flow release finish
git flow release publish
git flow release track
git flow release delete
Manage your release branches.
For more specific help type the command followed by --help
--
"
flags_help
}
cmd_default() {
......@@ -57,13 +430,28 @@ cmd_default() {
}
cmd_list() {
DEFINE_boolean verbose false 'verbose (more) output' v
OPTIONS_SPEC="\
git flow release [list] [-h] [-v]
List existing release branches
--
h,help! Show this help
v,verbose! verbose (more) output
"
local release_branches current_branch
local width branch len
local base develop_sha branch_sha nicename
# cmd_default may already define flags
# at this stage we can not use parse_args
if [ -z "${FLAGS_verbose}" ]; then
DEFINE_boolean 'verbose' false 'verbose (more) output' v
fi
# Parse arguments
parse_args "$@"
local release_branches
local current_branch
local short_names
release_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
release_branches=$(git_local_branches_prefixed "$PREFIX")
if [ -z "$release_branches" ]; then
warn "No release branches exist."
warn ""
......@@ -74,39 +462,35 @@ cmd_list() {
exit 0
fi
current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
short_names=$(echo "$release_branches" | sed "s ^$PREFIX g")
current_branch=$(git_current_branch)
# determine column width first
local width=0
local branch
for branch in $short_names; do
local len=${#branch}
# Determine column width first
width=0
for branch in $release_branches; do
len=${#branch}
width=$(max $width $len)
done
width=$(($width+3))
local branch
for branch in $short_names; do
local fullname=$PREFIX$branch
local base=$(git merge-base "$fullname" "$DEVELOP_BRANCH")
local develop_sha=$(git rev-parse "$DEVELOP_BRANCH")
local branch_sha=$(git rev-parse "$fullname")
if [ "$fullname" = "$current_branch" ]; then
width=$(($width+3-${#PREFIX}))
for branch in $release_branches; do
base=$(git merge-base "$branch" "$DEVELOP_BRANCH")
develop_sha=$(git rev-parse "$DEVELOP_BRANCH")
branch_sha=$(git rev-parse "$branch")
if [ "$branch" = "$current_branch" ]; then
printf "* "
else
printf " "
fi
if flag verbose; then
printf "%-${width}s" "$branch"
printf "%-${width}s" "${branch#$PREFIX}"
if [ "$branch_sha" = "$develop_sha" ]; then
printf "(no commits yet)"
else
local nicename=$(git rev-parse --short "$base")
nicename=$(git rev-parse --short "$base")
printf "(based on $nicename)"
fi
else
printf "%s" "$branch"
printf "%s" "${branch#$PREFIX}"
fi
echo
done
......@@ -117,66 +501,91 @@ cmd_help() {
exit 0
}
# Parse arguments and set common variables
parse_args() {
# parse options
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# read arguments into global variables
# Read arguments into global variables
if [ -z $1 ]; then
VERSION=''
else
VERSION=$1
fi
BRANCH=$PREFIX$VERSION
}
require_version_arg() {
if [ "$VERSION" = "" ]; then
warn "Missing argument <version>"
usage
exit 1
fi
}
require_no_existing_release_branches() {
local release_branches first_branch
require_base_is_on_develop() {
if ! git_do branch --no-color --contains "$BASE" 2>/dev/null \
| sed 's/[* ] //g' \
| grep -q "^$DEVELOP_BRANCH\$"; then
die "fatal: Given base '$BASE' is not a valid commit on '$DEVELOP_BRANCH'."
fi
}
release_branches=$(git_local_branches_prefixed "$PREFIX")
first_branch=$(echo ${release_branches} | head -n1)
require_no_existing_release_branches() {
local release_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
local first_branch=$(echo ${release_branches} | head -n1)
first_branch=${first_branch#$PREFIX}
[ -z "$release_branches" ] || \
die "There is an existing release branch ($first_branch). Finish that one first."
[ -z "$release_branches" ] || die "There is an existing release branch '$first_branch'. Finish that one first."
}
cmd_start() {
DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
OPTIONS_SPEC="\
git flow release start [options] <version> [<base>]
Start a new release branch
--
h,help! Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from $ORIGIN before performing finish
v,verbose! Verbose (more) output
"
local base
# Define flags
DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
# Override defaults with values from config
gitflow_override_flag_boolean "release.start.fetch" "fetch"
# Parse arguments
parse_args "$@"
BASE=${2:-$DEVELOP_BRANCH}
require_version_arg
require_base_is_on_develop
eval set -- "${FLAGS_ARGV}"
base=${2:-$DEVELOP_BRANCH}
# Run filter on the version
VERSION=$(run_filter_hook release-start-version $VERSION)
if [ $? -eq 127 ]; then
die $VERSION
fi
# As VERSION might have changed reset BRANCH with new VERSION
BRANCH=$PREFIX$VERSION
require_base_is_local_branch "$base"
gitflow_require_version_arg
gitflow_config_set_base_branch $base $BRANCH
require_no_existing_release_branches
# sanity checks
# Sanity checks
require_clean_working_tree
require_branch_absent "$BRANCH"
require_tag_absent "$VERSION_PREFIX$VERSION"
if flag fetch; then
git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
git_fetch_branch "$ORIGIN" "$base"
fi
if has "$ORIGIN/$DEVELOP_BRANCH" $(git_remote_branches); then
require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
if git_remote_branch_exists "$ORIGIN/$base"; then
require_branches_equal "$base" "$ORIGIN/$base"
fi
# create branch
git_do checkout -b "$BRANCH" "$BASE"
run_pre_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH" "$base"
# Create branch
git_do checkout -b "$BRANCH" "$base" || die "Could not create release branch '$BRANCH'."
run_post_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH" "$base"
echo
echo "Summary of actions:"
echo "- A new branch '$BRANCH' was created, based on '$BASE'"
echo "- You are now on branch '$BRANCH'"
echo "- A new branch '$BRANCH' was created, based on '$base'"
echo "- You are now on branch '$(git_current_branch)'"
echo
echo "Follow-up actions:"
echo "- Bump the version number now!"
......@@ -188,178 +597,491 @@ cmd_start() {
}
cmd_finish() {
DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean sign false "sign the release tag cryptographically" s
DEFINE_string signingkey "" "use the given GPG-key for the digital signature (implies -s)" u
DEFINE_string message "" "use the given tag message" m
DEFINE_string messagefile "" "use the contents of the given file as a tag message" f
DEFINE_boolean push false "push to $ORIGIN after performing finish" p
DEFINE_boolean keep false "keep branch after performing finish" k
DEFINE_boolean notag false "don't tag this release" n
DEFINE_boolean squash false "squash release during merge" S
OPTIONS_SPEC="\
git flow release finish [-h] [-F] [-s] [-u] [-m | -f] [-p] [-k] [-n] [-b] [-S] <version>
Finish a release branch
--
h,help Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from origin before performing finish
s,sign! Sign the release tag cryptographically
u,signingkey! Use the given GPG-key for the digital signature (implies -s)
m,message! Use the given tag message
f,[no]messagefile= Use the contents of the given file as a tag message
p,[no]push Push to origin after performing finish
[no]pushproduction Push the production branch
[no]pushdevelop Push the develop branch
[no]pushtag Push the tag
k,[no]keep Keep branch after performing finish
[no]keepremote Keep the remote branch
[no]keeplocal Keep the local branch
D,[no]force_delete Force delete release branch after finish
n,[no]tag Don't tag this release
b,[no]nobackmerge Don't back-merge master, or tag if applicable, in develop
S,[no]squash Squash release during merge
[no]ff-master Fast forward master branch if possible
T,tagname! Use given tag name
"
# Define flags
DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean 'sign' false "sign the release tag cryptographically" s
DEFINE_string 'signingkey' "" "use the given GPG-key for the digital signature (implies -s)" u
DEFINE_string 'message' "" "use the given tag message" m
DEFINE_string 'messagefile' "" "use the contents of the given file as a tag message" f
DEFINE_boolean 'push' false "push to $ORIGIN after performing finish" p
DEFINE_boolean 'pushproduction' false "push the production branch"
DEFINE_boolean 'pushdevelop' false "push the develop branch"
DEFINE_boolean 'pushtag' false "push the tag"
DEFINE_boolean 'keep' false "keep branch after performing finish" k
DEFINE_boolean 'keepremote' false "keep the remote branch"
DEFINE_boolean 'keeplocal' false "keep the local branch"
DEFINE_boolean 'force_delete' false "force delete release branch after finish" D
DEFINE_boolean 'notag' false "don't tag this release" n
DEFINE_boolean 'nobackmerge' false "don't back-merge $MASTER_BRANCH, or tag if applicable, in $DEVELOP_BRANCH " b
DEFINE_boolean 'squash' false "squash release during merge" S
DEFINE_boolean 'squash-info' false "add branch info during squash"
DEFINE_boolean 'ff-master' false "fast forward master branch if possible"
DEFINE_string 'tagname' "" "use the given tag name" T
# Override defaults with values from config
gitflow_override_flag_boolean "release.finish.fetch" "fetch"
gitflow_override_flag_boolean "release.finish.sign" "sign"
gitflow_override_flag_boolean "release.finish.push" "push"
gitflow_override_flag_boolean "release.finish.pushproduction" "pushproduction"
gitflow_override_flag_boolean "release.finish.pushdevelop" "pushdevelop"
gitflow_override_flag_boolean "release.finish.pushtag" "pushtag"
gitflow_override_flag_boolean "release.finish.keep" "keep"
gitflow_override_flag_boolean "release.finish.keepremote" "keepremote"
gitflow_override_flag_boolean "release.finish.keeplocal" "keeplocal"
gitflow_override_flag_boolean "release.finish.force-delete" "force_delete"
gitflow_override_flag_boolean "release.finish.notag" "notag"
gitflow_override_flag_boolean "release.finish.nobackmerge" "nobackmerge"
gitflow_override_flag_boolean "release.finish.squash" "squash"
gitflow_override_flag_boolean "release.finish.squash-info" "squash_info"
gitflow_override_flag_boolean "release.finish.ff-master" "ff-master"
gitflow_override_flag_string "release.finish.signingkey" "signingkey"
gitflow_override_flag_string "release.finish.message" "message"
gitflow_override_flag_string "release.finish.messagefile" "messagefile"
# Parse arguments
parse_args "$@"
require_version_arg
# handle flags that imply other flags
# Use current branch if no version is given
if [ "$VERSION" = "" ]; then
gitflow_use_current_branch_version
fi
# Run filter on the version
VERSION=$(run_filter_hook release-finish-version $VERSION)
if [ $? -eq 127 ]; then
die $VERSION
fi
# Use branch name if no tag name is given
if [ "$FLAGS_tagname" != "" ]; then
TAGNAME=$FLAGS_tagname
else
TAGNAME=$VERSION
fi
# As VERSION might have changed reset BRANCH with new VERSION
BRANCH=$PREFIX$VERSION
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't finish the release branch '$BRANCH'."
# Handle flags that imply other flags
if [ "$FLAGS_signingkey" != "" ]; then
FLAGS_sign=$FLAGS_TRUE
fi
# sanity checks
# Keeping both branches implies the --keep flag to be true.
if flag keepremote && flag keeplocal; then
FLAGS_keep=$FLAGS_TRUE
fi
# Pushing implies we push all.
if flag push; then
FLAGS_pushproduction=$FLAGS_TRUE
FLAGS_pushdevelop=$FLAGS_TRUE
FLAGS_pushtag=$FLAGS_TRUE
fi
# If we push either of these it means we need to do a push
if flag pushproduction || flag pushdevelop || flag pushtag; then
FLAGS_push=$FLAGS_TRUE
fi
# Sanity checks
require_branch "$BRANCH"
require_clean_working_tree
# We always fetch the Branch from Origin
# This is done to avoid possible commits on the remote that are not
# merged into the local branch
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_fetch_branch "$ORIGIN" "$BRANCH"
fi
if [ "$BASE_BRANCH" = "$DEVELOP_BRANCH" ]; then
_finish_from_develop
else
_finish_base
fi
}
cmd_branch() {
OPTIONS_SPEC="\
git flow release branch [-h] [-F] [-s] [-u] [-m] [-f] [-p] [-n] [-S] <version> [<name>]
Release a branch [<name>], if a name is not given it defaults to the develop branch, and use the given version <version>
--
h,help Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from origin before performing finish
s,sign! Sign the release tag cryptographically
u,signingkey! Use the given GPG-key for the digital signature (implies -s)
m,message! Use the given tag message
f,[no]messagefile= Use the contents of the given file as a tag message
p,[no]push Push to origin after performing finish
n,[no]tag Don't tag this release
S,[no]squash Squash release during merge
"
local opts
# Define flags
DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean 'sign' false "sign the release tag cryptographically" s
DEFINE_string 'signingkey' "" "use the given GPG-key for the digital signature (implies -s)" u
DEFINE_string 'message' "" "use the given tag message" m
DEFINE_string 'messagefile' "" "use the contents of the given file as a tag message" f
DEFINE_boolean 'push' false "push to $ORIGIN after performing finish" p
DEFINE_boolean 'notag' false "don't tag this release" n
DEFINE_boolean 'squash' false "squash release during merge" S
DEFINE_boolean 'squash-info' false "add branch info during squash"
# Override defaults with values from config
gitflow_override_flag_boolean "release.branch.fetch" "fetch"
gitflow_override_flag_boolean "release.branch.sign" "sign"
gitflow_override_flag_boolean "release.branch.push" "push"
gitflow_override_flag_boolean "release.branch.notag" "notag"
gitflow_override_flag_boolean "release.branch.squash" "squash"
gitflow_override_flag_boolean "release.branch.squash-info" "squash_info"
gitflow_override_flag_string "release.branch.signingkey" "signingkey"
gitflow_override_flag_string "release.branch.message" "message"
gitflow_override_flag_string "release.branch.messagefile" "messagefile"
# Parse arguments
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# Read arguments into global variables
VERSION=$1
BRANCH=${2:-$DEVELOP_BRANCH}
# Run filter on the version
VERSION=$(run_filter_hook branch-finish-version $VERSION)
if [ $? -eq 127 ]; then
die $VERSION
fi
gitflow_require_version_arg
# Handle flags that imply other flags
if [ "$FLAGS_signingkey" != "" ]; then
FLAGS_sign=$FLAGS_TRUE
fi
# Sanity checks
if gitflow_is_prefixed_branch "$BRANCH"; then
die "Branch '$BRANCH' seems to be a git-flow branch. It's not allowed to release this directly."
fi
if [ "$BRANCH" = "$MASTER_BRANCH" ]; then
die "Can not release from the the master branch"
fi
require_branch "$BRANCH"
require_clean_working_tree
# We always fetch the Branch from Origin
# This is done to avoid possible commits on the remote that are not
# merged into the local branch
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
git_fetch_branch "$ORIGIN" "$BRANCH"
fi
# Update local branches with remote branches
if flag fetch; then
git_do fetch -q "$ORIGIN" "$MASTER_BRANCH" || \
die "Could not fetch $MASTER_BRANCH from $ORIGIN."
git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH" || \
die "Could not fetch $DEVELOP_BRANCH from $ORIGIN."
git_fetch_branch "$ORIGIN" "$MASTER_BRANCH"
fi
if has "$ORIGIN/$MASTER_BRANCH" $(git_remote_branches); then
require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
# Check if the local branches have all the commits from the remote branches
if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
fi
if has "$ORIGIN/$DEVELOP_BRANCH" $(git_remote_branches); then
require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
if git_remote_branch_exists "$ORIGIN/$MASTER_BRANCH"; then
require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH"
fi
# try to merge into master
# in case a previous attempt to finish this release branch has failed,
run_pre_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH"
# Try to merge into master.
# In case a previous attempt to finish this release branch has failed,
# but the merge into master was successful, we skip it now
if ! git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH"; then
git_do checkout "$MASTER_BRANCH" || \
die "Could not check out $MASTER_BRANCH."
git_do checkout "$MASTER_BRANCH" || die "Could not check out branch '$MASTER_BRANCH'."
if noflag squash; then
git_do merge --no-ff "$BRANCH" || \
die "There were merge conflicts."
# TODO: What do we do now?
git_do merge --no-ff "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
else
git_do merge --squash "$BRANCH" || \
die "There were merge conflicts."
git_do merge --squash "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
flag squash_info && gitflow_create_squash_message "Merged release branch '$BRANCH'" "$MASTER_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG"
git_do commit
fi
fi
if noflag notag; then
# try to tag the release
# in case a previous attempt to finish this release branch has failed,
# Try to tag the release.
# In case a previous attempt to finish this release branch has failed,
# but the tag was set successful, we skip it now
local tagname=$VERSION_PREFIX$VERSION
if ! git_tag_exists "$tagname"; then
local opts="-a"
if ! git_tag_exists "$VERSION_PREFIX$VERSION"; then
if [ "$FLAGS_message" != "" ] && [ "$FLAGS_messagefile" != "" ]; then
die "Use either -m,--message or -f,--messagefile. Can not use both options at the same time"
fi
opts="-a"
flag sign && opts="$opts -s"
[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
[ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'"
[ "$FLAGS_messagefile" != "" ] && opts="$opts -F '$FLAGS_messagefile'"
eval git_do tag $opts "$tagname" "$BRANCH" || \
die "Tagging failed. Please run finish again to retry."
if [ "$FLAGS_message" != "" ]; then
# Run filter on the tag message
FLAGS_message=$(run_filter_hook release-branch-tag-message "${FLAGS_message}" "$VERSION_PREFIX$VERSION")
opts="$opts -m '$FLAGS_message'"
fi
fi
# try to merge into develop
# in case a previous attempt to finish this release branch has failed,
# but the merge into develop was successful, we skip it now
if ! git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH"; then
git_do checkout "$DEVELOP_BRANCH" || \
die "Could not check out $DEVELOP_BRANCH."
# TODO: Actually, accounting for 'git describe' pays, so we should
# ideally git merge --no-ff $tagname here, instead!
if noflag squash; then
git_do merge --no-ff "$BRANCH" || \
die "There were merge conflicts."
# TODO: What do we do now?
else
git_do merge --squash "$BRANCH" || \
die "There were merge conflicts."
# TODO: What do we do now?
git_do commit
[ "$FLAGS_messagefile" != "" ] && opts="$opts -F '$FLAGS_messagefile'"
eval git_do tag $opts "$VERSION_PREFIX$VERSION" || die "Tagging failed. Please run finish again to retry."
fi
fi
# delete branch
if noflag keep; then
if [ "$BRANCH" = "$(git_current_branch)" ]; then
git_do checkout "$MASTER_BRANCH"
fi
git_do branch -d "$BRANCH"
fi
run_post_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH"
if flag push; then
git_do push "$ORIGIN" "$DEVELOP_BRANCH" || \
die "Could not push to $DEVELOP_BRANCH from $ORIGIN."
git_do push "$ORIGIN" "$MASTER_BRANCH" || \
die "Could not push to $MASTER_BRANCH from $ORIGIN."
git_do push "$ORIGIN" "$MASTER_BRANCH" || die "Could not push branch '$MASTER_BRANCH' to remote '$ORIGIN'."
if noflag notag; then
git_do push --tags "$ORIGIN" || \
die "Could not push tags to $ORIGIN."
git_do push --tags "$ORIGIN" || die "Could not push tags to remote '$ORIGIN'."
fi
git_do push "$ORIGIN" :"$BRANCH" || \
die "Could not delete the remote $BRANCH in $ORIGIN."
fi
echo
echo "Summary of actions:"
if flag fetch; then
echo "- Latest objects have been fetched from '$ORIGIN'"
echo "- Release branch has been merged into '$MASTER_BRANCH'"
if noflag notag; then
echo "- The release was tagged '$tagname'"
fi
echo "- Release branch has been back-merged into '$DEVELOP_BRANCH'"
if flag keep; then
echo "- Release branch '$BRANCH' is still available"
else
echo "- Release branch '$BRANCH' has been deleted"
echo "- Branch '$BRANCH' has been merged into '$MASTER_BRANCH'"
if noflag notag; then
echo "- The release was tagged '$VERSION_PREFIX$VERSION'"
fi
if flag push; then
echo "- '$DEVELOP_BRANCH', '$MASTER_BRANCH' and tags have been pushed to '$ORIGIN'"
echo "- Release branch '$BRANCH' in '$ORIGIN' has been deleted."
echo "- '$MASTER_BRANCH' and tags have been pushed to '$ORIGIN'"
fi
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_publish() {
OPTIONS_SPEC="\
git flow release publish [-h] <name>
Publish the release branch <name> on $ORIGIN
--
h,help Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
require_version_arg
# sanity checks
# Use current branch if no version is given
if [ "$VERSION" = "" ]; then
gitflow_use_current_branch_version
fi
# Sanity checks
require_clean_working_tree
require_branch "$BRANCH"
git_do fetch -q "$ORIGIN"
git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
require_branch_absent "$ORIGIN/$BRANCH"
# create remote branch
git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
git_do fetch -q "$ORIGIN"
run_pre_hook "$VERSION" "$ORIGIN" "$BRANCH"
# configure remote tracking
git_do config "branch.$BRANCH.remote" "$ORIGIN"
git_do config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
git_do checkout "$BRANCH"
# Create remote branch with remote tracking
git_do push -u "$ORIGIN" "$BRANCH:$BRANCH"
git_do fetch -q "$ORIGIN" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'."
run_post_hook "$VERSION" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote branch '$BRANCH' was created"
echo "- The remote branch '$BRANCH' was created or updated"
echo "- The local branch '$BRANCH' was configured to track the remote branch"
echo "- You are now on branch '$BRANCH'"
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_track() {
OPTIONS_SPEC="\
git flow release track [-h] <name>
Start tracking release <name> that is shared on $ORIGIN
--
h,help Show this help
showcommands! Show git commands while executing them
"
# Parse arguments
parse_args "$@"
require_version_arg
# sanity checks
gitflow_require_version_arg
# Sanity checks
require_clean_working_tree
require_branch_absent "$BRANCH"
git_do fetch -q "$ORIGIN"
require_branch "$ORIGIN/$BRANCH"
require_local_branch_absent "$BRANCH"
run_pre_hook "$VERSION" "$ORIGIN" "$BRANCH"
git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
git_remote_branch_exists "$ORIGIN/$BRANCH"
# Create tracking branch
git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH" || die "Could not create branch '$BRANCH'."
# create tracking branch
git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH"
run_post_hook "$VERSION" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote tracking branch '$BRANCH' was created"
echo "- You are now on branch '$BRANCH'"
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_rebase() {
OPTIONS_SPEC="\
git flow release rebase [-h] [-i] [-p] [<name|nameprefix>]
Rebase <name> on <base_branch>
--
h,help! Show this help
showcommands! Show git commands while executing them
i,[no]interactive Do an interactive rebase
p,[no]preserve-merges Preserve merges
"
local opts
# Define flags
DEFINE_boolean 'interactive' false 'do an interactive rebase' i
DEFINE_boolean 'preserve-merges' false 'try to recreate merges' p
# Override defaults with values from config
gitflow_override_flag_boolean "release.rebase.interactive" "interactive"
gitflow_override_flag_boolean "release.rebase.preserve-merges" "preserve_merges"
# Parse arguments
parse_args "$@"
# Use current branch if no version is given
if [ "$VERSION" = "" ]; then
gitflow_use_current_branch_version
fi
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
warn "Will try to rebase '$NAME' which is based on '$BASE_BRANCH'..."
require_clean_working_tree
require_branch "$BRANCH"
git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't rebase the release branch '$BRANCH'."
git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'."
if flag interactive; then
opts="$opts -i"
fi
if flag preserve_merges; then
opts="$opts -p"
fi
git_do rebase $opts "$BASE_BRANCH"
}
cmd_delete() {
OPTIONS_SPEC="\
git flow release delete [-h] [-f] [-r] <name>
Delete the given release branch
--
h,help Show this help
showcommands! Show git commands while executing them
f,[no]force Force deletion
r,[no]remote Delete remote branch
"
local current_branch
# Define flags
DEFINE_boolean 'force' false "force deletion" f
DEFINE_boolean 'remote' false "delete remote branch" r
# Override defaults with values from config
gitflow_override_flag_boolean "release.delete.fetch" "fetch"
gitflow_override_flag_boolean "release.delete.remote" "remote"
# Parse arguments
parse_args "$@"
gitflow_require_version_arg
# Sanity checks
require_branch "$BRANCH"
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
run_pre_hook "$VERSION" "$ORIGIN" "$BRANCH"
current_branch=$(git_current_branch)
# We can't delete a branch we are on, switch to the develop branch.
if [ "$BRANCH" = "$current_branch" ]; then
require_clean_working_tree
if git_local_branch_exists "$BASE_BRANCH"; then
git_do checkout "$BASE_BRANCH"
else
git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
fi
fi
if ( git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH" && git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH" ); then
git_do branch -d "$BRANCH" || die "Could not delete the $BRANCH."
if flag remote; then
git_do push "$ORIGIN" :"$BRANCH" || die "Could not delete the remote $BRANCH in $ORIGIN."
fi
else
if flag force; then
git_do branch -D "$BRANCH" || die "Could not delete the $BRANCH."
if flag remote; then
git_do push "$ORIGIN" :"$BRANCH" || die "Could not delete the remote $BRANCH in $ORIGIN."
fi
else
die "Release branch '$BRANCH' has been not been merged in branch '$MASTER_BRANCH' and/or branch '$BASE_BRANCH'. Use -f to force the deletion."
fi
fi
gitflow_config_remove_base_section "$BRANCH"
run_post_hook "$VERSION" "$ORIGIN" "$BRANCH"
echo
echo "Summary of actions:"
echo "- Release branch '$BRANCH' has been deleted."
flag remote && echo "- Release branch '$BRANCH' in '$ORIGIN' has been deleted."
echo "- You are now on branch '$(git_current_branch)'"
echo
}
......@@ -2,54 +2,59 @@
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# Original blog post presenting this model is found at:
# http://nvie.com/git-model
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/nvie/gitflow
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of Vincent Driessen.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
init() {
initialize() {
require_git_repo
require_gitflow_initialized
git config --get gitflow.prefix.support >/dev/null 2>&1 || die "Support prefix not set. Please run 'git flow init'."
gitflow_load_settings
VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`")
VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
PREFIX=$(git config --get gitflow.prefix.support)
}
warn "note: The support subcommand is still very EXPERIMENTAL!"
warn "note: DO NOT use it in a production situation."
usage() {
echo "usage: git flow support [list] [-v]"
echo " git flow support start [-F] <version> <base>"
OPTIONS_SPEC="\
git flow support [list]
git flow support start
Manage your support branches.
For more specific help type the command followed by --help
--
"
flags_help
}
cmd_default() {
......@@ -57,13 +62,25 @@ cmd_default() {
}
cmd_list() {
DEFINE_boolean verbose false 'verbose (more) output' v
OPTIONS_SPEC="\
git flow support [list] [-h] [-v]
List all local support branches
--
h,help! Show this help
v,verbose Verbose (more) output
"
local support_branches current_branch width branch len
local base master_sha branch_sha
local tagname nicename
# Define flags
DEFINE_boolean 'verbose' false 'verbose (more) output' v
# Parse arguments
parse_args "$@"
local support_branches
local current_branch
local short_names
support_branches=$(echo "$(git_local_branches)" | grep "^$PREFIX")
support_branches=$(git_local_branches_prefixed "$PREFIX")
if [ -z "$support_branches" ]; then
warn "No support branches exist."
warn ""
......@@ -73,36 +90,31 @@ cmd_list() {
warn ""
exit 0
fi
current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
short_names=$(echo "$support_branches" | sed "s ^$PREFIX g")
# determine column width first
local width=0
local branch
for branch in $short_names; do
local len=${#branch}
current_branch=$(git_current_branch)
# Determine column width first
width=0
for branch in $support_branches; do
len=${#branch}
width=$(max $width $len)
done
width=$(($width+3))
local branch
for branch in $short_names; do
local fullname=$PREFIX$branch
local base=$(git merge-base "$fullname" "$MASTER_BRANCH")
local master_sha=$(git rev-parse "$MASTER_BRANCH")
local branch_sha=$(git rev-parse "$fullname")
if [ "$fullname" = "$current_branch" ]; then
width=$(($width+3-${#PREFIX}))
for branch in $support_branches; do
base=$(git merge-base "$branch" "$MASTER_BRANCH")
master_sha=$(git rev-parse "$MASTER_BRANCH")
branch_sha=$(git rev-parse "$branch")
if [ "$branch" = "$current_branch" ]; then
printf "* "
else
printf " "
fi
if flag verbose; then
printf "%-${width}s" "$branch"
printf "%-${width}s" "${branch#$PREFIX}"
if [ "$branch_sha" = "$master_sha" ]; then
printf "(no commits yet)"
else
local tagname=$(git name-rev --tags --no-undefined --name-only "$base")
local nicename
tagname=$(git name-rev --tags --no-undefined --name-only "$base")
if [ "$tagname" != "" ]; then
nicename=$tagname
else
......@@ -111,7 +123,7 @@ cmd_list() {
printf "(based on $nicename)"
fi
else
printf "%s" "$branch"
printf "%s" "${branch#$PREFIX}"
fi
echo
done
......@@ -122,63 +134,114 @@ cmd_help() {
exit 0
}
# Parse arguments and set common variables
parse_args() {
# parse options
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
# read arguments into global variables
# Read arguments into global variables
if [ -z $1 ]; then
VERSION=''
else
VERSION=$1
BASE=$2
BRANCH=$PREFIX$VERSION
}
require_version_arg() {
if [ "$VERSION" = "" ]; then
warn "Missing argument <version>"
usage
exit 1
fi
}
require_base_arg() {
if [ "$BASE" = "" ]; then
warn "Missing argument <base>"
usage
exit 1
fi
}
require_base_is_on_master() {
if ! git branch --no-color --contains "$BASE" 2>/dev/null \
| sed 's/[* ] //g' \
| grep -q "^$MASTER_BRANCH\$"; then
die "fatal: Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'."
if [ -z $2 ]; then
BASE=''
else
BASE=$2
fi
BRANCH=$PREFIX$VERSION
}
cmd_start() {
DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
OPTIONS_SPEC="\
git flow support start [-h] [-F] <version> <base>
Start a new support branch name <version> based on <base>
--
h,help! Show this help
showcommands! Show git commands while executing them
F,[no]fetch Fetch from origin before performing finish
"
# Define flags
DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
# Override defaults with values from config
gitflow_override_flag_boolean "support.start.fetch" "fetch"
# Parse arguments
parse_args "$@"
require_version_arg
require_base_arg
require_base_is_on_master
# sanity checks
gitflow_require_version_arg
gitflow_require_base_arg
# Sanity checks
require_clean_working_tree
# fetch remote changes
# Fetch remote changes
if flag fetch; then
git_do fetch -q "$ORIGIN" "$BASE"
git_fetch_branch "$ORIGIN" "$BASE"
fi
git_is_ancestor "$BASE" "$MASTER_BRANCH" || die "Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'."
require_branch_absent "$BRANCH"
# create branch
git_do checkout -b "$BRANCH" "$BASE"
# Create branch
git_do checkout -b "$BRANCH" "$BASE" || die "Could not create support branch '$BRANCH'."
echo
echo "Summary of actions:"
echo "- A new branch '$BRANCH' was created, based on '$BASE'"
echo "- You are now on branch '$BRANCH'"
echo "- You are now on branch '$(git_current_branch)'"
echo
}
cmd_rebase() {
OPTIONS_SPEC="\
git flow support rebase [-h] [-i] [-p] [<name|nameprefix>]
Rebase <name> on <base_branch>
--
h,help! Show this help
showcommands! Show git commands while executing them
i,[no]interactive Do an interactive rebase
p,[no]preserve-merges Preserve merges
"
local opts
# Define flags
DEFINE_boolean 'interactive' false 'do an interactive rebase' i
DEFINE_boolean 'preserve-merges' false 'try to recreate merges' p
# Override defaults with values from config
gitflow_override_flag_boolean "support.rebase.interactive" "interactive"
gitflow_override_flag_boolean "support.rebase.preserve-merges" "preserve_merges"
# Parse arguments
parse_args "$@"
# Use current branch if no version is given
if [ "$VERSION" = "" ]; then
gitflow_use_current_branch_version
fi
BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
warn "Will try to rebase '$NAME' which is based on '$BASE_BRANCH'..."
require_clean_working_tree
require_branch "$BRANCH"
git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't rebase the support branch '$BRANCH'."
git_do checkout -q "$BRANCH" || die "Could not check out branch '$BRANCH'."
if flag interactive; then
opts="$opts -i"
fi
if flag preserve_merges; then
opts="$opts -p"
fi
git_do rebase $opts "$BASE_BRANCH"
}
......@@ -2,48 +2,60 @@
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# Original blog post presenting this model is found at:
# http://nvie.com/git-model
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/nvie/gitflow
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of Vincent Driessen.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
GITFLOW_VERSION=0.4.5
GITFLOW_VERSION=0.4.7
initialize() {
# A function can not be empty. Comments count as empty.
local FOO=''
}
usage() {
echo "usage: git flow version"
OPTIONS_SPEC="\
git flow version
Shows version information.
For more specific help type the command followed by --help
--
"
flags_help
}
cmd_default() {
echo "$GITFLOW_VERSION dreidev"
echo "$GITFLOW_VERSION (DREIDEV Edition -- drazious)"
}
cmd_help() {
......
......@@ -2,99 +2,147 @@
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# Original blog post presenting this model is found at:
# http://nvie.com/git-model
# A blog post presenting this model is found at:
# http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
# http://github.com/nvie/gitflow
# http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2016 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY VINCENT DRIESSEN ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL VINCENT DRIESSEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of Vincent Driessen.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# Common functionality
#
# shell output
# Shell output
warn() { echo "$@" >&2; }
die() { warn "$@"; exit 1; }
die() { warn "Fatal: $@"; exit 1; }
die_help() { warn $@; flags_help; exit 1; }
escape() {
echo "$1" | sed 's/\([\.\$\*]\)/\\\1/g'
}
# set logic
has() {
local item=$1; shift
echo " $@ " | grep -q " $(escape $item) "
#
# String contains function
# $1 haystack
# $2 Needle
#
contains() {
local return
case $1 in
*$2*)
return=$FLAGS_TRUE
;;
*)
return=$FLAGS_FALSE
;;
esac
return $return
}
# basic math
# Basic math
min() { [ "$1" -le "$2" ] && echo "$1" || echo "$2"; }
max() { [ "$1" -ge "$2" ] && echo "$1" || echo "$2"; }
# basic string matching
# Basic string matching
startswith() { [ "$1" != "${1#$2}" ]; }
endswith() { [ "$1" != "${1%$2}" ]; }
# convenience functions for checking shFlags flags
# Convenience functions for checking shFlags flags
flag() { local FLAG; eval FLAG='$FLAGS_'$1; [ $FLAG -eq $FLAGS_TRUE ]; }
noflag() { local FLAG; eval FLAG='$FLAGS_'$1; [ $FLAG -ne $FLAGS_TRUE ]; }
# check_boolean
# Check if given value can be interpreted as a boolean
#
# This function determines if the passed parameter is a valid boolean value.
#
# Param $1: string Value to check if it's a valid boolean
#
# Return: string FLAGS_TRUE|FLAGS_FALSE|FLAGS_ERROR
# FLAGS_TRUE if the parameter is a boolean TRUE
# FLAGS_FALSE if the parameter is a boolean FALSE
# FLAGS_ERROR if the parameter is not a boolean
#
check_boolean() {
local _return _value
_value="${1}"
case "${_value}" in
${FLAGS_TRUE} | [yY] | [yY][eE][sS] | [tT] | [tT][rR][uU][eE])
_return=${FLAGS_TRUE}
;;
${FLAGS_FALSE} | [nN] | [nN][oO] | [fF] | [fF][aA][lL][sS][eE])
_return=${FLAGS_FALSE}
;;
*)
_return=${FLAGS_ERROR}
;;
esac
unset _value
return ${_return}
}
#
# Git specific common functionality
#
git_do() {
# equivalent to git, used to indicate actions that make modifications
if flag show_commands; then
echo "git $@" >&2
fi
git "$@"
}
git_local_branches() { git for-each-ref --sort refname --format='%(refname:short)' refs/heads; }
git_remote_branches() { git for-each-ref --sort refname --format='%(refname:short)' refs/remotes; }
git_all_branches() { git for-each-ref --sort refname --format='%(refname:short)' refs/remotes refs/heads; }
git_all_tags() { git for-each-ref --format='%(refname:short)' refs/tags; }
git_local_branches() { git branch --no-color | sed 's/^[* ] //'; }
git_remote_branches() { git branch -r --no-color | sed 's/^[* ] //'; }
git_all_branches() { ( git branch --no-color; git branch -r --no-color) | sed 's/^[* ] //'; }
git_all_tags() { git tag; }
git_local_branches_prefixed() {
[ -z $1 ] && die "Prefix parameter missing." # This should never happen.
git for-each-ref --format='%(refname:short)' refs/heads/$1\* ;
}
git_current_branch() {
git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g'
local branch_name
branch_name="$(git symbolic-ref --quiet HEAD)"
[ -z $branch_name ] && branch_name="(unnamed branch)" || branch_name="$(git for-each-ref --format='%(refname:short)' $branch_name)"
echo "$branch_name"
}
git_is_clean_working_tree() {
if ! git diff --no-ext-diff --ignore-submodules --quiet --exit-code; then
return 1
elif ! git diff-index --cached --quiet --ignore-submodules HEAD --; then
return 2
else
git rev-parse --verify HEAD >/dev/null || exit 1
git update-index -q --ignore-submodules --refresh
# Check for unstaged changes
git diff-files --quiet --ignore-submodules || return 1
# Check for Uncommited changes
git diff-index --cached --quiet --ignore-submodules HEAD -- || return 2
return 0
fi
}
git_repo_is_headless() {
......@@ -102,38 +150,53 @@ git_repo_is_headless() {
}
git_local_branch_exists() {
has $1 $(git_local_branches)
[ -n "$1" ] || die "Missing branch name"
[ -n "$(git for-each-ref --format='%(refname:short)' refs/heads/$1)" ]
}
git_remote_branch_exists() {
has $1 $(git_remote_branches)
[ -n "$1" ] || die "Missing branch name"
[ -n "$(git for-each-ref --format='%(refname:short)' refs/remotes/$1)" ]
}
git_remote_branch_delete() {
[ -n "$1" ] || die "Missing branch name"
if git_remote_branch_exists "$ORIGIN/$1"; then
git_do push "$ORIGIN" :"$1" || die "Could not delete the remote $1 in $ORIGIN."
else
warn "Trying to delete the remote branch $1, but it does not exists in $ORIGIN"
fi
}
git_branch_exists() {
has $1 $(git_all_branches)
[ -n "$1" ] || die "Missing branch name"
git_local_branch_exists "$1" || git_remote_branch_exists "$ORIGIN/$1"
}
git_tag_exists() {
has $1 $(git_all_tags)
[ -n "$1" ] || die "Missing tag name"
[ -n "$(git for-each-ref --format='%(refname:short)' refs/tags/$1)" ]
}
#
# git_compare_branches()
# git_compare_refs()
#
# Tests whether branches and their "origin" counterparts have diverged and need
# merging first. It returns error codes to provide more detail, like so:
# Tests whether two references have diverged and need merging
# first. It returns error codes to provide more detail, like so:
#
# 0 Branch heads point to the same commit
# 1 First given branch needs fast-forwarding
# 2 Second given branch needs fast-forwarding
# 3 Branch needs a real merge
# 4 There is no merge base, i.e. the branches have no common ancestors
# 0 References point to the same commit
# 1 First given reference needs fast-forwarding
# 2 Second given reference needs fast-forwarding
# 3 References need a real merge
# 4 There is no merge base, i.e. the references have no common ancestors
#
git_compare_branches() {
local commit1=$(git rev-parse "$1")
local commit2=$(git rev-parse "$2")
git_compare_refs() {
local commit1 commit2 base
commit1=$(git rev-parse "$1"^{})
commit2=$(git rev-parse "$2"^{})
if [ "$commit1" != "$commit2" ]; then
local base=$(git merge-base "$commit1" "$commit2")
base=$(git merge-base "$commit1" "$commit2")
if [ $? -ne 0 ]; then
return 4
elif [ "$commit1" = "$base" ]; then
......@@ -151,52 +214,99 @@ git_compare_branches() {
#
# git_is_branch_merged_into()
#
# Checks whether branch $1 is succesfully merged into $2
# Checks whether branch $1 is successfully merged into $2
#
git_is_branch_merged_into() {
local subject=$1
local base=$2
local all_merges="$(git branch --no-color --contains $subject | sed 's/^[* ] //')"
has $base $all_merges
local merge_hash base_hash
merge_hash=$(git merge-base "$1"^{} "$2"^{})
base_hash=$(git rev-parse "$1"^{})
# If the hashes are equal, the branches are merged.
[ "$merge_hash" = "$base_hash" ]
}
#
# git_is_ancestor()
#
# This is the same function as git_is_branch_merged_into but
# for readability given a different name.
#
git_is_ancestor() {
git_is_branch_merged_into "$1" "$2"
}
#
# git_fetch_branch()
#
# $1 Origin - Where to fetch from
# $2 Branch - Which branch to fetch
#
# This fetches the given branch from the given origin.
# Instead of storing it in FETCH_HEAD it will be stored in
# refs/remotes/<origin>/<branch>
#
git_fetch_branch() {
local origin branch
[ -n "$1" ] || die "Missing origin"
[ -n "$2" ] || die "Missing branch name"
origin="$1"
branch="$2"
if git_remote_branch_exists "$origin/$branch"; then
git_do fetch -q "$origin" "$branch":refs/remotes/"$origin"/"$branch" || die "Could not fetch $branch from $origin."
else
warn "Trying to fetch branch '$origin/$branch' but it does not exist."
fi
}
#
# gitflow specific common functionality
#
# check if this repo has been inited for gitflow
# Function used to check if the repository is git-flow enabled.
gitflow_has_master_configured() {
local master=$(git config --get gitflow.branch.master)
local master
master=$(git config --get gitflow.branch.master)
[ "$master" != "" ] && git_local_branch_exists "$master"
}
gitflow_has_develop_configured() {
local develop=$(git config --get gitflow.branch.develop)
[ "$develop" != "" ] && git_local_branch_exists "$develop"
}
local develop
gitflow_has_prefixes_configured() {
git config --get gitflow.prefix.feature >/dev/null 2>&1 && \
git config --get gitflow.prefix.release >/dev/null 2>&1 && \
git config --get gitflow.prefix.hotfix >/dev/null 2>&1 && \
git config --get gitflow.prefix.support >/dev/null 2>&1 && \
git config --get gitflow.prefix.versiontag >/dev/null 2>&1
develop=$(git config --get gitflow.branch.develop)
[ "$develop" != "" ] && git_local_branch_exists "$develop"
}
gitflow_is_initialized() {
gitflow_has_master_configured && \
gitflow_has_develop_configured && \
[ "$(git config --get gitflow.branch.master)" != \
"$(git config --get gitflow.branch.develop)" ] && \
gitflow_has_prefixes_configured
[ "$(git config --get gitflow.branch.master)" != "$(git config --get gitflow.branch.develop)" ] && \
$(git config --get-regexp gitflow.prefix >/dev/null 2>&1)
}
# loading settings that can be overridden using git config
# Loading settings that can be overridden using git config
gitflow_load_settings() {
export DOT_GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
export GIT_CURRENT_REPO_DIR="$(git rev-parse --show-toplevel 2>/dev/null)"
DOT_GIT_DIR=$(git rev-parse --git-dir)
export DOT_GIT_DIR="$(cd ${DOT_GIT_DIR} >/dev/null 2>&1 && pwd)"
export HOOKS_DIR="$(git config --get gitflow.path.hooks || echo ${DOT_GIT_DIR}/hooks)" # the second option is used to support previous versions of git-flow
export MASTER_BRANCH=$(git config --get gitflow.branch.master)
export DEVELOP_BRANCH=$(git config --get gitflow.branch.develop)
export ORIGIN=$(git config --get gitflow.origin || echo origin)
GITFLOW_CONFIG="$DOT_GIT_DIR/gitflow_config"
if [ -f "$GITFLOW_CONFIG" ]; then # move all settings from old .git/gitflow_config to the local conf.
warn "Migrating old \"$GITFLOW_CONFIG\" to the \"--local\" repo config."
_config_lines=`git config --list --file="$GITFLOW_CONFIG"`;
for _config_line in ${_config_lines}; do
_key=${_config_line%=*}
_value=${_config_line#=*}
git_do config --local gitflow.${_key} ${_value}
done;
mv "$GITFLOW_CONFIG" "$GITFLOW_CONFIG".backup 2>/dev/null
fi
}
#
......@@ -216,10 +326,11 @@ gitflow_load_settings() {
# 2: Multiple matches found. These matches are written to stderr
#
gitflow_resolve_nameprefix() {
local name=$1
local prefix=$2
local matches
local num_matches
local name prefix
local match matches num_matches
name=$1
prefix=$2
# first, check if there is a perfect match
if git_local_branch_exists "$prefix$name"; then
......@@ -231,7 +342,7 @@ gitflow_resolve_nameprefix() {
num_matches=$(echo "$matches" | wc -l)
if [ -z "$matches" ]; then
# no prefix match, so take it literally
warn "No branch matches prefix '$name'"
warn "No branches match '$prefix$name*'"
return 1
else
if [ $num_matches -eq 1 ]; then
......@@ -248,75 +359,290 @@ gitflow_resolve_nameprefix() {
fi
}
#
# Check if the given branch is a git-flow branch
#
gitflow_is_prefixed_branch() {
local branch return
branch=$1
case $branch in
$(git config --get gitflow.prefix.feature)* | \
$(git config --get gitflow.prefix.bugfix)* | \
$(git config --get gitflow.prefix.release)* | \
$(git config --get gitflow.prefix.hotfix)* | \
$(git config --get gitflow.prefix.support)* )
return=0
;;
*)
return=1
;;
esac
return $return
}
#
# Update the config with the base of a new git-flow branch.
#
# @param $1 Base of the new branch
# @param $2 Name of the branch
#
gitflow_config_set_base_branch() {
local base branch
base=$1
branch=$2
$(git_do config --local "gitflow.branch.$branch.base" $base)
}
#
# Get the base of a branch as set by gitflow_set_branch
#
# @param $1 Name of the branch
# @return string|empty String when a base is found otherwise empty
#
gitflow_config_get_base_branch() {
local branch
branch=$1
echo $(git config --local --get "gitflow.branch.$branch.base")
}
#
# Remove the section that contains the base of a branch as set by gitflow_set_branch
#
# @param $1 Name of the branch
#
gitflow_config_remove_base_section() {
local branch
branch=$1
$(git_do config --local --remove-section "gitflow.branch.$branch" 2>/dev/null)
}
#
# Remove the base of the git-flow branch from the.
# @param $1 Name of the branch
#
gitflow_config_remove_base_branch() {
local base
base=$1
$(git_do config --local --unset "gitflow.branch.$branch.base" 2>/dev/null)
}
# gitflow_override_flag_boolean()
#
# Override a boolean flag
#
# Param $1: string The name of the config variable e.g. "feature.start.fetch"
# Param $2: string The flag name
#
gitflow_override_flag_boolean() {
local _variable
_variable=$(git config --bool --get gitflow.$1 2>&1)
case $? in
0)
[ "${_variable}" = "true" ] && eval "FLAGS_${2}=${FLAGS_TRUE}" || eval "FLAGS_${2}=${FLAGS_FALSE}"
;;
128)
die "${_variable}"
;;
esac
unset _variable
return ${FLAGS_TRUE}
}
# gitflow_override_flag_string()
#
# Override a string flag
#
# Param $1: string The name of the config variable e.g. "feature.start.fetch"
# Param $2: string The flag name
#
gitflow_override_flag_string() {
local _variable
_variable=$(git config --get gitflow.$1 2>&1)
case $? in
0)
eval "FLAGS_${2}=\"${_variable}\""
;;
esac
unset _variable
return ${FLAGS_TRUE}
}
# gitflow_create_squash_message()
#
# Create the squash message, overriding the one generated by git itself
#
# Param $1: string The line to be added
# Param $2: string The base of the branch that will me merged
# Param $3: string The branch that will be merged.
#
gitflow_create_squash_message() {
echo Squashed commit of the following:
echo
echo $1
echo
git log --no-merges --pretty=medium ^"$2" $3
}
#
# Parameter functions
#
gitflow_require_name_arg() {
if [ "$NAME" = "" ]; then
die_help "Missing argument <name>"
fi
}
gitflow_expand_nameprefix_arg() {
local expanded_name exitcode
gitflow_require_name_arg
expanded_name=$(gitflow_resolve_nameprefix "$NAME" "$PREFIX")
exitcode=$?
case $exitcode in
0)
NAME=$expanded_name
BRANCH=$PREFIX$NAME
;;
*)
exit 1
;;
esac
}
gitflow_require_version_arg() {
if [ "$VERSION" = "" ]; then
die_help "Missing argument <version>"
fi
}
gitflow_expand_versionprefix_arg() {
local expanded_version exitcode
gitflow_require_version_arg
version=$(gitflow_resolve_nameprefix "$VERSION" "$PREFIX")
exitcode=$?
case $exitcode in
0)
VERSION=$version
BRANCH=$PREFIX$VERSION
;;
*)
exit 1
;;
esac
}
gitflow_require_base_arg() {
if [ "$BASE" = "" ]; then
die_help "Missing argument <base>"
fi
}
gitflow_use_current_branch_name() {
local current_branch
current_branch=$(git_current_branch)
if startswith "$current_branch" "$PREFIX"; then
BRANCH=$current_branch
NAME=${BRANCH#$PREFIX}
else
warn "The current HEAD is no ${SUBCOMMAND} branch."
warn "Please specify a <name> argument."
exit 1
fi
}
gitflow_use_current_branch_version() {
local current_branch
current_branch=$(git_current_branch)
if startswith "$current_branch" "$PREFIX"; then
BRANCH=$current_branch
VERSION=${BRANCH#$PREFIX}
else
warn "The current HEAD is no ${SUBCOMMAND} branch."
warn "Please specify a <version> argument."
exit 1
fi
}
#
# Assertions for use in git-flow subcommands
#
require_git_repo() {
if ! git rev-parse --git-dir >/dev/null 2>&1; then
die "fatal: Not a git repository"
fi
git rev-parse 2>/dev/null || die "Not a git repository"
}
require_gitflow_initialized() {
if ! gitflow_is_initialized; then
die "fatal: Not a gitflow-enabled repo yet. Please run \"git flow init\" first."
fi
gitflow_is_initialized || die "Not a gitflow-enabled repo yet. Please run 'git flow init' first."
$(git config --get gitflow.prefix.versiontag >/dev/null 2>&1) || die "Version tag not set. Please run 'git flow init'."
}
require_clean_working_tree() {
local result
git_is_clean_working_tree
local result=$?
result=$?
if [ $result -eq 1 ]; then
die "fatal: Working tree contains unstaged changes. Aborting."
die "Working tree contains unstaged changes. Aborting."
fi
if [ $result -eq 2 ]; then
die "fatal: Index contains uncommited changes. Aborting."
die "Index contains uncommited changes. Aborting."
fi
}
require_base_is_local_branch() {
git_local_branch_exists "$1" || die "Base '$1' needs to be a branch. It does not exist and is required."
}
require_local_branch() {
if ! git_local_branch_exists $1; then
die "fatal: Local branch '$1' does not exist and is required."
fi
git_local_branch_exists "$1" || die "Local branch '$1' does not exist and is required."
}
require_remote_branch() {
if ! has $1 $(git_remote_branches); then
die "Remote branch '$1' does not exist and is required."
fi
git_remote_branch_exists "$1" || die "Remote branch '$1' does not exist and is required."
}
require_branch() {
if ! has $1 $(git_all_branches); then
die "Branch '$1' does not exist and is required."
fi
git_branch_exists "$1" || die "Branch '$1' does not exist and is required."
}
require_branch_absent() {
if has $1 $(git_all_branches); then
die "Branch '$1' already exists. Pick another name."
fi
git_branch_exists "$1" && die "Branch '$1' already exists. Pick another name."
}
require_local_branch_absent() {
git_local_branch_exists "$1" && die "Branch '$1' already exists. Pick another name."
}
require_tag_absent() {
for tag in $(git_all_tags); do
if [ "$1" = "$tag" ]; then
die "Tag '$1' already exists. Pick another name."
fi
done
git_tag_exists "$1" && die "Tag '$1' already exists. Pick another name."
}
require_branches_equal() {
local compare_refs_result
require_local_branch "$1"
require_remote_branch "$2"
git_compare_branches "$1" "$2"
local status=$?
if [ $status -gt 0 ]; then
git_compare_refs "$1" "$2"
compare_refs_result=$?
if [ $compare_refs_result -gt 0 ]; then
warn "Branches '$1' and '$2' have diverged."
if [ $status -eq 1 ]; then
if [ $compare_refs_result -eq 1 ]; then
die "And branch '$1' may be fast-forwarded."
elif [ $status -eq 2 ]; then
elif [ $compare_refs_result -eq 2 ]; then
# Warn here, since there is no harm in being ahead
warn "And local branch '$1' is ahead of '$2'."
else
......@@ -324,3 +650,91 @@ require_branches_equal() {
fi
fi
}
#
# Show commands if flag is set.
#
git_do() {
if flag showcommands; then
echo "git $@" >&2
fi
git "$@"
}
#
# run_filter_hook
#
# Looks for a Git hook script called as defined by the first variable
#
# filter-flow-command
#
# If such a hook script exists and is executable, it is called with the given
# positional arguments.
#
run_filter_hook() {
local command scriptfile return
command=$1
shift
scriptfile="${HOOKS_DIR}/filter-flow-${command}"
if [ -x "$scriptfile" ]; then
return=`$scriptfile "$@"`
if [ $? -eq 127 ]; then
echo "$return"
exit 127
fi
echo $return
else
echo "$@"
fi
}
#
# run_pre_hook
#
# Looks for a Git hook script called
#
# pre-flow-<subcmd>-<subaction>
#
# If such a hook script exists and is executable, it is called with the given
# positional arguments. If its return code non-zero, the git-flow action is
# aborted.
#
run_pre_hook() {
local scriptfile exitcode
scriptfile="${HOOKS_DIR}/pre-flow-${SUBCOMMAND}-${SUBACTION}"
exitcode=0
if [ -x "$scriptfile" ]; then
"$scriptfile" "$@"
exitcode=$?
if [ $exitcode -gt 0 ]; then
die "Hook command $scriptfile ended with exit code $exitcode."
fi
fi
}
#
# run_post_hook
#
# Looks for a Git hook script called
#
# post-flow-<subcmd>-<subaction>
#
# If such a hook script exists and is executable, it is called with the given
# positional arguments. Its return code is ignored.
#
run_post_hook() {
local scriptfile
scriptfile="${HOOKS_DIR}/post-flow-${SUBCOMMAND}-${SUBACTION}"
if [ -x "$scriptfile" ]; then
"$scriptfile" "$@"
fi
}
flags_help() {
eval "$( echo "$OPTIONS_SPEC" | git rev-parse --parseopt -- "-h" || echo exit $? )"
}
#!/bin/bash
# git-flow make-less installer for *nix systems, by Rick Osborne
# Based on the git-flow core Makefile:
# http://github.com/nvie/gitflow/blob/master/Makefile
# Licensed under the same restrictions as git-flow:
# http://github.com/nvie/gitflow/blob/develop/LICENSE
# Does this need to be smarter for each host OS?
if [ -z "$INSTALL_PREFIX" ] ; then
INSTALL_PREFIX="/usr/local/bin"
fi
if [ -z "$REPO_NAME" ] ; then
REPO_NAME="gitflow"
fi
if [ -z "$REPO_HOME" ] ; then
REPO_HOME="http://github.com/nvie/gitflow.git"
fi
EXEC_FILES="git-flow"
SCRIPT_FILES="git-flow-init git-flow-feature git-flow-hotfix git-flow-release git-flow-support git-flow-version gitflow-common gitflow-shFlags"
SUBMODULE_FILE="gitflow-shFlags"
echo "### gitflow no-make installer ###"
case "$1" in
uninstall)
echo "Uninstalling git-flow from $INSTALL_PREFIX"
if [ -d "$INSTALL_PREFIX" ] ; then
for script_file in $SCRIPT_FILES $EXEC_FILES ; do
echo "rm -vf $INSTALL_PREFIX/$script_file"
rm -vf "$INSTALL_PREFIX/$script_file"
done
else
echo "The '$INSTALL_PREFIX' directory was not found."
echo "Do you need to set INSTALL_PREFIX ?"
fi
exit
;;
help)
echo "Usage: [environment] gitflow-installer.sh [install|uninstall]"
echo "Environment:"
echo " INSTALL_PREFIX=$INSTALL_PREFIX"
echo " REPO_HOME=$REPO_HOME"
echo " REPO_NAME=$REPO_NAME"
exit
;;
*)
echo "Installing git-flow to $INSTALL_PREFIX"
if [ -d "$REPO_NAME" -a -d "$REPO_NAME/.git" ] ; then
echo "Using existing repo: $REPO_NAME"
else
echo "Cloning repo from GitHub to $REPO_NAME"
git clone "$REPO_HOME" "$REPO_NAME"
fi
if [ -f "$REPO_NAME/$SUBMODULE_FILE" ] ; then
echo "Submodules look up to date"
else
echo "Updating submodules"
lastcwd=$PWD
cd "$REPO_NAME"
git submodule init
git submodule update
cd "$lastcwd"
fi
install -v -d -m 0755 "$INSTALL_PREFIX"
for exec_file in $EXEC_FILES ; do
install -v -m 0755 "$REPO_NAME/$exec_file" "$INSTALL_PREFIX"
done
for script_file in $SCRIPT_FILES ; do
install -v -m 0644 "$REPO_NAME/$script_file" "$INSTALL_PREFIX"
done
exit
;;
esac
......@@ -18,12 +18,10 @@
#
# DEFINE_string: takes any input, and intreprets it as a string.
#
# DEFINE_boolean: typically does not take any argument: say --myflag to set
# FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false.
# Alternately, you can say
# --myflag=true or --myflag=t or --myflag=0 or
# --myflag=false or --myflag=f or --myflag=1
# Passing an option has the same affect as passing the option once.
# DEFINE_boolean: does not take any arguments. Say --myflag to set
# FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false. For short
# flags, passing the flag on the command-line negates the default value, i.e.
# if the default is true, passing the flag sets the value to false.
#
# DEFINE_float: takes an input and intreprets it as a floating point number. As
# shell does not support floats per-se, the input is merely validated as
......@@ -50,14 +48,22 @@
# $ ./hello.sh -n Kate
# Hello, Kate.
#
# NOTE: Not all systems include a getopt version that supports long flags. On
# these systems, only short flags are recognized.
# CUSTOMIZABLE BEHAVIOR:
#
# A script can override the default 'getopt' command by providing the path to
# an alternate implementation by defining the FLAGS_GETOPT_CMD variable.
#
# NOTES:
#
# * Not all systems include a getopt version that supports long flags. On these
# systems, only short flags are recognized.
#==============================================================================
# shFlags
#
# Shared attributes:
# flags_error: last error message
# flags_output: last function output (rarely valid)
# flags_return: last return value
#
# __flags_longNames: list of long names for all flags
......@@ -78,59 +84,78 @@
# return if FLAGS already loaded
[ -n "${FLAGS_VERSION:-}" ] && return 0
FLAGS_VERSION='1.0.3'
FLAGS_VERSION='1.0.4pre'
# return values
# return values that scripts can use
FLAGS_TRUE=0
FLAGS_FALSE=1
FLAGS_ERROR=2
# reserved flag names
FLAGS_RESERVED='ARGC ARGV ERROR FALSE HELP PARENT RESERVED TRUE VERSION'
# determine some reasonable command defaults
__FLAGS_UNAME_S=`uname -s`
case "${__FLAGS_UNAME_S}" in
BSD) __FLAGS_EXPR_CMD='gexpr' ;;
*) __FLAGS_EXPR_CMD='expr' ;;
esac
_flags_debug() { echo "flags:DEBUG $@" >&2; }
_flags_warn() { echo "flags:WARN $@" >&2; }
_flags_error() { echo "flags:ERROR $@" >&2; }
_flags_fatal() { echo "flags:FATAL $@" >&2; }
# commands a user can override if needed
FLAGS_EXPR_CMD=${FLAGS_EXPR_CMD:-${__FLAGS_EXPR_CMD}}
FLAGS_GETOPT_CMD=${FLAGS_GETOPT_CMD:-getopt}
# specific shell checks
if [ -n "${ZSH_VERSION:-}" ]; then
setopt |grep "^shwordsplit$" >/dev/null
if [ $? -ne ${FLAGS_TRUE} ]; then
_flags_fatal 'zsh shwordsplit option is required for proper zsh operation'
exit ${FLAGS_ERROR}
fi
if [ -z "${FLAGS_PARENT:-}" ]; then
_flags_fatal "zsh does not pass \$0 through properly. please declare' \
\"FLAGS_PARENT=\$0\" before calling shFlags"
exit ${FLAGS_ERROR}
fi
fi
# can we use built-ins?
( echo "${FLAGS_TRUE#0}"; ) >/dev/null 2>&1
if [ $? -eq ${FLAGS_TRUE} ]; then
__FLAGS_USE_BUILTIN=${FLAGS_TRUE}
else
__FLAGS_USE_BUILTIN=${FLAGS_FALSE}
fi
#
# constants
#
# reserved flag names
__FLAGS_RESERVED_LIST=' ARGC ARGV ERROR FALSE GETOPT_CMD HELP PARENT TRUE '
__FLAGS_RESERVED_LIST="${__FLAGS_RESERVED_LIST} VERSION "
# getopt version
__FLAGS_GETOPT_VERS_STD=0
__FLAGS_GETOPT_VERS_ENH=1
__FLAGS_GETOPT_VERS_BSD=2
getopt >/dev/null 2>&1
${FLAGS_GETOPT_CMD} >/dev/null 2>&1
case $? in
0) __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD} ;; # bsd getopt
1)
# Probably BusyBox. Getting a return of 4 with -T will confirm
${FLAGS_GETOPT_CMD} -T >/dev/null 2>&1
if [ "$?" == 4 ] ; then
__FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_ENH}
else
_flags_fatal 'unable to determine getopt version'
fi
;;
2)
# TODO(kward): look into '-T' option to test the internal getopt() version
if [ "`getopt --version`" = '-- ' ]; then
if [ "`${FLAGS_GETOPT_CMD} --version`" = '-- ' ]; then
__FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD}
else
__FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_ENH}
fi
;;
*)
_flags_fatal 'unable to determine getopt version'
exit ${FLAGS_ERROR}
;;
*) _flags_fatal 'unable to determine getopt version' ;;
esac
# getopt optstring lengths
......@@ -180,9 +205,12 @@ unset __flags_const __flags_constants
# internal variables
#
__flags_boolNames=' ' # space separated list of boolean flag names
__flags_longNames=' ' # space separated list of long flag names
__flags_shortNames=' ' # space separated list of short flag names
# space separated lists
__flags_boolNames=' ' # boolean flag names
__flags_longNames=' ' # long flag names
__flags_shortNames=' ' # short flag names
__flags_definedNames=' ' # defined flag names (used for validation)
__flags_nonegateNames=' '
__flags_columns='' # screen width in columns
__flags_opts='' # temporary storage for parsed getopt flags
......@@ -191,6 +219,12 @@ __flags_opts='' # temporary storage for parsed getopt flags
# private functions
#
# logging functions
_flags_debug() { echo "flags:DEBUG $@" >&2; }
_flags_warn() { echo "flags:WARN $@" >&2; }
_flags_error() { echo "flags:ERROR $@" >&2; }
_flags_fatal() { echo "flags:FATAL $@" >&2; exit ${FLAGS_ERROR}; }
# Define a flag.
#
# Calling this function will define the following info variables for the
......@@ -225,12 +259,12 @@ _flags_define()
_flags_short_=${5:-${__FLAGS_NULL}}
_flags_return_=${FLAGS_TRUE}
# TODO(kward): check for validity of the flag name (e.g. dashes)
_flags_usName_=`_flags_removeExclamationName ${_flags_name_}`
_flags_usName_=`_flags_underscoreName ${_flags_usName_}`
# check whether the flag name is reserved
echo " ${FLAGS_RESERVED} " |grep " ${_flags_name_} " >/dev/null
if [ $? -eq 0 ]; then
_flags_itemInList ${_flags_usName_} "${__FLAGS_RESERVED_LIST}"
if [ $? -eq ${FLAGS_TRUE} ]; then
flags_error="flag name (${_flags_name_}) is reserved"
_flags_return_=${FLAGS_ERROR}
fi
......@@ -246,10 +280,8 @@ _flags_define()
# check for existing long name definition
if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
if _flags_itemInList "${_flags_name_}" \
${__flags_longNames} ${__flags_boolNames}
then
flags_error="flag name ([no]${_flags_name_}) already defined"
if _flags_itemInList ${_flags_usName_} ${__flags_definedNames}; then
flags_error="definition for ([no]${_flags_name_}) already exists"
_flags_warn "${flags_error}"
_flags_return_=${FLAGS_FALSE}
fi
......@@ -272,11 +304,13 @@ _flags_define()
if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
case ${_flags_type_} in
${__FLAGS_TYPE_BOOLEAN})
if _flags_validateBoolean "${_flags_default_}"; then
if _flags_validBool "${_flags_default_}"; then
case ${_flags_default_} in
true|t|0) _flags_default_=${FLAGS_TRUE} ;;
false|f|1) _flags_default_=${FLAGS_FALSE} ;;
esac
_flags_isNegate ${_flags_name_}
_flags_isNegate_=$?
else
flags_error="invalid default flag value '${_flags_default_}'"
_flags_return_=${FLAGS_ERROR}
......@@ -284,7 +318,7 @@ _flags_define()
;;
${__FLAGS_TYPE_FLOAT})
if _flags_validateFloat "${_flags_default_}"; then
if _flags_validFloat "${_flags_default_}"; then
:
else
flags_error="invalid default flag value '${_flags_default_}'"
......@@ -293,7 +327,7 @@ _flags_define()
;;
${__FLAGS_TYPE_INTEGER})
if _flags_validateInteger "${_flags_default_}"; then
if _flags_validInt "${_flags_default_}"; then
:
else
flags_error="invalid default flag value '${_flags_default_}'"
......@@ -312,27 +346,95 @@ _flags_define()
if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
# store flag information
eval "FLAGS_${_flags_name_}='${_flags_default_}'"
eval "__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}=${_flags_type_}"
eval "__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}=\
eval "FLAGS_${_flags_usName_}='${_flags_default_}'"
eval "__flags_${_flags_usName_}_${__FLAGS_INFO_TYPE}=${_flags_type_}"
eval "__flags_${_flags_usName_}_${__FLAGS_INFO_DEFAULT}=\
\"${_flags_default_}\""
eval "__flags_${_flags_name_}_${__FLAGS_INFO_HELP}=\"${_flags_help_}\""
eval "__flags_${_flags_name_}_${__FLAGS_INFO_SHORT}='${_flags_short_}'"
eval "__flags_${_flags_usName_}_${__FLAGS_INFO_HELP}=\"${_flags_help_}\""
eval "__flags_${_flags_usName_}_${__FLAGS_INFO_SHORT}='${_flags_short_}'"
# append flag name(s) to list of names
__flags_longNames="${__flags_longNames}${_flags_name_} "
# append flag names to name lists
__flags_shortNames="${__flags_shortNames}${_flags_short_} "
[ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
__flags_longNames="${__flags_longNames}`_flags_removeExclamationName ${_flags_name_}` "
if [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} \
-a ${_flags_isNegate_} -eq ${FLAGS_TRUE} ]; then
__flags_boolNames="${__flags_boolNames}no${_flags_name_} "
fi
# append flag names to defined names for later validation checks
__flags_definedNames="${__flags_definedNames}${_flags_usName_} "
if [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ]; then
if [ ${_flags_isNegate_} -eq ${FLAGS_TRUE} ]; then
__flags_definedNames="${__flags_definedNames}no${_flags_usName_} "
fi
fi
# append flag names to nonegateNames names for later validation checks
__flags_definedNames="${__flags_definedNames}${_flags_usName_} "
if [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ]; then
if [ ${_flags_isNegate_} -eq ${FLAGS_FALSE} ]; then
__flags_nonegateNames="${__flags_nonegateNames}`_flags_removeExclamationName ${_flags_name_}` "
fi
fi
fi
flags_return=${_flags_return_}
unset _flags_default_ _flags_help_ _flags_name_ _flags_return_ _flags_short_ \
_flags_type_
unset _flags_default_ _flags_help_ _flags_name_ _flags_return_ \
_flags_short_ _flags_type_ _flags_usName_
[ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
return ${flags_return}
}
# Underscore a flag name by replacing dashes with underscores.
#
# Args:
# unnamed: string: log flag name
# Output:
# string: underscored name
_flags_underscoreName()
{
echo $1 |tr '-' '_'
}
# Strip potential exclamation mark
#
# Args:
# unnamed: string: log flag name
# Output:
# string: exclamation stripped from name
_flags_removeExclamationName()
{
_flags_opt_=$1
if _flags_isNegate "${_flags_opt_}"; then
echo ${_flags_opt_}
else
if _flags_useBuiltin; then
echo ${_flags_opt_%!*}
else
echo ${_flags_opt_}|sed 's/!$//'
fi
fi
unset _flags_opt_
return ${FLAGS_TRUE}
}
# Check if a flag ends in an exclamation mark,
# if it does, there will not be a negate option
# Args:
# unnamed: string: flag name
# return:
# boolean
_flags_isNegate()
{
case $1 in
*!) flags_return=${FLAGS_FALSE} ;;
*) flags_return=${FLAGS_TRUE} ;;
esac
return ${flags_return}
}
# Return valid getopt options using currently defined list of long options.
#
# This function builds a proper getopt option string for short (and long)
......@@ -350,12 +452,15 @@ _flags_genOptStr()
_flags_opts_=''
for _flags_flag_ in ${__flags_longNames}; do
_flags_type_=`_flags_getFlagInfo ${_flags_flag_} ${__FLAGS_INFO_TYPE}`
for _flags_name_ in ${__flags_longNames}; do
_flags_usName_=`_flags_removeExclamationName ${_flags_name_}`
_flags_usName_=`_flags_underscoreName ${_flags_usName_}`
_flags_type_=`_flags_getFlagInfo ${_flags_usName_} ${__FLAGS_INFO_TYPE}`
[ $? -eq ${FLAGS_TRUE} ] || _flags_fatal 'call to _flags_type_ failed'
case ${_flags_optStrType_} in
${__FLAGS_OPTSTR_SHORT})
_flags_shortName_=`_flags_getFlagInfo \
${_flags_flag_} ${__FLAGS_INFO_SHORT}`
${_flags_usName_} ${__FLAGS_INFO_SHORT}`
if [ "${_flags_shortName_}" != "${__FLAGS_NULL}" ]; then
_flags_opts_="${_flags_opts_}${_flags_shortName_}"
# getopt needs a trailing ':' to indicate a required argument
......@@ -365,7 +470,7 @@ _flags_genOptStr()
;;
${__FLAGS_OPTSTR_LONG})
_flags_opts_="${_flags_opts_:+${_flags_opts_},}${_flags_flag_}"
_flags_opts_="${_flags_opts_:+${_flags_opts_},}`_flags_removeExclamationName ${_flags_name_}`"
# getopt needs a trailing ':' to indicate a required argument
[ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
_flags_opts_="${_flags_opts_}:"
......@@ -374,15 +479,15 @@ _flags_genOptStr()
done
echo "${_flags_opts_}"
unset _flags_flag_ _flags_opts_ _flags_optStrType_ _flags_shortName_ \
_flags_type_
unset _flags_name_ _flags_opts_ _flags_optStrType_ _flags_shortName_ \
_flags_type_ _flags_usName_
return ${FLAGS_TRUE}
}
# Returns flag details based on a flag name and flag info.
#
# Args:
# string: long flag name
# string: underscored flag name
# string: flag info (see the _flags_define function for valid info types)
# Output:
# string: value of dereferenced flag variable
......@@ -390,62 +495,68 @@ _flags_genOptStr()
# integer: one of FLAGS_{TRUE|FALSE|ERROR}
_flags_getFlagInfo()
{
_flags_name_=$1
_flags_info_=$2
# note: adding gFI to variable names to prevent naming conflicts with calling
# functions
_flags_gFI_usName_=$1
_flags_gFI_info_=$2
_flags_nameVar_="__flags_${_flags_name_}_${_flags_info_}"
_flags_strToEval_="_flags_value_=\"\${${_flags_nameVar_}:-}\""
_flags_infoVar_="__flags_${_flags_gFI_usName_}_${_flags_gFI_info_}"
_flags_strToEval_="_flags_infoValue_=\"\${${_flags_infoVar_}:-}\""
eval "${_flags_strToEval_}"
if [ -n "${_flags_value_}" ]; then
if [ -n "${_flags_infoValue_}" ]; then
flags_return=${FLAGS_TRUE}
else
# see if the _flags_name_ variable is a string as strings can be empty...
# see if the _flags_gFI_usName_ variable is a string as strings can be
# empty...
# note: the DRY principle would say to have this function call itself for
# the next three lines, but doing so results in an infinite loop as an
# invalid _flags_name_ will also not have the associated _type variable.
# Because it doesn't (it will evaluate to an empty string) the logic will
# try to find the _type variable of the _type variable, and so on. Not so
# good ;-)
_flags_typeVar_="__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}"
_flags_strToEval_="_flags_type_=\"\${${_flags_typeVar_}:-}\""
_flags_typeVar_="__flags_${_flags_gFI_usName_}_${__FLAGS_INFO_TYPE}"
_flags_strToEval_="_flags_typeValue_=\"\${${_flags_typeVar_}:-}\""
eval "${_flags_strToEval_}"
if [ "${_flags_type_}" = "${__FLAGS_TYPE_STRING}" ]; then
if [ "${_flags_typeValue_}" = "${__FLAGS_TYPE_STRING}" ]; then
flags_return=${FLAGS_TRUE}
else
flags_return=${FLAGS_ERROR}
flags_error="invalid flag name (${_flags_nameVar_})"
flags_error="missing flag info variable (${_flags_infoVar_})"
fi
fi
echo "${_flags_value_}"
unset _flags_info_ _flags_name_ _flags_strToEval_ _flags_type_ _flags_value_ \
_flags_nameVar_ _flags_typeVar_
echo "${_flags_infoValue_}"
unset _flags_gFI_usName_ _flags_gfI_info_ _flags_infoValue_ _flags_infoVar_ \
_flags_strToEval_ _flags_typeValue_ _flags_typeVar_
[ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
return ${flags_return}
}
# check for presense of item in a list. passed a string (e.g. 'abc'), this
# function will determine if the string is present in the list of strings (e.g.
# ' foo bar abc ').
# Check for presense of item in a list.
#
# Passed a string (e.g. 'abc'), this function will determine if the string is
# present in the list of strings (e.g. ' foo bar abc ').
#
# Args:
# _flags__str: string: string to search for in a list of strings
# _flags_str_: string: string to search for in a list of strings
# unnamed: list: list of strings
# Returns:
# boolean: true if item is in the list
_flags_itemInList()
{
_flags_itemInList() {
_flags_str_=$1
shift
_flags_list_=" ${*:-} "
echo " ${*:-} " |grep " ${_flags_str_} " >/dev/null
if [ $? -eq 0 ]; then
flags_return=${FLAGS_TRUE}
else
flags_return=${FLAGS_FALSE}
fi
case ${_flags_list_} in
*\ ${_flags_str_}\ *)
flags_return=$FLAGS_TRUE
;;
*)
flags_return=$FLAGS_FALSE
;;
esac
unset _flags_str_
unset _flags_str_ _flags_list_
return ${flags_return}
}
......@@ -477,7 +588,7 @@ _flags_columns()
# _flags__bool: boolean: value to validate
# Returns:
# bool: true if the value is a valid boolean
_flags_validateBoolean()
_flags_validBool()
{
_flags_bool_=$1
......@@ -495,54 +606,74 @@ _flags_validateBoolean()
# Validate a float.
#
# Args:
# _flags__float: float: value to validate
# _flags_float_: float: value to validate
# Returns:
# bool: true if the value is a valid float
_flags_validateFloat()
# bool: true if the value is a valid integer
_flags_validFloat()
{
flags_return=${FLAGS_FALSE}
[ -n "$1" ] || return ${flags_return}
_flags_float_=$1
if _flags_validateInteger ${_flags_float_}; then
if _flags_validInt ${_flags_float_}; then
flags_return=${FLAGS_TRUE}
elif _flags_useBuiltin; then
_flags_float_whole_=${_flags_float_%.*}
_flags_float_fraction_=${_flags_float_#*.}
if _flags_validInt ${_flags_float_whole_:-0} -a \
_flags_validInt ${_flags_float_fraction_}; then
flags_return=${FLAGS_TRUE}
fi
unset _flags_float_whole_ _flags_float_fraction_
else
flags_return=${FLAGS_TRUE}
case ${_flags_float_} in
-*) # negative floats
_flags_test_=`expr "${_flags_float_}" : '\(-[0-9][0-9]*\.[0-9][0-9]*\)'`
_flags_test_=`${FLAGS_EXPR_CMD} -- "${_flags_float_}" :\
'\(-[0-9]*\.[0-9]*\)'`
;;
*) # positive floats
_flags_test_=`expr "${_flags_float_}" : '\([0-9][0-9]*\.[0-9][0-9]*\)'`
_flags_test_=`${FLAGS_EXPR_CMD} -- "${_flags_float_}" :\
'\([0-9]*\.[0-9]*\)'`
;;
esac
[ "${_flags_test_}" != "${_flags_float_}" ] && flags_return=${FLAGS_FALSE}
unset _flags_test_
fi
unset _flags_float_ _flags_test_
unset _flags_float_ _flags_float_whole_ _flags_float_fraction_
return ${flags_return}
}
# Validate an integer.
#
# Args:
# _flags__integer: interger: value to validate
# _flags_int_: integer: value to validate
# Returns:
# bool: true if the value is a valid integer
_flags_validateInteger()
_flags_validInt()
{
flags_return=${FLAGS_FALSE}
[ -n "$1" ] || return ${flags_return}
_flags_int_=$1
flags_return=${FLAGS_TRUE}
case ${_flags_int_} in
-*) # negative ints
_flags_test_=`expr "${_flags_int_}" : '\(-[0-9][0-9]*\)'`
;;
*) # positive ints
_flags_test_=`expr "${_flags_int_}" : '\([0-9][0-9]*\)'`
-*.*) ;; # ignore negative floats (we'll invalidate them later)
-*) # strip possible leading negative sign
if _flags_useBuiltin; then
_flags_int_=${_flags_int_#-}
else
_flags_int_=`${FLAGS_EXPR_CMD} -- "${_flags_int_}" : '-\([0-9][0-9]*\)'`
fi
;;
esac
[ "${_flags_test_}" != "${_flags_int_}" ] && flags_return=${FLAGS_FALSE}
unset _flags_int_ _flags_test_
case ${_flags_int_} in
*[!0-9]*) flags_return=${FLAGS_FALSE} ;;
*) flags_return=${FLAGS_TRUE} ;;
esac
unset _flags_int_
return ${flags_return}
}
......@@ -602,7 +733,7 @@ _flags_getoptEnhanced()
|sed 's/^ *//;s/ *$//;s/ /,/g'`
_flags_longOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_LONG}`
__flags_opts=`getopt \
__flags_opts=`${FLAGS_GETOPT_CMD} \
-o ${_flags_shortOpts_} \
-l "${_flags_longOpts_},${_flags_boolOpts_}" \
-- "$@" 2>&1`
......@@ -642,12 +773,12 @@ _flags_parseGetopt()
eval set -- "$@"
fi
# provide user with number of arguments to shift by later
# Provide user with the number of arguments to shift by later.
# NOTE: the FLAGS_ARGC variable is obsolete as of 1.0.3 because it does not
# properly give user access to non-flag arguments mixed in between flag
# arguments. Its usage was replaced by FLAGS_ARGV, and it is being kept only
# for backwards compatibility reasons.
FLAGS_ARGC=`expr $# - 1 - ${_flags_argc_}`
FLAGS_ARGC=`_flags_math "$# - 1 - ${_flags_argc_}"`
# handle options. note options with values must do an additional shift
while true; do
......@@ -661,14 +792,22 @@ _flags_parseGetopt()
--) shift; break ;; # discontinue option parsing
--*) # long option
_flags_opt_=`expr "${_flags_opt_}" : '--\(.*\)'`
if _flags_useBuiltin; then
_flags_opt_=${_flags_opt_#*--}
else
_flags_opt_=`${FLAGS_EXPR_CMD} -- "${_flags_opt_}" : '--\(.*\)'`
fi
_flags_len_=${__FLAGS_LEN_LONG}
if _flags_itemInList "${_flags_opt_}" ${__flags_longNames}; then
_flags_name_=${_flags_opt_}
else
# check for negated long boolean version
if _flags_itemInList "${_flags_opt_}" ${__flags_boolNames}; then
_flags_name_=`expr "${_flags_opt_}" : 'no\(.*\)'`
if _flags_useBuiltin; then
_flags_name_=${_flags_opt_#*no}
else
_flags_name_=`${FLAGS_EXPR_CMD} -- "${_flags_opt_}" : 'no\(.*\)'`
fi
_flags_type_=${__FLAGS_TYPE_BOOLEAN}
_flags_arg_=${__FLAGS_NULL}
fi
......@@ -676,7 +815,11 @@ _flags_parseGetopt()
;;
-*) # short option
_flags_opt_=`expr "${_flags_opt_}" : '-\(.*\)'`
if _flags_useBuiltin; then
_flags_opt_=${_flags_opt_#*-}
else
_flags_opt_=`${FLAGS_EXPR_CMD} -- "${_flags_opt_}" : '-\(.*\)'`
fi
_flags_len_=${__FLAGS_LEN_SHORT}
if _flags_itemInList "${_flags_opt_}" ${__flags_shortNames}; then
# yes. match short name to long name. note purposeful off-by-one
......@@ -698,32 +841,34 @@ _flags_parseGetopt()
fi
# set new flag value
_flags_usName_=`_flags_removeExclamationName ${_flags_name_}`
_flags_usName_=`_flags_underscoreName ${_flags_usName_}`
[ ${_flags_type_} -eq ${__FLAGS_TYPE_NONE} ] && \
_flags_type_=`_flags_getFlagInfo \
"${_flags_name_}" ${__FLAGS_INFO_TYPE}`
"${_flags_usName_}" ${__FLAGS_INFO_TYPE}`
case ${_flags_type_} in
${__FLAGS_TYPE_BOOLEAN})
if [ ${_flags_len_} -eq ${__FLAGS_LEN_LONG} ]; then
if [ "${_flags_arg_}" != "${__FLAGS_NULL}" ]; then
eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
eval "FLAGS_${_flags_usName_}=${FLAGS_TRUE}"
else
eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
eval "FLAGS_${_flags_usName_}=${FLAGS_FALSE}"
fi
else
_flags_strToEval_="_flags_val_=\
\${__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}}"
\${__flags_${_flags_usName_}_${__FLAGS_INFO_DEFAULT}}"
eval "${_flags_strToEval_}"
if [ ${_flags_val_} -eq ${FLAGS_FALSE} ]; then
eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
eval "FLAGS_${_flags_usName_}=${FLAGS_TRUE}"
else
eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
eval "FLAGS_${_flags_usName_}=${FLAGS_FALSE}"
fi
fi
;;
${__FLAGS_TYPE_FLOAT})
if _flags_validateFloat "${_flags_arg_}"; then
eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
if _flags_validFloat "${_flags_arg_}"; then
eval "FLAGS_${_flags_usName_}='${_flags_arg_}'"
else
flags_error="invalid float value (${_flags_arg_})"
flags_return=${FLAGS_ERROR}
......@@ -732,8 +877,8 @@ _flags_parseGetopt()
;;
${__FLAGS_TYPE_INTEGER})
if _flags_validateInteger "${_flags_arg_}"; then
eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
if _flags_validInt "${_flags_arg_}"; then
eval "FLAGS_${_flags_usName_}='${_flags_arg_}'"
else
flags_error="invalid integer value (${_flags_arg_})"
flags_return=${FLAGS_ERROR}
......@@ -742,16 +887,16 @@ _flags_parseGetopt()
;;
${__FLAGS_TYPE_STRING})
eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
eval "FLAGS_${_flags_usName_}='${_flags_arg_}'"
;;
esac
# handle special case help flag
if [ "${_flags_name_}" = 'help' ]; then
if [ "${_flags_usName_}" = 'help' ]; then
if [ ${FLAGS_help} -eq ${FLAGS_TRUE} ]; then
flags_help
flags_error='help requested'
flags_return=${FLAGS_FALSE}
flags_return=${FLAGS_TRUE}
break
fi
fi
......@@ -769,14 +914,77 @@ _flags_parseGetopt()
done
unset _flags_arg_ _flags_len_ _flags_name_ _flags_opt_ _flags_pos_ \
_flags_strToEval_ _flags_type_ _flags_val_
_flags_strToEval_ _flags_type_ _flags_usName_ _flags_val_
return ${flags_return}
}
# Perform some path using built-ins.
#
# Args:
# $@: string: math expression to evaluate
# Output:
# integer: the result
# Returns:
# bool: success of math evaluation
_flags_math()
{
if [ $# -eq 0 ]; then
flags_return=${FLAGS_FALSE}
elif _flags_useBuiltin; then
# Variable assignment is needed as workaround for Solaris Bourne shell,
# which cannot parse a bare $((expression)).
_flags_expr_='$(($@))'
eval echo ${_flags_expr_}
flags_return=$?
unset _flags_expr_
else
eval expr $@
flags_return=$?
fi
return ${flags_return}
}
# Cross-platform strlen() implementation.
#
# Args:
# _flags_str: string: to determine length of
# Output:
# integer: length of string
# Returns:
# bool: success of strlen evaluation
_flags_strlen()
{
_flags_str_=${1:-}
if [ -z "${_flags_str_}" ]; then
flags_output=0
elif _flags_useBuiltin; then
flags_output=${#_flags_str_}
else
flags_output=`${FLAGS_EXPR_CMD} -- "${_flags_str_}" : '.*'`
fi
flags_return=$?
unset _flags_str_
echo ${flags_output}
return ${flags_return}
}
# Use built-in helper function to enable unit testing.
#
# Args:
# None
# Returns:
# bool: true if built-ins should be used
_flags_useBuiltin()
{
return ${__FLAGS_USE_BUILTIN}
}
#------------------------------------------------------------------------------
# public functions
#
# A basic boolean flag. Boolean flags do not take any arguments, and their
# value is either 1 (false) or 0 (true). For long flags, the false value is
# specified on the command line by prepending the word 'no'. With short flags,
......@@ -807,7 +1015,7 @@ FLAGS()
{
# define a standard 'help' flag if one isn't already defined
[ -z "${__flags_help_type:-}" ] && \
DEFINE_boolean 'help' false 'show this help' 'h'
DEFINE_boolean 'help!' false 'show this help' 'h'
# parse options
if [ $# -gt 0 ]; then
......@@ -832,7 +1040,7 @@ FLAGS()
return ${flags_return}
}
# This is a helper function for determining the `getopt` version for platforms
# This is a helper function for determining the 'getopt' version for platforms
# where the detection isn't working. It simply outputs debug information that
# can be included in a bug report.
#
......@@ -858,10 +1066,10 @@ flags_getoptInfo()
fi
# getopt info
getopt >/dev/null
${FLAGS_GETOPT_CMD} >/dev/null
_flags_getoptReturn=$?
_flags_debug "getopt return: ${_flags_getoptReturn}"
_flags_debug "getopt --version: `getopt --version 2>&1`"
_flags_debug "getopt --version: `${FLAGS_GETOPT_CMD} --version 2>&1`"
unset _flags_getoptReturn
}
......@@ -911,24 +1119,30 @@ flags_help()
for flags_name_ in ${__flags_longNames}; do
flags_flagStr_=''
flags_boolStr_=''
flags_usName_=`_flags_underscoreName ${flags_name_}`
flags_default_=`_flags_getFlagInfo \
"${flags_name_}" ${__FLAGS_INFO_DEFAULT}`
"${flags_usName_}" ${__FLAGS_INFO_DEFAULT}`
flags_help_=`_flags_getFlagInfo \
"${flags_name_}" ${__FLAGS_INFO_HELP}`
"${flags_usName_}" ${__FLAGS_INFO_HELP}`
flags_short_=`_flags_getFlagInfo \
"${flags_name_}" ${__FLAGS_INFO_SHORT}`
"${flags_usName_}" ${__FLAGS_INFO_SHORT}`
flags_type_=`_flags_getFlagInfo \
"${flags_name_}" ${__FLAGS_INFO_TYPE}`
"${flags_usName_}" ${__FLAGS_INFO_TYPE}`
[ "${flags_short_}" != "${__FLAGS_NULL}" ] \
&& flags_flagStr_="-${flags_short_}"
[ "${flags_short_}" != "${__FLAGS_NULL}" ] && \
flags_flagStr_="-${flags_short_}"
if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
[ "${flags_short_}" != "${__FLAGS_NULL}" ] \
&& flags_flagStr_="${flags_flagStr_},"
[ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] \
&& flags_boolStr_='[no]'
[ "${flags_short_}" != "${__FLAGS_NULL}" ] && \
flags_flagStr_="${flags_flagStr_},"
# add [no] to long boolean flag names, except the 'help' flag
if [ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ]; then
_flags_itemInList "${flags_name_}" ${__flags_nonegateNames}
if [ $? -eq ${FLAGS_FALSE} ]; then
flags_boolStr_='[no]'
fi
fi
flags_flagStr_="${flags_flagStr_}--${flags_boolStr_}${flags_name_}:"
fi
......@@ -947,8 +1161,10 @@ flags_help()
flags_defaultStr_="(default: ${flags_defaultStr_})"
flags_helpStr_=" ${flags_flagStr_} ${flags_help_} ${flags_defaultStr_}"
flags_helpStrLen_=`expr "${flags_helpStr_}" : '.*'`
_flags_strlen "${flags_helpStr_}" >/dev/null
flags_helpStrLen_=${flags_output}
flags_columns_=`_flags_columns`
if [ ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
echo "${flags_helpStr_}" >&2
else
......@@ -958,7 +1174,9 @@ flags_help()
flags_emptyStr_="`echo \"x${flags_flagStr_}x\" \
|awk '{printf "%"length($0)-2"s", ""}'`"
flags_helpStr_=" ${flags_emptyStr_} ${flags_defaultStr_}"
flags_helpStrLen_=`expr "${flags_helpStr_}" : '.*'`
_flags_strlen "${flags_helpStr_}" >/dev/null
flags_helpStrLen_=${flags_output}
if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD} \
-o ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
# indented to match help string
......@@ -974,7 +1192,7 @@ flags_help()
unset flags_boolStr_ flags_default_ flags_defaultStr_ flags_emptyStr_ \
flags_flagStr_ flags_help_ flags_helpStr flags_helpStrLen flags_name_ \
flags_columns_ flags_short_ flags_type_
flags_columns_ flags_short_ flags_type_ flags_usName_
return ${FLAGS_TRUE}
}
......@@ -987,7 +1205,9 @@ flags_help()
flags_reset()
{
for flags_name_ in ${__flags_longNames}; do
flags_strToEval_="unset FLAGS_${flags_name_}"
flags_usName_=`_flags_removeExclamationName ${flags_name_}`
flags_usName_=`_flags_underscoreName ${flags_usName_}`
flags_strToEval_="unset FLAGS_${flags_usName_}"
for flags_type_ in \
${__FLAGS_INFO_DEFAULT} \
${__FLAGS_INFO_HELP} \
......@@ -995,7 +1215,7 @@ flags_reset()
${__FLAGS_INFO_TYPE}
do
flags_strToEval_=\
"${flags_strToEval_} __flags_${flags_name_}_${flags_type_}"
"${flags_strToEval_} __flags_${flags_usName_}_${flags_type_}"
done
eval ${flags_strToEval_}
done
......@@ -1004,6 +1224,7 @@ flags_reset()
__flags_boolNames=' '
__flags_longNames=' '
__flags_shortNames=' '
__flags_definedNames=' '
unset flags_name_ flags_type_ flags_strToEval_
unset flags_name_ flags_type_ flags_strToEval_ flags_usName_
}
#!/bin/sh
#
# Runs during git flow hotfix finish and a tag message is given
#
# Positional arguments:
# $1 Message
# $2 Full version
#
# Return MESSAGE
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
MESSAGE="$1"
# Implement your script here.
# Return the MESSAGE
echo "${MESSAGE}"
exit 0
#!/bin/sh
#
# Runs during git flow hotfix start
#
# Positional arguments:
# $1 Version
#
# Return VERSION - When VERSION is returned empty, git-flow will stop as the
# version is necessary
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
VERSION=$1
# Implement your script here.
# Return the VERSION
echo ${VERSION}
exit 0
#!/bin/sh
#
# Runs during git flow release branch and a tag message is given
#
# Positional arguments:
# $1 Message
# $2 Full version
#
# Return MESSAGE
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
MESSAGE="$1"
# Implement your script here.
# Return the MESSAGE
echo "${MESSAGE}"
exit 0
#!/bin/sh
#
# Runs during git flow release finish and a tag message is given
#
# Positional arguments:
# $1 Message
# $2 Full version
#
# Return MESSAGE
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
MESSAGE="$1"
# Implement your script here.
# Return the MESSAGE
echo "${MESSAGE}"
exit 0
#!/bin/sh
#
# Runs during git flow release start
#
# Positional arguments:
# $1 Version
#
# Return VERSION - When VERSION is returned empty, git-flow will stop as the
# version is necessary
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
# Implement your script here.
# Return the VERSION
echo ${VERSION}
exit 0
#!/bin/sh
#
# Runs at the end of git flow bugfix delete
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the bugfix prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow bugfix finish
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the bugfix prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow bugfix publish
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the bugfix prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow bugfix pull.
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The remote to pull from
# $3 The full branch name (including the bugfix prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
REMOTE=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow bugfix start
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the bugfix prefix)
# $4 The base from which this bugfix is started
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
BASE=$4
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow bugfix track
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the bugfix prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow feature delete
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow feature finish
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow feature publish
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow feature pull.
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The remote to pull from
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
REMOTE=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow feature start
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
# $4 The base from which this feature is started
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
BASE=$4
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow feature track
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow hotfix delete
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow hotfix finish
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow hotfix publish
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow hotfix start
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
# $4 The base from which this feature is started
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
BASE=$4
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow release branch
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow release delete
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow release finish
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow release publish
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow release start
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the release prefix)
# $4 The base from which this release is started
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
BASE=$4
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs at the end of git flow release track
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
exit 0
#!/bin/sh
#
# Runs before git flow feature delete
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow feature finish
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow feature publish
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow feature pull.
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The remote to pull from
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
REMOTE=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow feature start
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
# $4 The base from which this feature is started
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
BASE=$4
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow feature track
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
NAME=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow hotfix delete
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow hotfix finish
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow hotfix publish
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow hotfix start
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the feature prefix)
# $4 The base from which this feature is started
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
BASE=$4
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow release branch
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow release delete
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow release finish
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow release publish
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow release start
#
# Positional arguments:
# $1 The version (including the version prefix)
# $2 The origin remote
# $3 The full branch name (including the release prefix)
# $4 The base from which this release is started
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
BASE=$4
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
#!/bin/sh
#
# Runs before git flow release track
#
# Positional arguments:
# $1 The friendly name of the branch
# $2 The origin remote
# $3 The full branch name (including the release prefix)
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as Develop
#
VERSION=$1
ORIGIN=$2
BRANCH=$3
# Implement your script here.
# To terminate the git-flow action, return a non-zero exit code.
exit 0
0 info it worked if it ends with ok
1 verbose cli [ '/home/clive/.nvm/versions/node/v6.6.0/bin/node',
1 verbose cli '/home/clive/.nvm/versions/node/v6.6.0/bin/npm',
1 verbose cli 'link' ]
2 info using npm@3.10.3
3 info using node@v6.6.0
4 verbose linkPkg /mnt/c/Users/clive/Code/dreidev/gitflow
5 silly gentlyRm /home/clive/.nvm/versions/node/v6.6.0/lib/node_modules/gitflow is being purged
6 verbose gentlyRm don't care about contents; nuking /home/clive/.nvm/versions/node/v6.6.0/lib/node_modules/gitflow
7 silly vacuum-fs purging /home/clive/.nvm/versions/node/v6.6.0/lib/node_modules/gitflow
8 silly vacuum-fs quitting because other entries in /home/clive/.nvm/versions/node/v6.6.0/lib/node_modules
9 verbose link build target /home/clive/.nvm/versions/node/v6.6.0/lib/node_modules/gitflow
10 silly loadCurrentTree Starting
11 silly install loadCurrentTree
12 silly install readLocalPackageData
13 silly install normalizeTree
14 silly loadCurrentTree Finishing
15 silly loadIdealTree Starting
16 silly install loadIdealTree
17 silly cloneCurrentTree Starting
18 silly install cloneCurrentTreeToIdealTree
19 silly cloneCurrentTree Finishing
20 silly loadShrinkwrap Starting
21 silly install loadShrinkwrap
22 silly loadShrinkwrap Finishing
23 silly loadAllDepsIntoIdealTree Starting
24 silly install loadAllDepsIntoIdealTree
25 silly loadAllDepsIntoIdealTree Finishing
26 silly loadIdealTree Finishing
27 silly currentTree gitflow@0.4.7
27 silly currentTree ├── balanced-match@0.4.2
27 silly currentTree ├── brace-expansion@1.1.6
27 silly currentTree ├── commander@2.9.0
27 silly currentTree ├── concat-map@0.0.1
27 silly currentTree ├── fs.realpath@1.0.0
27 silly currentTree ├── glob@7.1.1
27 silly currentTree ├── graceful-readlink@1.0.1
27 silly currentTree ├── inflight@1.0.6
27 silly currentTree ├── inherits@2.0.3
27 silly currentTree ├── interpret@1.0.1
27 silly currentTree ├── minimatch@3.0.3
27 silly currentTree ├── once@1.4.0
27 silly currentTree ├── path-is-absolute@1.0.1
27 silly currentTree ├── rechoir@0.6.2
27 silly currentTree ├── resolve@1.2.0
27 silly currentTree ├── shelljs@0.7.6
27 silly currentTree └── wrappy@1.0.2
28 silly idealTree gitflow@0.4.7
28 silly idealTree ├── balanced-match@0.4.2
28 silly idealTree ├── brace-expansion@1.1.6
28 silly idealTree ├── commander@2.9.0
28 silly idealTree ├── concat-map@0.0.1
28 silly idealTree ├── fs.realpath@1.0.0
28 silly idealTree ├── glob@7.1.1
28 silly idealTree ├── graceful-readlink@1.0.1
28 silly idealTree ├── inflight@1.0.6
28 silly idealTree ├── inherits@2.0.3
28 silly idealTree ├── interpret@1.0.1
28 silly idealTree ├── minimatch@3.0.3
28 silly idealTree ├── once@1.4.0
28 silly idealTree ├── path-is-absolute@1.0.1
28 silly idealTree ├── rechoir@0.6.2
28 silly idealTree ├── resolve@1.2.0
28 silly idealTree ├── shelljs@0.7.6
28 silly idealTree └── wrappy@1.0.2
29 silly generateActionsToTake Starting
30 silly install generateActionsToTake
31 silly generateActionsToTake Finishing
32 silly diffTrees action count 0
33 silly decomposeActions action count 0
34 silly executeActions Starting
35 silly install executeActions
36 silly doSerial global-install 0
37 silly doParallel fetch 0
38 verbose correctMkdir /home/clive/.npm/_locks correctMkdir not in flight; initializing
39 verbose lock using /home/clive/.npm/_locks/staging-1ced2b31bd2e26fd.lock for /mnt/c/Users/clive/Code/dreidev/gitflow/node_modules/.staging
40 silly doParallel extract 0
41 silly doParallel preinstall 0
42 silly doReverseSerial remove 0
43 silly doSerial move 0
44 silly doSerial finalize 0
45 silly doSerial build 0
46 silly doSerial global-link 0
47 silly doParallel update-linked 0
48 silly doSerial install 0
49 silly doSerial postinstall 0
50 verbose unlock done using /home/clive/.npm/_locks/staging-1ced2b31bd2e26fd.lock for /mnt/c/Users/clive/Code/dreidev/gitflow/node_modules/.staging
51 silly executeActions Finishing
52 silly rollbackFailedOptional Starting
53 silly rollbackFailedOptional Finishing
54 silly runTopLevelLifecycles Starting
55 silly install runTopLevelLifecycles
56 silly preinstall gitflow@0.4.7 /mnt/c/Users/clive/Code/dreidev/gitflow/gitflow-c45d7dad
57 info lifecycle gitflow@0.4.7~preinstall: gitflow@0.4.7
58 silly lifecycle gitflow@0.4.7~preinstall: no script for preinstall, continuing
59 silly build gitflow@0.4.7
60 info linkStuff gitflow@0.4.7
61 silly linkStuff gitflow@0.4.7 has /mnt/c/Users/clive/Code/dreidev as its parent node_modules
62 verbose linkBins gitflow@0.4.7
63 verbose linkMans gitflow@0.4.7
64 silly install gitflow@0.4.7 /mnt/c/Users/clive/Code/dreidev/gitflow/gitflow-c45d7dad
65 info lifecycle gitflow@0.4.7~install: gitflow@0.4.7
66 silly lifecycle gitflow@0.4.7~install: no script for install, continuing
67 silly postinstall gitflow@0.4.7 /mnt/c/Users/clive/Code/dreidev/gitflow/gitflow-c45d7dad
68 info lifecycle gitflow@0.4.7~postinstall: gitflow@0.4.7
69 verbose lifecycle gitflow@0.4.7~postinstall: unsafe-perm in lifecycle true
70 verbose lifecycle gitflow@0.4.7~postinstall: PATH: /home/clive/.nvm/versions/node/v6.6.0/lib/node_modules/npm/bin/node-gyp-bin:/mnt/c/Users/clive/Code/dreidev/gitflow/node_modules/.bin:/home/clive/.nvm/versions/node/v6.6.0/bin:/home/clive/.nvm/versions/node/v6.6.0/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/opt/go_appengine
71 verbose lifecycle gitflow@0.4.7~postinstall: CWD: /mnt/c/Users/clive/Code/dreidev/gitflow
72 silly lifecycle gitflow@0.4.7~postinstall: Args: [ '-c',
72 silly lifecycle 'curl https://raw.githubusercontent.com/dreidev/gitflow/develop/contrib/gitflow-installer.sh > gitflow-installer.sh; chmod a+x gitflow-installer.sh; sudo bash gitflow-installer.sh install stable' ]
73 silly lifecycle gitflow@0.4.7~postinstall: Returned: code: 2 signal: null
74 info lifecycle gitflow@0.4.7~postinstall: Failed to exec postinstall script
75 verbose stack Error: gitflow@0.4.7 postinstall: `curl https://raw.githubusercontent.com/dreidev/gitflow/develop/contrib/gitflow-installer.sh > gitflow-installer.sh; chmod a+x gitflow-installer.sh; sudo bash gitflow-installer.sh install stable`
75 verbose stack Exit status 2
75 verbose stack at EventEmitter.<anonymous> (/home/clive/.nvm/versions/node/v6.6.0/lib/node_modules/npm/lib/utils/lifecycle.js:242:16)
75 verbose stack at emitTwo (events.js:106:13)
75 verbose stack at EventEmitter.emit (events.js:191:7)
75 verbose stack at ChildProcess.<anonymous> (/home/clive/.nvm/versions/node/v6.6.0/lib/node_modules/npm/lib/utils/spawn.js:40:14)
75 verbose stack at emitTwo (events.js:106:13)
75 verbose stack at ChildProcess.emit (events.js:191:7)
75 verbose stack at maybeClose (internal/child_process.js:877:16)
75 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)
76 verbose pkgid gitflow@0.4.7
77 verbose cwd /mnt/c/Users/clive/Code/dreidev/gitflow
78 error Linux 3.4.0+
79 error argv "/home/clive/.nvm/versions/node/v6.6.0/bin/node" "/home/clive/.nvm/versions/node/v6.6.0/bin/npm" "link"
80 error node v6.6.0
81 error npm v3.10.3
82 error code ELIFECYCLE
83 error gitflow@0.4.7 postinstall: `curl https://raw.githubusercontent.com/dreidev/gitflow/develop/contrib/gitflow-installer.sh > gitflow-installer.sh; chmod a+x gitflow-installer.sh; sudo bash gitflow-installer.sh install stable`
83 error Exit status 2
84 error Failed at the gitflow@0.4.7 postinstall script 'curl https://raw.githubusercontent.com/dreidev/gitflow/develop/contrib/gitflow-installer.sh > gitflow-installer.sh; chmod a+x gitflow-installer.sh; sudo bash gitflow-installer.sh install stable'.
84 error Make sure you have the latest version of node.js and npm installed.
84 error If you do, this is most likely a problem with the gitflow package,
84 error not with npm itself.
84 error Tell the author that this fails on your system:
84 error curl https://raw.githubusercontent.com/dreidev/gitflow/develop/contrib/gitflow-installer.sh > gitflow-installer.sh; chmod a+x gitflow-installer.sh; sudo bash gitflow-installer.sh install stable
84 error You can get information on how to open an issue for this project with:
84 error npm bugs gitflow
84 error Or if that isn't available, you can get their info via:
84 error npm owner ls gitflow
84 error There is likely additional logging output above.
85 verbose exit [ 1, true ]
{
"name": "gitflow",
"version": "0.4.7",
"description": "Modified gitflow for dreidev",
"main": "src/index.js",
"scripts": {
"postuninstall": "sudo make uninstall",
"postinstall": "curl https://raw.githubusercontent.com/dreidev/gitflow/develop/contrib/gitflow-installer.sh > gitflow-installer.sh; chmod a+x gitflow-installer.sh; sudo bash gitflow-installer.sh install stable"
},
"files": [
"src/"
],
"bin": {
"flow": "src/flow.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/dreidev/gitflow.git"
},
"keywords": [
"gitflow",
"dreidev",
"version",
"control",
"git",
"drazious",
"cmosh"
],
"author": "cmosh <cmosh@live.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/dreidev/gitflow/issues"
},
"homepage": "https://github.com/dreidev/gitflow#readme",
"dependencies": {
"commander": "^2.9.0",
"shelljs": "^0.7.6"
}
}
Subproject commit 2fb06af13de884e9680f14a00c82e52a67c867f1
require('shelljs/global');
const program = require('commander');
program.parse(process.argv);
var args = program.args;
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
}
exec('git flow bugfix '+args,{silent:true}, function(code, stdout, stderr) {
console.log(stdout.replace("git ",""));
console.log(stderr);
});
require('shelljs/global');
const program = require('commander');
program.parse(process.argv);
var args = program.args;
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
}
exec('git flow config '+args,{silent:true}, function(code, stdout, stderr) {
console.log(stdout.replace("git ",""));
console.log(stderr);
});
require('shelljs/global');
const program = require('commander');
program.parse(process.argv);
var args = program.args;
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
}
exec('git flow feature '+args,{silent:true}, function(code, stdout, stderr) {
console.log(stdout.replace("git ",""));
console.log(stderr);
});
require('shelljs/global');
const program = require('commander');
program.parse(process.argv);
var args = program.args;
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
}
exec('git flow hotfix '+args,{silent:true}, function(code, stdout, stderr) {
console.log(stdout.replace("git ",""));
console.log(stderr);
});
require('shelljs/global');
const program = require('commander');
program.parse(process.argv);
var args = program.args;
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
}
exec('git flow init '+args,{silent:true}, function(code, stdout, stderr) {
console.log(stdout.replace("git ",""));
console.log(stderr);
});
require('shelljs/global');
const program = require('commander');
program.parse(process.argv);
var args = program.args;
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
}
exec('git flow log '+args,{silent:true}, function(code, stdout, stderr) {
console.log(stdout.replace("git ",""));
console.log(stderr);
});
require('shelljs/global');
const program = require('commander');
program.parse(process.argv);
var args = program.args;
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
}
exec('git flow release '+args,{silent:true}, function(code, stdout, stderr) {
console.log(stdout.replace("git ",""));
console.log(stderr);
});
require('shelljs/global');
const program = require('commander');
program.parse(process.argv);
var args = program.args;
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
}
exec('git flow support '+args,{silent:true}, function(code, stdout, stderr) {
console.log(stdout.replace("git ",""));
console.log(stderr);
});
#! /usr/bin/env node
'use strict';
const program = require('commander');
const version = require('../package.json').version;
program
.version(version)
.command('bugfix [options...]','Command wrapper for git flow bugfix').alias('b')
.command('config [options...]','Command wrapper for git flow config').alias('c')
.command('feature [options...]','Command wrapper for git flow feature',{isDefault: true}).alias('fwf')
.command('hotfix [options...]','Command wrapper for git flow hotfix').alias('h')
.command('init [options...]','Command wrapper for git flow init').alias('i')
.command('log [options...]','Command wrapper for git flow log').alias('l')
.command('release [options...]','Command wrapper for git release').alias('r')
.command('support [options...]','Command wrapper for git support').alias('s')
.parse(process.argv);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment