<!-- This is the MacCVS's Guide, originally written
by Alexandre Parenteau (aubonbeurre@hotmail.com).
-->

<!doctype linuxdoc system>
     
<article>
<title>CvsGui : MacCVS and WinCvs
<author>Alexandre Parenteau, <htmlurl url="mailto:aubonbeurre@hotmail.com" name="aubonbeurre@hotmail.com">
<date>v1.0 30 October 1997 - A contribution of Strata Inc. 1997
<abstract>
This document describes both the MacCvs and WinCvs client. More informations can be found on the <htmlurl url="http://www.wincvs.org" name="MacCVS home page"> and at the <htmlurl url="http://www.cyclic.com/" name="Cyclic Software"> home page.
</abstract>

<toc>

<sect>About CVS

<sect1>Where to find CVS ?
<p>

The official web site for CVS is <htmlurl url="http://www.cyclic.com" name="www.cyclic.com">.

Cyclic Software provides source code, informations and support for CVS.

Before reading this document, you should be familiar with CVS.

<sect1>What is CvsGui ?
<p>

<bf/CvsGui/ is a set of little applications with a <bf/user interface/ for several platforms
(right now only Mac and Windows 32). It is developped and used mostly in
<htmlurl url="http://www.strata3d.com" name="Strata Inc."> by several developers.

The user interface is <bf/not
designed to replace/ the command lines of cvs, but is provided in order to help people
to <bf/get started with cvs/ and to take <bf/advantages/ of platforms capabilities
(move to trash, multi-files picker, improved interface...).

While developping GuiCvs, we concentrate on <bf/speed and reliability/.

<sect1>Why Cvs and CvsGui ?
<p>

The main reason is because we had a very bad time by using a commercial product named
...$ :-\<.

The second reason is <bf/due to cvs itself/ : cvs is incredibly powerfull,
fast, well documented and has a great support with
<htmlurl url="http://www.cyclic.com" name="Cyclic Software">.

MacCvs was the first version of CvsGui : we finished the port of cvs on
Macintosh by <bf/fixing bugs/ and <bf/adding features/.

Then we did the WinCvs port so the Windows developper can have the same
features than the Mac developpers.

Finnally why not in the future a kdecvs, qtcvs, wtcvs, gtkcvs ? You will
find a <ref id="hacking" name="hacking"> section explaining the common architecture of CvsGui and
why it's so easy to make new ports by using the CvsGui architecture.

<sect1>Which are the features inside cvs that are not available in CvsGui ?
<p>

None. That's because CvsGui uses the cvs code and inherits of all
the features of cvs.

<sect1>Which are the features inside CvsGui that are not available in cvs ?
<p>

CvsGui is designed to add on the top of cvs some cool stuff that people
wants. You'll find an ISO8559 encoding support, MacBinary support,
extras features and more. But we still try to keep the cvs feeling.

<sect1>What is the relationship with the "official" maintainers of cvs ?
<p>

We try to keep in touch with them and look for the next version they'll
provide. We think we'll be able before the announcement of the next version
of cvs to provide some patches useful for all the platforms.

<sect1>What are the differences with jcvs, MacCvsClient, MacCvsPro ?
<p>

<bf/jcvs/ is a cvs client implemented in Java which has his own format. jcvs is not
compatible with MacCVS.

<bf/MacCvsClient/ and <bf/MacCvsPro/ are two cvs client implemented in C++ using PowerPlant
with a very nice user interface. Like jcvs,
MacCvsClient and MacCvsPro have their own format and are not compatibles with MacCvs.

MacCvs uses directly the cvs code (C code) : so it inherits all the capabilities
of cvs. jcvs, MacCvsClient and MacCvsPro use a private code so you can't expect some features
to be implemented in thses clients, unless the author implements it
(the Mac resources support, the patch support, the compression support, the
kerberos support and so on). But you may find in MacCVS some ideas stolen
from all of these excellents programs.

<sect1>What about Rhapsody ?
<p>

Hey, good news : Apple works on a version of cvs for Rhapsody. Should be nice
to have a MacCVS for it, isn't it ;-> ?

Note: We are using currently MacCVS on Rhapsody without any kind of problem using
the Blue Box.

<sect>The MacCVS Client

<sect1>Introduction
<p>

The first port on Macintosh was made by <htmlurl url="mike@twinpeaks.prc.com" 
name="Mike Ladwig"> using CodeWarrior 9, GUSI 1.7.2 and cvs 1.84. It allowed
to use MacCVS as a <bf/console/ program or as a <bf/MacPerl/ command.

