<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sect2 SYSTEM "../../../dtd/dblite.dtd">
<sect2 id="tsvn-dug-settings-hooks">
  <title>Client Side Hook Scripts</title>
  <?dbhh topicname="HIDD_SETTINGSHOOKS"?>
  <?dbhh topicname="HIDD_SETTINGSHOOKCONFIG"?>
  <indexterm>
    <primary>client hooks</primary>
  </indexterm>
  <indexterm>
    <primary>hook scripts</primary>
  </indexterm>
  <para>
    <figure id="tsvn-dug-settings-dia-hooks">
      <title>The Settings Dialog, Hook Scripts Page</title>
      <graphic fileref="../images/SettingsHooks.png"/>
    </figure>
    This dialog allows you to set up hook scripts which will be
    executed automatically when certain Subversion actions are performed.
    As opposed to the hook scripts explained in <xref linkend="tsvn-repository-hooks"/>,
    these scripts are executed locally on the client.
  </para>
  <para>
    One application for such hooks might be to call a program like
    <literal>SubWCRev.exe</literal> to update version numbers after a commit,
    and perhaps to trigger a rebuild.
  </para>
  <para>
    Note that you can also specify such hook scripts using special
    properties on your working copy. See the section <xref linkend="tsvn-dug-propertypage-tsvn-props"/>
    for details.
  </para>
  <para>
    <figure id="tsvn-dug-settings-dia-hook-edit">
      <title>The Settings Dialog, Configure Hook Scripts</title>
      <graphic fileref="../images/SettingsHookEdit.png"/>
    </figure>
    To add a new hook script, simply click <guibutton>Add</guibutton>
    and fill in the details.
  </para>
  <para>
    There are currently these types of hook script available
    <variablelist>
      <varlistentry>
        <term>Start-commit</term>
        <listitem>
          <para>
            Called before the commit dialog is shown.
            You might want to use this if the hook modifies a versioned
            file and affects the list of files that need to be committed
            and/or commit message. However you should note that because
            the hook is called at an early stage, the full list of objects
            selected for commit is not available.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Manual Pre-commit</term>
        <listitem>
          <para>
            If this is specified, the commit dialog shows a button
            <guibutton>Run Hook</guibutton> which when clicked runs
            the specified hook script. The hook script receives a list
            of all checked files and folders and the commit message
            if there was one entered.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Check-commit</term>
        <listitem>
          <para>
            Called after the user clicks <guibutton>OK</guibutton>
            in the commit dialog, and before the commit dialog closes.
            This hook gets a list of all the checked files. If the
            hook returns an error, the commit dialog stays open.
          </para>
          <para>
            If the returned error message contains paths on newline
            separated lines, those paths will get selected in the commit
            dialog after the error message is shown.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Pre-commit</term>
        <listitem>
          <para>
            Called after the user clicks <guibutton>OK</guibutton>
            in the commit dialog, and before the actual commit begins.
            This hook has a list of exactly what will be committed.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Post-commit</term>
        <listitem>
          <para>
            Called after the commit finishes successfully.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Start-update</term>
        <listitem>
          <para>
            Called before the update-to-revision dialog is shown.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Pre-update</term>
        <listitem>
          <para>
            Called before the actual Subversion update or switch begins.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Post-update</term>
        <listitem>
          <para>
            Called after the update, switch or checkout finishes (whether successful or not).
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Pre-connect</term>
        <listitem>
          <para>
            Called before an attempt to contact the repository.
            Called at most once in five minutes.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Pre-lock</term>
        <listitem>
          <para>
            Called before an attempt to lock a file.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Post-lock</term>
        <listitem>
          <para>
            Called after a file has been locked.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
  </para>
  <para>
    A hook is defined for a particular working copy path. You only need to
    specify the top level path; if you perform an operation in a sub-folder,
    TortoiseSVN will automatically search upwards for a matching path.
  </para>
  <para>
    Next you must specify the command line to execute, starting with the path
    to the hook script or executable.
    This could be a batch file, an executable file or any other file which
    has a valid windows file association, e.g. a perl script.
    Note that the script must not be specified using a UNC path as Windows
    shell execute will not allow such scripts to run due to security restrictions.
  </para>
  <para>
    The command line includes several parameters which get filled in
    by TortoiseSVN. The parameters passed depend upon which hook is called.
    Each hook has its own parameters which are passed in the following order:
    <variablelist>
      <varlistentry>
        <term>Start-commit</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>MESSAGEFILE</literal>
            <literal>CWD</literal>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Manual Pre-commit</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>MESSAGEFILE</literal>
            <literal>CWD</literal>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Check-commit</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>MESSAGEFILE</literal>
            <literal>CWD</literal>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Pre-commit</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>DEPTH</literal>
            <literal>MESSAGEFILE</literal>
            <literal>CWD</literal>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Post-commit</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>DEPTH</literal>
            <literal>MESSAGEFILE</literal>
            <literal>REVISION</literal>
            <literal>ERROR</literal>
            <literal>CWD</literal>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Start-update</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>CWD</literal>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Pre-update</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>DEPTH</literal>
            <literal>REVISION</literal>
            <literal>CWD</literal>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Post-update</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>DEPTH</literal>
            <literal>REVISION</literal>
            <literal>ERROR</literal>
            <literal>CWD</literal>
            <literal>RESULTPATH</literal>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Pre-connect</term>
        <listitem condition="pot">
          <para>
            no parameters are passed to this script. You can pass
            a custom parameter by appending it to the script path.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Pre-lock</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>LOCK</literal>
            <literal>FORCE</literal>
            <literal>MESSAGEFILE</literal>
            <literal>CWD</literal>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Post-lock</term>
        <listitem condition="pot">
          <para>
            <literal>PATH</literal>
            <literal>LOCK</literal>
            <literal>FORCE</literal>
            <literal>MESSAGEFILE</literal>
            <literal>ERROR</literal>
            <literal>CWD</literal>
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
  </para>
  <para>
    The meaning of each of these parameters is described here:
    <variablelist>
      <varlistentry>
        <term condition="pot">PATH</term>
        <listitem>
          <para>
            A path to a temporary file which contains all the
            paths for which the operation was started in UTF-8 encoding.
            Each path is on a separate line in the temp file.
          </para>
          <para>
            Note that for operations done remotely, e.g.
            in the repository browser, those paths are
            not local paths but the urls of the affected
            items.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term condition="pot">DEPTH</term>
        <listitem>
          <para>
            The depth with which the commit/update is done.
          </para>
          <para>
            Possible values are:
            <variablelist>
              <varlistentry>
                <term condition="pot">-2</term>
                <listitem>
                  <para>
                    <literal>svn_depth_unknown</literal>
                  </para>
                </listitem>
              </varlistentry>
              <varlistentry>
                <term condition="pot">-1</term>
                <listitem>
                  <para>
                    <literal>svn_depth_exclude</literal>
                  </para>
                </listitem>
              </varlistentry>
              <varlistentry>
                <term condition="pot">0</term>
                <listitem>
                  <para>
                    <literal>svn_depth_empty</literal>
                  </para>
                </listitem>
              </varlistentry>
              <varlistentry>
                <term condition="pot">1</term>
                <listitem>
                  <para>
                    <literal>svn_depth_files</literal>
                  </para>
                </listitem>
              </varlistentry>
              <varlistentry>
                <term condition="pot">2</term>
                <listitem>
                  <para>
                    <literal>svn_depth_immediates</literal>
                  </para>
                </listitem>
              </varlistentry>
              <varlistentry>
                <term condition="pot">3</term>
                <listitem>
                  <para>
                    <literal>svn_depth_infinity</literal>
                  </para>
                </listitem>
              </varlistentry>
            </variablelist>
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term condition="pot">MESSAGEFILE</term>
        <listitem>
          <para>
            Path to a file containing the log message for
            the commit. The file contains the text in UTF-8
            encoding. After successful execution of the
            start-commit hook, the log message is read back,
            giving the hook a chance to modify it.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term condition="pot">REVISION</term>
        <listitem>
          <para>
            The repository revision to which the update should
            be done or after a commit completes.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term condition="pot">LOCK</term>
        <listitem>
          <para>
            Either <literal>true</literal> when locking, or <literal>false</literal> when unlocking.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term condition="pot">FORCE</term>
        <listitem>
          <para>
            Either <literal>true</literal> or <literal>false</literal>, depending
            on whether the operation was forced or not.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term condition="pot">ERROR</term>
        <listitem>
          <para>
            Path to a file containing the error message.
            If there was no error, the file will be empty.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term condition="pot">CWD</term>
        <listitem>
          <para>
            The current working directory with which the script is run.
            This is set to the common root directory of all affected paths.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term condition="pot">RESULTPATH</term>
        <listitem>
          <para>
            A path to a temporary file which contains all the
            paths in UTF-8 encoding which were somehow touched by the operation.
            Each path is on a separate line in the temp file.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
  </para>
  <para>
    Note that although we have given these parameters names for convenience,
    you do not have to refer to those names in the hook settings.
    All parameters listed for a particular hook are always passed,
    whether you want them or not ;-)
  </para>
  <para>
    If you want the Subversion operation to hold off until the hook has completed,
    check <guilabel>Wait for the script to finish</guilabel>.
  </para>
  <para>
    Normally you will want to hide ugly DOS boxes when the script runs,
    so <guilabel>Hide the script while running</guilabel> is checked by default.
    Also you need to check this if your hook script might return an error that should
    stop the operation.
  </para>
    The <literal>force</literal> flag can be set if the user must not proceed
    with the operation without running the script, i.e. the script must always
    run. If the <literal>force</literal> flag is not checked, then the user
    is shown a button <guibutton>Retry without hooks</guibutton> to retry
    the operation without running the hook script.
  <para>
    
  </para>
  <para>
    Sample client hook scripts can be found in the <literal>contrib</literal> folder in the
    <ulink url="https://svn.code.sf.net/p/tortoisesvn/code/trunk/contrib/hook-scripts">
      <citetitle>TortoiseSVN repository</citetitle>
    </ulink>.
    (<xref linkend="tsvn-preface-source"/> explains how to access the repository.)
  </para>
  <para>
    When debugging hook scripts you may want to echo progress lines to the DOS console,
    or insert a pause to stop the console window disappearing when the script completes.
    Because I/O is redirected this will not normally work.
    However you can redirect input and output explicitly to CON to overcome this. e.g.
    <screen>
