Skip to content

Instantly share code, notes, and snippets.

@reedacartwright
Last active April 15, 2021 04:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reedacartwright/8622973baf89b263a6d7 to your computer and use it in GitHub Desktop.
Save reedacartwright/8622973baf89b263a6d7 to your computer and use it in GitHub Desktop.
A script to syncronize a local ports directory with the latest revision used to build FreeBSD packages.
#!/bin/sh
# Copyright (c) 2014-2015 Reed A. Cartwright <cartwright@asu.edu>
# Copyright (c) 2014-2015 Alberto Villa <avilla@FreeBSD.org>
# Copyright (c) 2015 Mike Clarke <jmc-freebsd2@milibyte.co.uk>
#
# This script determines the revision number used to build FreeBSD packages
# and syncs a local ports directory to match it.
#
# USAGE: sync-ports [name or abs_path]
#
# REQUIREMENTS: textproc/jq, ports-mgmt/poudriere (optional)
#
# If the argument is not an absolute path, the script will treat it as
# the name of a poudriere-managed ports directory. If poudriere is
# not installed, it will use /usr/ports as the ports directory.
#
# If the argument is not specified, it defaults to "default".
#
# The script uses uname to choose which pkg jail to sync with.
# You can specify PKG_SERVER, PKG_JAIL, and/or PKG_URL in the
# environment to override the default options.
# Set the path
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
# Determine PKG_JAIL
case `uname -r` in
*CURRENT) : ${PKG_JAIL:=head-`uname -m`-default} ;;
*) : ${PKG_JAIL:=`uname -r | cut -d- -f1 | tr -d .``uname -m`-default} ;;
esac
# Determine PKG_SERVER
if [ -z "${PKG_SERVER}" ]; then
case "${PKG_JAIL}" in
93i386-default) PKG_SERVER=beefy1.isc.freebsd.org ;;
101i386-quarterly) PKG_SERVER=beefy1.isc.freebsd.org ;;
93amd64-default) PKG_SERVER=beefy2.isc.freebsd.org ;;
101amd64-quarterly) PKG_SERVER=beefy2.isc.freebsd.org ;;
head-i386-default) PKG_SERVER=beefy3.isc.freebsd.org ;;
93i386-quarterly) PKG_SERVER=beefy3.isc.freebsd.org ;;
head-amd64-default) PKG_SERVER=beefy4.isc.freebsd.org ;;
93amd64-quarterly) PKG_SERVER=beefy4.isc.freebsd.org ;;
101i386-default) PKG_SERVER=beefy5.nyi.freebsd.org ;;
84i386-default) PKG_SERVER=beefy5.nyi.freebsd.org ;;
101amd64-default) PKG_SERVER=beefy6.nyi.freebsd.org ;;
84amd64-default) PKG_SERVER=beefy6.nyi.freebsd.org ;;
*) >&2 echo "ERROR: Unable to determine package server for ${PKG_JAIL}."
exit 1
;;
esac
fi
# Build PKG_URL
: ${PKG_URL:=http://${PKG_SERVER}/data/${PKG_JAIL}/.data.json}
# If the argument is not an absolute path, use poudriere to resolve it.
# We test for absolute path by seeing if it begins with a slash.
PORTSTREE="${1:-default}"
if [ "${PORTSTREE#/}" != "${PORTSTREE}" ]; then
PORTSDIR="${PORTSTREE}"
elif which poudriere >/dev/null 2>&1 ; then
PORTSDIR=`poudriere ports -ql | awk -v PT="${PORTSTREE}" '$1 == PT { print $3 }'`
else
PORTSTREE="/usr/ports"
PORTSDIR="${PORTSTREE}"
fi
# Check if the directory exists
if [ ! -d "${PORTSDIR}" ]; then
>&2 echo "ERROR: Unable to resolve ports tree '${PORTSTREE}' to a directory."
exit 1
fi
# Fetch data from server
JSON=`fetch -qo - "${PKG_URL}"`
if [ $? -ne 0 ]; then
>&2 echo "ERROR: Unable to fetch data from package server."
exit 1
fi
# Parse revision information from server (exclude incomplete builds)
REV=`printf %s "${JSON}" | jq -c '.builds[]' |
awk '/status":"stopped[^"]+done/ { build = $0 }; END { print build }' |
jq -r '.svn_url | split("@")[1]'`
# Check revision information
if expr "${REV}" : '^[[:digit:]][[:digit:]]*$' >/dev/null; then
# Skip update if revisions are in sync
CURREV=`svnlite info "${PORTSDIR}" | awk -F': ' '$1 == "Revision" {print $2; exit}'`
if [ -z "${CURREV}" ]; then
>&2 echo "ERROR: Unable to get current revision for ports tree '${PORTSTREE}'."
exit 1
fi
if [ "${CURREV}" -ne "${REV}" ]; then
echo "====>> Updating ports tree '${PORTSTREE}' from revision ${CURREV} to ${REV}"
svnlite up -q -r "${REV}" "${PORTSDIR}"
else
echo "====>> Ports tree '${PORTSTREE}' is up to date at revision ${CURREV}"
fi
exit
else
>& echo "ERROR: Unable to determine revision number for latest packages."
exit 1
fi
@xzhayon
Copy link

xzhayon commented Dec 7, 2014

I suggest some modifications to your script:
https://gist.github.com/xzhavilla/8be8f95885470804cc4a

@reedacartwright
Copy link
Author

Thanks. I merged your changes and added some more info.

@xzhayon
Copy link

xzhayon commented Jun 7, 2015

I made yet another modification to avoid checking out the ports tree for an incomplete build:
https://gist.github.com/xzhavilla/61dedc55c33cb32c1546

@reedacartwright
Copy link
Author

Merged thanks.

@simon-wright-44
Copy link

Hi! I used your script as a basis to sync my own ports tree. I have incorporated changes from several other authors as credited and some of my own and just updated it to work with using git instead of subversion in the ports tree.

Please feel free to cleanup my code, I am an "only when needed" scripter and I'm very sure there are lots of rationalisations to be done. However the script as is works for me running on a QNAP NAS which hosts my NFS-shared ports tree :).

#!/bin/sh

Version 1.2.0

Copyright (c) 2014-2015 Reed A. Cartwright cartwright@asu.edu

Copyright (c) 2014 Alberto Villa avilla@FreeBSD.org

Copyright (c) 2015 Mike Clarke jmc-freebsd2@milibyte.co.uk

April 2021 Simon Wright simon.wright@gmx.net

This script determines the revision number used to build FreeBSD packages

and syncs a local ports directory to match it.

USAGE: sync-ports [name or abs_path]

REQUIREMENTS: textproc/jq, git, ports-mgmt/poudriere (optional)

If the argument is not an absolute path, the script will treat it as

the name of a poudriere-managed ports directory. If poudriere is

not installed, it will use /usr/ports as the ports directory.

If the argument is not specified, it defaults to "default".

The script uses uname to choose which pkg jail to sync with.

You can specify PKG_SERVER, PKG_JAIL, and/or PKG_URL in the

environment to override the default options.

This version edited to work on the QNAP NAS that holds

the working copy of the ports tree

And changes to suit git ports tree (April 2021)

Set the path

PATH=/sbin:/bin:/usr/sbin:/usr/bin
GIT=/opt/bin/git
TMPFILE=/bin/mktemp
EMAILTO=xxx@xxxx.xxxx
EMAILFROM=xxx@xxx.xxxx
TMPEMAIL=/bin/mktemp
#MAILER=which mail
AWK=which awk
MAILER="/usr/sbin/sendmail"
JQ="/usr/local/sbin/jq"

Set use proxy to yes if you need it. Pkg servers are IPv6-only

since April 2021

USEIPV6PROXY=yes
IPV6PROXY="http://www.ipv6proxy.net/go.php?u="
PKG_JAIL=122amd64-default

if [ ! -f ${JQ} ]; then
echo.
echo $0
echo "This script requires the following packages installed:"
echo " git jq curl"
echo.
exit 1
fi

Determine PKG_JAIL

case uname -r in
*CURRENT) : ${PKG_JAIL:=head-uname -m-default} ;;
*) : ${PKG_JAIL:=uname -r | cut -d- -f1 | tr -d .``uname -m-default} ;;
esac