A second port was made by <htmlurl url="neeri@iis.ee.ethz.ch" 
name="Matthias Neeracher">. He implemented cvs as a <bf/MPW tool/ and used
the cvs 1.9 distribution, dmake and CodeWarrior 9. This version works nicely but was never
included into the official release of cvs.

Both use the excellent Matthias Neeracher's <htmlurl url="http://www.iis.ee.ethz.ch/~neeri/" name="GUSI Library">
(for Grand Unified Sockets Library) which allows to port easily Unix code on Macintosh.

Despite of this ports, the cvs implementation for Macintosh is still
experimental and only the <bf/client/ side is available.

This current port uses <bf/CodeWarrior Pro 3/, the <bf/MSL/ library, <bf/cvs 1.10/,
<bf/GUSI 1.8.4/, <bf/Waste 1.3/, <bf/TCL 8.1/
and optionnaly the <htmlurl url="ftp://ftp.cit.cornell.edu/pub/mac/kerberos/" name="KClient library">
(Kerberos authentication, a contribution of <htmlurl url="mailto:meeroh@MIT.EDU" name="Miro Jurisic">)

<sect1>What is inside
<p>

This is my second tentative to port CVS for Macintosh.

The first time I used the port of Mike Ladwig and added a little UI
to remember the CVSROOT and provide menu access.

Now using the Matthias Neeracher port, I've added again a little UI and
also enhanced or added some capabilities to the MacCVS client to :

<itemize>
<item>deal with Macintosh files with a <bf/resource fork/ (using a HQX encoding or
a MacBinary encoding).
<item>be <bf/scriptable/ by Apple Events.
<item>allow to <bf/import/ initial modules directly from the macintosh (see the problems
relative to the <ref id="import" name="import"> command).
<item><bf/control/ when adding files : that's because many user make mistakes
when adding files and forget to add "as binary" when the file is binary.
<item>use <bf/Internet Config/ to restore Mac signatures.
<item>provide a work around for files which <bf/auto-modify/ each time you open it (such as
CW Pro 2 projects) : this behaviour is not compatible with CVS which checks for the
modification date on your disk. We refer to this kind of files as <ref id="dirtyfiles" name="dirty files">
<item>rewrite the architecture of MacCVS so it uses cvs as a <bf/shared library/ (this
has several advantages I discuss in <ref id="hacking" name="Hacking CVS">).
</itemize>

For more informations, look at the <ref id="hacking" name="Hacking CVS"> section.

<sect1>Binary and Text files<label id="textandbinary">
<p>

For the macintosh cvs client :

<itemize>
<item>a <bf/plain binary/ file is a file with a signature different of "TEXT" (for example
a Word document .doc) and no resource fork.
<item>a <bf/mac binary file/ is a file with a signature different of "TEXT"
and a resource fork (for example a ResEdit file and most of the mac files).
<item>a <bf/text file/ is a file with a signature of "TEXT".
</itemize>

MacCVS now supply some <bf/controls when adding files/ : that's because many user make mistakes
when adding files and forget to add "as binary" when the file is binary. It will warn
you if you are about to make a mistake.

<bf/Important/ : You can force a binary file to be handled as <bf/plain binary/ when you
add or import files : that's because
sometimes you can accidentaly have a resource fork (like a <em/CKID/ resource) onto
a plain binary file (for example on a CW project, a GIF file...). If you want to add files types
to be handled as plain binary, go to the preferences and add a new type.

<bf/Note/ : The resource fork on a text file is <bf/ignored/. If you want to keep the resource
fork of a text file, force to add the file as binary : but you won't be able to use this file on others platforms.

<sect1>The "import" problem<label id="import">
<p>

The import command in cvs should be seen as inconsistent since it imports initially
all the files as text files (so it makes a line feed conversion between the client
and the server).

When the initial import is done and all the binary files have the binary attribute,
the server and the client agree to not convert this files and everything is working finely.

So the problem appears ONLY during the first import, and cvs user know that the
initial import is THE main difficulty with cvs.

Happy-fully, there are some turn-around :

