Beginning with FreeBSD 10.2, binary packages installed using pkg are built from a quarterly SVN branch that only receives security and build updates once it's created. The goal is to provide a more stable software repository than the ports tree, which is constantly being updated and may even include broken ports at times. However, portsnap uses the latest/HEAD branch for the ports tree. Since mixing quarterly packages with current ports could lead to trouble, you have to choose one of these paths:
- Switch pkg to install packages from the latest/HEAD branch.
- Use SVN instead of portsnap to fetch and update your local ports tree.
If you need the latest and greatest packages or prefer to live on the bleeding edge, option 1 is for you. Personally, I prefer to have the most stable system possible, so I decided to try option 2. The "problem" with using SVN to manage your local ports tree is that the quarterly branch changes every 3 months but not necessarily on day 1 of the new quarter. Therefore, you have to check to see what the current quarterly branch is and switch to the new branch each time it changes. Since I'm not a regular user of SVN from the command line (I access SVN via Eclipse at work and git from a terminal when I get to choose my VCS), I wasn't sure how to manage ports and the ever-changing branches using SVN. I asked about it on the ports mailing list and got a very helpful response from Mathieu Arnold (English) that included this useful tidbit:
Currently, all our tools working automatically with the quarterly branches do this before any run:
latest_branch=$(svn ls https://svn.freebsd.org/ports/branches/|sed -ne '/^2.*Q./s|/$||p'|tail -1)
All you'd need to do before running svn update would be to run:
svn switch ^/branches/$(svn ls https://svn.freebsd.org/ports/branches/|sed -ne '/^2.*Q./s|/$||p'|tail -1)
and it would automagically switch to the new branch when a new branch happens.
Armed with this, I decided to create a shell script to simplify the process:
Simply save the file to /usr/local/bin or ~/bin, make it executable using
chmod +x portsfetch, and run it. You can also pass an optional parameter to specify an alternate destination path, which means
portsfetch /usr/jails/basejail/usr/ports can be used to switch the ezjail ports tree to the quarterly branch.
The portsfetch script attempts to do the Right Thing for these common scenarios:
- If the local ports tree contains files but doesn't appear to be managed by SVN, portsfetch offers to delete the files for you. If you decline, it assumes you're using portsnap and uses it to update the ports tree. Agreeing to empty the directory moves on to use SVN.
- If the local ports tree is empty (including if it was emptied in scenario 1), portsfetch will check out a fresh copy of the current quarterly branch.
- If the local ports tree is already on the current quarterly branch, portsfetch updates from SVN.
- If the local ports tree is not on the right branch, portsfetch switches it to the current quarterly branch.
Other aspects of ports management are the same when using the quarterly branch. For example, you don't need to change how you build or install from ports—just start using portsfetch instead of portsnap to update your ports tree.
This is the second most popular download on my site, so I recently added it to my freebsd-scripts project on GitHub to make it easier for others to contribute improvements. If you see something I missed or have a suggestion for improvement, please mention it in the comments below or submit a pull request!