<!--  vim: set sw=2 sts=2 et ft=docbk:

  Part of the A-A-P recipe executive: Publishing

  Copyright (C) 2002-2003 Stichting NLnet Labs
  Permission to copy and use this file is specified in the file COPYING.
  If this file is missing you can find it here: http://www.a-a-p.org/COPYING

-->


<para>
Publishing means distributing the files of your project.
This is a generic mechanism.  You can use it to maintain a web site or to
release a new version of your application.
</para>
<para>
The most straightforward way to publish a file is with the
<literal>:publish</literal> command:
</para>
<programlisting>
        :attr {publish = ftp://ftp.my.org/upload/%file%} myfile
        :publish myfile
</programlisting>
<para>
This uses the "publish" attribute on each of the files.  When the "publish"
attribute is missing the "commit" attribute is used.  If both are missing this
is an error.
</para>
<para>
When a file didn't change since the last time it was published, it won't be
published again.  This works with signatures, like building a target.  The
remote file is the target in this case.  But &Aap; won't read the remote file
to compute the signature, it will remember the signature from when the file
was last uploaded (otherwise checking for outdated files would be slow).
</para>
<para>
  In the example %file% is used.  This is replaced with the name of the file
  being published, including the directory.  This means you can use the same
  attribute for several files:
</para>
<programlisting>
        Files = myfile yourfile hisfile
        :attr {publish = ftp://ftp.my.org/upload/%file%} $Files
        :publish $Files
</programlisting>
<para>
  Including the directory is sometimes not what you want.  To only use the
  last part of the path use %basename%.
</para>
<programlisting>
        Files = one/myfile two/yourfile three/hisfile
        :attr {publish = ftp://ftp.my.org/common/%basename%} $Files
        :publish $Files
</programlisting>
<para>
  The three files will be uploaded to the "common" directory.  The directory
  names "one", "two" and "three" will not be used on the ftp server.
</para>
<para>
To publish all files with a "publish" attribute start &Aap; like this:
</para>
<literallayout>      <userinput>aap publish</userinput>
</literallayout>
<para>
If the "publish' target is defined explicitly it will be executed.  Otherwise,
all files with the "publish" attribute are given to the
<link linkend='cmd-publish'>:publish</link>
command, just like using the
<link linkend='cmd-publishall'>:publishall</link> command.
</para>

<para>
  The "publish" attribute may consist of several items.  Publishing will use
  all these items.  This means a file can be distributed to several sites at
  once.  This is unlike fetching, which stops as soon as the file could be
  obtained from one of the items.
</para>
<para>
When publishing fails for one of the sites, e.g., because the server is down,
this is remembered.  When you publish again, uploading is done only for that
site.  The destinations for which pusblishing worked will be skipped then.
</para>

<bridgehead>Using Secure Copy</bridgehead>

<para>
Uploading files requires write access to the server.  There are several
methods for this, but some have the disadvantage that your password is sent as
normal text over the internet.  Or someone in between can change the files
that you send out.  There is one that provides sufficient security: scp
or secure copy.
</para>
<para>
To publish a file to a server through secure copy use a URL in this form:
</para>
<programlisting>
        :publish file {publish = scp://myname@the.server.com/dir/%file%}
</programlisting>
<para>
"myname" is your login name on the server "the.server.com".  The "file" will
be written there as "dir/file", relative to your login directory.
</para>
<para>
This requires the "scp" command, which is not a standard item.  If it does not
appear to exist then Aap will offer you to install it for you.  If the
automatic mechanism fails you will have to install it yourself.  You might
also want to do this if you have specific preferences for how the scp command
is to be installed (versions of scp exist with different kinds of encryption).
</para>
<para>
To avoid having to type a password each time you need to use public keys.  For
MS-Windows you can find information here:
<literallayout>      <ulink url="http://the.earth.li/~sgtatham/putty/0.53b/htmldoc/Chapter8.html">
      http://the.earth.li/~sgtatham/putty/0.53b/htmldoc/Chapter8.html
      </ulink>
</literallayout>
This is for the PuTTY version of scp, which is what Aap installs for you if
you let it.  For Unix try <userinput>man ssh-keygen</userinput>.  Use "SSH protocol
version 2" if possible.
</para>
<para>
You can specify the command to be executed with the <literal>$SCP</literal> variable,
see <link linkend="var-scp">the reference manual</link>.
Example:
</para>
<programlisting>
          SCP = scp -i c:/private/keyfile
</programlisting>


<bridgehead>Using Another Method</bridgehead>

<para>
Using "rsync" has an advantage if you have files with only a few changes.  The
rsync program will only transfer the differences.  This adds a bit of
overhead to find out what changed, thus it's a bit slower when copying whole
files.
</para>
<para>
  &Aap; uses the same secure channel as with "scp" by default.  This can be
  changed with the <literal>$RSYNC</literal> variable, see
  <link linkend="var-rsync">the reference manual</link>.
</para>
<para>
If your server does not support "scp", you might want to use "rcp".  However,
this is insecure, information is transferred unencoded over the internet and
making a connection is not secure.  Only use this when "scp" is not possible.
</para>
<para>
  Using "rcp" means changing the "scp://" part of the URL to "rcp://".
  The $RCP variable holds the name of the command, see
  <link linkend="var-rcp">the reference manual</link>.
</para>
<para>
  You can also use "ftp".  Some web servers require this, even though ftp
  sends your password as plain text over the internet, thus it is insecure.
  &Aap; uses the Python ftp library, thus an external command is not needed
  and there is no variable to specify the command.
</para>


<bridgehead>Changing A Url</bridgehead>

<para>
When you switch to another server you need to change the "publish" attribute.
The next time you invoke &Aap; for publishing it will automatically upload all
the files to the new server.
</para>
<para>
If you didn't actually change to another server, but the URL used for the
server changed, invoke Aap once with the "--contents" argument:
</para>
<literallayout>      <userinput>aap publish --contents</userinput>
</literallayout>
<para>
This will cause only files that changed to be published.  It avoids that all
the files with a changed "publish" attribute are published again.  It will
still upload files that you changed since the last upload and newly added
files.  But be careful: files that you once uploaded, deleted from the list of
files and now added will NOT be uploaded!
</para>


<bridgehead>Distributing Generated Files</bridgehead>

<para>
When publishing a new version of an application, you might want to include a
number of generated files.  This reduces the number of tools someone needs to
use when installing the application.  For example, the "configure" script
that "autoconf" produces from "configure.in" can be included.
</para>
<para>
To avoid these generated results to be generated again when the user runs aap,
explicitly specify a signature file to be used and distribute this signature
file together with the generated files.  For example, suppose you have a
directory with these files you created:
</para>
<literallayout>        main.aap
        prog.c
</literallayout>
<para>
Additionally there is the file "version.c" that is generated by the "main.aap"
recipe.  It contains the date of last modification.  To avoid it being
generated again, include the "mysign" file in the distribution.  The files to
be distributed are:
</para>
<literallayout>        mysign
        main.aap
        prog.c
        version.c
</literallayout>
<para>
In the "main.aap" recipe the "signfile" attribute is used for the dependency
that generates version.c:
</para>
<programlisting>
        version.c {signfile = mysign} : prog.c
                :print char *timestamp = "$TIMESTR"; >! $target
</programlisting>
<para>
The result is that "version.c" will only be generated when "prog.c" has
changed.  When the "signfile" attribute would not have been used, "version.c"
would have been generated after unpacking the distributed files.
</para>


<bridgehead>Copying All Files At Once</bridgehead>

<para>
The "finally" target is always executed after the other targets have been
successfully built.  Here is an example that uses the "finally" target to copy
all files that need to be uploaded with one command.
</para>
<programlisting>
        Source = *.html
        all: remote/$*Source {virtual} {remember}

        CFile =
        :rule remote/% : %
                _recipe.CFile += $source

        finally:
                @if _recipe.CFile:
                        :copy $_recipe.CFile ftp://my.org/www
</programlisting>
<para>
  Warning: When the
  <link linkend="cmd-copy">:copy</link> command fails, aap doesn't know the
  targets were not
made properly and won't do it again next time.  Using the "publish" attribute
works better.
</para>

<bridgehead id="publish-images">Publishing images for HTML files</bridgehead>

<para>
When publishing HTML files you most likely also want to publish the image
files referenced by them.  You can use a wildcard to select the images files,
but this may include images that are not actually used.  You can explicitly
specify the images, but if you miss one your locally tested web site won't
work properly on the server.
</para>
<para>
A good solution is to parse the HTML files and figure out what images are used
in them.  However, only image files that can be found locally should be
included, not ones that are on other web sites.  The
<link linkend="python-get-html-images">get_html_images()</link> function can
be used for this, as shown in an example:
</para>
<programlisting>
        Files = index.html
                contact.html
                forward.html
        Files += `get_html_images(Files)`
        :attr {publish = scp://user@ftp.foo.org/public_html/%file%} $Files

        all: publish
</programlisting>
<para>
  Note that this still isn't perfect.  Only images in plain "IMG" tags will be
  found and only when they use a relative path name.  Thus images from
  Javascript or PHP code will not be included.
</para>
