Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

replacing rcs tags in perl

by jettero (Monsignor)
on Jan 19, 2007 at 02:33 UTC ( #595400=perlquestion: print w/replies, xml ) Need Help??
jettero has asked for the wisdom of the Perl Monks concerning the following question:

I recently started using git (actually cogito, which is sorta the same thing). I liked it the best out of the twenty or so choices while I was trying to grow out of cvs. It has a lot of really slick features, but one thing that it doesn't have is those lovely little rcs tags (e.g $Id:,v 1.352 jettero 2003-09-13 19:00:00$).

I wrote a quick little app to go through and replace out the $Id, $Revision$, and $Date$ tags. I was happy with it. It used File::Find to find all the files, File::Copy to make a temp file and utime to fix the mtime after the search and replace.

I started running into trouble though, because it didn't understand the .gitignore file (which has the same format as the .cvsignore). I began adding clumsy glob support to my app, but it presented more trouble than I whould have thought. I ended up using open my $in, '-|', qw(git ls-files) or die $! to find the applicable files — since git knows how to list the files it's watching as a built in function. This fits well with the overall git model, because it's a collection of scripts that work together; but I'm still interested in how you'd do it in perl.

There's no way to guess the git revision before the commit, so instead of the revision I ended up using a Digest::SHA1 that skips the contents of the rcs tags. Actually, I prepend the number of lines and the number of bytes in the file also. For the $Date$ I used the mtime of the file.

my $h = $sha1->b64digest; my $rev = "$lines.$bytes.$h"; $rev =~ tr/$/_/; my $date = strftime('%Y-%m-%d %H:%M:%S UTC', gmtime($mtime));

My main question is concerning the best way to find all the files git finds. Before I thought to use qw(git ls-files) I was going to try opendir and build up a list of globs found in the .gitignore files I found along the way. (Something like the following, which is obviously incomplete.)

use warnings; use strict; use Text::Glob qw(glob_to_regex); sub do_a_dir { my $dir = shift; my @globs = @_; my @files = (); opendir my $dir, $dir or die "hrmph: $!"; while( my $ent = readdir $dir ) { next if $ent =~ m/\A\.\.?\z/; if( -d $ent ) { push @files, &do_a_dir(@globs) unless &a_glob_matches($ent +, @globs); } elsif( -f $ent ) { if( $ent eq ".gitignore" ) { open my $in, $ent or die "hrmph: $!"; while(<$in>) { chomp; push @globs, glob_to_regex( $_ ); } close $in; } else { push @files, $ent unless &a_glob_matches($ent, @globs) +; # although, this is spurious. In practice, I would ne +ed # to find all the .gitignores in this dir before I # can test the files. } } else { # agahrr, I don't want to think about these monsters right + now # I probably mean to skip them if I'm using opendir... } } closedir $dir; } sub a_glob_matches { my $ent = shift; my @globs = @_; for( @globs ) { return 1 if $ent =~ $_; } return 0; }


  1. How do you find all the appropriate files, skipping the files/dirs that match globs? Is opendir the way to go (doubtful)? Is it better to do these things in the &wanted callback of File::Find — and some kind of local our or global? Anything else of interest?
  2. How do you test strings to see if they match globs? glob doesn't seem to help with that without issuing a bunch of syscalls that aren't necessary. Text::Glob seems to do the job perfectly, are there better choices?
  3. All other input welcome — I'm sure I missed things, it's my way. I'm basically looking for any tools that make the job of replacing rcs tags easier and more robust.


Replies are listed 'Best First'.
Re: replacing rcs tags in perl
by Hofmator (Curate) on Jan 19, 2007 at 08:09 UTC
    This might be way off ... is there a possibility for adding a checkin hook in git? This would feel like the natural place for doing stuff like replacing RCS tags - and you wouldn't have to worry about finding all the files and such.

    -- Hofmator

    Code written by Hofmator and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      You are definitely correct.

      The problem is: I find that git is completely unusable without cogito (checkins would be 3 or 5 commands) and cogito doesn't execute pre-commit hooks, only post for some unknown reason.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://595400]
Approved by chargrill
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (4)
As of 2018-06-22 23:59 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (124 votes). Check out past polls.