bash string incorrectly split - bash

I have this script
#!/bin/bash
function clone {
url=$(cli-tool "$1" that finds url)
echo $url
$(git clone ${url})
}
echo prints the correct url in the format
"https://gitprovider.com/Example/_git/Repo%20Name" (not a real url but that mimics the real url)
But git clone outputs
fatal: could not create work tree dir 'Repo%20Name"': Invalid argument
If I execute
git clone "https://gitprovider.com/Example/_git/Repo%20Name"
the correct repo will be cloned.
So why isn't
$(git clone ${url})
Working?

Command substitution is only needed when you want to use the output of a command as an argument to another command. In your case, the output of git clone is then parsed as sequence of words used to build a command line. You don't want to do that; you just want git clone ... to run and have its output displayed on the terminal.
Compare
$ echo $(echo foo)
foo
$ $(echo foo)
bash: foo: command not found
You just want git clone "$url", not $(git clone "$url").

Instead of using $(git clone ${url}), just use git clone "${url}", i.e., drop the $( ) thing.

Related

git - how to get $(git_current_branch) variable from outside the git directory

I have a bash script containing the following code:
git -C "$1" push origin "$(git_current_branch)"
where "$1" is the git dir I am trying to push.
The problem is, I cannot get the correct "$(git_current_branch)" variable when I run the script from outside the git directory. I know I can just cd to "$1" before pushing, but I want a better solution (which makes my script cleaner).
Is there any way to do that? Thanks in advance!
Edit: I prefer to do this through git command option, if possible.
You can try that:
current_git_branch=$(git -C "$1" branch | sed '/^\*/!d;s/\* //')
explanation
call git in directory "$1" and print all branches
delete all branches without * at start of line
remove '* ' marker for current branch from line

How does eval stop the pathspec errors in this script?

I want to automate the many version control steps of Git. I was successful until I used git commit -S -m ${var} in my Bash script. This line gives me (pathspec errors x # of word) - 1... unless I use eval. How does eval make my script work?
I thought this article had the answer, but my issue involves a string, not an array.
Gif video of the broken vs. working Bash script
Broken code
brokenCommitCode () {
# Give it a multi-word, space-separated message
read -p 'Commit message (use quotes): ' commitMsg
commitMsg="'${commitMsg}'"
echo ${commitMsg}
git add -A &&
git commit -S -m ${commitMsg}
}
Working code
workingCommitCode () {
read -p 'Commit message (use quotes): ' commitMsg
commitMsg="'${commitMsg}'"
echo ${commitMsg}
git add -A &&
eval git commit -S -m ${commitMsg}
}
I expected the brokenCommitCode to commit properly with the message I enter on the prompt. The actual result is a pathspec error when it reaches git commit -S -m ${commitMsg}. How does eval make this work?
I'm using GNU bash, version 4.4.19(1)-release (x86_64-pc-msys) with git version 2.16.2.windows.1 on a Windows 8.1 PC.
Correct fix is
funname() {
read -p 'Commit message (use quotes): ' commitMsg
echo "${commitMsg}"
git add -A &&
git commit -S -m "${commitMsg}"
}
Why eval seems to fix:
single quotes where added to commitMsg variable (seems intent was to prevent message argument to be split on a whitespace)
looking what happens with the following message:
commitMsg="this is a message"
git commit -S -m ${commitMsg}
git commit -S -m this is a message
[error because "is" "a" "message" are taken as different additional arguments]
however it doesn't prevent because single quote is not re-interpreted but is like any other character in variable content
following with the example
git commit -S -m ${commitMsg}
git commit -S -m \'this is a message\'
[error "is" "a" "message'" are taken as different additional arguments]
with eval the single quotes are re-interpreted but also any other character which has a particular meaning in bash (;, &, ${..}, ..)
Suppose for example the following commit message which can inject arbitrary command.
commitMsg="message'; ls -l; echo 'done"
git commit -S -m 'message'; ls -l; echo 'done'

how to run a shell script as an alias?

I wanna alias a script to my zsh. Aliasing a script in zshrc does not work, the output of the script in nothing
There are no syntax errors in my script. i have tried running
"sh ./script.sh" in the script containing folder which does fetches the desired result but alias something="sh ~/script.sh" does not work
even alias something="source ~/script.sh" does not work
the script creates a local project and a github repo
contents of the script:
#!/bin/bash
function create () {
read -p 'Repository Name: ' uservar
projects_directory = ~/Downloads/Projects/ #change this path to the directory where you want to store you files
mkdir $projects_directory/$uservar
cd $projects_directory/$uservar
git init
touch README.md
echo -e "#$uservar" >> $projects_directory/$uservar/README.md
# this is where we make a github repo from cli
repo_name=$uservar
test -z $repo_name && echo "Repo name required." 1>&2 && exit 1
curl -u 'thisisshub' https://api.github.com/user/repos -d "{\"name\":\"$repo_name\"}" #change thisisshub to your <username>
#making a git repo from cli ends
git add .
git commit -m "Initial Commit"
git push -u origin master
code .
}
expected result: successful aliasing of a script
actual result: no output

Cannot suppress git branch error when not in a git repository

I would like my command prompt to display the current branch in my Prompt String 1 (PS1). The command works in git repositories, but when not in a git repo, I get the rightful error message: fatal: Not a git repository (or any of the parent directories): .git
I would like to suppress that error message otherwise every time I switch directories and I am not in a git repo, that error is printed to the terminal.
I read up on suppressing terminal output by sending error output to the null device /dev/null, but the error message still prints in my terminal.
Here is the command I am using to extract the current branch:
git branch 2>/dev/null | grep '*' | cut -d ' ' -f2.
Make sure to escape the $ in the $() construct, so that it will be evaluated anew when each prompt is generated instead of only when the PS1 variable is set.
Here's what it looks like for me in practice:
# Set PS1
$ PS1="\$(git branch 2>/dev/null | grep '*' | cut -d ' ' -f 2) $ "
# Currently in directory that is not a Git repository, change into one.
$ cd dotfiles/
# Git branch is then displayed in the prompt, leave the directory.
master $ cd ..
# No git branch displayed, change back into it for good measure.
$ cd dotfiles/
# Branch is displayed again.
master $

retrieve the path of a repo from the "git bash" from windows with right format

I am trying to retrieve the path of a repository from the "git bash" shell in windows, as follows
user#CND7293ZVV MINGW64 /c/Work/git/repository/subfolder (master)
$ git rev-parse --show-toplevel
C:/Work/git/repository
The problem is that I want to use the ouptut path to use it from a bash script, but it is not in bash format. I want to get /c/Work/git/repository. Is there any way to get the path in a way that can be used directly in the git bash shell?
extra information: The target is to store that path in a variable to be used inside a bash script, independently of whether I am running bash from a linux terminal, or when I am running from the git bash.
Update:
To be able to use the command inside the git-bash environment, and also inside native linux bash, we can use the following:
REPODIR=$(git rev-parse --show-toplevel)
# If we are inside mingw* environment, then we update the path to proper format
if [[ $(uname) == MINGW* ]] ; then REPODIR=$(cygpath -u "${REPODIR}"); fi; echo ${REPODIR}
When running on the Git bash command line, you have an buildin utility with the name cygpath that does this:
$ cygpath -u "C:/Work/git/repository"
/c/Work/git/repository
This can be combined with your existing command to do everything on 1 line:
$ cygpath -u "$(git rev-parse --show-toplevel)"
/c/Work/git/repository

Resources