Bash Script that uses Git to Update Only Itself - bash

I have a bash script that gets updated fairly often that I would like to have self-update only itself using git, but not affect anything else.
I found an Example Script that updates itself, but it uses git pull --force which updates everything. Most of the time this should be fine, but I hesitate to automatically do something with the potential to have unintended consequences, safer to just affect only itself.
My attempts to modify that script to use checkout or cherry-pick have not been successful.
Does anyone have a function that updates only $0 or can write one?
Edit:
This is the messy code I wrote for my script.
#!/bin/bash
BRANCH="master"
SCRIPTNAME=$1
REPOSITORY="https://stash.xxx/projects/IT/repos/xxx/browse/$SCRIPTNAME"
self_update() {
git fetch
if [[ -n $(git diff --name-only origin/$BRANCH | grep $SCRIPTNAME) ]]
then
echo The version you have and the version on stash are different
echo
echo Do you want to:
echo
echo s. Show messy differences
echo c. Open repository in Chrome
echo
echo d. Download the stash version, overwrite your current version, and exit script
echo
echo q. return to the previous menu
read choice
case $choice in
s)
git diff origin/$BRANCH
echo
read -p "Enter to Return " enterkey
;;
c)
open -a "/Applications/Google Chrome.app" "$REPOSITORY"
;;
d)
git checkout -f origin/$BRANCH -- $SCRIPTNAME
#head -5 $SCRIPTNAME
exit
;;
q)
break
;;
*)
echo Please enter one of the choices.
;;
esac
else
echo You are using the current version of $SCRIPTNAME
break
fi
}
#testing code
head -5 $SCRIPTNAME
while :
do
self_update
done
head -5 $SCRIPTNAME

Checkout should work
git fetch the-remote
git checkout the-remote/the-branch -- the-file.sh
This better not run on windows because it will reject rewrite the script while it's running.

Related

While loop with if statement plus result of variable

I was doing a script for myself to summarize commands I use daily in one handy script. So basically I ended doing it with a conditional checking if the .git folder exists first but I'd like to make it more interesting and like so understand better the loop. My desire is to have a variable like:
"output=$(git status)" and if the result is 0, continue depending on the statement. If the result is other than 0, break the loop and end the script with a message like "the actual directory hasn't a .git repo".
I let you my first idea of it but without the git status as I don't know how to add it neither where to. Thank you guys!
set -e
gitrepo=true
while [ $gitrepo == true ]; do
if [[ $? -ne 0 ]]; then
echo "not a git directory"
$gitrepo=false
else
read -p "Commit message: " commit
git commit -am "$commit"
fi
done
Try this: I did as Cyrus suggested:
#!/usr/bin/env bash
set -e
gitrepo=True
while [[ $gitrepo ]]; do
if [[ ! $? ]]; then
echo "not a git directory"
gitrepo=False
else
read -p "Commit message: " -r commit
git commit -am "$commit"
exit 0
fi
done

Push nuget package only if the package version matches the Tag on Git's master branch