<itemize>
<item>Make the initial import directly from the cvs server machine
(for now on Unix or Windows platforms). But be careful with the line feeds
automatic translation when you copy files from and to !
<item>Use the cvs <bf/wrappers/ file to mark extensions as binary. But you'll still not be
able to import from the client since all the files are initially transfered as text
to the server.
<item>Use the <bf/-W/ option of cvs import : the problem is that you have to figure
yourself all the extensions to map to a binary format (the -W option works this way :
you can tell cvs that an extension, .gif for example, represents a set of binary file).
My experience shows you can make a lot of errors this way.
</itemize>

That's why the MacCVS port was implemented for :

<itemize>
<item>Using the <bf/import/ command of the MacCVS client, you'll be able to have a
dialog which tells you the current binary mapping and let you modify it. It detects
also a lot of common errors and sometimes warn you about something you may care about.
<item>When you hit continue, MacCVS will prepare automatically the line command
to cvs with the <bf/binary wrappers/ you want to use.
<item>Finally you can import safely. Both the client and the server will know exactly
which files are binary and which one are text.
</itemize>

<bf/Very important note/ : You still have to set the binary preferences in order to force MacCVS
to send the files as plain-binary to the server.

<bf/Very important note 2/ : When you use plain binary files, be sure to have Internet Config
well-configured for these files : if not, you may loose your plain binary representation and won't
be able to open these files on others platforms (since they would be mac-encoded).

<sect1>Getting started
<p>

<itemize>
<item>Be sure to be familiar with the <ref id="import" name="import"> problem.
<item>While you use CVS, make sure your Internet Config is always up-to-date
when using plain-binary files or if you set the Internet Config option for text.
<item>Set in the preferences the <bf/CVSROOT/ and the kind of <bf/authentication/.
<item>If you create a <bf/new module/ using the import command, use first
carefully the report and fix all the errors or conflicts.
<item>Use the <bf/online-help/ available on most of the menu entries or dialogs by activating
"Show ballons" in the help menu (unavailable on MacCVS 3.1).
</itemize>

<sect1>Hacking MacCvs<label id="hacking">
<p>

The MacCvs port consists in :

<itemize>
<item>A shared library with a MixedMode interface which contains the cvs code
and mimic the cvs command line. This architecture allows to re-initialize the
globals of cvs as well to separate really the implementation of the client and cvs.
<item>An application which implements a UI, Apple Events, a console and call
the shared library to make the stuff.
</itemize>

What I've done after is to change a little bit client.c to oblige the client
to convert the file whenever it sends it to the server. This allows to encode/decode
the files in HQX format and also the disable/enable the line feed conversion when the
file is flat (no resource fork) and is not a text file.

<sect>The WinCVS Client and Local

<sect1>Introduction
<p>

The first port on cvs on Windows was done by Cyclic Software and is excellent. Why ?
Because they ported also the <bf/server and local capability/ and made a great work to deal
with the <bf/non-case sensitive/ Windows file system.

Except some hacks inside the cvs code to take advantages of the cvs features,
WinCvs does not change the cvs source code : all it does it is to compile
cvs as a <bf/dll/ (Dynamic Linked Library).

<sect1>What is inside
<p>

You will find inside WinCvs a set of commands (all have a on-line help entry)
that you can use to manage source repositories.

WinCvs looks like that :

<itemize>
<item>An <bf/ouput console/ : you see all the messages of WinCvs, cvs client
and cvs server so you can control that everything is going fine.
<item>A <bf/preferences dialog/ : the CVSROOT, authentication...
<item>A set of <bf/common menu commands/ (Copy, Save, Paste...).
<item>A set of <bf/cvs menu commands/.
<item>A <bf/line commands/ dialog provided when the menu command is not available.
</itemize>

<sect1>Binary and Text files
<p>

You have to be very carefull about the usage of <bf/binary/ files : read the
cvs documentation carefully.

WinCvs provides two ways to <bf/add files/ to a repository :

<itemize>
<item>Add files...
<item>Add binary files...
</itemize>

WinCVS now supply some <bf/controls when adding files/ : that's because many user make mistakes
when adding files and forget to add "as binary" when the file is binary. It will warn
you if you are about to make a mistake.

<sect1>The "import" problem<label id="winimport">
<p>

The import command in cvs should be seen as inconsistent since it imports initially
all the files as text files (so it makes a line feed conversion between the client
and the server).

When the initial import is done and all the binary files have the binary attribute,
the server and the client agree to not convert this files and everything is working finely.

So the problem appears ONLY during the first import, and cvs user know that the
initial import is THE main difficulty with cvs.