Determine PKG_SERVER

if [ -z "${PKG_SERVER}" ]; then
case "${PKG_JAIL}" in
113i386-quarterly) PKG_SERVER=beefy1.nyi.freebsd.org ;;
122amd64-quarterly) PKG_SERVER=beefy2.nyi.freebsd.org ;;
114amd64-quarterly) PKG_SERVER=beefy3.nyi.freebsd.org ;;
122i386-quarterly) PKG_SERVER=beefy4.nyi.freebsd.org ;;
122i386-default) PKG_SERVER=beefy5.nyi.freebsd.org ;;
122amd64-default) PKG_SERVER=beefy6.nyi.freebsd.org ;;
head-mips-default) PKG_SERVER=beefy7.nyi.freebsd.org ;;
head-armv6-default) PKG_SERVER=beefy8.nyi.freebsd.org ;;
main-armv6-default) PKG_SERVER=beefy8.nyi.freebsd.org ;;
13stable-armv6-quarterly) PKG_SERVER=beefy8.nyi.freebsd.org ;;
130releng-armv6-quarterly) PKG_SERVER=beefy8.nyi.freebsd.org ;;
114amd64-default) PKG_SERVER=beefy9.nyi.freebsd.org ;;
113i386-default) PKG_SERVER=beefy10.nyi.freebsd.org ;;
114i386-default) PKG_SERVER=beefy10.nyi.freebsd.org ;;
*) >&2 echo "ERROR: Unable to determine package server for ${PKG_JAIL}."
exit 1
;;
esac
fi