In our development environment, we have set up a NuGet local server (BaGet). We have adopted the Gitflow idea. When a library is ready to be released on Baget, the developer should first increase the Tag on the master branch (which needs to be approved first via a pull-request), then push the library to the Baget. We do this to keep the version of Git and Nuget in sync.
The process of keeping versions in sync (Git tag & NuGet version) is controlled manually by the developer and sometimes some team members forget to define the Git version tag and just push the library to Baget.
It would be a great help if the script could check the Current Git Tag before pushing the library to the Baget server, and only push it if the Tag and Version are the same. This can prevent pushing a version without matching Tag on git.
We use this script for pushing to Baget:
#!/bin/bash
clear
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR
ostype=`uname`
KEY=$NUGET_KEY
SOURCE=$NUGET_URL
while :
do
clear
echo "Input your package version: "
read version
Common="Dayan.Common/bin/Debug/Dayan.Common."$version".nupkg"
dotnet nuget push $Common -s $SOURCE -k $KEY
echo "press enter to continue ..."
read
done
Can I somehow check use git commands in the bash to get the Tag of the last commit on the master branch of the project, and check it with the user input for version?
One way to make that check would be to use the git command rev-list.
This command will output the commit SHA of the most recent commit:
$ git rev-list -n 1 HEAD
dfe4a9989b33e97f25645d79fd62900cc3209ec7
While this command will output the commit SHA of the tag 3.1.5:
$ git rev-list -n 1 "3.1.5"
a35117a201290b63b53ba6372dbf8bbfc68f28b9
The following example script should get you started:
#!/bin/bash
echo "Input your package version: "
read version
last_commit=$(git rev-list -n 1 HEAD 2>/dev/null)
last_commit_result=$?
if [ "$last_commit_result" != "0" ]; then
echo "Failed to get the SHA of the most recent commit"
exit 1
fi
version_commit=$(git rev-list -n 1 "$version" 2>/dev/null)
version_commit_result=$?
if [ "$version_commit_result" != "0" ]; then
echo "There is no commit with the tag: $version"
exit 1
fi
if [ "$last_commit" = "$version_commit" ]; then
echo "The most recent commit has the tag: $version"
else
echo "The most recent commit does NOT have the tag: $version"
fi
If you also want to make sure the script is only run from master then add this near the script's start:
active_branch=$(git branch --show-current 2>/dev/null)
active_branch_result=$?
if [ "$active_branch_result" != "0" ]; then
echo "Failed to get the active branch"
exit 1
elif [ "$active_branch" != "master" ]; then
echo "The active branch is not master"
exit 1
fi

Git Bash Script Check Working Tree

Is there a way in Git Bash to check if the working tree is clean, that is no uncommitted changes or untracked files?
I'm working on a bash script for my group to automate the process of daily rebasing working branches. Unclean working trees is a common problem. I can manually correct the problem by executing git checkout .. This would have the desired result most of the time, but not always, so I need to be able to have my script programatically check that the working directory/tree is clean.
The git-sh-setup script included with git contains a number of useful functions for working with git repositories. Among them is require_clean_work_tree:
require_clean_work_tree () {
git rev-parse --verify HEAD >/dev/null || exit 1
git update-index -q --ignore-submodules --refresh
err=0
if ! git diff-files --quiet --ignore-submodules
then
echo >&2 "Cannot $1: You have unstaged changes."
err=1
fi
if ! git diff-index --cached --quiet --ignore-submodules HEAD --
then
if [ $err = 0 ]
then
echo >&2 "Cannot $1: Your index contains uncommitted changes."
else
echo >&2 "Additionally, your index contains uncommitted changes."
fi
err=1
fi
if [ $err = 1 ]
then
test -n "$2" && echo >&2 "$2"
exit 1
fi
}
This is in addition to being able to check the output from git status --porcelain and/or git status -z if you need to be more specific about what the state currently is.

iterm2 zshell cmd+click open to github diff page

I have been researching how to change this behavior all day with no luck, so here goes.
Is there a way in iterm2, when viewing git logs, to change the way the cmd+click functions on the git log hash? Ideally, I am hoping that cmd+click would would open a browser window with the correct github url where the change set could be viewed.
If this is not possible, please let me know. I believe this would be very helpful to others, I wish I had the magic wand to figure out how to configure this.
Thoughts?
While this is not ideal, here is how I was able to work around this issue. I built a commit hook! Not perfect, I know. Ideas?
#!/bin/sh
#
# Automatically adds branch name and branch description to every commit message.
# Edit .git/hooks/commit-msg & make sure it is excutable chmod +x
# Requires git config --add remote.github.url {value}
#
NAME=$(git branch | grep '*' | sed 's/* //')
DESCRIPTION=$(git config branch."$NAME".description)
TEXT=$(cat "$1" | sed '/^#.*/d')
GIT_COMMIT_SHORT_ID=$(git rev-parse --short HEAD)
GIT_COMMIT_ID=$(git rev-parse HEAD)
GIT_GITHUB_URL=$(git config --get remote.github.url)
if [ -n "$TEXT" ]
then
echo "$NAME"': '$(cat "$1" | sed '/^#.*/d') > "$1"
if [ -n "$DESCRIPTION" ]
then
echo "" >> "$1"
echo $DESCRIPTION >> "$1"
fi
echo $GIT_GITHUB_URL$GIT_COMMIT_ID >> "$1"
else
echo "Aborting commit due to empty commit message."
exit 1
fi