Happy-fully, there are some turn-around :

<itemize>
<item>Make the initial import directly from the cvs server machine
(for now on Unix or Windows platforms). But be careful with the line feeds
automatic translation when you copy files from and to !
<item>Use the cvs <bf/wrappers/ file to mark extensions as binary. But you'll still not be
able to import from the client since all the files are initially transfered as text
to the server.
<item>Use the <bf/-W/ option of cvs import : the problem is that you have to figure
yourself all the extensions to map to a binary format (the -W option works this way :
you can tell cvs that an extension, .gif for example, represents a set of binary files).
My experience shows you can make a lot of errors this way.
</itemize>

That's why the WinCVS port was implemented for :

<itemize>
<item>Using the <bf/import/ command of the WinCVS client, you'll be able to have a
dialog which tells you the current binary mapping and let you modify it. It detects
also a lot of common errors and sometimes warn you about something you may care about.
<item>When you hit continue, WinCVS will prepare automatically the line command
to cvs with the <bf/binary wrappers/ you want to use.
<item>Finally you can import safely. Both the client and the server will know exactly
which files are binary and which one are text.
</itemize>

<sect1>Getting started
<p>

<itemize>
<item>Be sure to be familiar with the <ref id="winimport" name="import"> problem.
<item>Set in the preferences the <bf/CVSROOT/ and the kind of <bf/authentication/.
<item>Use the <bf/online-help/ available on most of the menu entries or dialogs by
clicking on the arrow located on the right of the toolbar which enables
a sensitive help.
</itemize>

<sect1>Hacking WinCvs<label id="winhacking">
<p>

The WinCvs port consists in :

<itemize>
<item>A dll which contains the cvs code
and mimic the cvs command line. This architecture allows to re-initialize the
globals of cvs as well to separate really the implementation of the client and cvs.
<item>A MFC application which implements a UI, a console and call
the dll to make the stuff.
</itemize>

<sect>Summary of CvsGui commands
<p>

<sect1><bf/Cvs Main/ menu
<p>

Main cvs commands : Most of the time you will use only the update and commit commands.

<label id="HID_APP_UPDATE">
<sect2>Update folder...
<p>

Merge recursively on your disk your changes with the cvs repository. Use "Commit folder..."
to commit your changes INTO the cvs repository.

<label id="HIDD_COMMIT_MAIN">
<label id="HID_APP_COMMIT">
<sect2>Commit folder...
<p>

Commit your changes INTO the cvs repository. You may use "Update folder..." first to merge
locally on your disk your changes with the cvs repository.

The <bf/no recursive/ option let you commit a folder without the sub-folders.

<label id="HID_APP_PREFERENCES">
<sect2>Preferences...
<p>

Use this option to change settings like the CVSROOT, the read-only option,
the TCP/IP compression and many other things...

<label id="HIDD_CMDLINE_MAIN">
<label id="HID_APP_CMDLINE">
<sect2>Command line...
<p>

Allows to enter a cvs command line (like "cvs rtags -b -r arev arevbranch") when
ever the cvs command is not available thru the menus.

Note that you don't have necessary to specify a local directory. That's because
some commands (like rtags) execute only on the server. For the most of the
others commands, you need to specify <bf/where/ the command is executed.

<label id="HIDD_CHECKOUT_MAIN">
<label id="HID_APP_CHECKOUT">
<sect2>Checkout module...
<p>

Use this option to checkout from scratch a new module on your disk. You need
to give the complete path of the module on the server : for example :
"myprog/mysubfolder1/mysubfolder2"

The <bf/no recursive/ option let you commit a folder without the sub-folders.

<label id="HIDD_IMPORT_MAIN">
<label id="HIDD_IMPORT_TAGS">
<label id="HID_APP_IMPORT">
<sect2>Import module...
<p>

Use this option to create a new module into the cvs repository located on the
cvs server machine. After importing, you should use the "Checkout module..."
command to start using this new module.

You need to give the complete path of the module on the server : for example :
"myprog/mysubfolder1/finalPlaceForTheModule"

Refer to the explanation of the import problem (<ref id="import" name="Mac import"> or
<ref id="winimport" name="Windows import">).

The <bf/vendor/ and <bf/release/ tags are usefull whenever you'll want to get
back to the initial version or create a branch. Refer to the cvs documentation
for more details.

<label id="HID_APP_LOGIN">
<sect2>Login...
<p>