Build PKG_URL

: ${PKG_URL:=http://${PKG_SERVER}/data/${PKG_JAIL}/.data.json}
PORTSTREE="$1"

if [ -z "${PORTSTREE}" ]; then
PORTSTREE="default"

We test for absolute path by seeing if it begins with a slash.

fi

if [ "${PORTSTREE#/}" != "${PORTSTREE}" ]; then
PORTSDIR="${PORTSTREE}"
else
PORTSTREE="/share/freebsd_ports"
PORTSDIR="${PORTSTREE}"
fi

Check if the directory exists

if [ ! -d "${PORTSDIR}" ]; then

&2 echo "ERROR: Unable to resolve ports tree '${PORTSTREE}' to a directory."
exit 1
fi

Fetch data from server

if [ ${USEIPV6PROXY} = "yes" ]; then
JSON=/sbin/curl -so - ${IPV6PROXY}${PKG_URL}
else
JSON=/sbin/curl -so - ${PKG_URL}
fi

if [ $? -gt 0 ]; then

>&2 echo "ERROR: Unable to fetch data from package server."

echo "ERROR: Unable to fetch data from package server."
exit 1
fi

Parse revision information from server

REV=printf %s "${JSON}" | "${JQ}" -r '.builds[.builds.latest].buildname'
#REV=printf %s "${JSON}" | "${JQ}" -r '.builds[.builds.latest].buildname' | /bin/cut -c 1-11

Check revision information

if [ ! -z ${REV} ]; then

Skip update if revisions are in sync

cd ${PORTSDIR}

CURREV=${GIT} status | ${AWK} '{print $4; exit}'

CURREV=cat git.revision
if [ "${CURREV}" != "${REV}" ]; then
echo "====>> Updating ports tree '${PORTSTREE}' from ${CURREV} to ${REV}"
echo "Updating ports treee using ${PKG_JAIL}" > ${TMPFILE}
echo >> ${TMPFILE}
cd ${PORTSDIR}
/bin/sleep 10
${GIT} pull --ff-only >> ${TMPFILE}
echo >> ${TMPFILE}
echo "Checking out ${REV} . . ." >> ${TMPFILE}
${GIT} checkout ${REV} >> ${TMPFILE}
echo -n ${REV} > ${PORTSDIR}/git.revision
logger hostname -s:${PORTSDIR} has been updated to the current git level ${REV}

${MAILER} -s "FreeBSD ports tree on ${PORTSDIR} has been updated from ${CURREV} to ${REV}" ${EMAILTO} < ${TMPFILE}

 echo "To: ${EMAILTO}" > ${TMPEMAIL} 
 echo "From: ${EMAILFROM}" >> ${TMPEMAIL} 
 echo "Subject: FreeBSD ports tree on ${PORTSDIR} has been updated from ${CURREV} to ${REV}"  >> ${TMPEMAIL} 
 cat ${TMPFILE} >> ${TMPEMAIL} 
 cat ${TMPEMAIL} | ${MAILER} -t
 rm ${TMPEMAIL} 

else
echo "====>> FreeBSD ports tree '${PORTSTREE}' is up to date at ${CURREV}"
fi

else
echo "ERROR: Unable to determine revision number for latest packages."
exit 1
fi

rm ${TMPFILE}

if [ -f ${TMPEMAIL} ]; then
rm ${TMPEMAIL}
fi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment