Convert Bash Script That Accepts Argument to Zsh Script

Convert Bash Script That Accepts Argument to Zsh Script

I have a bash script that uses hub to create pull-requests easily. In bash it works fine, I just type gpr <base_branch> and does the logic in the code.

# git pr
function gpr() {
    # exit if no base branch supplied
    if [[ ! $1 ]]; then
        echo "No base branch supplied. Exiting"
        return
    fi

    if [[ ! $2 ]]; then
        echo "Creating pull-request"
        echo "No pull-request message set."
        read -p "Do you want to use the last commit message as pull-request message. Y or N? " choice
        if [[ $choice =~ ^[Yy]$ ]]; then
            # Use last commit message
            COMMIT=$(git log -1 HEAD --pretty=format:%s)
            echo "Using last commit message: $COMMIT"
            MESSAGE="-m '$COMMIT'"
        else
            # Use own message
            read -p "Enter message: " message
            MESSAGE=-"m '$message'"
        fi
    fi
    COMMAND="hub pull-request -b $1 $MESSAGE"
    echo "Creating pull-request against $1 branch with message: $MESSAGE"
    eval $COMMAND
    echo "Pull-request created successfully"
}

Which in the end will result to hub pull-request -b <base_branch> -m <pull-request message or last commit message>

But how do I convert this to zsh?

I tried pasting the code to .zshrc but it seems to be not working. I get the following when running gpr <base_branch>

gpr develop
Creating pull-request
No pull-request message set.
gpr:read:10: -p: no coprocess
gpr:read:18: -p: no coprocess
Creating pull-request against develop branch with message: -m ''
And vim appears

In bash the process goes like this

gpr develop
Creating pull-request
No pull-request message set.
Do you want to use the last commit message as pull-request message. Y or N? y
Using last commit message: [UIUX-x] Commit message
Creating pull-request against develop branch with message: -m '[UIUX-x] Commit message'

Pull-request created successfully
3

1 Answer

The problem is that zsh's read function takes different options than bash's. In bash, read -p specifies a prompt; in zsh, it says to read from a coprocess (which doesn't exist). You need to switch to the zsh syntax, which puts the prompt after the variable to read (delimited by a question mark):

read "choice?Do you want to use the last commit message as pull-request message. Y or N? "
...
read -p "message?Enter message: "

Also, I'd make two other recommendations (for both bash and zsh): first, use lowercase or mixed-case variable names; there are a large number of all-caps variable names with special meaning to the shell, system, etc (and they're not the same between bash and zsh), and it's way to easy to accidentally re-use one of them with weird consequences.

Second, building the command in a variable and then evaling it is not safe (in either bash or zsh). Either use an array, or just put the message (and just the message) in a variable and execute the command directly:

if ...
    message=$commit
else ...
    read message
fi

echo "Creating pull-request against $1 branch with message: $message"
hub pull-request -b "$1" -m "$message"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

James H. Sterling
Author

James H. Sterling

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.