Use this option when you want to login for the first time to a cvs server machine.
You should need to login ONLY if the kind of authentication in the preferences
is "pserver" (password authenticate).

<sect1><bf/Cvs Files/ menu
<p>

Menu with cvs commands which apply on files.

<label id="HID_APP_UPDATEF">
<sect2>Update files...
<p>

Merge locally on your disk your changes and the changes of the cvs repository so
you can use the "Commit files..." command to commit your change on the cvs server
repository.

<label id="HID_APP_COMMITF">
<sect2>Commit files...
<p>

Commit your changes into the cvs server repository. You may need first to
"Update files..." in order to merge your changes with the cvs server before
you can commit them.

<label id="HID_APP_DIFF">
<sect2>Diff files...
<p>

Show the difference between your files and the files located on the cvs
server repository : this way you can check the changes with the remote server.

<label id="HID_APP_LOG">
<sect2>Log files...
<p>

Ask the server to tell the history of the files (comments, revision number,
tags and so on...)

<label id="HID_APP_ADDF">
<sect2>Add files...
<p>

Mark the files to be added to the master repository located on the server.
These files will be really added AFTER you did commit them. In order to
add files enclosed into a new folder, use the "Add folder..." option first
on the folder.

<label id="HID_APP_ADDB"> (Windows only)
<sect2>Add binary files...
<p>

Same as the previous but add binary files.

<label id="HID_APP_REMOVEF">
<sect2>Remove files...
<p>

Mark the files to be removed from the master repository located on the
server. These files will be really removed AFTER you did commit the folder
where these files were located.

<label id="HID_APP_STATUS">
<sect2>Status files...
<p>

Ask the cvs server to tell the status of the files (changed locally,
unchanged, current status, locks, and so on...).

<label id="HID_APP_CANCELC">
<sect2>Cancel changes...
<p>

It is not a real cvs command but it's provided for convenience.
This option will send to trash the files in the trash (you can
on Macintosh use the "Put Away" option of the Finder to recover them) then
will ask the cvs server to update these files.

<sect1><bf/Cvs Folder/ menu
<p>

The cvs commands which apply on a folder.

<label id="HID_APP_ADD">
<sect2>Add a folder...
<p>

Whenever you add files to the repository, you need first to add the folders.

<label id="HID_APP_DIFFF">
<sect2>Diff a folder...
<p>

Print the differences recursively with the cvs remote repository for all the
files enclosed in the folder.

<label id="HIDD_PREFS_CVSROOT">
<label id="HIDD_PREFS_GLOBALS">
<label id="HIDD_PREFS_PORTS">
<sect1><bf/Preferences/ dialog
<p>

The cvs commands which apply on a folder.

<label id="HIDC_CVSROOT">
<sect2>The CVSROOT field
<p>

It should be something like alexp@cvs.strata3d.com:/cvsroot.
Never enter the ":pserver:" or ":kserver:" directly, use the
radio buttons instead.

<label id="HIDC_CHECKOUTRO">
<sect2>Checkout read-only
<p>

Turn-on if you want the files created by MacCVS to appear
locked in the finder.

<label id="HIDC_PRUNE">
<sect2>Prune empty directories
<p>

If On, this option will automatically remove empty folders
when you update a module.

<label id="HIDC_TCPIP">
<sect2>TCP/IP compression
<p>

When this option is on, the server and MacCVS compress informations
so they use less bandwidth : use only if you have a slow (modem)
connection with the server because it causes the server to work
much more.

<label id="HIDC_QUIET">
<sect2>Quiet mode
<p>

If on, cause the command to be somewhat quiet; informational messages,
such as reports of recursion through subdirectories, are
suppressed.

<label id="HIDC_CTNLADD">
<sect2>Control when adding files
<p>

Most of the errors using cvs are related to binary files. Since the client and the server usually <bf/convert/ the line feeds, it's important when you add a file to specify if you add a binary file <bf/or/ a text file. This option will help you to not make errors by parsing the file you add and check if it's a binary file, if the file has the good line feed for the machine and so on...

<label id="HIDC_RHOSTS">
<sect2>".rhosts" authentication
<p>

If On, the cvs server will authenticate MacCVS regarding the IP number
of the machine running MacCVS : you should have a proper ".rhosts" file
on the server account with an access 0600 which contains something like
"192.10.10.37 alexp" or "alexpmac.strata3d.com alexp".

<label id="HIDC_PSERVER">
<sect2>":pserver:" authentication
<p>

