monotone

monotone Commit Details

Date:2010-02-13 16:11:36 (9 years 5 months ago)
Author:Tony Cooper
Branch:net.venge.monotone.contrib.lib.automate-stdio
Commit:1a3b6af9f4ec930adf45c930178f4ab31719085a
Parents: a6e1be675a2bcb18d53504eefccc90a092bdfe99
Message:- Added support for extracting the extra automate stdio data streams new in

0.46.
- Added support for automate remote_stdio via the new_from_service() contructor.
- Added the pull(), push() and sync() methods.
- The version numbers are not treated as floating point numbers.
Changes:
Mlib/Monotone/AutomateStdio.pm (25 diffs)

File differences

lib/Monotone/AutomateStdio.pm
6464
6565
6666
67
6768
6869
6970
......
9091
9192
9293
93
94
95
96
97
94
95
96
97
98
99
100
101
98102
99103
100104
......
102106
103107
104108
109
110
111
112
113
114
105115
106116
107117
......
246256
247257
248258
259
249260
250261
251262
......
306317
307318
308319
320
309321
310322
311323
......
321333
322334
323335
336
337
324338
325339
326340
......
365379
366380
367381
382
368383
369384
370385
386
387
371388
372389
373390
374391
375
392
393
394
376395
377
396
378397
379398
380399
......
443462
444463
445464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
446530
447531
448532
......
27492833
27502834
27512835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
27522907
27532908
27542909
......
33893544
33903545
33913546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
33923592
33933593
33943594
......
34163616
34173617
34183618
3419
3619
34203620
34213621
34223622
......
34263626
34273627
34283628
3429
3629
34303630
34313631
34323632
......
34383638
34393639
34403640
3441
3641
34423642
34433643
34443644
......
34463646
34473647
34483648
3449
3649
34503650
34513651
34523652
......
34563656
34573657
34583658
3459
3659
34603660
34613661
34623662
......
34673667
34683668
34693669
3470
3670
34713671
34723672
34733673
......
34753675
34763676
34773677
3478
3479
3678
3679
34803680
34813681
34823682
......
34853685
34863686
34873687
3488
3688
34893689
34903690
34913691
34923692
34933693
3494
3694
34953695
3496
3696
34973697
34983698
3499
3699
3700
3701
35003702
35013703
3502
3704
35033705
3504
3505
3706
35063707
35073708
3709
3710
3711
3712
35083713
35093714
35103715
......
45014706
45024707
45034708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
45044763
4764
45054765
45064766
45074767
......
45904850
45914851
45924852
4593
4853
4854
45944855
45954856
45964857
4597
4858
4859
4860
4861
4862
4863
4864
4865
45984866
45994867
46004868
......
46074875
46084876
46094877
4610
4878
46114879
46124880
46134881
......
46804948
46814949
46824950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
46834967
46844968
46854969
......
47044988
47054989
47064990
4707
4708
4991
4992
4993
4994
4995
4996
4997
4998
47094999
47105000
47115001
......
48755165
48765166
48775167
5168
48785169
48795170
48805171
......
48865177
48875178
48885179
4889
4890
5180
48915181
5182
5183
48925184
48935185
48945186
use IO::Poll qw(POLLHUP POLLIN POLLPRI);
use IPC::Open3;
use POSIX qw(:errno_h);
use Socket;
use Symbol qw(gensym);
# ***** GLOBAL DATA DECLARATIONS *****
use constant MTN_M_SELECTOR => 16;
use constant MTN_P_SELECTOR => 17;
use constant MTN_READ_PACKETS => 18;
use constant MTN_SET_ATTRIBUTE => 19;
use constant MTN_SET_DB_VARIABLE => 20;
use constant MTN_SHOW_CONFLICTS => 21;
use constant MTN_U_SELECTOR => 22;
use constant MTN_W_SELECTOR => 23;
use constant MTN_REMOTE_CONNECTIONS => 19;
use constant MTN_SET_ATTRIBUTE => 20;
use constant MTN_SET_DB_VARIABLE => 21;
use constant MTN_SHOW_CONFLICTS => 22;
use constant MTN_STREAM_IO => 23;
use constant MTN_SYNCHRONISATION => 24;
use constant MTN_U_SELECTOR => 25;
use constant MTN_W_SELECTOR => 26;
# Constants used to represent the different error levels.
use constant MTN_SEVERITY_ERROR => 0x01;
use constant MTN_SEVERITY_WARNING => 0x02;
# Constants used to represent data streams from Monotone that can be tied into
# file handles by the caller.
use constant MTN_P_STREAM => 0;
use constant MTN_T_STREAM => 1;
# Constant used to represent the exception thrown when interrupting waitpid().
use constant WAITPID_INTERRUPT => __PACKAGE__ . "::waitpid-interrupt";
# Constructors and destructor.
sub new_from_db($;$$);
sub new_from_service($$;$);
sub new_from_ws($;$$);
*new = *new_from_db;
sub DESTROY($);
sub register_db_locked_handler(;$$$);
sub register_error_handler($;$$$);
sub register_io_wait_handler(;$$$$);
sub register_stream_handle($$$);
sub roots($$);
sub select($$$);
sub set_attribute($$$$);
*attributes = *get_attributes;
*db_set = *set_db_variable;
*pull = *sync;
*push = *sync;
# Private methods and routines.
MTN_M_SELECTOR
MTN_P_SELECTOR
MTN_READ_PACKETS
MTN_REMOTE_CONNECTIONS
MTN_SET_ATTRIBUTE
MTN_SET_DB_VARIABLE
MTN_SHOW_CONFLICTS
MTN_STREAM_IO
MTN_SYNCHRONISATION
MTN_U_SELECTOR
MTN_W_SELECTOR)],
severities => [qw(MTN_SEVERITY_ALL
MTN_SEVERITY_ERROR
MTN_SEVERITY_WARNING)]);
MTN_SEVERITY_WARNING)],
streams => [qw(MTN_P_STREAM
MTN_T_STREAM)]);
our @EXPORT = qw();
Exporter::export_ok_tags(qw(capabilities severities));
Exporter::export_ok_tags(qw(capabilities severities streams));
our $VERSION = 0.06;
#
##############################################################################
#
##############################################################################
#
# Routine - new_from_service
#
# Description - Class constructor. Construct an object using the specified
# Monotone service.
#
# Data - $class : Either the name of the class that is to be
# created or an object of that class.
# $service : The name of the Monotone server to connect
# to, optionally followed by a colon and the
# port number.
# $options : A reference to a list containing a list of
# options to use on the mtn subprocess.
# Return Value : A reference to the newly created object.
#
##############################################################################
sub new_from_service($$;$)
{
my $class = (ref($_[0]) ne "") ? ref($_[0]) : $_[0];
shift();
my($service, $options) = @_;
$options = [] unless (defined($options));
my($server,
$this);
# Check all the arguments given to us.
validate_mtn_options($options);
# Check that the server is know to us.
if ($service =~ m/^([^:]+):\d+$/)
{
$server = $1;
}
else
{
$server = $service;
}
&$croaker("`" . $server . "' is not known")
unless (defined(inet_aton($server)));
# Actually construct the object.
$this = create_object_data();
$this->{db_name} = ":memory:";
$this->{network_service} = $service;
$this->{mtn_options} = $options;
bless($this, $class);
# Startup the mtn subprocess (also determining the interface version).
$this->startup();
return $this;
}
#
##############################################################################
#
# Routine - new_from_ws
#
# Description - Class constructor. Construct an object using the specified
#
##############################################################################
#
# Routine - sync
#
# Description - Synchronises database changes between the local database
# and the specified remote server. This member function also
# provides the implementation to the pull and push methods.
#
# Data - $this : The object.
# $options : A reference to a list containing the options
# to use.
# $service : The name of the server to synchronise with,
# optionally followed by a colon and the port
# to connect to or a URI.
# @patterns : A list of branch patterns to include in the
# pull operation.
# Return Value : True on success, otherwise false on failure.
#
##############################################################################
sub sync($;$$@)
{
my($this, $options, $service, @patterns) = @_;
my($cmd,
$dummy,
@opts);
# Find out how we were called (and hence the command that is to be run).
$cmd = (caller(0))[3];
# Process any options.
if (defined($options))
{
for (my $i = 0; $i < scalar(@$options); ++ $i)
{
if ($$options[$i] eq "set-default")
{
push(@opts, {key => $$options[$i], value => ""});
}
else
{
push(@opts, {key => $$options[$i], value => $$options[++ $i]});
}
}
}
# Run the command.
if (defined($service))
{
return $this->mtn_command_with_options($cmd,
1,
1,
\$dummy,
\@opts,
$service,
@patterns);
}
else
{
return $this->mtn_command_with_options($cmd, 1, 1, \$dummy, \@opts);
}
}
#
##############################################################################
#
# Routine - tags
#
# Description - Get all the tags attached to revisions on branches that
#
##############################################################################
#
# Routine - register_stream_handle
#
# Description - Register the specified file handle to receive data from the
# specified mtn automate stdio output stream.
#
# Data - $this : The object.
# $stream : The mtn output stream from which data is to be
# read and then written to the specified file
# handle.
# $handle : The file handle that is to receive the data from
# the specified output stream. If this is not
# provided then any existing file handle for that
# stream is unregistered.
#
##############################################################################
sub register_stream_handle($$$)
{
my($this, $stream, $handle) = @_;
if (defined($handle)
&& ref($handle) !~ m/^IO::[^:]+/ && ref($handle) ne "GLOB")
{
croak("Handle must be either undef or a valid handle");
}
if ($stream == MTN_P_STREAM)
{
$this->{p_stream_handle} = $handle;
}
elsif ($stream == MTN_T_STREAM)
{
$this->{t_stream_handle} = $handle;
}
else
{
croak("Unknown stream specified");
}
}
#
##############################################################################
#
# Routine - supports
#
# Description - Determine whether a certain feature is available with the
# These are only available from version 0.36 (i/f version 5.x).
return 1 if ($this->{mtn_aif_major} >= 5);
return 1 if ($this->{mtn_aif_version} >= 5);
}
elsif ($feature == MTN_IGNORING_OF_SUSPEND_CERTS
# These are only available from version 0.37 (i/f version 6.x).
return 1 if ($this->{mtn_aif_major} >= 6);
return 1 if ($this->{mtn_aif_version} >= 6);
}
elsif ($feature == MTN_DROP_DB_VARIABLES
# These are only available from version 0.39 (i/f version 7.x).
return 1 if ($this->{mtn_aif_major} >= 7);
return 1 if ($this->{mtn_aif_version} >= 7);
}
elsif ($feature == MTN_DB_GET)
# This is only available prior version 0.39 (i/f version 7.x).
return 1 if ($this->{mtn_aif_major} < 7);
return 1 if ($this->{mtn_aif_version} < 7);
}
elsif ($feature == MTN_GET_WORKSPACE_ROOT
# These are only available from version 0.41 (i/f version 8.x).
return 1 if ($this->{mtn_aif_major} >= 8);
return 1 if ($this->{mtn_aif_version} >= 8);
}
elsif ($feature == MTN_CONTENT_DIFF_EXTRA_OPTIONS
# These are only available from version 0.42 (i/f version 9.x).
return 1 if ($this->{mtn_aif_major} >= 9);
return 1 if ($this->{mtn_aif_version} >= 9);
}
elsif ($feature == MTN_M_SELECTOR || $feature == MTN_U_SELECTOR)
# These are only available from version 0.43 (i/f version 9.x).
return 1 if ($this->{mtn_aif_major} >= 10
|| ($this->{mtn_aif_major} == 9
return 1 if ($this->{mtn_aif_version} >= 10
|| (int($this->{mtn_aif_version}) == 9
&& $mtn_version == 0.43));
}
# These are only available from version 0.44 (i/f version 10.x).
return 1 if ($this->{mtn_aif_major} >= 10);
return 1 if ($this->{mtn_aif_version} >= 10);
}
elsif ($feature == MTN_HASHED_SIGNATURES)
{
# These are only available from version 0.45 (i/f version 11.x).
# This is only available from version 0.45 (i/f version 11.x).
return 1 if ($this->{mtn_aif_major} >= 11);
return 1 if ($this->{mtn_aif_version} >= 11);
}
else
elsif ($feature == MTN_REMOTE_CONNECTIONS
|| $feature == MTN_STREAM_IO
|| $feature == MTN_SYNCHRONISATION)
{
# An unknown feature was requested.
# These are only available from version 0.46 (i/f version 12.x).
$this->{error_msg} = "Unknown feature requested";
&$carper($this->{error_msg});
return 1 if ($this->{mtn_aif_version} >= 12);
}
else
{
croak("Unknown feature requested");
}
return;
}
else
{
my($data,
$data_ref,
$fh);
# We have finished processing the current data chunk so if it
# belongs to a stream that is to be redirected to a file handle
# then send the data down it.
if (defined($this->{p_stream_handle}) && $stream eq "p")
{
# The p or progress stream is simply text so just send the
# data.
$fh = $this->{p_stream_handle};
$data_ref = $buffers{p}->{buffer_ref};
}
elsif (defined($this->{t_stream_handle}) && $stream eq "t")
{
# The t or ticker stream contains messages and not
# unstructured text so send the raw data straight through
# (i.e. include the headers).
$fh = $this->{t_stream_handle};
$data = $header . $buffers{p}->{buffer_ref};
$data_ref = \$data;
}
if (defined($fh))
{
my($bytes_written,
$offset,
$size);
$offset = 0;
$size = length($$data_ref);
while ($size > 0)
{
if (! defined($bytes_written = syswrite($fh,
$$data_ref,
$size,
$offset)))
{
croak("syswrite failed: " . $!);
}
$size -= $bytes_written;
$offset += $bytes_written;
}
$$buffer_ref = "";
$$offset_ref = 0;
}
$chunk_start = 1;
}
}
elsif ($size == 1)
# subprocess.
@args = ("mtn");
push(@args, "--db=" . $this->{db_name}) if ($this->{db_name});
push(@args, "--db=" . $this->{db_name}) if (defined($this->{db_name}));
push(@args, "--quiet") if (defined($this->{network_service}));
push(@args, "--ignore-suspend-certs")
if (! $this->{honour_suspend_certs});
push(@args, @{$this->{mtn_options}});
push(@args, "automate", "stdio");
if (defined($this->{network_service}))
{
push(@args, "automate", "remote_stdio", $this->{network_service});
}
else
{
push(@args, "automate", "stdio");
}
# Actually start the mtn subprocess. If a database name has been
# provided then run the mtn subprocess in the system's root directory
$my_pid = $$;
eval
{
if (defined($this->{db_name}))
if (defined($this->{db_name}) || defined($this->{network_service}))
{
die("chdir failed: " . $!)
unless (chdir(File::Spec->rootdir()));
{
my($char,
$last_char);
if (defined($this->{network_service}))
{
my $poll_result;
for (my $i = 0;
$i < 10
&& ($poll_result
= $this->{poll}->poll($io_wait_handler_timeout))
== 0;
++ $i)
{
&$io_wait_handler($this, $io_wait_handler_data);
}
&$croaker("Cannot connect to service `"
. $this->{network_service} . "'")
if ($poll_result == 0);
}
$char = "";
do
{
# Get the interface version.
$this->interface_version(\$version);
($this->{mtn_aif_major}, $this->{mtn_aif_minor}) =
($version =~ m/^(\d+)\.(\d+)$/);
if ($version =~ m/^(\d+)\.(\d+)$/)
{
$this->{mtn_aif_version} = $1;
}
else
{
&$croaker("Cannot get automate stdio interface version number");
}
}
return {db_name => undef,
ws_path => undef,
network_service => undef,
ws_constructed => undef,
cd_to_ws_root => $cd_to_ws_root,
convert_to_utf8 => $convert_to_utf8,
poll => undef,
error_msg => "",
honour_suspend_certs => 1,
mtn_aif_major => 0,
mtn_aif_minor => 0,
mtn_aif_version => undef,
cmd_cnt => 0,
p_stream_handle => undef,
t_stream_handle => undef,
db_is_locked => undef,
db_locked_handler => undef,
db_locked_handler_data => undef,

Archive Download the corresponding diff file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status