Skip to content

Commit eb5dcb2

Browse files
Matthew Ogilviegitster
authored andcommitted
cvsserver: implement req_Sticky and related utilities
Nothing sets sticky yet, or uses the values set by this, but soon... Signed-off-by: Matthew Ogilvie <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 658b57a commit eb5dcb2

File tree

1 file changed

+169
-2
lines changed

1 file changed

+169
-2
lines changed

git-cvsserver.perl

Lines changed: 169 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
'Valid-responses' => \&req_Validresponses,
6161
'valid-requests' => \&req_validrequests,
6262
'Directory' => \&req_Directory,
63+
'Sticky' => \&req_Sticky,
6364
'Entry' => \&req_Entry,
6465
'Modified' => \&req_Modified,
6566
'Unchanged' => \&req_Unchanged,
@@ -470,21 +471,80 @@ sub req_Directory
470471
{
471472
$log->info("Setting prepend to '$state->{path}'");
472473
$state->{prependdir} = $state->{path};
474+
my %entries;
473475
foreach my $entry ( keys %{$state->{entries}} )
474476
{
475-
$state->{entries}{$state->{prependdir} . $entry} = $state->{entries}{$entry};
476-
delete $state->{entries}{$entry};
477+
$entries{$state->{prependdir} . $entry} = $state->{entries}{$entry};
477478
}
479+
$state->{entries}=\%entries;
480+
481+
my %dirMap;
482+
foreach my $dir ( keys %{$state->{dirMap}} )
483+
{
484+
$dirMap{$state->{prependdir} . $dir} = $state->{dirMap}{$dir};
485+
}
486+
$state->{dirMap}=\%dirMap;
478487
}
479488

480489
if ( defined ( $state->{prependdir} ) )
481490
{
482491
$log->debug("Prepending '$state->{prependdir}' to state|directory");
483492
$state->{directory} = $state->{prependdir} . $state->{directory}
484493
}
494+
495+
if ( ! defined($state->{dirMap}{$state->{directory}}) )
496+
{
497+
$state->{dirMap}{$state->{directory}} =
498+
{
499+
'names' => {}
500+
#'tagspec' => undef
501+
};
502+
}
503+
485504
$log->debug("req_Directory : localdir=$data repository=$repository path=$state->{path} directory=$state->{directory} module=$state->{module}");
486505
}
487506

507+
# Sticky tagspec \n
508+
# Response expected: no. Tell the server that the directory most
509+
# recently specified with Directory has a sticky tag or date
510+
# tagspec. The first character of tagspec is T for a tag, D for
511+
# a date, or some other character supplied by a Set-sticky
512+
# response from a previous request to the server. The remainder
513+
# of tagspec contains the actual tag or date, again as supplied
514+
# by Set-sticky.
515+
# The server should remember Static-directory and Sticky requests
516+
# for a particular directory; the client need not resend them each
517+
# time it sends a Directory request for a given directory. However,
518+
# the server is not obliged to remember them beyond the context
519+
# of a single command.
520+
sub req_Sticky
521+
{
522+
my ( $cmd, $tagspec ) = @_;
523+
524+
my ( $stickyInfo );
525+
if($tagspec eq "")
526+
{
527+
# nothing
528+
}
529+
elsif($tagspec=~/^T([^ ]+)\s*$/)
530+
{
531+
$stickyInfo = { 'tag' => $1 };
532+
}
533+
elsif($tagspec=~/^D([0-9.]+)\s*$/)
534+
{
535+
$stickyInfo= { 'date' => $1 };
536+
}
537+
else
538+
{
539+
die "Unknown tag_or_date format\n";
540+
}
541+
$state->{dirMap}{$state->{directory}}{stickyInfo}=$stickyInfo;
542+
543+
$log->debug("req_Sticky : tagspec=$tagspec repository=$state->{repository}"
544+
. " path=$state->{path} directory=$state->{directory}"
545+
. " module=$state->{module}");
546+
}
547+
488548
# Entry entry-line \n
489549
# Response expected: no. Tell the server what version of a file is on the
490550
# local machine. The name in entry-line is a name relative to the directory
@@ -511,6 +571,8 @@ sub req_Entry
511571
tag_or_date => $data[5],
512572
};
513573

574+
$state->{dirMap}{$state->{directory}}{names}{$data[1]} = 'F';
575+
514576
$log->info("Received entry line '$data' => '" . $state->{directory} . $data[1] . "'");
515577
}
516578

