# # # patch "lib/Monotone/AutomateStdio.pm" # from [d836d368cd79a3154b0bf39dbcb6041ca17c92e2] # to [ea2fd5df67329d15eafed8b635be9706ccdafbf9] # # patch "lib/Monotone/AutomateStdio.pod" # from [ade191d9e5c4b7f689052b18f93539dfa41709bf] # to [8a2a3510ba0de46b79bf06d68e747ab6cc2583ce] # ============================================================ --- lib/Monotone/AutomateStdio.pm d836d368cd79a3154b0bf39dbcb6041ca17c92e2 +++ lib/Monotone/AutomateStdio.pm ea2fd5df67329d15eafed8b635be9706ccdafbf9 @@ -197,9 +197,14 @@ my %tags_keys = ("branches" => NUL "signer" => STRING, "tag" => STRING); -# Global error, database locked and io wait callback routine references and -# associated client data. +# Flag for determining whether the mtn subprocess should be started in a +# workspace's root directory. +my $cd_to_ws_root = 1; + +# Error, database locked and io wait callback routine references and associated +# client data. + my $carper = sub { return; }; my $croaker = \&croak; my $db_locked_handler = sub { return; }; @@ -278,6 +283,7 @@ sub show_conflicts($$;$$$); sub set_attribute($$$$); sub set_db_variable($$$$); sub show_conflicts($$;$$$); +sub switch_to_ws_root($$); sub tags($$;$); sub toposort($$@); @@ -446,6 +452,7 @@ sub new_from_ws($;$$) $this = create_object_data(); $this->{ws_path} = $ws_path; + $this->{ws_constructed} = 1; $this->{mtn_options} = $options; bless($this, $class); @@ -2952,7 +2959,7 @@ sub db_locked_condition_detected($) # Data - $this : The object. # Return Value : The file name of the database as given to # the constructor or undef if no database was -# given. +# specified. # ############################################################################## @@ -3022,15 +3029,16 @@ sub get_pid($) # # Description - Return the the workspace's base directory as either given # to the constructor or deduced from the current workspace. +# If neither condition holds true then undef is returned. # Please note that the workspace's base directory may differ # from that given to the constructor if the specified # workspace path is actually a subdirectory within that # workspace. # # Data - $this : The object. -# Return Value : The workspace's base directory as given to -# the constructor or undef if no workspace was -# given and there is no current workspace. +# Return Value : The workspace's base directory or undef if +# no workspace was specified and there is no +# current workspace. # ############################################################################## @@ -3053,13 +3061,12 @@ sub get_ws_path($) # ignored or not. If the head revisions on a branch are all # suspended then that branch is also ignored. # -# Data - $this : The object. -# $ignore : True if suspend certs are to be ignored -# (i.e. all revisions are `visible'), -# otherwise false if suspend certs are to be -# honoured. -# Return Value : True on success, otherwise false on -# failure. +# Data - $this : The object. +# $ignore : True if suspend certs are to be ignored +# (i.e. all revisions are `visible'), +# otherwise false if suspend certs are to be +# honoured. +# Return Value : True on success, otherwise false on failure. # ############################################################################## @@ -3076,7 +3083,7 @@ sub ignore_suspend_certs($$) { if (can($this, MTN_IGNORE_SUSPEND_CERTS)) { - $this->{honour_suspend_certs} = 0; + $this->{honour_suspend_certs} = undef; closedown($this); startup($this); } @@ -3337,6 +3344,74 @@ sub register_io_wait_handler(;$$$$) # ############################################################################## # +# Routine - switch_to_ws_root +# +# Description - Control whether this class automatically switches to a +# workspace's root directory before running the mtn +# subprocess. The default action is to do so as this is +# generally safer. +# +# Data - $this : The object. +# $switch : True if the mtn subprocess should be started +# in a workspace's root directory, otherwise +# false if it should be started in the current +# working directory. +# Return Value : True on success, otherwise false on failure. +# +############################################################################## + + + +sub switch_to_ws_root($$) +{ + + my $this; + if (ref($_[0]) eq __PACKAGE__) + { + $this = shift(); + } + elsif ($_[0] eq __PACKAGE__) + { + shift(); + } + my $switch = $_[0]; + + if (defined($this)) + { + if (! $this->{ws_constructed}) + { + if ($this->{cd_to_ws_root} && ! $switch) + { + $this->{cd_to_ws_root} = undef; + closedown($this); + startup($this); + } + elsif (! $this->{cd_to_ws_root} && $switch) + { + $this->{cd_to_ws_root} = 1; + closedown($this); + startup($this); + } + } + else + { + $this->{error_msg} = "Cannot call $mtn->switch_to_ws_root() on " + . "objects constructed with new_from_ws()"; + &$carper($this->{error_msg}); + return; + } + } + else + { + $cd_to_ws_root = $switch ? 1 : undef; + } + + return 1; + +} +# +############################################################################## +# # Routine - parse_revision_data # # Description - Parse the specified revision data into a list of records. @@ -3991,7 +4066,8 @@ sub startup($) # provided then run the mtn subprocess in the system's root directory # so as to avoid any database/workspace clash. Likewise if a workspace # has been provided then run the mtn subprocess in the base directory - # of that workspace. + # of that workspace (although in this case the caller can override this + # feature if it wishes to do so). $cwd = getcwd(); eval @@ -4001,7 +4077,7 @@ sub startup($) die("chdir failed: " . $!) unless (chdir(File::Spec->rootdir())); } - elsif (defined($this->{ws_path})) + elsif ($this->{cd_to_ws_root} && defined($this->{ws_path})) { die("chdir failed: " . $!) unless (chdir($this->{ws_path})); } @@ -4193,6 +4269,8 @@ sub create_object_data() return {db_name => undef, ws_path => undef, + ws_constructed => undef, + cd_to_ws_root => $cd_to_ws_root, mtn_options => undef, mtn_pid => 0, mtn_in => undef, ============================================================ --- lib/Monotone/AutomateStdio.pod ade191d9e5c4b7f689052b18f93539dfa41709bf +++ lib/Monotone/AutomateStdio.pod 8a2a3510ba0de46b79bf06d68e747ab6cc2583ce @@ -59,8 +59,8 @@ Creates a new Monotone::AutomateStdio ob =back -Please note that $mtn-Enew() is simply an alias for -$mtn-Enew_from_db(). +Please note that Monotone::AutomateStdio-Enew() is simply an alias for +Monotone::AutomateStdio-Enew_from_db(). The @options parameter specifies what options are to be passed to the mtn subprocess. The currently supported list (in vaguely the format in which it @@ -80,6 +80,29 @@ would be passed to the constructor) is: =over 4 +=item Bregister_db_locked_handler([$handler[, +$client_data]])> + +Registers the handler specified as a subroutine reference in $handler for +database locked conditions. The value of $client_data is simply passed to the +handler and can be used by the caller to provide a context. This is both a +class method as well as an object one. When used as a class method, the +specified database locked handler is used for all Monotone::AutomateStdio +objects that do not specify their own handlers. If no handler is given then the +database locked condition handling is reset to the default behaviour. + +The handler subroutine is given two arguments, the first one is the +Monotone::AutomateStdio object that encountered the locked database and the +second is the value passed in as $client_data when the hander was +registered. If the handler returns true then the request that failed is +retried, if false is returned (undef) then the default behaviour is performed, +which is to treat it like any other error. + +Typically one would register a database locked handler when you are using this +class in a long running application where it is quite possible that a user +might do an mtn sync in the background. For example, mtn-browse uses this +handler to display a `Database is locked, please retry...' dialog window. + =item Bregister_error_handler($severity[, $handler[, $client_data]])> @@ -140,29 +163,6 @@ following to load in this library. =back -=item Bregister_db_locked_handler([$handler[, -$client_data]])> - -Registers the handler specified as a subroutine reference in $handler for -database locked conditions. The value of $client_data is simply passed to the -handler and can be used by the caller to provide a context. This is both a -class method as well as an object one. When used as a class method, the -specified database locked handler is used for all Monotone::AutomateStdio -objects that do not specify their own handlers. If no handler is given then the -database locked condition handling is reset to the default behaviour. - -The handler subroutine is given two arguments, the first one is the -Monotone::AutomateStdio object that encountered the locked database and the -second is the value passed in as $client_data when the hander was -registered. If the handler returns true then the request that failed is -retried, if false is returned (undef) then the default behaviour is performed, -which is to treat it like any other error. - -Typically one would register a database locked handler when you are using this -class in a long running application where it is quite possible that a user -might do an mtn sync in the background. For example, mtn-browse uses this -handler to display a `Database is locked, please retry...' dialog window. - =item Bregister_io_wait_handler([$handler, $timeout[, $client_data]])> @@ -186,6 +186,17 @@ Gtk2 events so that the application can something. For example, mtn-browse uses this handler to process any outstanding Gtk2 events so that the application can keep its windows up to date. +=item Bswitch_to_ws_root($switch)> + +Controls whether this class automatically switches to a workspace's root +directory before running the mtn subprocess. The default action is to do so as +this is generally safer. This setting only affects objects constructed from +calling Monotone::AutomateStdio-Enew() and +Monotone::AutomateStdio-Enew_from_db(). This is both a class method as well +as an object one. When used as a class method, the setting is used for all +applicable Monotone::AutomateStdio objects that do not specify their own +setting. + =back =head1 OBJECT METHODS @@ -565,9 +576,10 @@ Return the the workspace's base director =item B<$mtn-Eget_ws_path()> Return the the workspace's base directory as either given to the constructor or -deduced from the current workspace. Please note that the workspace's base -directory may differ from that given to the constructor if the specified -workspace path is actually a subdirectory within that workspace. +deduced from the current workspace. If neither condition holds true then undef +is returned. Please note that the workspace's base directory may differ from +that given to the constructor if the specified workspace path is actually a +subdirectory within that workspace. =item B<$mtn-Egraph(\$buffer | address@hidden)> @@ -943,6 +955,33 @@ waiting for the mtn subprocess to finish =head1 NOTES +=head2 Using This Class With Monotone Workspaces + +Certain features are only available when used inside a Monotone workspace, so +consequently this class does support the use of workspaces. However certain +aspects of a workspace can affect the mtn subprocess. For example, when you run +mtn in a workspace's subdirectory then all file name arguments get translated +into paths relative to the workspace's root directory (i.e. given a path of +/home/freddy/workspace/include/system.h when one runs C in +the include directory the file name gets changed to include/system.h). + +This makes perfect sense on the command line but possibly less so when using +mtn from inside an application. This is why this class runs the mtn subprocess +in specific directories depending upon how the object is constructed. If the +object is constructed by calling Monotone::AutomateStdio-Enew() or +Monotone::AutomateStdio-Enew_from_db() with the name of a database, then +the mtn subprocess is run in the root directory, otherwise it is run in the +workspace's root directory. This guarantees correct behaviour. + +If however you want the mtn subprocess to run in the current directory within a +workspace then simply use the Monotone::AutomateStdio-Eswitch_to_ws_root() +method to before calling Monotone::AutomateStdio-Enew() without specifying +a database. + +Any changing of directory does not affect the caller. + +=head2 Process Handling + There are situations where this class does legitimately terminate the mtn subprocess (for example when a database locked condition is detected). When this happens the subprocess is reaped and its id is reset, i.e. the @@ -957,6 +996,8 @@ worry about. problem, otherwise, as far as this class is concerned, there is nothing to worry about. +=head2 Use Of SIGALRM + In order to reliably shutdown the mtn subprocess, the alarm() routine is used and will consequently reset any SIGALRM timers. In C I would obviously use setitimer() to set up any timeout timers and then restore their previous state, @@ -966,6 +1007,8 @@ opinions on this then please let me know to have a thread do that for you rather than use signals. If you have different opinions on this then please let me know. +==head2 General + When the output of a command from the automate stdio interface changes dramatically, it will probably not be possible to protect Perl applications from those changes. This class is a convenience wrapper rather than something