Skip to content

Commit 51a7e6d

Browse files
Matthew Ogilviegitster
authored andcommitted
cvsserver: define a tag name character escape mechanism
CVS tags are officially only allowed to use [-_0-9A-Za-f]. Git refs commonly uses other characters, especially [./]. Such characters need to be escaped from CVS in order to be referenced. This just defines functions to escape/unescape names. The functions are not used yet. Signed-off-by: Matthew Ogilvie <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1899cbc commit 51a7e6d

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

git-cvsserver.perl

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3807,6 +3807,97 @@ sub gethistorydense
38073807
return $result;
38083808
}
38093809

3810+
=head2 escapeRefName
3811+
3812+
Apply an escape mechanism to compensate for characters that
3813+
git ref names can have that CVS tags can not.
3814+
3815+
=cut
3816+
sub escapeRefName
3817+
{
3818+
my($self,$refName)=@_;
3819+
3820+
# CVS officially only allows [-_A-Za-z0-9] in tag names (or in
3821+
# many contexts it can also be a CVS revision number).
3822+
#
3823+
# Git tags commonly use '/' and '.' as well, but also handle
3824+
# anything else just in case:
3825+
#
3826+
# = "_-s-" For '/'.
3827+
# = "_-p-" For '.'.
3828+
# = "_-u-" For underscore, in case someone wants a literal "_-" in
3829+
# a tag name.
3830+
# = "_-xx-" Where "xx" is the hexadecimal representation of the
3831+
# desired ASCII character byte. (for anything else)
3832+
3833+
if(! $refName=~/^[1-9][0-9]*(\.[1-9][0-9]*)*$/)
3834+
{
3835+
$refName=~s/_-/_-u--/g;
3836+
$refName=~s/\./_-p-/g;
3837+
$refName=~s%/%_-s-%g;
3838+
$refName=~s/[^-_a-zA-Z0-9]/sprintf("_-%02x-",$1)/eg;
3839+
}
3840+
}
3841+
3842+
=head2 unescapeRefName
3843+
3844+
Undo an escape mechanism to compensate for characters that
3845+
git ref names can have that CVS tags can not.
3846+
3847+
=cut
3848+
sub unescapeRefName
3849+
{
3850+
my($self,$refName)=@_;
3851+
3852+
# see escapeRefName() for description of escape mechanism.
3853+
3854+
$refName=~s/_-([spu]|[0-9a-f][0-9a-f])-/unescapeRefNameChar($1)/eg;
3855+
3856+
# allowed tag names
3857+
# TODO: Perhaps use git check-ref-format, with an in-process cache of
3858+
# validated names?
3859+
if( !( $refName=~m%^[^-][-a-zA-Z0-9_/.]*$% ) ||
3860+
( $refName=~m%[/.]$% ) ||
3861+
( $refName=~/\.lock$/ ) ||
3862+
( $refName=~m%\.\.|/\.|[[\\:?*~]|\@\{% ) ) # matching }
3863+
{
3864+
# Error:
3865+
$log->warn("illegal refName: $refName");
3866+
$refName=undef;
3867+
}
3868+
return $refName;
3869+
}
3870+
3871+
sub unescapeRefNameChar
3872+
{
3873+
my($char)=@_;
3874+
3875+
if($char eq "s")
3876+
{
3877+
$char="/";
3878+
}
3879+
elsif($char eq "p")
3880+
{
3881+
$char=".";
3882+
}
3883+
elsif($char eq "u")
3884+
{
3885+
$char="_";
3886+
}
3887+
elsif($char=~/^[0-9a-f][0-9a-f]$/)
3888+
{
3889+
$char=chr(hex($char));
3890+
}
3891+
else
3892+
{
3893+
# Error case: Maybe it has come straight from user, and
3894+
# wasn't supposed to be escaped? Restore it the way we got it:
3895+
$char="_-$char-";
3896+
}
3897+
3898+
return $char;
3899+
}
3900+
38103901
=head2 in_array()
38113902
38123903
from Array::PAT - mimics the in_array() function

0 commit comments

Comments
 (0)