If On, the cvs server will authenticate MacCVS regarding a password
located in the cvs administration file "passwd" on the server :
you should have a proper entry for you in this file, something like 
"alexp:X5gFtdhaDke93j".

<label id="HIDC_KSERVER">
<sect2>":kserver:" authentication
<p>

If On, the cvs server will authenticate MacCVS regarding a Kerberos
authentication session. Refer to your adminstrator to know how to use
Kerberos.

<sect2>Modify the server ports & name
<p>

Regarding the authentication you use (pserver, kserver...) you can change
the default TCP <bf/ports and name/ cvs uses to reach the server. Refer to the cvs
documentation for more details.

<sect2>ISO8559 translation on text files (Mac only)
<p>

If on, MacCvs will translate (only on text files) the mac characters encoding
into a standard ISO8559_xxx encoding when it sends the file <bf/to/ the server. It
will obviously translate back ISO8559_xxx characters encoding into the Mac encoding
when getting a file <bf/from/ the server. This option is usefull if you use
accentuations in text files because the accents will remain readable on
others systems (Windows, Unix). Only ISO8559_1 Latin 1 (Western Europe) is
implemented right now. Thanks to Jim Matthews to provide the ISO8559_1 table
in the <bf/Fetch/ program.

<sect2>Use Internet Config for text files (Mac only)
<p>

MacCvs usually asks <bf/Internet Config/, whenever it creates a <bf/binary/ file,
the default <bf/type and creator/ signature for the file. So by using
Internet Config, you can tell MacCvs that, for example, all the files
ending by the extension .mcp have the file type/creator set to MMPr/CWIE.
By using this option, you can extend this behaviour to the <bf/text/ files so you
can for example map a type/creator for the .c, .h, .html...

<label id="dirtyfiles">
<sect>Note on dirty files
<p>

<sect1>A little bit of history first 
<p>

We started using cvs in our company when
we turned to Code Warrior Pro 2. We realized Code Warrior had a very annoying
bug and we were unable to find a work around with Source Safe. When you
lock the projects, and if you have a very deep and complex set of projects,
the projects behave badly and recompile each time, plus, they take a long-long
time to open...

So we thought : "OK, let's unlock them". Then the horror : the project
were auto-modifying themselves when unlocked. The problem appeared
when everybody tried to check-in the first time : all the projects
were modified each time, resulting in corrupting and
increasing fastly the size of the repository.

<sect1>Advantage of "Open Code Software"
<p>

Then I suggested we tried cvs so we could hack cvs by making it behave
the way we expect.

We came up with this solution :

<itemize>

<item>1. The file with the extension <bf/.mcp/ will be a dirty file.

<item>2. The file will be ignored by cvs, like .cvsignore does, <bf/unless/
the user asks to <bf/explicitely/ to something with this file :
the method to tell cvs to commit a dirty file is to ask to commit
<bf/this/ files and <bf/only/ this file (a recursive commit
will ignore the dirty file).

<item>3. The only way to add, remove, commit, merge a dirty file is
to explicitly invoke cvs with this operation and with only this file.

</itemize>

No need to tell you we'll be happy when finally Metrowerks will have
fixed this bug :<...

<label id="goodies">
<sect>Goodies with MacCvs/WinCvs
<p>

<sect1>CWCVS : a cvs plug-in for Metrowerks (Mac only)
<p>

We use it all the time and it's nice !

Since Richard Wesley, the author, is American, you'd better go directly to 
<htmlurl url="http://www.electricfish.com/hawkfish/CWCVS/CWCVS.html"
name="http://www.electricfish.com/hawkfish/CWCVS/CWCVS.html"> for
a good explanation in plain English...

Only the Mac side is provided right now and it is a shareware.

<sect1>MPW tools (Mac only)
<p>

<sect2>Description
<p>

Right now, two MPW tools are provided with MacCVS with complete
source code :

<itemize>

<item><bf/cvs/ : the same exact code which uses MacCvs.

<item><bf/cvslog/ : invokes "cvs log" but filters the ouput
for a more convenient use. Basically it allows to retrieve
a set of files by date/user/branch/revision/tags.

</itemize>

<sect2>Getting started with MPW cvs tools
<p>

Place these tools into the tools folder of MPW.

To get the usage of these tools, simply type the
command + enter.

