David Boyce


ClearCase::SyncTree - Synchronize a tree of files with a tree of elements


    # Create a 'synctree' object.
    my $sync = ClearCase::SyncTree->new;
    # Tell it where the files are coming from ...
    # Tell it where they're going to ...
    # Supply the list of files to work on (relative or absolute paths).
    $sync->srclist(keys %files);
    # Compare src and dest lists and figure out what to do.
    # Create new elements in the target area.
    # Update existing files which differ between src and dest.
    # Remove any files from dest that aren't in src.
    # Check in the changes.

See the enclosed synctree script for full example usage.


This module provides an infrastructure for programs which want to synchronize a set of files, typically a subtree, with a similar destination subtree in VOB space. The enclosed synctree script is an example of such a program.

The source area may be in a VOB or may be a regular filesystem; the destination area must be in a VOB. Methods are supplied for adding, subtracting, and modifying destination files so as to make that area look identical to the source.

Symbolic links are supported, even on Windows (of course in this case the source filesystem must support them, which is only likely in the event of an MVFS->MVFS transfer). Note that the text of the link is transported verbatim from source area to dest area; thus relative symlinks may no longer resolve in the destination.


Use ClearCase::SyncTree->new to construct a SyncTree object, which can then be filled in and used via the instance methods below.


Following is a brief description of each supported method. Examples are given for all methods that take parameters; if no example is given usage may be assumed to look like:

  • ->srcbase

    Provides the base by which to 'relativize' the incoming pathnames. E.g. with a srcbase of /tmp/x the incoming file /tmp/x/y/z will become y/z and will be deposited under the dstbase (see) by that path. Example:

  • ->dstbase

    Provides the root of the tree into which to place the relative paths derived from srcbase as described above. Example:

  • ->srclist/->srcmap

    There are two ways to specify the list of incoming files. They may be provided as a simple list via srclist, in which case they'll be relativized as described above and deposited in dstbase, or they can be specified via srcmap which allows the destination file to have a different name from the source.

    srclist takes a list of input filenames. These may be absolute or relative; they will be canonicalized internally.

    srcmap is similar but takes a hash which maps input filenames to their destination counterparts.


        $obj->srclist(@ARGV);       # check in the named files
        my %filemap = (x/y/z.c => 'x/y/z.cxx', a/b => 'foo');
        $obj->srcmap(%filemap);     # check in the named files
  • ->analyze

    After the object knows its srcbase, dstbase, and input file lists, this method compares the source and target trees and categorizes the required actions into additions (new files in the destination area), modifications (those which exist but need to be updated) and subtractions (those which no longer exist in the source area). After analysis is complete, the corresponding actions may be taken via the add, modify, and subtract methods as desired.

    However, note that subtract analysis is optional; it must be requested by setting the ->remove attribute prior to calling ->analyze.

  • ->add

    Takes the list of additions as determined by the analyze method and creates them as new elements.

  • ->modify

    Takes the list of modifications as determined by the analyze method and updates them in the destination tree.

  • ->subtract

    Takes the list of subtractions as determined by the analyze method and rmname's them in the destination tree. The ->remove attribute must have been set prior to calling analyze.

  • ->remove

    Boolean. The list of files to subtract from the destination area will not be derived unless this attribute is set before analysis begins. This is because it takes time to do subtract analysis, so there's no sense doing it unless you plan to call ->subtract later.

  • ->label

    Labels the new work. The label type can be specified as a parameter; otherwise it will be taken from the attribute previously set by the lbtype method.

    Labeling consists of a mklabel -recurse from dstbase down, followed by labeling of parent directories from dstbase up to the vob root. Example:


    See also ->label_mods, as well as Support for incremental label families.

  • ->checkin

    Checks in all checkouts under the dstbase area.

  • ->cleanup

    Undoes all checkouts under the dstbase area.

  • ->fail

    Calls the cleanup method, then exits with a failure status. This is the default exception handler; a different handler can be registered via the err_handler method (see).

  • ->err_handler

    Registers an exception handler to be called upon failure of any cleartool command. Call with 0 to have no handler. Pass it a code ref to register a function, with an object and method name to register a method, with a scalar ref to count errors. Examples:

        $obj->err_handler(0);               # ignore cleartool errors
        $obj->err_handler(\$rc);            # count errors in $rc
        $obj->err_handler(\&func);          # register func() for errors
        $obj->err_handler($self, 'method'); # register $obj->method
  • ->protect

    Sets an attribute which causes the checkin method to align file permissions after checking in. The meaning of this varies by platform: on Unix an attempt is made to bring destination mode bits into alignment with those of the source file. On Windows, files with extensions such as .exe and .dll are made executable (though most Windows filesystems don't pay attention to executable modes, MVFS does and thus the execute bit becomes a source of frequent confusion for Windows ClearCase users). Example:

        $obj->protect(0);                   # no dest mode fixups
  • ->reuse

    Attempt "element reuse". Before creating a new file with mkelem, look through its directory's version tree to see if another of the same name exists in any other version. If so, assume the new file intended to be the same element and link the old and new names.

  • ->vreuse

    Attempt "version reuse". Instead of creating a new version, apply the label provided onto an old suitable one, even if it wasn't selected by the config spec.

  • ->ctime

    Sets a boolean indicating whether to throw away the timestamp of the source file and give modified files their checkin date instead. This flag is false by default (i.e. checkins have -ptime behavior).

  • ->ignore_co/->overwrite_co

    By default, no view private files are allowed in the dest dir at ->analyze time. This generally means either classic view-private files or checked-out elements, which are a form of view-private files. The ->ignore_co attribute causes existing checkouts to be ignored instead of being disallowed; they do not cause the operation to abort, nor do their contents get modified. The ->overwrite_co attribute also prevents existing checkouts from aborting the operation but it causes the checked-out version to be replaced by the contents of the source file (if that exists and has different contents of course).

  • ->label_mods

    By default the ->label method will recursively label all visible elements under the dstbase directory. With this attribute set it will label only modified elements instead. Note that this may cause confusion if an element is labeled but its parent directory isn't.

  • ->no_cr

    By default, checkins initiated by the checkin method are done one at a time using the -from flag. This will preserve config records in the case where the input file is a derived object. Setting the no_cr attribute causes checkins to be done in one big "cleartool ci" operation, which is faster but loses CR's.

  • ->no_cmp

    This attribute causes all files which exist in both src and dest areas to be considered modified by the analyze method. An update will be forced for all such elements.

  • ->cmp_func

    Sets or returns the coderef that's used to compare the source and destination files. The default is File::Compare::compare() but can be replaced with a ref to your preferred function, eg:


    The function takes the names of the two files to compare. It should set $! if a file cannot be opened.

  • ->comment

    Provides a comment to be used by the checkin method. The default comment is "By:$0". Example:

        $obj->comment("your comment here");
  • ->eltypemap

    In case the eltype of a particular file or set of files needs to be overridden at creation time. Example:

        $obj->eltypemap('\.(ht|x)ml$' => 'compressed_file');

Support for the BranchOff feature.

BranchOff is a feature you can set up via an attribute in your config spec. The rationale and the design are documented in:


Instead of branching off the selected version, the strategy is to branch off the root of the version tree, copy-merging there from the former.

This allows to avoid both merging back to /main or to a delivery branch, and cascadig branches indefinitely. The logical version tree is restituted by navigating the merge arrows, to find all the direct or indirect contributors.

See also ClearCase::Wrapper::MGi on CPAN.

Support for incremental label families

ClearCase::Wrapper::MGi supports managing families of incremental fixed label types, as lists, linked with hyperlinks. The top of a list is accessible as the equivalent fixed label type of a floating label type, which has a stable name. This allows to move the floating labels, and keep track of their successive positions with sparse fixed labels.

ClearCase::SyncTree follows this strategy if the label type provided has an EqInc hyperlink.

Using an incremental type with the label method, label_mods is implicit (and ignored).

Support for Cygwin

VOB paths show under Cygwin with forward slashes as separators. UNC paths start with //, and drives are presented with a /cygdrive/ prefix. Cygwin also offers a mount tool, allowing the user to mount her views under /view, to match the UNIX convention.

The support for Cygwin normalizes the paths on the UNC syntax.


  • If a file is removed via the ->subtract method and later added back via ->add, the result will be a new element (aka evil twin). The ->reuse method (see) may be used to prevent evil twins.

  • I have not tested SyncTree in snapshot views and would not expect that to work out of the box, though I did make some effort to code for the possibility.

Following items are from Uwe Nagler of Lucent, unverified:

  • Mode changes of files should be supported.

    Currently: If ONLY the protections of an existing file (in source and VOB destination ) is changed in the source then this change is NOT transferred into the VOB destination. E.g. If a file later gets "execute" permissions (scripts) in the source then the file in VOB destination keeps the old permissions.

  • File type changes should be supported

    Currently: If the type of an existing file (in source and VOB destination) is changed in the source (ASCII->Binary) then the change in VOB destination fails because of a ClearCase error (wrong file type).

  • Cleanup Bug #1

    Wrong cleanup after detection of own checkouts below VOB destination: If the current view has a checkout at the same branch where synctree wants to checkout then (a) the whole synctree run is marked as failed (which is OK) but (b) the cleanup performs a uncheckout and the user will lose the data of its checkout.

  • Cleanup Bug #2

    Wrong cleanup after detecting other checkouts below VOB destination: If another view has a checkout at the same branch where synctree wants to checkout then (a) the whole synctree run is NOT marked as failed (b) only this element is not updated


Based on code originally written by Paul D. Smith <pausmith@nortelnetworks.com>. Paul's version was based on the Bourne shell script 'citree' delivered as sample code with ClearCase.

Rewritten for Unix/Win32 portability by David Boyce in 8/1999, then reorganized into a module in 1/2000. This module no longer bears the slightest resemblance to any version of citree.

Support for 2 features compatible with ClearCase::Wrapper::MGi (branching off the root of the version tree--usually, /main/0, and applying incremental labels), as well as for cygwin, added by Marc Girod.


Copyright 1997,1998 Paul D. Smith and Bay Networks, Inc.

Copyright 1999-2010 David Boyce (dsbperl AT boyski.com).

This script is distributed under the terms of the GNU General Public License. You can get a copy via ftp://ftp.gnu.org/pub/gnu/ or its many mirrors. This script comes with NO WARRANTY whatsoever, not even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


SyncTree is currently ALPHA code and thus I reserve the right to change the API incompatibly. At some point I'll bump the version suitably and remove this warning, which will constitute an (almost) ironclad promise to leave the interface alone.


This module is known to work on Solaris 2.6-10 and Windows NT 4.0SP3-5 to Vista SP2, and with perl 5.004_04 to 5.10. As these platforms cover a fairly wide range there should be no major portability issues, but please send bug reports or patches to the address above.


perl(1), synctree(1), ClearCase::Argv(3), Getopt::Long(3), IPC::ChildSafe(3)