++ed by:

1 PAUSE user
2 non-PAUSE users.

Author image Abe Timmerman
and 1 contributors


Test::Smoke::Syncer - OO interface for syncing the perl source-tree


    use Test::Smoke::Syncer;

    my $type = 'rsync'; # or 'snapshot' or 'copy'
    my $syncer = Test::Smoke::Syncer->new( $type => %sync_config );
    my $patch_level = $syncer->sync;


At this moment we support three basic types of syncing the perl source-tree.


This method uses the rsync program with the --delete option to get your perl source-tree up to date.


This method uses the Net::FTP or the LWP module to get the latest snapshot. When the server attribute starts with http:// the fetching is done by LWP::Simple::mirror(). To emulate the rsync --delete effect, the current source-tree is removed.

The snapshot tarball is handled by either tar/gzip or Archive::Tar/Compress::Zlib.


This method uses the File::Copy module to copy an existing source-tree from somewhere on the system (in case rsync doesn't work), this also removes the current source-tree first.


This method will sync the source-tree in one of the above basic methods. After that, it will create an intermediate copy of the master directory as hardlinks and run the regen_headers.pl script. This should yield an up-to-date source-tree. The intermadite directory is now copied as hardlinks to its final directory ({ddir}).

This can be used to change the way make distclean is run from mktest.pl (removes all files that are not in the intermediate directory, which may prove faster than traditional make distclean).


Test::Smoke::Syncer->new( $type, %sync_config )

[ Constructor | Public ]

Initialise a new object and check all relevant arguments. It returns an object of the appropriate Test::Smoke::Syncer::* class.

Test::Smoke::Syncer->config( $key[, $value] )

[ Accessor | Public ]

config() is an interface to the package lexical %CONFIG, which holds all the default values for the new() arguments.

With the special key all_defaults this returns a reference to a hash holding all the default values.

$syncer->_clear_souce_tree( [$tree_dir] )

[ Method | private-ish ]

_clear_source_tree() removes all files in the source-tree using File::Path::rmtree(). (See File::Path for caveats.)

If $tree_dir is not specified, $self->{ddir} is used.

$syncer->_relocate_tree( $source_dir )

[ Method | Private-ish ]

_relocate_tree() uses File::Copy::move() to move the source-tree from $source_dir to its destination ($self->{ddir}).

$syncer->check_dot_patch( )

[ Method | Public ]

check_dot_patch() checks if there is a '.patch' file in the source-tree. It will try to create one if it is not there (this is the case for snapshots).

It returns the patchlevel found or undef.

version_from_patchlevel_h( $ddir )

version_from_patchlevel_h() returns a "dotted" version as derived from the patchlevel.h file in the distribution.

$syncer->clean_from_directory( $source_dir[, @leave_these] )

clean_from_directory() uses File::Find to get the contents of $source_dir and compare these to {ddir} and remove all other files.

The contents of @leave_these should be in "MANIFEST-format" (See Test::Smoke::SourceTree).


pre_sync() should be called by the sync() methos to setup the sync environment. Currently only useful on OpenVMS.


post_sync() should be called by the sync() methos to unset the sync environment. Currently only useful on OpenVMS.


This handles syncing with the rsync program. It should only be visible from the "parent-package" so no direct user-calls on this.

Test::Smoke::Syncer::Rsync->new( %args )

This crates the new object. Keys for %args:

  * ddir:   destination directory ( ./perl-current )
  * source: the rsync source ( ftp.linux.activestate.com::perl-current )
  * opts:   the options for rsync ( -az --delete )
  * rsync:  the full path to the rsync program ( rsync )
  * v:      verbose
$object->sync( )

Do the actual sync using a call to the rsync program.

rsync can also be used as a smart version of copy. If you use a local directory to rsync from, make sure the destination path ends with a path separator! (This does not seem to work for source paths mounted via NFS.)


This handles syncing from a snapshot with the Net::FTP module. It should only be visible from the "parent-package" so no direct user-calls on this.

Test::Smoke::Syncer::Snapshot->new( %args )

This crates the new object. Keys for %args:

  * ddir:    destination directory ( ./perl-current )
  * server:  the server to get the snapshot from ( public.activestate.com )
  * sdir:    server directory ( /pub/apc/perl-current-snap )
  * snapext: the extension used for snapdhots ( tgz )
  * tar:     howto untar ( Archive::Tar or 'gzip -d -c %s | tar x -' )
  * v:       verbose
$syncer->sync( )

Make a connection to the ftp server, change to the {sdir} directory. Get the list of snapshots (/^perl@\d+\.tgz$/) and determin the highest patchlevel. Fetch this file. Remove the current source-tree and extract the snapshot.

$syncer->_fetch_snapshot( )

_fetch_snapshot() checks to see if $self->{server} =~ m|^https?://| && $self->{sfile}. If so let LWP::Simple do the fetching else do the FTP thing.

$syncer->_fetch_snapshot_HTTP( )

_fetch_snapshot_HTTP() simply invokes LWP::Simple::mirror().

__find_snap_name( $ftp, $snapext[, $verbose] )

[Not a method!]

Get a list with all the perl@\d+ files, use an ST to sort these and return the one with the highes number.

$syncer->_extract_snapshot( )

_extract_snapshot() checks the tar attribute to find out how to extract the snapshot. This could be an external command or the Archive::Tar/Comperss::Zlib modules.

$syncer->_extract_with_Archive_Tar( )

_extract_with_Archive_Tar() uses the Archive::Tar and Compress::Zlib modules to extract the snapshot. (This tested verry slow on my Linux box!)

$syncer->_extract_with_external( )

_extract_with_external() uses $self->{tar} as a sprintf() template to build a command. Yes that might be dangerous!

__vms_untargz( $untargz, $tgzfile, $verbose )

Gunzip and extract the archive in $tgzfile using a small DCL script

$syncer->patch_a_snapshot( $patch_number )

patch_a_snapshot() tries to fetch all the patches between $patch_number and perl-current and apply them. This requires a working patch program.

You should pass this extra information to Test::Smoke::Syncer::Snapshot->new():

  * patchup:  should we do this? ( 0 )
  * pserver:  which FTP server? ( public.activestate.com )
  * pdir:     directory ( /pub/apc/perl-current-diffs )
  * unzip:    ( gzip ) [ Compress::Zlib ]
  * patchbin: ( patch )
  * cleanup:  remove patches after applied? ( 1 )
$syncer->_get_patches( [$patch_number] )

_get_patches() sets up the FTP connection and gets all patches beyond $patch_number. Remember that patch numbers do not have to be consecutive.

$syncer->_apply_patches( @patch_list )

_apply_patches() calls the patch program to apply the patch and updates .patch accordingly.

@patch_list is a list of filenames of these patches.

Checks the unzip attribute to find out how to unzip the patch and uses the Test::Smoke::Patcher module to apply the patch.

$syncer->_read_patch( $file )

_read_patch() unzips the patch and returns the contents.

$syncer->_fix_dot_patch( $new_level );

_fix_dot_patch() updates the .patch file with the new patch level.

__get_directory_names( [$dir] )

[This is not a method]

__get_directory_names() retruns all directory names from $dir || cwd(). It does not look at symlinks (there should not be any in the perl source-tree).


This handles syncing with the File::Copy module from a local directory. It uses the MANIFEST file is the source directory to determine which fiels to copy. The current source-tree removed before the actual copying.

Test::Smoke::Syncer::Copy->new( %args )

This crates the new object. Keys for %args:

  * ddir:    destination directory ( ./perl-current )
  * cdir:    directory to copy from ( undef )
  * v:       verbose
$syncer->sync( )

This uses Test::Smoke::SourceTree to do the actual copying. After that it will clean up the source-tree (from MANIFEST, but ignoring MANIFEST.SKIP!).


This handles syncing by copying the source-tree from a local directory using the link function. This can be used as an alternative for make distclean.

Thanks to Nicholas Clark for donating this suggestion!

Keys for %args:

  * ddir: destination directory
  * hdir: source directory
  * v:    verbose
$syncer->sync( )

sync() uses the File::Find module to make the hardlink forest in {ddir}.


This handles syncing by getting the source-tree from ActiveState's APC repository. It uses the Test::Smoke::FTPClient that implements a mirror function.

Test::Smoke::Syncer::FTP->new( %args )

Known args for this class:

    * ftphost (public.activestate.com)
    * ftpusr  (anonymous)
    * ftppwd  (smokers@perl.org)
    * ftpsdir (/pub/apc/perl-????)
    * ftpcdir (/pub/apc/perl-????-diffs)
    * ftype (undef|binary|ascii)

    * ddir
    * v


This does the actual syncing:

    * Check {ftpcdir} for the latest changenumber
    * Mirror 


This needs to go to the *-diffs directory on APC and find the patch whith the highest number, that should be our current patchlevel.


This handles syncing by setting up a master directory that is in sync with either a snapshot or the repository. Then it creates a copy of this master directory as a hardlink forest and the regenheaders.pl script is run (if found). Now the source-tree should be up to date and ready to be copied as a hardlink forest again, to its final destination.

Thanks to Nicholas Clark for donating this idea.

Test::Smoke::Syncer::Forest->new( %args )

Keys for %args:

  * All keys from the other methods (depending on {fsync})
  * fsync: which master sync method is to be used
  * mdir:  master directory
  * fdir:  intermediate directory (first hardlink forest)
$syncer->sync( )

sync() starts with a "traditional" sync according to {ftype} in {mdir}. It then creates a copy of {mdir} in {fdir} with hardlinks an tries to run the regen_headers.pl script in {fdir}. This directory should now contain an up to date (working) source-tree wich again using hardlinks is copied to the destination directory {ddir}.


rsync, gzip, tar, Archive::Tar, Compress::Zlib, File::Copy, Test::Smoke::SourceTree


(c) 2002-2003, All rights reserved.

  * Abe Timmerman <abeltje@cpan.org>

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


  * <http://www.perl.com/perl/misc/Artistic.html>,
  * <http://www.gnu.org/copyleft/gpl.html>

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.