Skip to content

Commit

Permalink
Fix: refactored code, standardised sanity checks, dropped unused comm…
Browse files Browse the repository at this point in the history
…ands
  • Loading branch information
stuartherbert committed Feb 28, 2013
1 parent 078f43c commit 1651730
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 471 deletions.
227 changes: 25 additions & 202 deletions git-hf-feature
Original file line number Diff line number Diff line change
Expand Up @@ -198,19 +198,18 @@ parse_remote_name() {
}

cmd_start() {
DEFINE_boolean fetch true 'fetch from origin before performing local operation' F
DEFINE_boolean fetch true 'fetch from $ORIGIN before creating the new branch' F
parse_args "$@"
BASE=${2:-$DEVELOP_BRANCH}
require_name_arg

# sanity checks
git fetch -q "$ORIGIN"
require_branch_absent "$ORIGIN/$BRANCH"

# update the local repo with remote changes, if asked
if noflag nofetch; then
git fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
require_clean_working_tree
require_remote_available
if flag fetch ; then
hubflow_fetch_latest_changes_from_origin
fi
require_branch_absent "$ORIGIN/$BRANCH"

# if the origin branch counterpart exists, assert that the local branch
# isn't behind it (to avoid unnecessary rebasing)
Expand All @@ -224,12 +223,7 @@ cmd_start() {
fi

# push it back up to remote repo
git push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
git fetch -q "$ORIGIN"

# configure remote tracking
git config "branch.$BRANCH.remote" "$ORIGIN"
git config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
hubflow_push_latest_changes_to_origin

echo
echo "Summary of actions:"
Expand All @@ -253,11 +247,11 @@ cmd_submit() {
require_branch "$BRANCH"
require_clean_working_tree
require_github_origin_repo
require_remote_available
hubflow_fetch_latest_changes_from_origin

# push to origin
if ! git push "$ORIGIN" "$BRANCH"; then
die "Failed to push '$BRANCH' to '$ORIGIN'"
fi
hubflow_push_latest_changes_to_origin

# pull request details
PR_FILE="./COMMIT_MSG"
Expand Down Expand Up @@ -343,57 +337,13 @@ cmd_finish() {

# sanity checks
require_branch "$BRANCH"
require_remote_available

# detect if we're restoring from a merge conflict
if [ -f "$DOT_GIT_DIR/.hubflow/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/.hubflow/MERGE_BASE")

# Since the working tree is now clean, either the user did a
# succesfull 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/.hubflow/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/.hubflow/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 hf feature finish $NAME"
echo
exit 1
fi
fi

# sanity checks
require_clean_working_tree
require_remote_available

# update local repo with remote changes first, if asked
if has "$ORIGIN/$BRANCH" $(git_remote_branches); then
if flag fetch; then
git fetch -q "$ORIGIN" "$BRANCH"
git fetch -q "$ORIGIN" "$DEVELOP_BRANCH"
fi
if flag fetch; then
# fetch and merge the latest changes from origin
hubflow_merge_latest_changes_from_origin
fi

if has "$ORIGIN/$BRANCH" $(git_remote_branches); then
Expand Down Expand Up @@ -423,41 +373,14 @@ cmd_finish() {
fi
fi

# merge into BASE
git checkout "$DEVELOP_BRANCH"
if [ "$(git rev-list -n2 "$DEVELOP_BRANCH..$BRANCH" | wc -l)" -eq 1 ]; then
git merge --ff "$BRANCH"
else
git merge --no-ff "$BRANCH"
fi

if [ $? -ne 0 ]; then
# oops.. we have a merge conflict!
# write the given $DEVELOP_BRANCH to a temporary file (we need it later)
mkdir -p "$DOT_GIT_DIR/.hubflow"
echo "$DEVELOP_BRANCH" > "$DOT_GIT_DIR/.hubflow/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 hf feature finish $NAME"
echo
exit 1
fi
# merge into the develop branch
# the merge_helper will not return if there is a merge conflict
# we want to remain on the DEVELOP_BRANCH after the merge is complete
hubflow_local_merge_helper "$BRANCH" "$DEVELOP_BRANCH" no_checkout_afterwards

# when no merge conflict is detected, just clean up the feature branch
helper_finish_cleanup
}

helper_finish_cleanup() {
# sanity checks
require_branch "$BRANCH"
require_clean_working_tree

# delete branch
if noflag nofetch; then
if flag fetch; then
git push "$ORIGIN" ":refs/heads/$BRANCH"
fi

Expand All @@ -471,37 +394,19 @@ helper_finish_cleanup() {

echo
echo "Summary of actions:"
if flag fetch ; then
echo "- The latest changes from '$ORIGIN' were merged into '$MASTER_BRANCH' and '$DEVELOP_BRANCH'"
fi
echo "- The feature branch '$BRANCH' was merged into '$DEVELOP_BRANCH'"
if flag keep; then
echo "- Feature branch '$BRANCH' is still available"
else
echo "- Feature branch '$BRANCH' has been removed"
fi
if noflag nofetch; then
if flag fetch; then
echo "- Feature branch '$ORIGIN/$BRANCH' has been removed"
fi
echo "- You are now on branch '$DEVELOP_BRANCH'"
echo
}

cmd_track() {
parse_args "$@"
require_name_arg

# sanity checks
require_clean_working_tree
require_branch_absent "$BRANCH"
git fetch -q "$ORIGIN"
require_branch "$ORIGIN/$BRANCH"

# create tracking branch
git checkout -b "$BRANCH" "$ORIGIN/$BRANCH"

echo
echo "Summary of actions:"
echo "- A new remote tracking branch '$BRANCH' was created"
echo "- You are now on branch '$BRANCH'"
echo
}

cmd_diff() {
Expand Down Expand Up @@ -564,93 +469,11 @@ 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
parse_remote_name "$@"

if [ -z "$REMOTE" ]; then
REMOTE="$ORIGIN"
fi
name_or_current

# 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)
if startswith "$current_branch" "$PREFIX"; then
# 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
# 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 pull --rebase "$REMOTE" "$BRANCH"; then
warn "Pull was aborted. There might be conflicts during rebase or '$REMOTE' might be inaccessible."
exit 1
fi
else
git pull "$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 fetch "$REMOTE" "$BRANCH" || die "Fetch failed." # stores in FETCH_HEAD
git branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed."
git checkout "$BRANCH" || die "Checking out new local branch failed."
echo "Created local branch $BRANCH based on $REMOTE's $BRANCH."
fi
git hf pull "$@"
}

cmd_push() {
DEFINE_boolean force false "Forces a destructive push using the --force/-f flag" F

parse_remote_name "$@"
if [ -z "$REMOTE" ]; then
REMOTE="$ORIGIN"
fi
name_or_current

# sanity checks
require_clean_working_tree
require_branch "$BRANCH"
git fetch -q "$REMOTE"

# are we publishing for the first time, or pushing?
if ! git_branch_exists "$REMOTE/$BRANCH" ; then

# create remote branch
git push "$REMOTE" "$BRANCH:refs/heads/$BRANCH"
git fetch -q "$REMOTE"

# configure remote tracking
git config "branch.$BRANCH.remote" "$REMOTE"
git config "branch.$BRANCH.merge" "refs/heads/$BRANCH"

echo
echo "Summary of actions:"
echo "- A new remote branch '$REMOTE/$BRANCH' was created"
echo "- The local branch '$BRANCH' was configured to track the remote branch"
echo
else
if flag force ; then
git push --force "$REMOTE" "$BRANCH:refs/heads/$BRANCH" || die "Push failed"
else
git push "$REMOTE" "$BRANCH:refs/heads/$BRANCH" || die "Push failed"
fi

echo
echo "Summary of actions:"
echo "- The remote branch '$REMOTE/$BRANCH' was updated with your changes"
fi
git hf push "$@"
}

cmd_cancel() {
Expand Down
Loading

0 comments on commit 1651730

Please sign in to comment.