echo Checking Status &gt; con
pause &lt; con &gt; con
    </screen>
  </para>
  <para>
    A small tool is included in the TortoiseSVN installation folder named
    <literal>ConnectVPN.exe</literal>. You can use this tool configured as a
    pre-connect hook to connect automatically to your VPN before TortoiseSVN
    tries to connect to a repository.
    Just pass the name of the VPN connection as the first parameter to the tool.
  </para>
  <sect3 id="tsvn-dug-settings-hooks-issuetracker">
    <title>Issue Tracker Integration</title>
    <?dbhh topicname="HIDD_SETTINGSBUGTRAQ"?>
    <?dbhh topicname="HIDD_SETTINGSBUGTRAQADV"?>
    <para>
      TortoiseSVN can use a COM plugin to query issue trackers when in the
      commit dialog. The use of such plugins is described in
      <xref linkend="tsvn-dug-bugtracker-ref" />.
      If your system administrator has provided you with a plugin, which
      you have already installed and registered, this is the place to
      specify how it integrates with your working copy.
    </para>
    <para>
      <figure id="tsvn-dug-settings-dia-issuetracker">
        <title>The Settings Dialog, Issue Tracker Integration Page</title>
        <graphic fileref="../images/SettingsIssueTracker.png"/>
      </figure>
      Click on <guibutton>Add...</guibutton> to use the plugin with
      a particular working copy. Here you can specify the working copy
      path, choose which plugin to use from a drop down list of all
      registered issue tracker plugins, and any parameters to pass.
      The parameters will be specific to the plugin, but might include
      your user name on the issue tracker so that the plugin can
      query for issues which are assigned to you.
    </para>
    <para>
      If you want all users to use the same COM plugin for your project, you
      can specify the plugin also with the properties <literal>bugtraq:provideruuid</literal>,
      <literal>bugtraq:provideruuid64</literal> and <literal>bugtraq:providerparams</literal>.

      <variablelist>
        <varlistentry>
          <term condition="pot">bugtraq:provideruuid</term>
          <listitem>
            <para>
              This property specifies the COM UUID of the IBugtraqProvider,
              for example <literal>{0044f6c0-b999-11e1-afa6-0800200c9a66}</literal>.
              (This example is the UUID of the
              <ulink url="https://github.com/scottiemc7/YurtleTrack">
                <citetitle>YurtleTrack provider</citetitle>
              </ulink>,
              which is a provider for the
              <ulink url="http://www.jetbrains.com/youtrack/">
                <citetitle>JetBrains YouTrack 6.0</citetitle>
              </ulink>
              issue tracker.)
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term condition="pot">bugtraq:provideruuid64</term>
          <listitem>
            <para>
              This is the same as <literal>bugtraq:provideruuid</literal>, but
              for the 64-bit version of the IBugtraqProvider.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term condition="pot">bugtraq:providerparams</term>
          <listitem>
            <para>
              This property specifies the parameters passed to the IBugtraqProvider.
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
      Please check the documentation of your IBugtraqProvider plugin to find out what
      to specify in these two properties.
    </para>
  </sect3>
</sect2>
