Getting Started with JavaCVS

Introduction

This short document helps you get started with JavaCVS. There is a design overview document that goes into more details about the library's classes but you should not need to know the details to use the library.

Prerequisites are:

  • Know how to program in Java (obviously)
  • Have used CVS before, know what the commands do etc. You do not need to understand the protocol or any details of the cvs implementation, but anything you know will make things easier for you.

Details

Getting the CVSROOT

The first thing you need to do is set up some global options for whichever command(s) you want to run. The most important thing is obviously the setting for CVSROOT.

You can do at least two things:

  1. Check if you have a CVS directory in the current working directory and read the value from the Root file within it.
  2. Read a system property
Here is some code to help you out with both of these tasks:
    String root = null;
    BufferedReader r = null;
    try
    {
        File f = new File(System.getProperty("user.dir"));
        File rootFile = new File(f, "CVS/Root");            
        if (rootFile.exists())
        {
            r = new BufferedReader(new FileReader(rootFile));
            root = r.readLine();                
        }
    }
    catch (IOException e)
    {
        // ignore
    }
    finally
    {
        try
        {
            if (r != null)
                r.close();
        }
        catch (IOException e)
        {
            System.err.println("Warning: could not close CVS/Root file!");
        }
    }
    if (root==null)
    {
        root = System.getProperty("cvs.root");
    }

Having got some value for CVSROOT you should create a GlobalOptions object and set the root on it:

    GlobalOptions globalOptions = new GlobalOptions();
    globalOptions.setCVSRoot(getCVSRoot());

Your application will probably want to make use of the various fields within the CVSROOT in order to connect and so on. You can do that any way you want but this class is a handy way of parsing CVSROOT:

    /**
     * A struct containing the various bits of information in a CVS root
     * string, allowing easy retrieval of individual items of information
     */
    private static class CVSRoot
    {
        public String connectionType;
        public String user;
        public String host;
        public String repository;
        
        public CVSRoot(String root) throws IllegalArgumentException
        {
            if (!root.startsWith(":"))
                throw new IllegalArgumentException();
            
            int oldColonPosition = 0;
            int colonPosition = root.indexOf(':', 1);
            if (colonPosition==-1)
                throw new IllegalArgumentException();
            connectionType = root.substring(oldColonPosition + 1, colonPosition);
            oldColonPosition = colonPosition;
            colonPosition = root.indexOf('@', colonPosition+1);
            if (colonPosition==-1)
                throw new IllegalArgumentException();
            user = root.substring(oldColonPosition+1, colonPosition);
            oldColonPosition = colonPosition;
            colonPosition = root.indexOf(':', colonPosition+1);
            if (colonPosition==-1)
                throw new IllegalArgumentException();
            host = root.substring(oldColonPosition+1, colonPosition);
            repository = root.substring(colonPosition+1);
            if (connectionType==null || user==null || host==null ||
                repository==null)
                throw new IllegalArgumentException();
        }
    }
From that you can get the connection type to determine what sort of connection to the server to create. We will assume you are using pserver although other connections are handled similarly.

Establishing a connection

We assume that you have obtained the password from somewhere (e.g. looking up the .cvspass file). To connect:
    PServerConnection c = new PServerConnection();
    connection = c;
    c.setUserName(userName);
    c.setEncodedPassword(encodedPassword);
    c.setHostName(hostName);
    c.setRepository(repository);        
    c.open();        

Creating a Client to execute commands

The org.netbeans.lib.cvsclient.Client class is the central controller for the library. To create one, you pass in a Connection instance and an AdminHandler.

An AdminHandler is used to store and retrieve all the administration files that CVS uses to know about which versions of files you have checked out and so on. You don't have to worry about how it works and a standard implementation is provided for you that works exactly like command-line CVS. It creates a CVS subdirectory in all CVS directories and stores its details in there.

Hence constructing a StandardAdminHandler is all you need to do:

    Client client = new Client(c, new StandardAdminHandler());     

The client also needs to know the local path. This is the directory where the application is logically working from. This is easiest to understand with command-line CVS - the localPath is just the directory you are in when you are typing in your commands. From within a GUI application this is not always so clear but basically any relative paths are constructed using localPath as their root.

So set the local path to something appropriate:

    client.setLocalPath(localPath);

Listening

You are almost ready to run a command. However, you need to register at least one listener if you want to be able to do anything useful.

The library uses listeners to tell the application of any files that have been updated, added, or removed and to communicate messages and progress with the application.

Sophisticated GUI applications will want to handle all the events (see the design overview document for more details) however our simple client can just use the message events to find out what has been going on.

The following class can be used as a simple listener. CVSAdapter is a class that implements the CVSListener interface with empty methods (cf. java.awt.MouseAdapter).

public class BasicListener extends CVSAdapter
{
    /**
     * Stores a tagged line
     */
    private final StringBuffer taggedLine = new StringBuffer();

    /**
     * Called when the server wants to send a message to be displayed to
     * the user. The message is only for information purposes and clients
     * can choose to ignore these messages if they wish.
     * @param e the event
     */
    public void messageSent(MessageEvent e)
    {
        String line = e.getMessage();
        PrintStream stream = e.isError() ? System.err
                                         : System.out;

        if (e.isTagged())
        {
            String message = e.parseTaggedMessage(taggedLine);
	    // if we get back a non-null line, we have something
	    // to output. Otherwise, there is more to come and we
	    // should do nothing yet.
            if (message != null)
            {
                stream.println(message);
            }
        }
        else
        {
            stream.println(line);
        }
    }
}
At first glance, this might appear bizarre. The reason is that CVS can send back several messages intended as one (so-called "tagged messages"). Fortunately, the library handles this for you. All you need to do is pass in a StringBuffer to the parseTaggedMessage method of the MessageEvent class and if enough data has been sent to make a decent message, you will be given back a String message. Otherwise, the data is appended to the buffer.

Non-tagged messages are straightforward and can just be sent to an output stream.

Having created an event listener, add it to the client's event manager:

    client.getEventManager().addCVSListener(new BasicListener());

Running a command

Executing a command is simply a matter of instantiating an appropriate Command class and pass it to the client to execute.

Many commands use a Builder to generate useful data structures containing information (such as the output from the Status command). For our simple application we won't use a builder since we just output the details straight to the console.

   UpdateCommand command = new UpdateCommand();
   command.setBuilder(null);
   
   command.setRecursive(true);
   command.setBuildDirectories(true);
   command.setPruneDirectories(true);

   client.executeCommand(command);
That executes the equivalent of cvs update -dP.

Project Features

About this Project

VersionControl was started in November 2009, is owned by tpavek, and has 105 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20160708.bf2ac18). © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
 
 
Close
loading
Please Confirm
Close