App Engine: Launching a script upon update/run

I'm working with App Engine and I'm thinking about using the LESS CSS extension in my next project. There's no good LESS CSS library written in Python so I went on with the original Ruby one which works great and out of the box. I'd like App Engine to execute lessc ./templates/css/style.less before running the development server and before uploading the files to the cloud. What is the best way to automate this? I'm thinking:
#run.sh:
lessc ./templates/css/style.less
.gae/dev_appserver.py --use_sqlite .
And
#deploy.sh
lessc ./templates/css/style.less
.gae/appcfg.py update .
Am I on the correct path or is there a more elegant way of doing things, perhaps at the appcfg.py level?
Thanks.
One option is to use the javascript version of Less and hence do the less-to-css conversion in the browser.. simply upload your less formatted file (see http://lesscss.org/ for details).
Alternately, I do the conversion (first with less, now I use sass) in a deploy script which does a number of things
checks that my source code control has no outstanding files checked out (uncommited changes)
joins and minifies my .js code (and runs jslint over it) into a single file
generates other content (including stamping the source code control version as a version number into certain key files and as a parameter on some files to avoid caching issues) so my main page pulls in scripts with URLs such as "allmysource.js?v=585".. the file might be static but the added params force cache invalidation
calls appcfg to perform the upload and checks the return code
makes some calls to the real site with wget to check the previously generated files are actually returned, by checking they're stamped with the expected version
applies another source code control tag to say that the intended version was successfully deployed
My script also accepts a "-preview" flag in which case it doesn't actually do the upload, but reports the version control comments for what's changed since the previous deployment.
me#here $ ./deploy -preview
Deployment preview...
Would deploy v596 to the production site (currently v593, previously v587)
594 Fix blah blah blah for X Y Z
595 New feature nah nah nah
596 Update help pages
This is pretty handy as a reminder of what I need to put in things like a changelog
I plan to also expand it so that I can, as part of my source code control, add any code that needs running once only when deployed (eg database schema changes) and know that it'll be automatically run when I next deploy a new version.
Essence of the script below as people asked... it doesn't show my "check code, generate, join, and minify" as that's another script... I realise that the original question was asking about that step of course :) but you can see where you'd add the call to generate CSS etc
#!/bin/sh
function abort () {
echo
echo "ERROR: $1"
echo "$2"
exit 99
}
function warn () {
echo
echo "WARNING: $1"
echo "$2"
}
# Overrides the Gentoo eselect mechanism to force the python version the GAE scripts expect
export EPYTHON=python2.5
# names of tags used to label bzr versions
CURR_DTAG=deployed
PREV_DTAG=prevDeployed
# command line options
PREVIEW=0
IGNORE_BZR=0
# These next few vars are set to values to identify my site, insert your own values here...
APPID=your_gae_appid_here
ADMIN_EMAIL=your_admin_email_address_here
SRCDIR=directory_to_deploy
CHECK_URL=url_of_page_to_retrive_that_does_upload_initialisation
for ARG; do
if [[ "$ARG" == "-preview" ]]; then
echo "Deployment preview..."
PREVIEW=1
fi
if [[ "$ARG" == "-force" ]]; then
echo "Ignoring the fact some files may not be committed to bzr..."
IGNORE_BZR=1
fi
done
echo
# check bzr for uncommited changed
BSTATUS=`bzr status`
if [[ "$BSTATUS" != "" ]]; then
if [[ "$IGNORE_BZR" == "0" ]]; then
abort "There are uncommited changes - commit/revert/ignore all files before deploying" "$BSTATUS"
else
warn "There are uncommited changes" "$BSTATUS"
fi
fi
# get version of numbers of last deployed etc
currver=`bzr log -l1 --line | sed -e 's/: .*//'`
lastver=`bzr log -rtag:${CURR_DTAG} --line | sed -e 's/: .*//'`
prevver=`bzr log -rtag:${PREV_DTAG} --line | sed -e 's/: .*//'`
lastlog=`bzr log -l 1 --line gae/changelog | sed -e 's/: .*//'`
RELEASE_NOTES=`bzr log --short --forward -r $lastver..$currver \
| perl -ne '$ver = $1 if /^ {0,4}(\d+) /; print " $ver $_" if ($ver and /^ {5,}\w/)' \
| grep -v "^ *$lastver "`
LOG_NOTES=`bzr log --short --forward -r $lastlog..$currver \
| perl -ne '$ver = $1 if /^ {0,4}(\d+) /; print " $ver $_" if ($ver and /^ {5,}\w/)' \
| grep -v "^ *$lastlog "`
# Crude but old habit - BUGBUGBUG is a marker in the code for things to be fixed before deployment
echo "Checking code for outstanding issues before deployment"
BUGSTATUS=`grep BUGBUGBUG js/*js`
if [[ "$BUGSTATUS" != "" ]]; then
if [[ "$IGNORE_BZR" == "0" ]]; then
abort "There are outstanding BUGBUGBUGs - fix them before deploying" "$BUGSTATUS"
else
warn "There are outstanding BUGBUGBUGs" "$BUGSTATUS"
fi
fi
echo
echo "Deploy v$currver to the production site (currently v$lastver, previously v$prevver)"
echo "$RELEASE_NOTES"
echo
if [[ "$currver" -gt "$lastlog" && "$lastver" -ne "$lastlog" ]]; then
echo "Changes since the changelog was last updated"
echo "$LOG_NOTES"
echo
fi
if [[ "$IGNORE_BZR" == "0" && $lastver -ge $currver ]]; then
abort "There don't appear to be any changes to deploy..."
fi
if [[ "$PREVIEW" == "1" ]]; then
exit 0
fi
$EPYTHON -c "import ssl" \
|| abort "$EPYTHON can't find ssl module for $EPYTHON - download it from pypi and install with the inbuilt setup.py"
# REMOVED - call to my script that calls jslint, generates files and compresses JS etc
# || abort "Generation of code failed"
/opt/google_appengine/appcfg.py --email=$ADMIN_EMAIL -v -A $APPID update $SRCDIR \
|| abort "Appcfg failed - upload presumably incomplete"
# move the tags to show we deployed properly
bzr tag -r $lastver --force ${PREV_DTAG}
bzr tag -r $currver --force ${CURR_DTAG}
echo
echo "Production site updated from v$lastver to v$currver (in turn from v$prevver)"
echo
echo "Now visiting $CHECK_URL to upload the source to the database"
# new version doesn't seem to always be there (may be caching by the webserver etc) to be uploaded into the database.. try again just in case
for cb in $RANDOM $RANDOM $RANDOM $RANDOM ; do
prodver=`wget $CHECK_URL?_cb=$cb -q -O - | perl -ne 'print $1 if /^\s*Rev #(\d+)\s*$/'`
if [[ "$currver" == "$prodver" ]]; then
echo "OK: New version $prodver successfully deployed"
exit 0
fi
echo "Retrying the upload of source to the database"
sleep 5
done
abort "The new source doesn't seem to be loading into the database" "Try 'wget $CHECK_URL?_cb=$RANDOM -q -O -'"
It's not particularly big or clever, but it automates the upload job

Resources