@@ -2213,13 +2275,118 @@ sub argsfromdir
22132275
}
22142276
}
22152277

2278+
2279+
## look up directory sticky tag, of either fullPath or a parent:
2280+
sub getDirStickyInfo
2281+
{
2282+
my($fullPath)=@_;
2283+
2284+
$fullPath=~s%/+$%%;
2285+
while($fullPath ne "" && !defined($state->{dirMap}{"$fullPath/"}))
2286+
{
2287+
$fullPath=~s%/?[^/]*$%%;
2288+
}
2289+
2290+
if( !defined($state->{dirMap}{"$fullPath/"}) &&
2291+
( $fullPath eq "" ||
2292+
$fullPath eq "." ) )
2293+
{
2294+
return $state->{dirMap}{""}{stickyInfo};
2295+
}
2296+
else
2297+
{
2298+
return $state->{dirMap}{"$fullPath/"}{stickyInfo};
2299+
}
2300+
}
2301+
2302+
# Resolve precedence of various ways of specifying which version of
2303+
# a file you want. Returns undef (for default head), or a ref to a hash
2304+
# that contains "tag" and/or "date" keys.
2305+
sub resolveStickyInfo
2306+
{
2307+
my($filename,$stickyTag,$stickyDate,$reset) = @_;
2308+
2309+
# Order of precedence of sticky tags:
2310+
# -A [head]
2311+
# -r /tag/
2312+
# [file entry sticky tag]
2313+
# [the tag specified in dir req_Sticky]
2314+
# [the tag specified in a parent dir req_Sticky]
2315+
# [head]
2316+
2317+
my $result;
2318+
if($reset)
2319+
{
2320+
# $result=undef;
2321+
}
2322+
elsif( defined($stickyTag) && $stickyTag ne "" )
2323+
# || ( defined($stickyDate) && $stickyDate ne "" ) # TODO
2324+
{
2325+
$result={ 'tag' => (defined($stickyTag)?$stickyTag:undef) };
2326+
2327+
# TODO: Convert -D value into the form 2011.04.10.04.46.57,
2328+
# similar to an entry line's sticky date, without the D prefix.
2329+
# It sometimes (always?) arrives as something more like
2330+
# '10 Apr 2011 04:46:57 -0000'...
2331+
# $result={ 'date' => (defined($stickyDate)?$stickyDate:undef) };
2332+
}
2333+
elsif( defined($state->{entries}{$filename}) &&
2334+
defined($state->{entries}{$filename}{tag_or_date}) &&
2335+
$state->{entries}{$filename}{tag_or_date} ne "" )
2336+
{
2337+
my($tagOrDate)=$state->{entries}{$filename}{tag_or_date};
2338+
if($tagOrDate=~/^T([^ ]+)\s*$/)
2339+
{
2340+
$result = { 'tag' => $1 };
2341+
}
2342+
elsif($tagOrDate=~/^D([0-9.]+)\s*$/)
2343+
{
2344+
$result= { 'date' => $1 };
2345+
}
2346+
else
2347+
{
2348+
die "Unknown tag_or_date format\n";
2349+
}
2350+
}
2351+
else
2352+
{
2353+
$result=getDirStickyInfo($filename);
2354+
}
2355+
2356+
return $result;
2357+
}
2358+
2359+
# Convert a stickyInfo (ref to a hash) as returned by resolveStickyInfo into
2360+
# a form appropriate for the sticky tag field of an Entries
2361+
# line (field index 5, 0-based).
2362+
sub getStickyTagOrDate
2363+
{
2364+
my($stickyInfo)=@_;
2365+
2366+
my $result;
2367+
if(defined($stickyInfo) && defined($stickyInfo->{tag}))
2368+
{
2369+
$result="T$stickyInfo->{tag}";
2370+
}
2371+
# TODO: When/if we actually pick versions by {date} properly,
2372+
# also handle it here:
2373+
# "D$stickyInfo->{date}" (example: "D2011.04.13.20.37.07").
2374+
else
2375+
{
2376+
$result="";
2377+
}
2378+
2379+
return $result;
2380+
}
2381+
22162382
# This method cleans up the $state variable after a command that uses arguments has run
22172383
sub statecleanup
22182384
{
22192385
$state->{files} = [];
22202386
$state->{args} = [];
22212387
$state->{arguments} = [];
22222388
$state->{entries} = {};
2389+
$state->{dirMap} = {};
22232390
}
22242391

22252392
# Return working directory CVS revision "1.X" out

0 commit comments

Comments
 (0)