Add a directory tree to a CVS repository

29 May 2004  in the wee hours  Matt Winckler

Sometimes you want to add an entire directory tree to CVS, but you don’t want to use the “import” command because you want to graft it into an existing repository instead of creating a new one. After an entire day’s worth of experimentation in Linux, here’s the answer on how to do this.

First, checkout a working version of the target repository.


$ cd /dir/to/checkout/to
$ cvs checkout MyModule


Then, copy the directory tree you want to add into its proper location in your working version:


$ cp -ap /new/directory/tree /dir/to/checkout/to/MyModule/newdirectorytree


In my case, some people had evidently tried to add the directory tree by hand already, so it had some extraneous ‘CVS’ directories that were causing trouble when adding things. So I ran this command to be rid of them:


$ cd /dir/to/checkout/to/MyModule/newdirectorytree
$ find . -name CVS -type d -exec rm -rf {} \;


That should get rid of all the CVS directories and their contents. Next, you must first add the top-level directory of the new directory tree:


$ cd ../
$ cvs add newdirectorytree


Next, you must add the directories, followed by the files in those directories:


$ cd newdirectorytree
$ find . ! -name CVS -type d -exec cvs add {} \;
$ find . ! -path ‘*/CVS/*’ ! -type d -exec cvs add {} \;


Then you’re done…if you don’t have any binary files in the source. However, if you do have binary files, you need to adjust them so that they’re updated properly by CVS (specifically, so that CVS doesn’t try to fix their line terminators when checking out from Linux servers to Windows clients–or vice versa, I imagine). You can adjust the files’ status in CVS using the following command (this assumes that all my binary files have a ‘.bin’ extension; adjust the filter for your case):


$ find . -name *.bin ! -type d -exec cvs admin -kb {} \;
$ find . -name *.bin ! -type d -exec cvs update -A {} \;



That will change the kflag on all files named *.bin, then update those files so you’ve got the right version in your working directory.

I also found that I had some troubles when I tried to add files that originated in Windows, but I added them via the Linux CVS client. So the files had CRLF line terminators, when Linux only expects an LF. There’s probably a way to tell CVS about this and have it fix the problem, but I didn’t know what that way was. So I wrote a PHP script to do it for me:


<?

function Sanitize($curpath) {
$dir = dir($curpath);
while ($file = $dir->read()) {
if($file != “.” && $file != “..”) {
if (is_dir($curpath.$file)) {
Sanitize($curpath.$file.”/”);
} else {
$filetype = exec(’file -b “‘.$curpath.$file.’”‘);
if (strpos($filetype, ‘text’) > 0 || substr($file, -4) == ‘.dat’) {
echo $curpath.$file.”\n”;
$lines = file($curpath.$file);
$text = implode(”", $lines);
$text = str_replace(”^M”, “”, $text);
$fp = fopen($curpath.$file, ‘w’);
fwrite($fp, $text);
fclose($fp);
}
}
}
}
$dir->close();
return;
}

Sanitize(’/path/you/want/to/sanitize/’);

?>



The tabs don’t want to display properly here, but copy it into a decent editor and auto-indent it and it should look fine. It’ll work either way. Note that I specified that files with the extension “.dat” are text files, regardless of what the “file -b” command says. That was true in my particular case; it might not be in yours, so understand what the script is doing and modify it accordingly before you use it.

React

This comment form is Markdown-enabled, in addition to allowing the following XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> .