Thursday, April 6, 2017

CVS tidbits

Environment / assumptions for this post:
  • CVS
  • shell access to server
Yes I know - CVS or Concurrent Versions System is as old as time. Well, 1990 anyway. But sometimes you just don't have a lot of choice with the tools you have to work with. If it is working perfectly fine, then changing for the sake of changing turns out to be a low priority.

In any case, here are a few tidbits I've needed over the years. I may not need them that much, but once in a while I come back to them since I forget from one usage to the next.

So in no particular order, here are some CVS Tidbits.

CVS Vendor Tags

  1. First, import the 3rd party code with a vendor and release tags. In this case, repo/foo is the repository location, FOO is the vendor tag, and FOO_1_0 is the release tag.
     cvs import -m "Import of Foo 1.0" repo/foo FOO FOO_1_0
     
  2. Second, checkout the project, make modifications as usual, and commit
     
  3. Third, when a new version of the 3rd party software comes out, import it like above, but with a different release tag (same Vendor tag). It will report conflicts.:
     cvs -q import -m "Import of Foo 2.0" repo/foo FOO FOO_2_0
     
  4. Fourth, do a merge (under checkout command) between the two release tags:
     cvs checkout -j FOO_1_0-j FOO_2_0 repo/foo
     
  5. Fifth, resolve the conflicts and commit
     
  6. Sixth, do a fresh checkout.

CVS Restore from Attic

This is an administrator function, you will need command-line access to the repository. To restore a file from the attic, first discover what the last version was before it got deleted.  Navigate to the Attic of the directory where the file was, and look at the top of the deleted file.
Note: Make sure not to select the "dead" revision, or else it will restore a dead file of 0 bytes.  Go back one more.

Next, do the following:

 cd ~/local/path/to/folder/of/deleted/file

 cvs -Q update -p -r 1.11 DeletedFileName.java > DeletedFileName.java

 cvs add DeletedFileName.java

 cvs ci -m "reviving DeletedFileName.java" DeletedFileName.java

CVS Move Tag

This happens when I tag a release, but forgot one tiny little change to a file. I really want the tag to apply to the new version of that one file. So for example, if I want to move a tag say from 1.8 to 1.9:

 cvs tag -F -r 1.9 PROD_3_2 MyFile.java

CVS loginfo settings

There are two nice integrations we use CVS with:
  • One with Atlassian's JIRA bug tracking software. This allows us make a connection between a particular bug, and all the files that were changed to fix that bug. This is done by matching the JIRA bug number with the CVS commit comments (which are added to a commit database).
  • Two, with ViewVC which lets you browse a repo via browser, and also compare versions, etc. See ViewVC website.
So, the following settings will enable these things by doing two things:
  1. log the commit to a commit database (e.g. viewvc uses mysql)
  2. force the user to enter a commit message conforming to a template e.g. to include a bug tracking number
Under CVSROOT in the loginfo file:
 ALL /usr/local/viewvc-1.0.7/bin/loginfo-handler %{sVv}

Under CVSROOT (or other location) in a file such as commit_template.txt. This is arbitrary, but gives the user a format to follow:
[PRJ-000]

Under CVSROOT in the verifymsg file:
 Proj1 /home/cvs/CVSROOT/verify_commit
 Proj2 /home/cvs/CVSROOT/verify_commit

Under CVSROOT (or other location) in a script such as verify_commit:
 #!/bin/sh
 #
 #
 #  Verify that the log message contains a valid Jira bugid
 #  e.g. ABC-203   or   XYZ-35
 if head -1 < $1 | grep '\[[A-Z]*\-[0-9]\]*'' > /dev/null; then
     exit 0
 else
     echo "No Jira issue number found: expecting [PRJ-000] in commit message e.g.. ABC-203."
     exit 1
 fi

CVS Import

I always forget the right way to import into CVS, especially when using WinCVS. I'm apparently not the only one, as I see MANY files imported at the root repository level that clearly shouldn't be there. So use a good GUI tool, or use the command-line I guess.

Using WinCVS

This will probably benefit exactly no one, you'd be hard pressed to find anybody using CVS anymore let alone WinCVS. Never-the-less, here is the method:
  • Navigate to one level above the directory, so you see it listed on the left side of the screen in WinCvs (do a Browse Location to the parent dir)
  • Right-click the directory (in the left side), select import
  • Specify file types for any unknown files (text, binary, etc)
  • For Repository Path, if you are importing a directory css,  and you want it under a root level project called FooBar, then enter FooBar/css (no leading slash)
  • Specify a log message such as 'Initial Release' or something else
  • Click 'OK'
Now you can do a fresh checkout operation into your project directory.

Using Command-Line

Let's say you have a directory css e.g. /tmp/css. Setup the env variable however you need to:

export CVSROOT /home/cvs
cd /tmp/css
cvs import -m "initial import" FooBar/css vendor start


CVS Bulk Delete

You remove files, not directories from CVS.  To remove directories, delete the files and then update with the "prune directories" option checked. In any case, to mass delete a directory and its contents:

First, open a shell (cmd window for Windows machines), and cd into the directory:
cd /directory/to/be/removed

Now, schedule for deletion all the files in question.
cvs remove -f *

Commit the changes:
cvs ci -m "my log message"

Update, pruning empty directories:
cvs update -P

This procedure will move everything to the "Attic" i.e. it will still be visible in the repository on the server.  It will still be retrievable by tag, version number, etc.  If it was a mistake and you want to permanently banish it, then you can go follow the above operation, then log in to the server and just '''rm -rf''' the directory.

CVS Change Log Message

To change a commit comment:

  • must do this from a checked-out copy, not directly in the repository
  • must cd to the directory, cannot specify absolute path
  • must specify a specific version and file

cd /my/path
cvs admin -m 1.8:"My new commit comment" MyJavaFile.java

CVS adding a password for a user

In $CVSHOME/CVSROOT/passwd, the entries look like:

 userid:pass:userToRunAsIfAuthenticationSucceeds

e.g. jjames:$uiu&Q32lN9:cvs

The password is encrypted using unix crypt. Get encrypted password by using the script cvspasswd, which if you don't have it is essentially this:

 #!/usr/bin/perl
 $user = shift @ARGV || die "cvspasswd user\n";
 print "Enter password for $user: ";
 system "stty -echo";
 chomp ($plain = <>);
 system "stty echo";
 print "\n";
 @chars = ('A'..'Z', 'a'..'z', '0'..'9');
 $salt = $chars[rand(@chars)] . $chars[rand(@chars)];
 $passwd = crypt($plain, $salt);
 print "$user:$passwd\n";

No comments:

Post a Comment