
Ran into a unique problem with one of my clients.
- They use Subversion (SVN) for source control.
- Their site is mainly flat HTML files (once compiled) and media files.
- Because of IT governance restrictions, I can deploy ONLY the files that have been add/changed since the last deployment.
This seems pretty simple, right? Wrong. SVN doesn’t give you an easy way to export ONLY the files that changed in a changeset. So I was forced to write a short bash script to handle it for me. How to get Subversion (SVN) Changed Files for Deployment – Which I now share with you.
It works as follows:
It’s pretty simple, really. The bash file below will compare a list of files from a discrete SVN changeset and move those files, and only those files, from the website folder that contains ALL the files.
Create SVN CHangeset Text File
Get a list of files changed from SVN by running a simple command (where “1234” is your revision number in svn):
svn st –changelist 1234 | grep -v Changelist | cut -b 3- > changeset.txt
The output of this will look something like this (but with your changes and your filenames):
trunk/dib.html
trunk/examinations/college-admissions/sat.html
trunk/examinations/earn-college-credit/clep.html
trunk/examinations/equivalency/equivalency-guide.html
trunk/examinations/index.html
trunk/examinations/test-control-officer.html
trunk/index.html
trunk/service-members/counselor-search.html
Copy / Move the SVN Changeset Files
Run the following bash script to move those changed files from your Working Copy / folder to a new folder structure identical to the structure of the working copy.
It basically creates a bunch of mkdir and cp commands to create the folder/file structure needed, like so:
mkdir -p ~/Documents/Deployments/2.0.2/ && cp ~/Documents/DantesWebV2/dib.html “$_”
mkdir -p ~/Documents/Deployments/2.0.2/examinations/college-admissions/ && cp ~/Documents/DantesWebV2/examinations/college-admissions/sat.html “$_”
mkdir -p ~/Documents/Deployments/2.0.2/examinations/earn-college-credit/ && cp ~/Documents/DantesWebV2/examinations/earn-college-credit/clep.html “$_”
mkdir -p ~/Documents/Deployments/2.0.2/examinations/high-school-equivalency/ && cp ~/Documents/DantesWebV2/examinations/high-school-equivalency/high-school-equivalency-guide.html “$_”
Command Line Parameters
I wrote the script to accept 5 command line arguments, so I don’t have to change the script every time I want to run it:
- $1 = the input file, a list of files changed/added in the changeset
- $2 = the output filename will be created to copy the changed files to the new folder. Does not have to exist.
- $3 = the new folder to move the files to. Does not have to exist, will be created, with all subfolders, when script is run
- $4 = the root folder of the source files – where your working svn copy is
- $5 = text to strip from the filenames. “svn st” outputs the files relative to /trunk in my tree, but that is not an actual folder on my system.
Sample Call
bash copyDeploymentFiles.sh changeset.txt output.txt “~/Documents/Deployments/2.0.2” “~/Documents/DantesWebV2/” “trunk/”
That’s it. Run the script and it will open the input file, loop through it, and create a new script designed to create the folder structure in a new location, and copy over the new/changed files from the Subversion changeset.
The resulting script is just a list of mkdir and cp commands that can be run automatically with the script or manually by yourself should you wish to do so. It’s pretty simple, but it saves me a lot of time with my deployments.
The BAsh Script
I saved this on my machine as copyDeploymentFiles.sh. You can call it what you will.
# AUTHOR: 2015 Ron Sparks – www.ronsparks.com
#
# LICENSE
# This utility is released as freeware. You are allowed to freely distribute this utility via floppy disk, CD-ROM,
# Internet, or in any other way, as long as you don’t charge anything for this. If you distribute this utility,
# you must distribute it without any modification, including comments, author name, license, and disclaimers!
#
# DISCLAIMER
# The software is provided “AS IS” without any warranty, either expressed or implied, including, but not limited to,
# the implied warranties of merchantability and fitness for a particular purpose. The author will not be liable for any
# special, incidental, consequential or indirect damages due to loss of data or any other reason.
#
# PURPOSE:
# To take a list of files and move them to an identical folder structure somewhere else.
# This is useful in moving only changed files from an SVN working copy to another folder for deployment.
#
# For brevity, this script assumes you’ve already created a list of files to move, With SVN you can get
# this list from the command line by:
# svn st –changelist 1234 | grep -v Changelist | cut -b 3-
# inputFileName is a list of folder/files changed in an SVN changeset.
inputFilename=”$1″
# outputFileName is the name of the file you will output the resulting script to
outputFilename=”$2″
# deploymentFolder is the where the resulting files will be copied to.
deploymentFolder=”$3″
# when building the output script, this is the source folder where the files to
# move are located
sourceFolder=”$4″
# svn appends “trunk/” or other folder names not necessary into checkin log. We want to strip it out.
stripText=”$5″
# read the file line-by-line. The last line might not have a newline
# character, so we account for that with “|| [[ -n “$line” ]]” while read line || [[ -n “$line” ]]
do
# lineFileName is the actual “foo.txt” at the end of “/trunk/dir2/foo.txt”
lineFileName=$(basename $line)
# folder is the $line without $lineFileName, it’s replaced with null in the following
# effectively strips the file name leaving me with only the folder path.
folder=${line//$lineFileName/}
folderStripped=${folder/$stripText/}
# strip out the SVN leading structure I don’t want from the input
folderAndFileName=${line/$stripText/}
# create the output.
# 1. Make a folder that matches the folder structure of the input $line
# -if it already exists there is no error or problem, which is why
# -you can run this multiple times for many files in the same folder.
# 2. Copy the file to the new folder. The “$_” copies the file to the
# path created with the mkdir statement before it.
echo “mkdir -p “$deploymentFolder”/”$folderStripped “&& cp” $sourceFolder$folderAndFileName \”\$_\”
echo “mkdir -p “$deploymentFolder”/”$folderStripped “&& cp” $sourceFolder$folderAndFileName \”\$_\” >> $outputFilename done < “$inputFilename”
# if you want to automatically execute the file you created, uncomment the following.
#/bin/bash $outputFilename
# cleanup – if you want to delete the file you just created, uncomment the following
#rm -f $outputFilename
Good luck; if you have any questions just ask. I am by no means an expert, and there’s probably a better way to do this, but this little script helped me and I hope it helps you as well.
EDIT:
Yes, I know I don’t have to create the output file; I can run the commands one at a time as I loop. Feel free to change the script to do just that if you want, but I like the sanity check the output file gives me.