The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Conjury::Core - the foundation of Perl Conjury

SYNOPSIS

  use Conjury::Core;

  tie I<HASH>, Conjury::Core::Journal, F<filename>;

  $spell = Conjury::Core::Spell->new ( I<HASH> );

  cast_warning ( I<LIST> );
  cast_error ( I<LIST> );

  [$spell =] name_spell ( I<HASH> );

  @spells = fetch_spells ( I<HASH> );

  $spell = Conjury::Core::deferral ( I<HASH> );

  $spell = Conjury::Core::filecopy ( I<HASH> );

  $spell = Conjury::Core::dispell ( I<HASH> );

DESCRIPTION

The Conjury::Core module is the foundation of the Perl Conjury software construction framework. You need to understand this module before you design other Perl Conjury modules, especially application-specific ones referenced in your Conjury.pl files.

In addition to some exported functions, there are four Perl packages in the Conjury::Core namespace: Conjury::Core::Context, Conjury::Core::Journal and Conjury::Core::Spell.

Conjury::Core::Context

A "context" is an association between a directory within the source file hierarchy and the spells defined by the Conjury.pl file there. (The name of the spell definition file may differ on your platform. See Conjury.)

A Conjury::Core::Context object encapsulates this association. It should be treated like a structure with named members. Most of its methods are not really for public use.

The 'Directory' method returns the name of the directory associated with the context.

The $Current_Context package variable always contains a reference to the current context object. The $Top_Context package variable always contains a reference to the context at the top of the source file hierarchy.

Conjury::Core::Journal

A "journal" is a file that contains the persistent data that Perl Conjury uses to record the signatures of actions as they are performed, so that they can be skipped on subsequent runs when the signature for products are known not to have changed.

It probably should not be implemented as a tied hash, but it is. It should be treated like an opaque object.

Create a journal using the tie builtin and specifying the name of the file to write.

Conjury::Core::Spell

A "spell" is an object that encapsulates the action required to perform a task, typically for constructing or erasing files. A spell is usually associated with a list of factors, other spells representing actions that must be taken first, if the spell is to succeed.

All spells have a profile which is used in computing the signature of the spell. Before an action is taken for a spell, the signatures of all its factors are appended to the profile for the spell, then reduced with the MD5 cryptographic hash function to become the signature for the spell.

When a spell creates product files, the names of the files and the signature of the spell that produced them is journaled to a file. In this way, if the signature for a file is found to have changed since it was last journaled, it is because the spell responsible for creating it has acquired a new profile, or one of its factors has a new signature.

If a factor of a spell specifies a file not produced by any spells, that file is treated as a source file, and its modification time is appended to the profile of the spell which considers it a factor. In this way, changes to the modification time of a source file results in a cascading change to the signature of every spell that references it in its tree of factors.

Use the Conjury::Core::Spell-new> subroutine to construct a spell object. The named parameters are all optional, but using some of them implies a requirement for the use of others. A spell constructed with no parameters has no action, no profile, i.e. it generates no effect on the signature of spells that consider it a factor.

The named parameters of the new method in detail:

Journal => \%journal

Associates the spell with a journal object. This is usually not necessary when the spell has no product files. Spells that have products should always journal their signatures, but it is not required.

Factors => [ factor1, factor2, ... ]

Specifies the list of factors for the spell. These may be references to other spell objects or the names of spells to fetch using the fetch_spells function.

Product => filename
Product => [ filename1, filename2, ... ]

Specifies the name of the file, or a list of the names of files, produced by the action of the spell. When the spell is created, the names of the products are stored internally in a global hash available to the fetch_spells function.

Action => SCALAR
Action => [ PROGRAM, ARG1, ARG2, ... ]
Action => CODE

Specifies the action to take when the spell is invoked. The first and second form result in the scalar (or the list of scalars) to be used with the system builtin function.

The third form is for specifying a closure that takes a reference to the spell object as its only argument. If you use a closure, you will be required to specify a profile for the closure. This is because you cannot convert a code block into a string very easily in Perl.

When a spell is invoked, its action is executed in the context in which it was created. Actions return boolean true on failure.

Profile => SCALAR
Profile => CODE

Specifies the profile for an action. The first form is the simple case, i.e. the string is used as the profile for an action closure. You should provide a profile that uniquely describes the action to take, including the name of the action function and the values of any parameters used in the construction of the closure.

The second form is the more complicated case, i.e. the profile is, itself, a closure. Closure profiles require no arguments, and they are called during the invocation phase immediately before the factors are invoked. The explanation for why you would want to use this form is tedious, esoteric and best not presented during dinner. Hint: C language dependency scanning is one case.

