using bash to get revision number from subversion - bash

I want to write a shell script in bash to deploy websites from an svn repository. When I deploy a website, I name the exported directory website_name-Rrevision_number. I'd like the bash script to automatically rename the exported directory, so it needs to learn the current revision number from the export directory. If I run
$> svn info http://svn-repository/trunk
Path: trunk
URL: http://svn-repository/mystery/trunk
Repository Root: http://svn-repository/mystery
Repository UUID: b809e6ab-5153-0410-a985-ac99030dffe6
Revision: 624
Node Kind: directory
Last Changed Author: author
Last Changed Rev: 624
Last Changed Date: 2010-02-19 15:48:16 -0500 (Fri, 19 Feb 2010)
The number after the string Revision: is what I want. How do I get that into a bash variable? Do I do string parsing of the output from the svn info command?

Use svnversion. This will output the revision number/range with minimal additional cruft

REVISION=`svn info http://svn-repository/trunk |grep '^Revision:' | sed -e 's/^Revision: //'`
It's simple, if inelegant.

Parsing the 'Revision' string is not portable across different locales.
Eg. with my locale it is like:
...
Wersja: 6583
Rodzaj obiektu: katalog
Zlecenie: normalne
Autor ostatniej zmiany: ...
Ostatnio zmieniona wersja: 6583
Data ostatniej zmiany: 2013-03-21 11:33:44 +0100 (czw)
...
You don't wanna parse that :)
So, the best approach is to use 'svnversion' as oefe suggested. This is the tool mentioned for this purpose.

