File Coverage

blib/lib/App/Sqitch/Target.pm
Criterion Covered Total %
statement 98 99 98.9
branch 48 50 96.0
condition 15 20 75.0
subroutine 14 14 100.0
pod 2 3 66.6
total 177 186 95.1


line stmt bran cond sub pod time code
1             package App::Sqitch::Target;
2              
3 43     43   33081 use 5.010;
  43         212  
4 43     43   285 use Moo;
  43         130  
  43         432  
5 43     43   18062 use strict;
  43         112  
  43         1179  
6 43     43   343 use warnings;
  43         112  
  43         2212  
7 43     43   335 use App::Sqitch::Types qw(Maybe URIDB Str Dir Engine Sqitch File Plan HashRef);
  43         117  
  43         654  
8 43     43   80733 use App::Sqitch::X qw(hurl);
  43         141  
  43         471  
9 43     43   15374 use Locale::TextDomain qw(App-Sqitch);
  43         140  
  43         498  
10 43     43   10518 use Path::Class qw(dir file);
  43         148  
  43         3790  
11 43     43   20201 use URI::db;
  43         623149  
  43         1406  
12 43     43   376 use namespace::autoclean;
  43         114  
  43         440  
13              
14             our $VERSION = 'v1.4.0'; # VERSION
15              
16             has name => (
17             is => 'ro',
18             isa => Str,
19             required => 1,
20             );
21 13     13 1 4710 sub target { shift->name }
22              
23             has uri => (
24             is => 'ro',
25             isa => URIDB,
26             required => 1,
27             handles => {
28             engine_key => 'canonical_engine',
29             dsn => 'dbi_dsn',
30             },
31             );
32              
33             has username => (
34             is => 'ro',
35             isa => Maybe[Str],
36             lazy => 1,
37             default => sub {
38             my $self = shift;
39             $ENV{SQITCH_USERNAME} || $self->uri->user
40             },
41             );
42              
43             has password => (
44             is => 'ro',
45             isa => Maybe[Str],
46             lazy => 1,
47             default => sub {
48             $ENV{SQITCH_PASSWORD} || shift->uri->password
49             },
50             );
51              
52             has sqitch => (
53             is => 'ro',
54             isa => Sqitch,
55             required => 1,
56             handles => {
57             _config => 'config',
58             _options => 'options',
59             },
60             );
61              
62             has engine => (
63             is => 'ro',
64             isa => Engine,
65             lazy => 1,
66             default => sub {
67             my $self = shift;
68             require App::Sqitch::Engine;
69             App::Sqitch::Engine->load({
70             sqitch => $self->sqitch,
71             target => $self,
72             });
73             },
74             );
75              
76             sub _fetch {
77 1133     1133   2997 my ($self, $key) = @_;
78 1133         19922 my $config = $self->_config;
79             return $config->get( key => "target." . $self->name . ".$key" )
80 1133   100     58077 || do {
81             my $ekey = $self->engine_key;
82             $ekey ? $config->get( key => "engine.$ekey.$key") : ();
83             } || $config->get( key => "core.$key");
84             }
85              
86             has variables => (
87             is => 'rw',
88             isa => HashRef[Str],
89             lazy => 1,
90             default => sub {
91             my $self = shift;
92             my $config = $self->sqitch->config;
93             return {
94             map { %{ $config->get_section( section => "$_.variables" ) || {} } } (
95             'engine.' . $self->engine_key,
96             'target.' . $self->name,
97             )
98             };
99             },
100             );
101              
102             has registry => (
103             is => 'ro',
104             isa => Str,
105             lazy => 1,
106             default => sub {
107             my $self = shift;
108             $self->_fetch('registry') || $self->engine->default_registry;
109             },
110             );
111              
112             has client => (
113             is => 'ro',
114             isa => Str,
115             lazy => 1,
116             default => sub {
117             my $self = shift;
118             $self->_fetch('client') || do {
119             my $client = $self->engine->default_client;
120             return $client unless App::Sqitch::ISWIN;
121             return $client if $client =~ /[.](?:exe|bat)$/;
122             return $client . '.exe';
123             };
124             },
125             );
126              
127             has plan_file => (
128             is => 'ro',
129             isa => File,
130             lazy => 1,
131             default => sub {
132             my $self = shift;
133             if ( my $f = $self->_fetch('plan_file') ) {
134             return file $f;
135             }
136             return $self->top_dir->file('sqitch.plan')->cleanup;
137             },
138             );
139              
140             has plan => (
141             is => 'ro',
142             isa => Plan,
143             lazy => 1,
144             default => sub {
145             my $self = shift;
146             App::Sqitch::Plan->new(
147             sqitch => $self->sqitch,
148             target => $self,
149             );
150             },
151             );
152              
153             has top_dir => (
154             is => 'ro',
155             isa => Dir,
156             lazy => 1,
157             default => sub {
158             my $self = shift;
159             dir $self->_fetch('top_dir') || ();
160             },
161             );
162              
163             has reworked_dir => (
164             is => 'ro',
165             isa => Dir,
166             lazy => 1,
167             default => sub {
168             my $self = shift;
169             if ( my $dir = $self->_fetch('reworked_dir') ) {
170             return dir $dir;
171             }
172             $self->top_dir;
173             },
174             );
175              
176             for my $script (qw(deploy revert verify)) {
177             has "$script\_dir" => (
178             is => 'ro',
179             isa => Dir,
180             lazy => 1,
181             default => sub {
182             my $self = shift;
183             if ( my $dir = $self->_fetch("$script\_dir") ) {
184             return dir $dir;
185             }
186             $self->top_dir->subdir($script)->cleanup;
187             },
188             );
189             has "reworked_$script\_dir" => (
190             is => 'ro',
191             isa => Dir,
192             lazy => 1,
193             default => sub {
194             my $self = shift;
195             if ( my $dir = $self->_fetch("reworked_$script\_dir") ) {
196             return dir $dir;
197             }
198             $self->reworked_dir->subdir($script)->cleanup;
199             },
200             );
201             }
202              
203             has extension => (
204             is => 'ro',
205             isa => Str,
206             lazy => 1,
207             default => sub {
208             shift->_fetch('extension') || 'sql';
209             },
210             );
211              
212             sub BUILDARGS {
213 612     612 0 975322 my $class = shift;
214 612 50 33     4375 my $p = @_ == 1 && ref $_[0] ? { %{ +shift } } : { @_ };
  0         0  
215              
216             # Fetch params. URI can come from passed name.
217 612 100       2637 my $sqitch = $p->{sqitch} or return $p;
218 611   100     4687 my $name = $p->{name} || $ENV{SQITCH_TARGET} || '';
219 611         1487 my $uri = $p->{uri};
220              
221             # If we have a URI up-front, it's all good.
222 611 100       3104 if ($uri) {
223 139 100       5969 unless ($name) {
224             # Set the URI as the name, sans password.
225 98 100       867 if ($uri->password) {
226 8         702 $uri = $uri->clone;
227 8         192 $uri->password(undef);
228             }
229 98         6868 $p->{name} = $uri->as_string;
230             }
231 139         3871 return $p;
232             }
233              
234 472         915 my $ekey;
235 472         9014 my $config = $sqitch->config;
236              
237             # If no name, try to find one.
238 472 100       5192 if (!$name) {
239             # There are a couple of places to look for a name.
240             NAME: {
241             # Look for core target.
242 272 100       626 if ( $uri = $config->get( key => 'core.target' ) ) {
  272         1482  
243             # We got core.target.
244 3         518 $p->{name} = $name = $uri;
245 3         10 last NAME;
246             }
247              
248             # No core target, look for an engine key.
249 269 100       37263 $ekey = $config->get( key => 'core.engine' ) or do {
250 5 100       580 hurl target => __(
251             'No engine specified; specify via target or core.engine'
252             ) if $config->initialized;
253 4         26 hurl target => __(
254             'No project configuration found. Run the "init" command to initialize a project'
255             );
256             };
257 264         42161 $ekey =~ s/\s+$//;
258              
259             # Find the name in the engine config, or fall back on a simple URI.
260 264   66     1528 $uri = $config->get( key => "engine.$ekey.target" ) || "db:$ekey:";
261 264         36983 $p->{name} = $name = $uri;
262             }
263             }
264              
265             # Now we should have a name. What is it?
266 467 100       2344 if ($name =~ /:/) {
267             # The name is a URI.
268 384         880 $uri = $name;
269 384         1010 $name = $p->{name} = undef;
270             } else {
271 83         231 $p->{name} = $name;
272             # Well then, there had better be a config with a URI.
273 83 100       466 $uri = $config->get( key => "target.$name.uri" ) or do {
274             # Die on no section or no URI.
275             hurl target => __x(
276             'Cannot find target "{target}"',
277             target => $name
278 3 100       420 ) unless %{ $config->get_section(
  3         18  
279             section => "target.$name"
280             ) };
281 1         10 hurl target => __x(
282             'No URI associated with target "{target}"',
283             target => $name,
284             );
285             };
286             }
287              
288             # Instantiate the URI.
289 464         17825 $uri = $p->{uri} = URI::db->new( $uri );
290 464 100 100     118110 $ekey ||= $uri->canonical_engine or hurl target => __x(
291             'No engine specified by URI {uri}; URI must start with "db:$engine:"',
292             uri => $uri->as_string,
293             );
294              
295             # Override with optional parameters.
296 462         5404 for my $attr (qw(user host port dbname)) {
297 1848 100       4794 $uri->$attr(delete $p->{$attr}) if exists $p->{$attr};
298             }
299              
300 462 100       1967 unless ($name) {
301             # Set the name.
302 382 100       2394 if ($uri->password) {
303             # Remove the password from the name.
304 11         705 my $tmp = $uri->clone;
305 11         236 $tmp->password(undef);
306 11         1452 $p->{name} = $tmp->as_string;
307             } else {
308 371         22836 $p->{name} = $uri->as_string;
309             }
310             }
311              
312 462         17305 return $p;
313             }
314              
315             sub all_targets {
316 39     39 1 19710 my ($class, %p) = @_;
317 39 50       228 my $sqitch = $p{sqitch} or hurl 'Missing required argument: sqitch';
318 39   33     1367 my $config = delete $p{config} || $sqitch->config;
319 39         533 my (@targets, %seen);
320 39         379 my %dump = $config->dump;
321              
322             # First, load the default target.
323 39   100     1859 my $core = $dump{'core.target'} || do {
324             if ( my $engine = $dump{'core.engine'} ) {
325             $engine =~ s/\s+$//;
326             $dump{"engine.$engine.target"} || "db:$engine:";
327             }
328             };
329 39 100       973 push @targets => $seen{$core} = $class->new(%p, name => $core)
330             if $core;
331              
332             # Next, load named targets.
333 39         4080 for my $key (keys %dump) {
334 196 100       1307 next if $key !~ /^target[.]([^.]+)[.]uri$/;
335             push @targets => $seen{$1} = $class->new(%p, name => $1)
336 13 100       324 unless $seen{$1};
337             }
338              
339             # Now, load the engine targets.
340 39         378 while ( my ($key, $val) = each %dump ) {
341 196 100       796 next if $key !~ /^engine[.]([^.]+)[.]target$/;
342             push @targets => $seen{$val} = $class->new(%p, name => $val)
343 16 100       187 unless $seen{$val};
344 16         496 $seen{$1} = $seen{$val};
345             }
346              
347             # Finally, load any engines for which no target name was specified.
348 39         218 while ( my ($key, $val) = each %dump ) {
349 196 100       4268 my ($engine) = $key =~ /^engine[.]([^.]+)/ or next;
350 107         314 $engine =~ s/\s+$//;
351 107 100       802 next if $seen{$engine}++;
352 66         327 my $uri = URI->new("db:$engine:");
353             push @targets => $seen{$uri} = $class->new(%p, uri => $uri)
354 66 100       16047 unless $seen{$uri};
355             }
356              
357             # Return all the targets.
358 39         1300 return @targets;
359             }
360              
361             1;
362              
363             __END__
364              
365             =head1 Name
366              
367             App::Sqitch::Target - Sqitch deployment target
368              
369             =head1 Synopsis
370              
371             my $plan = App::Sqitch::Target->new(
372             sqitch => $sqitch,
373             name => 'development',
374             );
375             $target->engine->deploy;
376              
377             =head1 Description
378              
379             App::Sqitch::Target provides collects, in one place, the
380             L<engine|App::Sqitch::Engine>, L<plan|App::Sqitch::Engine>, and file locations
381             required to carry out Sqitch commands. All commands should instantiate a
382             target to work with the plan or database.
383              
384             =head1 Interface
385              
386             =head2 Constructors
387              
388             =head3 C<new>
389              
390             my $target = App::Sqitch::Target->new( sqitch => $sqitch );
391              
392             Instantiates and returns an App::Sqitch::Target object. The most important
393             parameters are C<sqitch>, C<name>, and C<uri>. The constructor tries really
394             hard to figure out the proper name and URI during construction. If the C<uri>
395             parameter is passed, this is straight-forward: if no C<name> is passed,
396             C<name> will be set to the stringified format of the URI (minus the password,
397             if present).
398              
399             Otherwise, when no URI is passed, the name and URI are determined by taking
400             the following steps:
401              
402             =over
403              
404             =item *
405              
406             If there is no name, get the engine key from or the C<core.engine>
407             +configuration option. If no key can be determined, an exception will be
408             thrown.
409              
410             =item *
411              
412             Use the key to look up the target name in the C<engine.$engine.target>
413             configuration option. If none is found, use C<db:$key:>.
414              
415             =item *
416              
417             If the name contains a colon (C<:>), assume it is also the value for the URI.
418              
419             =item *
420              
421             Otherwise, it should be the name of a configured target, so look for a URI in
422             the C<target.$name.uri> configuration option.
423              
424             =back
425              
426             As a general rule, then, pass either a target name or URI string in the
427             C<name> parameter, and Sqitch will do its best to find all the relevant target
428             information. And if there is no name or URI, it will try to construct a
429             reasonable default from the command-line options or engine configuration.
430              
431             All Target attributes may be passed as parameters to C<new()>. In addition,
432             C<new()> accepts a few non-attribute parameters that may be used to override
433             parts of the connection URI. They are:
434              
435             =over
436              
437             =item * C<user>
438              
439             =item * C<host>
440              
441             =item * C<port>
442              
443             =item * C<dbname>
444              
445             =back
446              
447             For example, if the the named target had its URI configured as
448             C<db:pg://fred@example.com/work>, The C<uri> would be set as such by:
449              
450             my $target = App::Sqitch::Target->new(sqitch => $sqitch, name => 'work');
451             say $target->uri;
452              
453             However, passing the URI parameters like this:
454              
455             my $target = App::Sqitch::Target->new(
456             sqitch => $sqitch,
457             name => 'work',
458             user => 'bill',
459             port => 1212,
460             );
461             say $target->uri;
462              
463             Sets the URI to C<db:pg://bill@example.com:1212/work>.
464              
465             =head3 C<all_targets>
466              
467             Returns a list of all the targets defined by the local Sqitch configuration
468             file. Done by examining the configuration object to find all defined targets
469             and engines, as well as the default "core" target. Duplicates are removed and
470             the list returned. This method takes the same parameters as C<new>; only
471             C<sqitch> is required. All other parameters will be set on all of the returned
472             targets.
473              
474             =head2 Accessors
475              
476             =head3 C<sqitch>
477              
478             my $sqitch = $target->sqitch;
479              
480             Returns the L<App::Sqitch> object that instantiated the target.
481              
482             =head3 C<name>
483              
484             =head3 C<target>
485              
486             my $name = $target->name;
487             $name = $target->target;
488              
489             The name of the target. If there was no name specified, the URI will be used
490             (minus the password, if there is one).
491              
492             =head3 C<uri>
493              
494             my $uri = $target->uri;
495              
496             The L<URI::db> object encapsulating the database connection information.
497              
498             =head3 C<username>
499              
500             my $username = $target->username;
501              
502             Returns the target username, if any. The username is looked up from the URI.
503              
504             =head3 C<password>
505              
506             my $password = $target->password;
507              
508             Returns the target password, if any. The password is looked up from the URI
509             or the C<$SQITCH_PASSWORD> environment variable.
510              
511             =head3 C<engine>
512              
513             my $engine = $target->engine;
514              
515             A L<App::Sqitch::Engine> object to use for database interactions with the
516             target.
517              
518             =head3 C<registry>
519              
520             my $registry = $target->registry;
521              
522             The name of the registry used by the database. The value comes from one of
523             these options, searched in this order:
524              
525             =over
526              
527             =item * C<--registry>
528              
529             =item * C<target.$name.registry>
530              
531             =item * C<engine.$engine.registry>
532              
533             =item * C<core.registry>
534              
535             =item * Engine-specific default
536              
537             =back
538              
539             =head3 C<client>
540              
541             my $client = $target->client;
542              
543             Path to the engine command-line client. The value comes from one of these
544             options, searched in this order:
545              
546             =over
547              
548             =item * C<--client>
549              
550             =item * C<target.$name.client>
551              
552             =item * C<engine.$engine.client>
553              
554             =item * C<core.client>
555              
556             =item * Engine-and-OS-specific default
557              
558             =back
559              
560             =head3 C<top_dir>
561              
562             my $top_dir = $target->top_dir;
563              
564             The path to the top directory of the project. This directory generally
565             contains the plan file and subdirectories for deploy, revert, and verify
566             scripts. The value comes from one of these options, searched in this order:
567              
568             =over
569              
570             =item * C<--top-dir>
571              
572             =item * C<target.$name.top_dir>
573              
574             =item * C<engine.$engine.top_dir>
575              
576             =item * C<core.top_dir>
577              
578             =item * F<.>
579              
580             =back
581              
582             =head3 C<plan_file>
583              
584             my $plan_file = $target->plan_file;
585              
586             The path to the plan file. The value comes from one of these options, searched
587             in this order:
588              
589             =over
590              
591             =item * C<--plan-file>
592              
593             =item * C<target.$name.plan_file>
594              
595             =item * C<engine.$engine.plan_file>
596              
597             =item * C<core.plan_file>
598              
599             =item * F<C<$top_dir>/sqitch.plan>
600              
601             =back
602              
603             =head3 C<deploy_dir>
604              
605             my $deploy_dir = $target->deploy_dir;
606              
607             The path to the deploy directory of the project. This directory contains all
608             of the deploy scripts referenced by changes in the C<plan_file>. The value
609             comes from one of these options, searched in this order:
610              
611             =over
612              
613             =item * C<--dir deploy_dir=$deploy_dir>
614              
615             =item * C<target.$name.deploy_dir>
616              
617             =item * C<engine.$engine.deploy_dir>
618              
619             =item * C<core.deploy_dir>
620              
621             =item * F<C<$top_dir/deploy>>
622              
623             =back
624              
625             =head3 C<revert_dir>
626              
627             my $revert_dir = $target->revert_dir;
628              
629             The path to the revert directory of the project. This directory contains all
630             of the revert scripts referenced by changes the C<plan_file>. The value comes
631             from one of these options, searched in this order:
632              
633             =over
634              
635             =item * C<--dir revert_dir=$revert_dir>
636              
637             =item * C<target.$name.revert_dir>
638              
639             =item * C<engine.$engine.revert_dir>
640              
641             =item * C<core.revert_dir>
642              
643             =item * F<C<$top_dir/revert>>
644              
645             =back
646              
647             =head3 C<verify_dir>
648              
649             my $verify_dir = $target->verify_dir;
650              
651             The path to the verify directory of the project. This directory contains all
652             of the verify scripts referenced by changes in the C<plan_file>. The value
653             comes from one of these options, searched in this order:
654              
655             =over
656              
657             =item * C<--dir verify_dir=$verify_dir>
658              
659             =item * C<target.$name.verify_dir>
660              
661             =item * C<engine.$engine.verify_dir>
662              
663             =item * C<core.verify_dir>
664              
665             =item * F<C<$top_dir/verify>>
666              
667             =back
668              
669             =head3 C<reworked_dir>
670              
671             my $reworked_dir = $target->reworked_dir;
672              
673             The path to the reworked directory of the project. This directory contains
674             subdirectories for reworked deploy, revert, and verify scripts. The value
675             comes from one of these options, searched in this order:
676              
677             =over
678              
679             =item * C<--dir reworked_dir=$reworked_dir>
680              
681             =item * C<target.$name.reworked_dir>
682              
683             =item * C<engine.$engine.reworked_dir>
684              
685             =item * C<core.reworked_dir>
686              
687             =item * C<$top_dir>
688              
689             =back
690              
691             =head3 C<reworked_deploy_dir>
692              
693             my $reworked_deploy_dir = $target->reworked_deploy_dir;
694              
695             The path to the reworked deploy directory of the project. This directory
696             contains all of the reworked deploy scripts referenced by changes in the
697             C<plan_file>. The value comes from one of these options, searched in this
698             order:
699              
700             =over
701              
702             =item * C<--dir reworked_deploy_dir=$reworked_deploy_dir>
703              
704             =item * C<target.$name.reworked_deploy_dir>
705              
706             =item * C<engine.$engine.reworked_deploy_dir>
707              
708             =item * C<core.reworked_deploy_dir>
709              
710             =item * F<C<$reworked_dir/reworked_deploy>>
711              
712             =back
713              
714             =head3 C<reworked_revert_dir>
715              
716             my $reworked_revert_dir = $target->reworked_revert_dir;
717              
718             The path to the reworked revert directory of the project. This directory
719             contains all of the reworked revert scripts referenced by changes the
720             C<plan_file>. The value comes from one of these options, searched in this
721             order:
722              
723             =over
724              
725             =item * C<--dir reworked_revert_dir=$reworked_revert_dir>
726              
727             =item * C<target.$name.reworked_revert_dir>
728              
729             =item * C<engine.$engine.reworked_revert_dir>
730              
731             =item * C<core.reworked_revert_dir>
732              
733             =item * F<C<$reworked_dir/reworked_revert>>
734              
735             =back
736              
737             =head3 C<reworked_verify_dir>
738              
739             my $reworked_verify_dir = $target->reworked_verify_dir;
740              
741             The path to the reworked verify directory of the project. This directory
742             contains all of the reworked verify scripts referenced by changes in the
743             C<plan_file>. The value comes from one of these options, searched in this
744             order:
745              
746             =over
747              
748             =item * C<--dir reworked_verify_dir=$reworked_verify_dir>
749              
750             =item * C<target.$name.reworked_verify_dir>
751              
752             =item * C<engine.$engine.reworked_verify_dir>
753              
754             =item * C<core.reworked_verify_dir>
755              
756             =item * F<C<$reworked_dir/reworked_verify>>
757              
758             =back
759              
760             =head3 C<extension>
761              
762             my $extension = $target->extension;
763              
764             The file name extension to append to change names to create script file names.
765             The value comes from one of these options, searched in this order:
766              
767             =over
768              
769             =item * C<--extension>
770              
771             =item * C<target.$name.extension>
772              
773             =item * C<engine.$engine.extension>
774              
775             =item * C<core.extension>
776              
777             =item * C<"sql">
778              
779             =back
780              
781             =head3 C<variables>
782              
783             my $variables = $target->variables;
784              
785             The database variables to use in change scripts. The value are merged from
786             these options, in this order:
787              
788             =over
789              
790             =item * C<target.$name.variables>
791              
792             =item * C<engine.$engine.variables>
793              
794             =back
795              
796             The C<core.variables> configuration is not read, because command-specific
797             configurations, such as C<deploy.variables> and C<revert.variables> take
798             priority. The command themselves therefore pass them to the engine in the
799             proper priority order.
800              
801             =head3 C<engine_key>
802              
803             my $key = $target->engine_key;
804              
805             The key defining which engine to use. This value defines the class loaded by
806             C<engine>. Convenience method for C<< $target->uri->canonical_engine >>.
807              
808             =head3 C<dsn>
809              
810             my $dsn = $target->dsn;
811              
812             The DSN to use when connecting to the target via the DBI. Convenience method
813             for C<< $target->uri->dbi_dsn >>.
814              
815             =head3 C<username>
816              
817             my $username = $target->username;
818              
819             The username to use when connecting to the target via the DBI. Convenience
820             method for C<< $target->uri->user >>.
821              
822             =head3 C<password>
823              
824             my $password = $target->password;
825              
826             The password to use when connecting to the target via the DBI. Convenience
827             method for C<< $target->uri->password >>.
828              
829             =head1 See Also
830              
831             =over
832              
833             =item L<sqitch>
834              
835             The Sqitch command-line client.
836              
837             =back
838              
839             =head1 Author
840              
841             David E. Wheeler <david@justatheory.com>
842              
843             =head1 License
844              
845             Copyright (c) 2012-2023 iovation Inc., David E. Wheeler
846              
847             Permission is hereby granted, free of charge, to any person obtaining a copy
848             of this software and associated documentation files (the "Software"), to deal
849             in the Software without restriction, including without limitation the rights
850             to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
851             copies of the Software, and to permit persons to whom the Software is
852             furnished to do so, subject to the following conditions:
853              
854             The above copyright notice and this permission notice shall be included in all
855             copies or substantial portions of the Software.
856              
857             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
858             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
859             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
860             AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
861             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
862             OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
863             SOFTWARE.
864              
865             =cut