All you need after is to read how to set-up <ref id="envariable" name="environment variables">
for cvs, then you can use it straight. Most of the time
you don't even need to set any variable because cvs
keeps track on your disk about the informations it needs.

<bf/Important note/ : these tools require to find the
shared library provided with MacCVS. So you can place
the shared library in the system folder or create two
aliases of thse libraries at the same directory level than
the mpw tools.

<sect>Annex
<p>

<label id="envariable">
<sect1>Environment variables used by MacCVS/WinCVS
<p>

Most the communication of MacCVS & WinCVS with cvs is done
thru <bf/environment variables/.

The cvs documentation will tell you about these variables. We'll refer
here only to the most used ones or to the one only used by WinCVS/MacCVS.

The reason you may want to be aware of this variables is because
you want to use the AppleEvent capability of MacCVS or the MPW
tools.

<bf/Mac Note/ : Some of the variables are noted as "globals" : it means that if you do not
define it, the MPW tool or MacCVS by AppleEvent will get these
values directly from the MacCVS preferences. So you don't need to define
them, unless you want to overide these values.

<itemize>

<item><bf/CVSROOT/ : your CVSROOT, something
like <bf/alexp@cvs.strata3d.com:/path/to/repository/.

<item><bf/CVSREAD/ : if set to "yes" or "1" or any non-null
value, means you want to check-out read-only.

<item><bf/USER/ (Mac only) : the user account you use on the
remote server.

<item><bf/LOGNAME/ : overides the result of getlogin(). Set it
on Windows when your cvs account is different from your login account
(for example "administrator").

<item><bf/CVS_GETPASS/ (MacCVS/WinCVS only) : used by CvsGui to prompt
a password for the pserver authentication. You have only to define
it the first time you login to the cvs server (see cvs login).
After don't define it, that's not safe to define a clear password.
cvs stores the password in a scrambled file named ".cvspass".
You might prefer to login in MacCVS/WinCVS before so you
don't have to use it.

<item><bf/HOME (global)/ : used by cvs to get globals settings files like
the .cvspass, .cvsrc... You need it most of the time so it's usefull to define
it to your preference folder on Mac and somewhere else for Windows.
<bf/Mac only/ : the '@@@' trick have been removed and you should give now
a regular Mac path instead (e.g. System:System Folder:Preferences:).
The default is automatically set to your preference folder.

<item><bf/IC_ON_TXT (global)/ (Mac only) : Use Internet Config services
also on text files when set to "1".

<item><bf/ISO8859 (global)/ : use ISO-Latin-1 encoding on text files
when set to "1".

<item><bf/CVS_PSERVER_PORT (global)/ : default to null. Overides
the default port for pserver authentication (usually 2401).

<item><bf/CVS_RCMD_PORT (global)/ : default to null. Overides
the default port for rcmd authentication (usually 514).

<item><bf/CVS_SERVER (global)/ : default to null. Overides
the default cvs server's name (usually "cvs").

<item><bf/MAC_DEFAULT_RESOURCE_ENCODING (global)/ : the value can be either
"HQX" or "AppleSingle".

<item><bf/MAC_BINARY_TYPES_PLAIN (global)/ : the value is a semi-colon separated
set of Mac signatures that you want to be turned into plain binary 
on the server (ex: "MMPr;JPEG"). This option will force to ignore the resource
fork.

<item><bf/MAC_BINARY_TYPES_HQX (global)/ : the value is a semi-colon separated
set of Mac signatures that you want to be turned into hqx format on the server.

<item><bf/MAC_BINARY_TYPES_SINGLE (global)/ : the value is a semi-colon separated
set of Mac signatures that you want to be turned into AppleSingle format on the server.

</itemize>

<sect1>A discussion about MacCVS architecture and the CR/LF problem
<p>

email of <htmlurl url="mailto:meeroh@MIT.EDU" name="Miro Jurisic">
to <htmlurl url="mailto:aubonbeurre@hotmail.com" name="Alexandre Parenteau">

I think it's very important that you know what was going on, so I'll write
a hopefully clear description here... if you have any questions please ask
:)

<itemize>
<item>1. How MSL writes to a file: When MSL writes to a disk file, every \r
will be replaced with \n, and
every \n will be replaced with \r, if the file was _not_ opened in the
binary mode. If the file was opened in binary mode, this replacement does
not occur. The exact place where this replacement occurs is in
__flush_buffer (buffer_io.c). This routine is called from fclose to write
the data out before a file is closed.