Exported Functions

The name_spell and fetch_spells functions should probably be moved into an appropriate Conjury::Core::Xxxxx namespace. If they stay where they are, then the contents of @EXPORT should be moved to @EXPORT_OK. It remains unclear what is the right thing to do here-- but it will be. It will.

    cast_warning

    Prints a warning message to the standard output. Use this function like the print builtin function. A prefix is inserted to identify the message as a warning from the cast utility, and a newline is appended.

    cast_error

    Prints an error message to the standard output and dies. Use this function like the die builtin function. A prefix is inserted to identify the message as an error from the cast utility, and a newline is appended.

    name_spell

    name_spell (Spell => spell, Context => context, Name => [ name1, name2, ... ], # array or scalar is okay Default => 1)

    Assigns names in a context to a spell. The 'Spell' argument is the only required argument. The others are all optional.

    If no context is specified, then the current context is assumed.

    If the 'Default' argument is specified, or the 'Name' argument is unspecified or specifies an empty list, then the spell is explicitly assigned to the list of unnamed spells in the context. These spells are typically the 'default' spells that are invoked when no names are given to the cast utility from the command line.

    fetch_spells

    fetch_spells(Name => name, Context => context, Require => 1)

    Returns a list containing references to all the spell objects with the name in the context.

    If the name is not specified, then the list will contain references to all the unnamed spell objects. You can use a list of names to fetch all the spell objects for the whole list at once. A spell will be fetched if its product matches the specified name, or the spell was explicitly assigned the name with the name_spell function.

    If the context is not specified, the current context is assumed.

    Spells for products created in other contexts can be fetched using either an absolute or a relative pathname. Be careful that the path you specify contains no symbolic links or references to parent directory pointers, i.e. the '..' directory, as these may not be resolved properly.

    If the 'Require' argument is not set, then an empty list is a permissible result.

    deferral

    $spell = deferral(Directory => [ dir1, dir2, ...], Name => name, If_Present => 1);

    Creates a spell object that defers its actions to the named spells in contexts associated with other directories. The 'Name' argument is used with the fetch_spells function to find all the named spells in each directory.

    There must be a spells definition file in each of the named directories, unless the 'If_Present' argument is defined.

    The 'Name' argument may specify a single name or a list of names. If it is a list of names, then all the names are passed to the fetch_spells function for each directory at a time.

    filecopy

    $spell = filecopy (Journal => journal, Factors => [ spell1, spell2, ... ], Directory => directory, File => [ file1, file2, ... ], # array or scalar is okay Permission => permission, Owner => [ user, group ];

    Creates a spell object that copies a file or a list of files to a directory.

    The 'File' argument is required and must specify a filename or a list of filenames. The 'Directory' argument is required and must specify the destination directory for the copy action.

    Use the optional 'Factors' argument to add spells explicitly to the list of factors. If there are already spells that produce the files in the 'File' list, they need not be listed here. They will be fetched and automatically appended to the factors list.

    Use the optional 'Journal' argument to specify a journal object for the spell.

    Use the optional 'Permission' argument to specify that the chmod builtin should be used to set the access permissions associated with the files after they have been copied to the destination. The syntax requirements for chmod apply.

    Use the optional 'Owner' argument to specify that the chown builtin should be used to set the user and group ownership after the files have been copied to the destination. The syntax requirements for chown apply.

    dispell

    $spell = dispell (Journal => journal, Factors => [ spell1, spell2, ... ], Directory => [ directory1, directory2, ...] # array or scalar okay File => [ file1, file2, ... ], # array or scalar okay Glob => [ expression1, expression2, ...] # array or scalar okay Require => 1;

    Creates a spell object that erases files or lists of files in a directory.

    At least one of the arguments, 'File', 'Glob' and 'Directory' is required. The 'File' argument specifies a filename or a list of filenames to unlink with the 'unlink' builtin function. The 'Directory' argument specifies a directory or a list of directories to remove with the 'rmtree' function in File::Path. The 'Glob' argument specifies a filename globbing expression that is resolved in the action function into a list of files and directories that are dispelled as if they were specified in 'File' or 'Directory' argument lists.

    The 'Require' argument is optional. If it is set, then the files and directories to be unlinked or removed are required to exist when the action is executed to erase them.

    Use the optional 'Factors' argument to add spells explicitly to the list of factors.

    Use the optional 'Journal' argument to specify a journal object for the spell.

AUTHOR

James Woodyatt <jhw@wetware.com>

1 POD Error

The following errors were encountered while parsing the POD:

Around line 932:

You can't have =items (as at line 1049) unless the first thing after the =over is an =item