13

Is there a way to directly tar the latest version of an SVN folder without the SVN hidden files? I would like to create a tar archive without the SVN files. I know you can get the latest with the SVN tracking files, but is there a one liner that will directly send the information to an archive?

1
  • I don't know about svn, but github allows you to download .tar.gzs of a git repo. – Macha Nov 29 '09 at 13:54
12

The easiest way to make a copy of the latest version of a repository without all the .svn folders is to use the svn export command.

Here's how I would make the archive:

$ svn export URL PATH ; tar czf exported_copy.tgz PATH

Where URL is the URL of your svn repository and PATH is a local path suitable for saving a copy of the exported repository. I don't know a way to do it more directly than this. Unfortunately you do end up with the exported copy hanging around, so you might just want to put the whole thing in a short bash script which then deletes the temp files afterwards.

EDIT: While this is the easiest method and is what I used as well I would be careful. In my research I found this http://narfation.org/2009/01/08/creating-recreatable-tar-gz-from-svn which clearly tells us the problem of preserved group/user ownership which causes problems when deploying to another system. I have tried this script with modifications of my own to suit my purpose and you might benefit as well.

10

Maybe version 1.23 of tar allows you to exclude all versioning files from command line but unfortunately don't work on my 1.20 version:

tar --exclude-vcs -cvzf archive.tar.gz directory/
1
4

Go to the subversion working directory (checkout) and run this:

find -name .svn -prune -o -print | cpio -o -H tar | gzip > archive.tar.gz

If you're using GNU utilities you can also run:

find -name .svn -prune -o -print0 | cpio -o -0 -H tar | gzip > archive.tar.gz

If possible, I would recommend using the ustar format (-H ustar).

3

I see as well:

tar cvfz archive.tar.gz directory/  --exclude='*/.svn'

Thanks tar.

2

If I understand correctly, you're wanting to tar the results of an svn checkout?

So, in pseudocode, it'd look something like this:

svn export branch; find branch | grep -v '/.' | xargs cp tarbranch ; tar -zcf tarbranch.tgz tarbranch
0

This is adapted from a one-liner I wrote. It assumes you have a ~/tmp directory. You'll need to change the PROJ and URL variables in the first two steps. The rest should work.

For easy copying:

PROJ='yourproj' && URL='http://svn.example.com/svn/repo/$PROJ' && REV=`svn info $URL | fgrep Revision | cut -d ' ' -f 2` &&  cd ~/tmp &&  svn export $URL $PROJ && tar czv -f $PROJ.r$REV.tar.gz $PROJ && rm -r $PROJ.r$REV

For easy viewing:

PROJ='yourproj' && 
URL='http://svn.example.com/svn/repo/$PROJ' && 
REV=`svn info $URL | fgrep Revision | cut -d ' ' -f 2` &&  
cd ~/tmp && 
svn export $URL $PROJ && 
tar czv -f $PROJ.r$REV.tar.gz $PROJ && 
rm -r $PROJ.r$REV
0

This is my effort of trying to make a deterministic tarball from an SVN repo.

Requires GNU tar 1.27 or later.

Features:

  • Deterministic tarball
  • Timestamp precision in microseconds from SVN, thanks to pax extended header
  • Revision ID stored in archive comments just like git archive would do
  • I demonstrate both .tar.gz and .tar.xz compressions. For gzip, you may optimize the compression further by using advdef from AdvanceCOMP (advdef uses zopfli library).

As an example, I use subversion repo itself as a source for checkout and creation of the tarball. Note that this isn't the way SVN package their tarballs and I'm no way related to SVN development. It's just an example, after all.

# URL of repository to export
url="https://svn.apache.org/repos/asf/subversion/tags/1.9.7/"
# Name of distribution sub-directory
dist_name=subversion-1.9.7-test
# ---------------------------------------------------------------------

info=$(svn info --xml "$url" | tr -- '\t\n' '  ')
revision=$(echo "$info" |
    sed 's|.*<commit[^>]* revision="\{0,1\}\([^">]*\)"\{0,1\}>.*|\1|')
tar_name=${dist_name}-r${revision}
# Subversion's commit timestamps can be as precise as 0.000001 seconds,
# but sub-second precision is only available through --xml output
# format.
date=$(echo "$info" |
    sed 's|.*<commit[^>]*>.*<date>\([^<]*\)</date>.*</commit>.*|\1|')

# Factors that would make tarball non-deterministic include:
# - umask
# - Ordering of file names
# - Timestamps of directories ("svn export" doesn't update them)
# - User and group names and IDs
# - Format of tar (gnu, ustar or pax)
# - For pax format, the name and contents of extended header blocks

umask u=rwx,go=rx
svn export -r "$revision" "$url" "$dist_name"
# "svn export" will update file modification time to latest time of
# commit that modifies the file, but won't do so on directories.
find . -type d | xargs touch -c -m -d "$date" --

trap 's=$?; rm -f "${tar_name}.tar" || : ; exit $s' 1 2 3 15
# pax extended header allows sub-second precision on modification time.
# The default extended header name pattern ("%d/PaxHeaders.%p/%f")
# would contain a process ID that makes tarball non-deterministic.
# "git archive" would store a commit ID in pax global header (named
# "pax_global_header"). We can do similar.
# GNU tar (<=1.30) has a bug that it rejects globexthdr.mtime that
# contains fraction of seconds.
pax_options=$(printf '%s%s%s%s%s%s' \
    "globexthdr.name=pax_global_header," \
    "globexthdr.mtime={$(echo ${date}|sed -e 's/\.[0-9]*Z/Z/g')}," \
    "comment=${revision}," \
    "exthdr.name=%d/PaxHeaders/%f," \
    "delete=atime," \
    "delete=ctime")
find "$dist_name" \
    \( -type d -exec printf '%s/\n' '{}' \; \) -o -print |
    LC_ALL=C sort |
    tar -c --no-recursion --format=pax --owner=root:0 --group=root:0 \
    --pax-option="$pax_options" -f "${tar_name}.tar" -T -

# Compression (gzip/xz) can add additional non-deterministic factors.
# xz format does not store file name or timestamp...
trap 's=$?; rm -f "${tar_name}.tar.xz" || : ; exit $s' 1 2 3 15
xz -9e -k "${tar_name}.tar"

# ...but for gzip, you need either --no-name option or feed the input
# from stdin. This example uses former, and also tries advdef to
# optimize compression if available.
trap 's=$?; rm -f "${tar_name}.tar.gz" || : ; exit $s' 1 2 3 15
gzip --no-name -9 -k "${tar_name}.tar" &&
{ advdef -4 -z "${tar_name}.tar.gz" || : ; }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.