<item>2. How MSL writes to console: When MSL writes to a console, it treats
it as an ASCII file. This means
that when __flush_buffer is called for the console, \n\r conversion occurs,
and then WriteCharsToConsole is written.

<item>3. What 'Map newlines to CR' does: If this is turned on in language
settings, compilers will switch \n and \r when compiling your code
</itemize>

Now that we got those clearly written, let's see what the cvsLib glue does:

cvsLib has its own WriteCharsToConsole which calls into MacCVS. This is
setup when the library is loaded (in function loadCVS). Specifically,
cvsLib's WriteCharsToConsole calls MacCVS' consoleout. consoleout does one
of two things: if MacCVS is being run via AppleEvents, it writes output to
the reply event. Otherwise, if calls fwrite on stdout to write the data to
the console.

Okay, so the way that the 3.0b3 code works is like this:

<itemize>
<item>Case 1: MacCVS writing to the console :
MacCVS calls printf (or fprintf/write on stdout/stderr). Since MacCVS is
compiled with 'Map newlines to CR' off, there is exactl one conversion
going on, and that is MSL converting \r\n when flushing the console buffer.
That works fine.

<item>Case 2: cvsLib writing to an ASCII file (the broken case) :
cvsLib calls fwrite/fprintf. Since cvsLib is compiled with 'Map newlines to
CR', \r\n conversion occurs _twice_: first, at compile time, becaue of the
settings; second, at the time __flush_buffer is called, because we are
writing to an ASCII file. This causes files written by cvsLib to have the
wrong linebreaks.

<item>Case 3: cvsLib writing to the console (the tricky case) :
cvsLib calls fwrite/fprintf/printf on stdout/stderr. First \n\r conversion
occured at compile time. When it is the time to flush the console buffer,
__flush_bufer is called. It performs a \n\r conversion and then calls
WriteCharsToConsole. This is the glue WriteCharsToConsole, which calls
consoleout. consoleout calls fwrite, which eventually calls __flush_buffer
again. __flush_buffer performs another conversion, and then calls the real
WriteCharsToConsole. Since there were 3 conversions happening, the overall
effect is that \n is converted to \r and vice versa.
</itemize>

Hopefully, now you see where the problem is (this is where I was late
Monday afternoon).

I decided that it was not necessary to go through the process of loading
and unloading cvsLib all the time (I was not aware of the problems that
would cause), so I rearranged the libraries between fragments. I fixed the
\n\r problem, but I introduced a new problem: cvs was crashing reproducibly
the _second_ time a cvs command was invoked. This is where I went to bed on
Monday.

On Tuesday, I woke up and started stepping through the code to determine
why the garbage collector is blowing up. I traced the problem to some
globals being freed twice. What was going on? Since I changed the linkage
so that cvsLib was only loaded once, its globals were initialized when
MacCVS was started up. The first time cvsLib was called, it allocated space
for some strings and set some globals to point to them. Before returning it
freed those globals - but it didn't set them to NULL after freeing them.
The second time cvsLib was invoked, some of those globals were freed again
(because they weren't NULL), which was wrong.

At that point I realized that the library must be loaded and unloaded
repeatedly; I also got your email in which you said that GUSI should be
loaded and unloaded repeatedly because it contains those static destructors
that clean up MacTCP state.

After reading that I stepped away from my computer, went to the drawing
board, and concluded that it is impossible to do anything but to have a
closer look at the cvsLib glue, and see whether the hidden conversion can
be eliminated. This turned out to be far simpler that I could hope for:
instead of calling fwrite from consoleout, I called directly
WriteCharsToConsole, thereby avoiding the extra conversing that was the
problem. Of course, I also had to turn 'Map newline to CR' in the settings,
to even everything out. The result is that:

<itemize>
<item>Case 1: MacCVS writing to the console : Nothing changed

<item>Case 2: cvsLib writing to an ASCII file (the fixed case) :
Since there is only one \r\n conversion going on (in __flush_buffer), the
files are written correctly.

<item>Case 3: cvsLIb writing to console (the less tricky case) :
Two conversion were removed: the compile-time conversion, and the hidden
conversion in the cvsLib glue. Therefore, nothing changed - the console
still works perfectly.
</itemize>

Whew!

Please let me know if you are unclear on this... now I have a good view of
the problem and how I fixed it, and some really great insight on how pieces
of MacCVS fit together.

[...]

cheers,

meeroh

</article>
