- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
- <meta name="description" content="Manual for p4ftpsync, a Python script to synchronize a remote site with a P4 depot via FTP." />
- <meta name="keywords" content="Perforce,P4,FTP,sync,synchronization,remote,site,web,python" />
- <meta name="author" content="Richard Gruet" />
- <title>p4ftpsync Manual</title>
-
- <style type="text/css">
- h1,h2,h3,h4,h5 {
- font-family:Arial, Helvetica, sans-serif;
- margin-left: 5px;
- }
-
- h1 {
- margin: 25px 10% 40px 10%;
- margin-bottom: 40px;
- border: gray dotted 2px;
- background-color:#FFCC99;
- }
-
- h2 {
- border-bottom: black solid 1px;
- }
-
- h4 {
- margin-bottom: 5px;
- }
- div {
- margin-bottom: 10px;
- margin-left: 15px;
- font-family: Georgia, "Times New Roman", Times, serif;
- /* font-family: Geneva, Arial, Helvetica, sans-serif; */
- font-size:12px;
- }
-
- div.optionCategory {
- margin-top: 20px;
- margin-right: 5%;
- font-weight: bold;
- font-style: italic;
- border-bottom: gray solid 1px;
- }
-
- div.option {
- font-weight: bold;
- margin-left: 40px;
- margin-bottom: 2px;
- }
-
- div.optionDesc {
- margin-left: 80px;
- }
-
- pre {
- border: black solid 1px;
- border-width: 1px 0 1px 0;
- margin: 7px 5% 7px 3%;
- padding: 5px 5px 5px 5px;
- background-color: #EFEFEF /* #FFCC99;*/
- }
- </style>
- </head>
-
- <body>
- <div style="font-size:smaller">
- <a href="javascript:location='mailto:\u0070\u0034\u0066\u0074\u0070\u0073\u0079\u006e\u0063\u0040\u0072\u0067\u0072\u0075\u0065\u0074\u002e\u006e\u0065\u0074';void 0">Richard Gruet</a> - Created September 15, 2005 - Last revised
- <!-- #BeginDate format:Am1 -->September 20, 2005<!-- #EndDate --></div>
- <h1 align="center">p4ftpsync <span style="font-size:smaller">- Synchronizes a remote site with a P4 depot via FTP</span></h1>
-
- <h2>Table Of Contents</h2>
- <div class="toc">
- <ul>
- <li><a href="#overview">Overview</a></li>
- <li><ul>
- <li><a href="#Whatsthat">What's that ?</a></li>
- <li><a href="#WhatsFor">What's for ?</a></li>
- </ul></li>
- <li><a href="#requirements">Requirements</a></li>
- <li><a href="#installation">Installation</a></li>
- <li><a href="#startup">Start-up</a></li>
- <li><a href="#commandReference">Command Reference</a></li>
- <li><ul>
- <li><a href="#reverseSync">Reverse Synchronization</a></li>
- <li><a href="#validOptions">Valid Options</a></li>
- <li><a href="#defaultValues">Default Values</a></li>
- <li><a href="#cache">Cache</a></li>
- <li><a href="#generatedScript">Generated FTP script</a></li>
- <li><a href="#log">Log</a></li>
- </ul></li>
- <li><a href="#limitations">Limitation, Bugs, Todo</a></li>
- <li><a href="#license">License</a></li>
- </ul>
- </div>
-
- <!-- OVERVIEW -->
- <a name="overview" id="overview"></a><h2>Overview</h2>
-
- <a name="Whatsthat" id="Whatsthat"></a>
- <h3>What's that ?</h3>
- <div><code>p4ftpsync.py</code> is a Python script which synchronizes a remote site with a P4 repository via Ftp, and vice versa. It is specially useful when you have not enough control over the remote host to be able to install a Perforce client there, which would make synchronization easy (at least the P4 to remote site sync).</div>
-
- <a name="WhatsFor" id="WhatsFor"></a><h3>What for ?</h3>
- <div>I am a member of a team which designs web sites. We want to keep the pages and code for our sites under P4 control,
- and <strong>synchronize</strong> the remote live sites from time to time to reflect the changes. Occasionally we
- have also to modify the pages <strong>directly</strong> on the live sites (in emergency situations!), and some
- of our clients can even edit the pages directly using Macromedia <a href="http://www.macromedia.com/software/contribute/"
- title="Macromedia Contribute">Contribute</a>: In these cases we want to have the P4 repository <strong>synced back</strong>.</div>
-
- <div>If you have enough control over the web host where your live site resides, i.e. if you can install a P4 client, the first sync
- (P4 to the live site) is easily accomplished via a <code>P4 sync</code> command, but not the second since P4 doesn't detect
- automatically changes in workspaces, you still have to manually open the files for add or delete.
- And if you have not enough privileges to be able to install a P4 client, which is the case of a lot of small to medium
- sites using cheap Web Hosting, you just can't use the P4 client install/P4 sync strategy [this strategy and others are developped
- in an interesting article on the P4 web site: <a href="http://www.perforce.com/perforce/wcm.html"> Web Content management in
- Perforce</a>].</div>
-
- <div>I searched for alternate solutions but could not find any - I could have missed something though, please let me know! -
- So I eventually wrote a program to perform the P4 to remote site synchronization, which I extended later to perform
- the reverse sync as well.</div>
-
- <div> The problem is to emulate a P4 remote client accessible only via FTP. The basic idea is to use a dedicated local
- client/workspace that reflects (mirrors) the state of the remote site. If we P4 sync this workspace to a certain
- revision, we get the exact list of changes that occurred, which we can then propagate (<em>push</em>) to the remote
- site using FTP operations. Conversely, with the restriction that the remote site be synced to the head revision,
- we can detect changes made directly to the site by comparing the remote site and the local workspace (synced to
- the head revision beforehand).</div>
-
- <div>Basically that's what <code>p4ftpsync</code> does. It's plain <a href="http://python.org/"
- title="Python language official site" target="_blank">Python</a>, one single loooooong file (>3000 lines!),
- uses no external library (not even the Perforce Python API) and requires only the basic P4 client install + the
- Python language (not required with the (almost) standalone executable version). It works with Perforce
- server version 2005.1 but should work with older versions as well (it doesn't use any fancy features but relies
- on P4 output parsing so it could be sensitive to change in format). The code uses some tricks to optimize speed
- (file caching, multi-threaded FTP operations) and so far it seems to be rather reliable, at least for common simple
- operations (eg sync to head revision).</div>
-
- <!-- REQUIREMENTS -->
- <a name="requirements" id="requirements"></a><h2>Requirements</h2>
- <ul>
- <li>Python 2.2+ (not required if the Windows standalone executable version is used). </li>
- <li>Basic (text mode) Perforce client installed locally. No Python API required.</li>
- <li>Your remote site accessible via FTP. The more possible simultaneous connections the faster transfers will be. </li>
- </ul>
-
- <!-- INSTALLATION -->
- <a name="installation" id="installation"></a><h2>Installation</h2>
- <div>You have the choice between 2 distributions : </div>
- <ul>
- <li>A Python script <a href="p4ftpsync.py" title="Python script">p4ftpsync.py</a>
- (you will need <a href="http://www.python.org/download/">Python</a> 2.2+ to execute it).</li>
- <li>A Win32 standalone executable <a href="p4ftpsync.exe" title="Standalone executable">p4ftpsync.exe</a>.
- Actually you may also need to download <a href="MSVCR71.dll" title="MicroSoft C Runtime library">MSVCR71.dll</a>
- if not already present on your system (this is because Python 2.4 is compiled with MicroSoft VC7, which creates
- executables that depend on that dll). Put it in the same directory as the .exe.</li>
- </ul>
-
- <div>In both cases you must have installed at least the <a href="http://perforce.com/perforce/loadprog.html"
- title="Perforce downloads" target="_blank">Perforce client</a>, and added the P4 install directory to
- your <code>PATH</code> environment variable before you can run <code>p4ftpsync</code>.
- Check it by opening a terminal and type: </div>
- <pre>p4</pre>
- <div>You should get a P4 help message. If not, check your P4 install and <code>PATH</code> envt var.</div>
-
- <div><code>p4ftpsync</code> also requires that you <strong>create a dedicated P4 <em>client</em></strong> (workspace).
- This workspace will be used to <em>mirror</em> the remote site in order to perform the synchronization.
- Use the Perforce command <code>p4 client</code> to create a client. Define the client <em>map spec</em>
- so to include the part of the depot that you want to synchronize.</div>
-
- <!-- START-UP -->
- <a name="startup" id="startup"></a><h2>Start-up </h2>
- <div>We assume that you have installed everything as described above and created a dedicated P4 client
- (called here <em>syncClient</em>). The examples described use the python script <code>p4ftpsync.py</code>,
- but apply to the executable version as well.</div>
-
- <div>To get help, type :</div>
- <pre>[python] p4ftpsync[.py] -h (or --help)
- </pre>
- <div>You can skip the "python" if <code>p4ftpsync.py</code> is in your <code>PATH</code> and files with extension
- <code>.py</code> are associated to the Python interpreter (which is generally the case). On windows, you can even
- omit the extension <code>.py</code>, provided you have added .py to the list of extensions in the <code>PATHEXT</code>
- environment variable.</div>
-
- <div>Let's try a normal (P4 to remote site) synchronization. Say you have your site on ftp server <em>ftpServerAddress</em>
- accessible by user <em>userName</em>, password <em>passwd</em>, rooted at <em>/mySite/www/</em>. Say the corresponding
- location in the P4 depot is at <em>//depot/mySite/www/...</em>. You want to synchronize the remote site with the
- head revision of the depot. Type:
- </div>
- <pre>
- p4ftpsync.py -v -t --p4Passwd <em>password</em> --p4Client <em>syncClient</em> --ftpHost <em>ftpServerAddress</em>
- --ftpUser <em>userName</em> --ftpPasswd <em>passwd</em> --ftpRoot <em>/mySite/www/</em> <em>//depot/mySite/www/...</em>
- </pre>
- <div>
- <ul>
- <li>If you omit a mandatory option, p4ftpsync will ask you to enter it interactively. Some P4 options are
- <em>guessed</em> from the environment, and p4ftpsync saves certain option values from one session to the
- other and uses them as defaults (more details about this later).</li>
- <li>Option <strong>-v</strong> (or --verbose) displays more detailed information messages on the screen (there
- is also an -always verbose- log, see file <code><em>sameDirAsP4ftpsync</em>/p4ftpsync.log</code>.</li>
- <li>Option <strong>-t</strong> (or --test) performs a <em>dry run</em>: synchronization actions are listed but not
- actually executed. The 2 options can be grouped together as <code>-vt</code> since they have no parameters.</li>
- </ul>
- </div>
-
- <div>If you perform this sync for the <strong>first time</strong>, <code>p4ftpsync</code> will try to upload
- <strong>all</strong> the files in <em>//depot/mySite/www/...</em> to the remote site. Actually, the actions
- are the same as a <code>p4 sync //depot/mySite/www/...</code> would do, except that they are converted to ftp
- actions to update the remote site (viewed as a remote P4 workspace). Next runs will only transfer changes since
- the last run, as <code>P4 sync</code> would do (however option <strong>-f</strong> allows to <strong>force</strong>
- the complete refresh of the workspace and therefore will upload all the files again).
- </div>
- <div>As you can see, there are a <strong>lot of parameters</strong> to provide to <code>p4ftpsync</code> !
- Fortunately the program tries to <strong>help you</strong> :
- <ul>
- <li>by defaulting missing P4 parameters p4Host, p4User, p4Passwd to their current values in the environment
- (P4PORT, P4USER, P4PASSWORD - actually the program gets this info by parsing the output of a <code>p4 info</code> command).</li>
- <li> The values of several options are also <strong>saved</strong> on disk during a session and used as defaults in
- the next session (passwords are <strong>never</strong> stored).</li>
- <li> Finally, the user is prompted to dynamically enter the missing <strong>required</strong> parameters. </li>
- </ul>
- In spite of these facilities, if you have to routinely perform a sync task, it is more convenient to define
- a small <strong>script</strong> for each site to synchronize, which will call <code>pftpsync</code> with the
- appropriate arguments. I find personally easier to define <strong>two</strong> scripts for the normal and reverse
- sync respectively (since they have different options), that I call (on Windows) <code>sync<em>MySite</em>live.bat</code>
- and <code><strong>r</strong>sync<em>MySite</em>live.bat</code>. Here is an example of such scripts :
- </div>
- <pre>
- @echo off
- REM <strong>sync<em>MySite</em>live.bat</strong>:
- REM Synchronizes (depot head revision -> live site) the <em>MySite</em> live site via FTP.
- REM
- REM For reverse synchronization, see rsync<em>MySite</em>live.bat.
- REM Uses P4 workspace ("client") <em>syncClient</em> as a mirror.
- REM You can pass additional args like :
- REM -v, --verbose to get a more detailed trace,
- REM -f, --force to force P4 to resync to the given revision
- REM ... and many more! use option -h for details.
- REM
- p4ftpsync.py %* --p4Passwd <em>password</em> --p4Client <em>syncClient</em> --ftpHost <em>ftpServerAddress</em>
- --ftpUser <em>userName</em> --ftpPasswd <em>passwd</em> /mySite/www/ --exclude @<em>p4ftpSyncDir</em>\sync<em>MySite</em>live.excludes.txt
- //depot/mySite/www/...
- </pre>
- <div>(Replace <code>p4ftpsync.py</code> with <code>p4ftpsync.exe</code> if needed)</div>
-
- <pre>
- @echo off
- REM <strong>rsync<em>MySite</em>live.bat</strong>:
- REM <strong>Reverse</strong> synchronization (live site -> P4) of live site <em>MySite</em> via FTP.
- REM Creates a P4 changelist for the changes and submits it.
- REM
- REM For normal synchronization (p4 -> live site), see sync<em>MySite</em>live.bat.
- REM Uses P4 workspace ("client") <em>syncClient</em> as a mirror.
- REM You can pass additional args like :
- REM -v, --verbose to get a more detailed trace,
- REM -f, --force to disable the file desc cache and force re-reading of remote files
- REM ... and many more! use option -h for details.
- REM
- p4ftpsync.py %* <strong>--reverse --submit</strong> --p4Passwd <em>password</em> --p4Client <em>syncClient</em> --ftpHost <em>ftpServerAddress</em>
- --ftpUser <em>userName</em> --ftpPasswd <em>passwd</em> /mySite/www/ <strong>--comment "GG3:rsync: Integrated changes made on the
- <em>mySite</em> live site." --mailto "john@doe.org,jane@jungle.com"</strong> --exclude @<em>p4ftpSyncDir</em>\sync<em>MySite</em>live.excludes.txt
- <strong>--smtpServer smtp.myIsp.com</strong> //depot/mySite/www/...
- </pre>
- <div>(options specific to <strong>reverse</strong> sync are in bold).
- <ul>
- <li>option <strong>--reverse</strong> tells <code>p4ftpsync</code> to perform a <em>reverse</em> synchronisation, instead
- of the default "normal" one.</li>
- <li>option <strong>--submit</strong> tells <code>p4ftpsync</code> to automatically submit the P4 changelist created
- for the changes detected (if any). By default the changelist is not submitted to let you have a look at the
- changes and possibly revert some of them (useful during your first trials).</li>
- <li>option <strong>--comment</strong> overrides the default auto-generated changelist comment with a customized one.</li>
- <li>option <strong>--mailto</strong> tells <code>p4ftpsync</code> to send a report e-mail to each address listed.
- The <strong>--smtpServer</strong> option specifies the address of the SMTP server to use (the default is
- <em>localhost:25</em>. Use options --smtpUser and --smtpPasswd if the server requires authentication).
- Default is to <strong>not</strong> send an email report.</li>
- </ul>
- </div>
-
- <div>Both scripts share the same <strong>list of exclusions</strong> (which makes sense). This is why the list is
- contained in a <strong>external file</strong> (<em>p4ftpSyncDir</em>\syncMySitelive.excludes.txt), rather than
- directly passed as a command line argument (this is indicated by the use of <code><strong>@</strong></code>
- in option --exclude). Files to exclude from the sync are specified as <em>patterns</em>, one per line.
- Patterns are actually Python <em>regular expressions</em>, implicitely terminated by <code>$</code>
- and preceded by <code>^.*</code>, which in practice means that patterns will be matched against the
- <strong>end</strong> of the files to check. For examples of patterns, see option <strong>--exclude</strong>
- in the <em><a href="#commandReference">Command Reference</a></em> section below.
- </div>
- <div>Once you have perfectly tuned the parameters in your 2 scripts, you may consider <strong>scheduling</strong> their
- execution, for example on a daily basis, using Control Panel/Scheduled Tasks on Windows, cron on Unix, etc...<br />
- Synchronizing and reverse synchronizing is like having two different p4 clients accessing and modifying the
- same files. If a file can be modified <strong>directly</strong> on the live site, then a situation of
- <strong>conflict</strong> (e.g. simultaneous edits of the same file) is possible, and must be <em>resolved</em>.
- By scheduling the <strong>reverse</strong> sync <strong>first</strong>, then the "normal" sync, rather
- than the contrary, one guarantees that any conflict will be detected by Perforce and scheduled for resolve.
- This is not true if the scripts are scheduled the other way (normal, then reverse): in this case any change
- on the live site will be silently overwritten by a change (done elsewhere) already submitted in P4.
- </div>
- <div>The strategy above is somewhat "blind" in that it synchronizes the live site at fixed intervals without any
- consideration for actual changes made. You don't always want to propagate changes submitted in P4 to
- the live site ASAP. Maybe you want to accumulate changes somewhere and once you are ready, transfer
- them to the live site. A possible strategy to achieve this is to create a <strong>branch for the sync</strong>:
- you make the changes into the main/development branch, and when you feel ready you <em>integrate</em>
- them into the sync branch, which of course will be the one specified for the <em>whatToSync</em> parameter
- to <code>p4ftpsync</code>.
- </div>
-
- <!-- COMMAND REFERENCE -->
- <a name="commandReference" id="commandReference"></a>
- <h2>Command Reference</h2>
- <div style="font-size:smaller">(this is basically a formatted copy of the ouput of <code>p4ftpsync --help</code>)</div>
-
- <pre>[python] p4ftpsync[.py] [options] <em>whatToSync</em></pre>
- <div> <em>whatToSync</em> specifies what to sync, and must be a valid P4 file spec such as the ones used in the
- <code>P4 sync</code> command (e.g. <code>//depot/MyProject/MyDir/...</code>,
- <code>//depot/Proj2/main.c#2</code>, <code>@label</code>, etc...). For the <em>reverse</em> sync, the revision
- range info is N.S., since the comparison is always done with the HEAD revision.</div>
-
- <a name="reverseSync" id="reverseSync"></a><h4>Reverse sync</h4>
- <div><code>p4ftpsync</code> may also be run in <em>reverse sync mode</em> (option -r). In this mode, the files
- on the remote site are compared with the latest revision files in P4 and any change on the remote site is reported
- into a new P4 <em>changelist</em> (optionally submitted at the end of the process). This mode is handy if some changes are
- done directly on the remote site and you want to easily keep your P4 repository up to date. <em>Symbolic links</em>
- are supported on the remote site but <strong>mapped to real files</strong> locally/in P4 named like the link.</div>
-
- <a name="validOptions" id="validOptions"></a><h4>Valid options</h4>
-
- <div class="optionCategory">Perforce options</div>
-
- <div class="option">--p4Port <span style="font-weight:normal"><em>host</em>[:<em>port</em>]</span></div>
- <div class="optionDesc">P4 host:port to use, default port 1666 [default: current config, see
- <a href="#defaultValues" target="_self">Default values</a>]</div>
-
- <div class="option">--p4User <span style="font-weight:normal"><em>userName</em></span></div>
- <div class="optionDesc">P4 user name to use [default: see <a href="#defaultValues" target="_self">Default values</a>].</div>
-
- <div class="option">--p4Passwd <span style="font-weight:normal"><em>password</em></span></div>
- <div class="optionDesc">P4 user password [default: see <a href="#defaultValues" target="_self">Default values</a>].</div>
-
- <div class="option">--p4Client <span style="font-weight:normal"><em>client</em></span></div>
- <div class="optionDesc">P4 client to use as the mirror of the remote site [default: see
- <a href="#defaultValues" target="_self">Default values</a>]. </div>
-
- <div class="optionCategory">FTP options (for the remote site)</div>
-
- <div class="option">--ftpHost <span style="font-weight:normal"><em>host</em>[:<em>port</em>]</span></div>
- <div class="optionDesc">FTP host IP address, default port 21 [mandatory]</div>
-
- <div class="option">--ftpUser <span style="font-weight:normal"><em>userName</em></span></div>
- <div class="optionDesc">FTP user name [mandatory]</div>
-
- <div class="option">--ftpPasswd <span style="font-weight:normal"><em>password</em></span></div>
- <div class="optionDesc">FTP user password [default: will be prompted]</div>
-
- <div class="option">--ftpRoot <span style="font-weight:normal"><em>rootRelativePath</em></span></div>
- <div class="optionDesc">Path of the root folder of the site [mandatory]</div>
-
- <div class="optionCategory">Normal sync (p4 to remote site) options</div>
- <div class="option">-o, --scriptDir <span style="font-weight:normal"><em>localPath</em></span></div>
- <div class="optionDesc">Directory in which to generate the Python update script in normal sync
- [default: <code><em>thisProgDir</em>/p4FtpSyncScripts</code>]</div>
-
- <div class="optionCategory">Reverse sync (remote site to P4) options</div>
-
- <div class="option">-r, --reverse</div>
- <div class="optionDesc">Reverse synchronization: Changes occurred on the remote site are detected, and
- a P4 changelist is created but not submitted, unless option -s is specified.</div>
-
- <div class="option">-s, --submit</div>
- <div class="optionDesc">Submit the P4 changelist created for the changes detected. The default is to <strong>not</strong>
- submit, so the changes can be reviewed before (manual) submit.</div>
-
- <div class="option">-c, --comment <span style="font-weight:normal"><em>"COMMENT"</em></span></div>
- <div class="optionDesc">Optional description for the changelist. A default will be generated if none is specified.</div>
-
- <div class="option">-m, --mailto <span style="font-weight:normal"><em>addr1,addr2,...</em></span></div>
- <div class="optionDesc">A list of email addresses to send a "file change report" to [default: don't send an email].
- For now the mail server settings are globals in <code>p4ftpsync.py</code> !</div>
-
- <div class="option">--smtpServer <span style="font-weight:normal"><em>host</em>[:<em>port</em>]</span></div>
- <div class="optionDesc">SMTP server IP address to use for sending the above mail [default localhost:25]</div>
-
- <div class="option">--smtpUser <span style="font-weight:normal"><em>userName</em></span></div>
- <div class="optionDesc">SMTP user name if authentication is required [default: None]</div>
-
- <div class="option">--smtpPasswd <span style="font-weight:normal"><em>password</em></span></div>
- <div class="optionDesc">SMTP user password [default: None]</div>
-
- <div class="option">--fromAddr <span style="font-weight:normal"><em>addr</em></span></div>
- <div class="optionDesc">Email address to put in the 'From' field of the report emails [default: p4ftpsync@p4ftpsync.net -dummy!]</div>
-
- <div class="optionCategory">Common sync. options</div>
-
- <div class="option">-f, --force</div>
- <div class="optionDesc">For <em>normal</em> sync: If specified, the target will be resynced even if supposedly up
- to date (same as P4 sync option -f).<br />
- For <em>reverse</em> sync: If specified, the file description <a href="#cache" title="File description Cache">cache</a>
- will <strong>not</strong> be used and the file download & comparison will <strong>always</strong> be done.</div>
-
- <div class="option">-t, --test</div>
- <div class="optionDesc">Test/preview mode: For <em>normal</em> sync: do not really P4 sync the mirror client workspace,
- generate the script but do not actually FTP.<br />
- For <em>reverse</em> sync: do not create P4 changelist or copy files to client space.</div>
-
- <div class="option">-x, --exclude <span style="font-weight:normal"><em>FILE1,FILE2,... | <strong>@</strong>FILE</em></span></div>
- <div class="optionDesc">Exclude files from the list of updates to do (handy if some files must remain different locally
- from remotely, e.g. config files, system files). FILEs are specified as a comma separated list (no spaces) of
- <em>patterns</em>, or alternatively listed in a file (@FILE), one per line. <em>Patterns</em> are Python compatible
- <em>regular expressions</em>. They are implicitely completed with a <code>^.*</code> on the left and a <code>$</code>
- on the end (unless they already include them), meaning that if the <strong>end</strong> of the path of a file to sync
- matches one of the patterns, then it will be excluded from the sync. The <code>(?i)</code> flag (IGNORECASE) can be added
- to a pattern to make the match case-independent.<br /><br />
- <strong>Examples of patterns</strong><br />
- <code>.htaccess</code> (exclude the .htaccess file wherever it appears)<br />
- <code>/A/B/f.txt</code> (exclude file f.txt located in folder /A/B/)<br />
- <code>/log/.*</code> (exclude all files in directory log/)<br />
- <code>/~.*</code> (exclude all files whose name starts with ~)<br />
- <code>.pdf</code> (exclude all pdf files)<br />
- <code>.pdf<strong>(?i)</strong></code> (ditto, but (?i) specifies to <strong>ignore case</strong>,
- so .PDF matches too)<br /><br />
- </div>
-
- <div class="optionCategory">Misc options</div>
-
- <div class="option">-v, --verbose</div>
- <div class="optionDesc">Verbose: More trace/error messages on stdout.</div>
-
- <div class="option">-V, --version</div>
- <div class="optionDesc">Print p4ftpsync version on stdout and exit.</div>
-
- <div class="option">-h, --help</div>
- <div class="optionDesc">Print help message on stdout and exit.</div>
-
- <a name="defaultValues" id="defaultValues"></a><h4>Default values</h4>
- <div>p4ftpsync stores (in file <code>p4ftpsync.opt</code>) the last values used for options p4Client,
- ftpHost, ftpUser and ftpRoot and uses them if no value is provided on the command line.
- Options are stored twice: as associated to the specific target sync spec, and as generic
- "last session defaults" (ftpRoot is not stored in the latter case).<br />
- When trying to reload the values for a new session, p4ftpsync first attempts to reload the
- target specific values, then the non specific ones.</div>
-
- <a name="cache" id="cache"></a><h4>File description cache (reverse sync only)</h4>
- <div> Remote file descriptions are saved on disk after a successful synchronization and used on
- subsequent syncs to determine if a file has changed (different file descs), without having to
- download the file, which can save a tremendous amount of time. There is a different cache for every
- ftp host+user (file <code><em>user</em>@<em>ftpHost</em>.fdc</code>)<br />
-
- On the <strong>first</strong> run of <code>p4ftpsync</code> for a given site, <strong>all</strong>
- files from the remote site will be downloaded and compared to the files in the depot, quite a lengthy
- and bandwith consuming operation ! However next iterations should use the cache and be considerably
- faster (the only relatively long operation that can't be shortened is the determination of the current
- file structure on the remote site). When the cache is missing or corrupted, the download of the entire
- site (minus the exclusions) occurs again.<br />
-
- The cache can be <strong>disabled</strong> with option -f, --force (it is then not used for the current
- iteration but will still be saved for future use).
- </div>
-
- <a name="generatedScript" id="generatedScript"></a><h4>Generated FTP Script</h4>
- <div>In normal sync, a <strong>Python script</strong> is created in the directory indicated by option -o
- for the specified target (<em>whatToSync</em>). The script is named <em>what</em>_<em>date</em>.py
- (with / and spaces replaced by _). It contains the set of FTP actions required to synchronize
- the remote client (site) as requested, therefore its execution will perform the actual update,
- which can prove very useful, should the FTP session fail before completion: executing the script will
- <em>ftp</em> the changes again.
- </div>
-
- <a name="log" id="log"></a><h4>Log</h4>
- <div> A file <code>p4ftpsync.log</code> is generated in <code>p4ftpsync</code>'s folder (always
- <em>verbose</em>, unlike the on-screen trace which depends on option -v). Logs are rotated to
- <code>p4ftpsync.log.<em>n</em>.zip</code> when they exceed a certain size (4MB by default).
- </div>
-
- <!-- LIMITATIONS -->
- <a name="limitations" id="limitations"></a><h2>Limitations, Bugs, ToDo</h2>
- <div>The most obvious limitations and todos I can think of right now are:
- <ul>
- <li>A limited support for <em>symbolic links</em>. Currently links are recognized on the remote site
- but translated into normal files in P4 during reverse sync. That is, we tolerate that links
- exist on the remote site but not locally and in P4. Since P4 supports symbolic links, it
- could potentially be changed, though. (<em>Due to the comparison strategy used during reverse
- sync, I'm not sure that the case where 2 links withing the site point to the same file is
- correctly handled: it will create as many real files in p4</em>). </li>
- <li>An uncertain support of <strong>older versions of the P4 server</strong> (<2005.1). This program probably works
- with not-too-old versions of the server, but I wouldn't bet on it.</li>
- <li>Support of <strong>all ftp servers</strong> is not guaranteed either. I tried on at least
- 3 different servers, but they are sometimes surprising in their use of error codes. </li>
- <li>... and probably many other ones I don't think of ...</li>
- </ul>
- </div>
-
- <div>Please report bugs or suggestions to <a href="javascript:location='mailto:\u0070\u0034\u0066\u0074\u0070\u0073\u0079\u006e\u0063\u0040\u0072\u0067\u0072\u0075\u0065\u0074\u002e\u006e\u0065\u0074';void 0">Richard Gruet</a>. I'd be happy to hear from you. I'll try to fix bugs
- and implement suggestions if I think they can improve p4ftpsync (and are not to complex !). Don't hold your breath, though.
- I'm quite busy.
- </div>
-
- <!-- LICENSE -->
- <a name="license" id="license"></a><h2>License</h2>
- <div>Copyright © 2004-2005 <a href="javascript:location='mailto:\u0070\u0034\u0066\u0074\u0070\u0073\u0079\u006e\u0063\u0040\u0072\u0067\u0072\u0075\u0065\u0074\u002e\u006e\u0065\u0074';void 0">Richard Gruet</a></div>
- <div>Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee or royalty is hereby
- granted, provided that the above copyright notice appear in all copies
- and that both that copyright notice and this permission notice appear
- in supporting documentation or portions thereof, including modifications,
- that you make.</div>
-
- <div>THE AUTHOR RICHARD GRUET DISCLAIMS ALL WARRANTIES WITH REGARD TO
- THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
- INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
- FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !</div>
-
- <div>In short: I publish this program in hope it can be useful to others. Use it as you wish but keep the copyright
- intact, and don't hold me responsible for any problem you run into ;)</div>
-
- </body>
- </html>