syncvsvn: synchronize CVS working copy with SVN working copy
I keep all my Drupal sites up-to-date by updating a single Drupal core instance and one install profile. And I keep Drupal core and all modules in this install profile updated through CVS. But then a problem poses: what if a file was added to or removed from CVS? Until now, you’d have to manually svn add
or svn rm
the file. And in the case of some modules (e.g. Views), that’s a lot of files you’ll have to check.
The solution: syncvsvn
I’m aware that this probably isn’t the best name, but it gets the job done :).
Suppose you’ve just updated the xmlsitemap module:
>: svn status
? xmlsitemap_user/translations
M xmlsitemap_user/xmlsitemap_user.module
M xmlsitemap_user/xmlsitemap_user.install
? xmlsitemap_user/CVS/Entries.Log
M xmlsitemap_user/CVS/Entries
? translations/includes.pot
? translations/docs.pot
? translations/general.pot
! translations/da.po
! translations/ru.po
! translations/es.po
! translations/fr.po
M translations/xmlsitemap.pot
M translations/de.po
! translations/nl.po
! translations/ja.po
M translations/CVS/Entries
Your mission: ignore any CVS/Entries.log
files, add all files marked with question marks and remove all files marked with exclamation marks. This is a frustrating and time consuming task. This is where syncvsvn comes in to the rescue:
>: syncvsvn
A xmlsitemap_user/translations
Deleted xmlsitemap_user/CVS/Entries.Log
A translations/includes.pot
A translations/docs.pot
A translations/general.pot
D translations/da.po
D translations/ru.po
D translations/es.po
D translations/fr.po
D translations/nl.po
D translations/ja.po
The script
Now, the actual script (you can also download it below):
#!/usr/bin/php
<?php
define('REGEXP_SVN_ADD', "/^\?.{6}(.*)(?<!CVS\/Entries\.Log)$/");
define('REGEXP_SVN_RM', "/^\!.{6}(.*)(?<!CVS\/Entries\.Log)$/");
define('REGEXP_FILE_RM', "/^\?.{6}(.*CVS\/Entries\.Log)$/");
// Run svn status.
$output = shell_exec('svn status');
$lines = explode("\n", $output);
// Add/remove files to/from the svn repository and delete CVS/Entries.Log files.
foreach ($lines as $line) {
if (preg_match(REGEXP_SVN_ADD, $line, $matches)) {
print shell_exec("svn add $matches[1]");
}
elseif (preg_match(REGEXP_SVN_RM, $line, $matches)) {
print shell_exec("svn rm $matches[1]");
}
elseif (preg_match(REGEXP_FILE_RM, $line, $matches)) {
shell_exec("rm $matches[1]");
print "Deleted $matches[1]\n";
}
}
As you can see, it decides what to do based on the output of svn status
. This means that if you’ve got a file
foo
that’s not added to the repository yet, it will be added as well. I.e. any temporary files will be added as well. You could prevent this by actually looking at CVS’ metadata, but this was sufficient for me.
Put this wherever you store your shell scripts and chmod +x
it to make it executable. In case your PHP interpreter cannot be found, use type -a php
to find out its location and update this in the first line of the script.
Comments
I need this
Thanks, I have almost the same problem. I never used CVS versions from Drupal.org because I assumed it would be a pain to get them into my svn. So I grab the tar.gz and hope no files were deleted. To move to CVS I guess the only thing I need to do is figure out the easy way to stay on released versions of modules from CVS (as opposed to just the HEAD revision).
drush or stand-alone shell commands
You could use drush. Or alternatively, if you want to be able to check out a drupal module (and update it) anywhere, add these to your
~/.bash_profile
:alias dupdate="cvs update -dP"
function drupal { if [ $# -eq "2" ] then cvs -z6 -d:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal checkout -d $1 -r DRUPAL-$2 drupal else cvs -z6 -d:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal checkout -d $1 drupal fi }
function drupal_module { if [ $# -eq "2" ] then cvs checkout -d $1 -r DRUPAL-$2 contributions/modules/$1 else cvs checkout -d $1 contributions/modules/$1 fi }
Now you can check out the Drupal 6 branch of Views 2 with this command:
drupal_module views 6--2
Or the 2.1 tag with this command:
drupal_module views 6--2-1
And update to the 2.2 tag with this command:
dupdate -r DRUPAL-6--2-2
I know, it’s not the most consistent or complete system, but at least it doesn’t have any dependencies. I find it comfortable enough to use.
Similar commands, but a bit more automated. ;)
Hey Wim,
Here are the commands I’ve been using in my own .bash_profile.
You can also find these in the comments on my site.
These are functions in my .bashrc file Get a new drupal moduled6mod() { MODULE="${1}"; cd $DRUPALROOT/sites/all/modules/; \ cvs -z6 -d:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal-contrib co -d ./$MODULE contributions/modules/$MODULE cd $MODULE drevs $MODULE.module }
Get a new drupal themed6theme() { THEME="${1}"; cd $DRUPALROOT/sites/all/themes/; \ cvs -z6 -d:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal-contrib co -d ./$THEME contributions/themes/$THEME cd $THEME drevs page.tpl.php }
List the revisions of the supplied filedrevs() { cvs log "${1}" | egrep 'DRUPAL-.*:' | sort }
Do a cvs update using the specified revisiondup() { cvs up -dP -r "${1}" }
Thanks for the feedback!
Thanks for the feedback Matt :) I had already referenced your article in the comments on this page, by the way :)
Your
drevs
command looks very useful, thanks!Since you seem to be very much into these kinds of handy shortcuts, you may also want to look at two more blog posts.
Thanks!
I’ve been contemplating writing this for some time. Thanks for taking the time to write and pubishing this! :)
You're welcome :)
You’re welcome :)
Similar script – less automated, more powerful
I just bumped into a similar script with less automation but more power via gotdrupal.com of Kathleen Murtagh.
One-liner
I came up with a one-liner that you may be interested in http://milanadamovsky.blogspot.com/2010/04/automatic-svn-file-handling-one-liner.html.
Thanks for sharing Milan!
Thanks for sharing Milan! :)
I’m sticking with my script on my local machine because I find the code far more readable. But yours is probably better to get going faster :)
Fix to script, to support space at filenames
<?php
define(‘REGEXP_SVN_ADD’, “/^\?.{7}(.)(?<!CVS\/Entries.Log)$/”); define(‘REGEXP_SVN_RM’, “/^!.{7}(.)(?<!CVS\/Entries.Log)$/”); define(‘REGEXP_FILE_RM’, “/^\?.{7}(.*CVS\/Entries.Log)$/”);
// Run svn status. $output = shell_exec(‘svn status’); $lines = explode(“\n”, $output);
// Add/remove files to/from the svn repository and delete CVS/Entries.Log files. foreach ($lines as $line) { if (preg_match(REGEXP_SVN_ADD, $line, $matches)) { print shell_exec(“svn add "$matches[1]"”); } elseif (preg_match(REGEXP_SVN_RM, $line, $matches)) { print shell_exec(“svn rm "$matches[1]"”); } elseif (preg_match(REGEXP_FILE_RM, $line, $matches)) { shell_exec(“rm "$matches[1]"”); print “Deleted "$matches[1]"\n”; } }