just use one awk command. much simpler as well.
var=$(svn info http://svn-repository/trunk | awk '/^Revision:/{print $2}')

Without using sed, grep or awk:
REVISION=`svn info --show-item=revision --no-newline`

svn info http://svn-repository/trunk | grep Revision | tr -d 'Revison: '
Spits out the revision
Use backticks in your shell script to execute this and assign the results to a variable:
REVISION=`svn info http://svn-repository/trunk | grep Revision | tr -d 'Revison: '`

There are probably a dozen different ways to do this, but I'd go with something simple like:
revision="$(svn info http://svn-repository/trunk | grep "^Revision:" | cut -c 11-)"

This will give you the head revision number
svn info -r 'HEAD' | grep Revision | egrep -o "[0-9]+"
egrep is extended grep.

REVISION=$(svn info http://svn-repository/trunk |grep '^Revision:' | sed -e 's/^Revision: //p')
echo $REVISION

Related

format TAG release ref for Github Workflow Action

I would like to tag my release with v as prefix and product type as a suffix.
E.g. Initial release v1.0.0-alpha01-internal or v1.0.0-alpha01-external
Now I am running a GitHub action workflow to publish a release.
# The GITHUB_REF tag comes in the format 'refs/tags/xxx'.
# So if we split on '/' and take the 3rd value, we can get the release name.
run: |
NEW_VERSION=$(echo "${GITHUB_REF}" | cut -d "/" -f3)
echo "New version: ${NEW_VERSION}"
with the above code snippet, I get my new version v1.0.0-alpha01-internal or v1.0.0-alpha01-external now I don't want my version to be the same as TAG so I would like to cut v from start and -internal or -external from the end of the release TAG.
The expectation of a new version would be 1.0.0-alpha01
NEW_VERSION=$(echo "${GITHUB_REF}" | cut -d "/" -f3) | cut -c 2- | cut -c 1-13 maybe?
at this point your issue is just with string manipulation in Bash and has nothing to do with GH or GH Actions.
So you can just find what is the best way to modify a string in Bash. I recommend you start here:
https://www.baeldung.com/linux/bash-string-manipulation
TAG_VERSION=v1.0.0-alpha01-internal
TAG_VERSION=$(echo ${TAG_VERSION//v/})
TAG_VERSION=$(echo ${TAG_VERSION//-internal/})
TAG_VERSION=$(echo ${TAG_VERSION//-external/})
Or using sed
There is probably a better regex to use here but you can decide based on all the use cases
echo $TAG_VERSION | sed 's/-internal//g' | sed 's/-external//g' | sed 's/v//g'

How to use grep to get mercurial changeset id?

So from the below I want to fetch the 6e4a01192927part in my bash script
$ hg log -l1
changeset: 1775:6e4a01192927
branch: xxx
tag: tip
parent: 1772:7892c965215d
parent: 1774:5a9a3e060869
user: Firstname Lastname <someone#something.xyz>
date: Thu Jan 25 09:55:35 2018 +0000
summary: Merged in fix/something (pull request #85)
I am on Mac, El Capitan so it seems I am very limited in the ways I can grep it..
For example grep -oP isn't supported..
I have gotten this far but then hit a brick wall..
$ hg log -l1 | sed -n 1p # fetching first line only
changeset: 1775:6e4a01192927
If you are absolutely sure of the search string use Awk to match the first field and print the field next to it
hg log -l1 | awk -F: '$1=="changeset"{print $NF}'
Here $1 and $NF represent the first and the last fields split by the de-limiter :
Also a bash trick do it would be to read the first line from the command and use paramter expansion syntax
read -r firstLine < <(hg log -l1)
echo "${firstLine##*:}"
Mercurial has many ways to give you just the id of the most recent (or any) commit.
$ hg id -i -r .
68e111c5bd42
or using log:
$ hg log -l 1 --template '{node|short}'
68e111c5bd42
fewer processes spawned and more portable.

Getting max version by file name

I need to write a shell script that does the following:
In a given folder with files that fit the pattern: update-8.1.0-v46.sql I need to find the maximum version
I need to write the maximum version I've found into a configuration file
For 1, I've found the following answer: Shell script: find maximum value in a sequence of integers without sorting
The only problem I have is that I can't get down to a list of only the versions,
I tried:
ls | grep -o "update-8.1.0-v\(\d*\).sql"
but I get the entire file name in return and not just the matching part
Any ideas?
Maybe move everything to awk?
I ended up using:
SCHEMA=`ls database/targets/oracle/ | grep -o "update-$VERSION-v.*.sql" | sed "s/update-$VERSION-v\([0-9]*\).sql/\1/p" | awk '$0>x{x=$0};END{print x}'`
based on dreamer's answer
you can use sed for this:
echo "update-8.1.0-v46.sql" | sed 's/update-8.1.0-v\([0-9]*\).sql/\1/p'
The output in this case will be 46
grep isn't really the best tool for extracting captured matches, but you can use look-behind assertions if you switch it to use perl-like regular expressions. Anything in the assertion will not be printed when using the -o flag.
ls | grep -Po "(?<=update-8.1.0-v)\d+"
46

Get UTC date of last commit

I'm trying to put together a bash/sh script that gets the UTC time of the last commit from a svn repo (the other VCSs are easy)
I understand that i can just do svn propget --revprop -rHEAD svn:date and get it rather easily, but there is no guarantee that the svn checkout will be online, so I'd prefer an offline version, if possible.
Maybe something to do with getting the UTC time from svn info? (by screwing with the timezones)
Summary: How can i get the UTC time of a svn commit, while not having access to the server?
Thanks
You can use svn log -r COMMITTED and extract date info from it. This is valid for offline copies.
svn log -r COMMITTED | sed -nE 's/^r.*\| ([0-9]{4}-[0-9]{2}-[0-9]{2} \S+ \S+).*/\1/p' | xargs -i -- date -ud '{}' '+%s'
The -u option makes date show UTC time instead.
Actually we don't need to use xargs:
date -ud "$(exec svn log -r COMMITTED | sed -nE 's/^r.*\| ([0-9]{4}-[0-9]{2}-[0-9]{2} \S+ \S+).*/\1/p')" '+%s'
UPDATE: I got the wrong command. The command above won't work offline. Here's the right one:
date -ud "$(svn info | sed -nE 's/^Last Changed Date: (\S+ \S+ \S+).*/\1/p')" '+%s'
I'm silly. As soon as i actually realised i just need to convert one timezone to another, it was obvious:
date -u +[format] -d $(svn info | <some grepping and cutting here>)
In my case, this is:
date -u +"%Y%m%d-%H%M" -d "$(svn info | grep 'Date' | cut -d' ' -f4-6)"
Of course, my solution probably isn't optimal, and if someone knows a better way, that'd be much appreciated :)
It turns out that the xml output of "svn info" has a zulu timestamp:
$ svn info --xml | grep date
<date>2015-04-30T15:38:49.371762Z</date>
So your bash command might be:
svn info --xml | grep -oP '(?<=<date>).*?(?=</date>)'
I just stumbled on this post. Ended up figuring out that svn uses env variable TZ, so for example:
TZ= svn log
will log dates in UTC

find latest version of rpms from a mirror

I want to write a script to find the latest version of rpm of a given package available from a mirror for eg: http://mirror.centos.org/centos/5/updates/x86_64/RPMS/
The script should be able to run on majority of linux flavors (eg centos, redhat, ubuntu). So yum based solution is not an option. Is there any existing script that does this? Or can someone give me a general idea on how to go about this?
Thx to levislevis85 for the wget cli. Try this:
ARCH="i386"
PKG="pidgin-devel"
URL=http://mirror.centos.org/centos/5/updates/x86_64/RPMS
DL=`wget -O- -q $URL | sed -n 's/.*rpm.>\('$PKG'.*'$ARCH'.rpm\).*/\1/p' | sort | tail -1`
wget $URL/$DL
I Will put my comment here, otherwise the code will not be readable.
Try this:
ARCH="i386"
PKG="pidgin-devel"
URL=http://mirror.centos.org/centos/5/updates/x86_64/RPMS
DL=`wget -O- -q $URL | sed -n 's/.*rpm.>\('$PKG'.*'$ARCH'.rpm\).*<td align="right">\(.*\)-\(.*\)-\(.*\) \(..\):\(..\) <\/td><td.*/\4 \3 \2 \5 \6 \1/p' | sort -k1n -k2M -k3n -k4n -k5n | cut -d ' ' -f 6 | tail -1`
wget $URL/$DL
What it does is:
wget - get the index file
sed - cut out some parts and put it together in different order. Should result in Year Month Day Hour Minute and Package, like:
2009 Oct 27 01 14 pidgin-devel-2.6.2-2.el5.i386.rpm
2009 Oct 30 10 49 pidgin-devel-2.6.3-2.el5.i386.rpm
sort - order the columns n stays for numerical and M for month
cut - cut out the filed 6
tail - show only last entry
the problem with this could be, if some older package release comes after a newer then this script will also fail. If the output of the site changes, the script will fail. There are always a lot of points where a script could fail.
using wget and gawk
#!/bin/bash
pkg="kernel-headers"
wget -O- -q http://mirror.centos.org/centos/5/updates/x86_64/RPMS | awk -vpkg="$pkg" 'BEGIN{
RS="\n";FS="</a>"
z=split("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec",D,"|")
for(i=1;i<=z;i++){
date[D[i]]=sprintf("%02d",i)
}
temp=0
}
$1~pkg{
p=$1
t=$2
gsub(/.*href=\042/,"",p)
gsub(/\042>.*/,"",p)
m=split(t,timestamp," ")
n=split(timestamp[1],d,"-")
q=split(timestamp[2],hm,":")
datetime=d[3]date[d[2]]d[1]hm[1]hm[2]
if ( datetime >= temp ){
temp=datetime
filepkg = p
}
}
END{
print "Latest package: "filepkg", date: ",temp
}'
an example run of the above:
linux$ ./findlatest.sh
Latest package: kernel-headers-2.6.18-164.6.1.el5.x86_64.rpm, date: 200911041457
Try this (which requires lynx):
lynx -dump -listonly -nonumbers http://mirror.centos.org/centos/5/updates/x86_64/RPMS/ |
grep -E '^.*xen-libs.*i386.rpm$' |
sort --version-sort |
tail -n 1
If your sort doesn't have --version-sort, then you'll have to parse the version out of the filename or hope that a regular sort will do the right thing.
You may be able to do something similar with wget or curl or even a Bash script using redirections with /dev/tcp/HOST/PORT. The problem with these is that you would then have to parse HTML.

Resources