60
60
' Valid-responses' => \&req_Validresponses,
61
61
' valid-requests' => \&req_validrequests,
62
62
' Directory' => \&req_Directory,
63
+ ' Sticky' => \&req_Sticky,
63
64
' Entry' => \&req_Entry,
64
65
' Modified' => \&req_Modified,
65
66
' Unchanged' => \&req_Unchanged,
@@ -470,21 +471,80 @@ sub req_Directory
470
471
{
471
472
$log -> info(" Setting prepend to '$state ->{path}'" );
472
473
$state -> {prependdir } = $state -> {path };
474
+ my %entries ;
473
475
foreach my $entry ( keys %{$state -> {entries }} )
474
476
{
475
- $state -> {entries }{$state -> {prependdir } . $entry } = $state -> {entries }{$entry };
476
- delete $state -> {entries }{$entry };
477
+ $entries {$state -> {prependdir } . $entry } = $state -> {entries }{$entry };
477
478
}
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 ;
478
487
}
479
488
480
489
if ( defined ( $state -> {prependdir } ) )
481
490
{
482
491
$log -> debug(" Prepending '$state ->{prependdir}' to state|directory" );
483
492
$state -> {directory } = $state -> {prependdir } . $state -> {directory }
484
493
}
494
+
495
+ if ( ! defined ($state -> {dirMap }{$state -> {directory }}) )
496
+ {
497
+ $state -> {dirMap }{$state -> {directory }} =
498
+ {
499
+ ' names' => {}
500
+ # 'tagspec' => undef
501
+ };
502
+ }
503
+
485
504
$log -> debug(" req_Directory : localdir=$data repository=$repository path=$state ->{path} directory=$state ->{directory} module=$state ->{module}" );
486
505
}
487
506
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
+
488
548
# Entry entry-line \n
489
549
# Response expected: no. Tell the server what version of a file is on the
490
550
# local machine. The name in entry-line is a name relative to the directory
@@ -511,6 +571,8 @@ sub req_Entry
511
571
tag_or_date => $data [5],
512
572
};
513
573
574
+ $state -> {dirMap }{$state -> {directory }}{names }{$data [1]} = ' F' ;
575
+
514
576
$log -> info(" Received entry line '$data ' => '" . $state -> {directory } . $data [1] . " '" );
515
577
}
516
578
@@ -2213,13 +2275,118 @@ sub argsfromdir
2213
2275
}
2214
2276
}
2215
2277
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
+
2216
2382
# This method cleans up the $state variable after a command that uses arguments has run
2217
2383
sub statecleanup
2218
2384
{
2219
2385
$state -> {files } = [];
2220
2386
$state -> {args } = [];
2221
2387
$state -> {arguments } = [];
2222
2388
$state -> {entries } = {};
2389
+ $state -> {dirMap } = {};
2223
2390
}
2224
2391
2225
2392
# Return working directory CVS revision "1.X" out
0 commit comments