File Coverage

blib/lib/Tree/Walker.pm
Criterion Covered Total %
statement 18 273 6.5
branch 0 98 0.0
condition 0 11 0.0
subroutine 6 38 15.7
pod 18 19 94.7
total 42 439 9.5


line stmt bran cond sub pod time code
1             package Tree::Walker;
2            
3 1     1   24820 use 5.006;
  1         5  
  1         52  
4 1     1   7 use strict;
  1         1  
  1         40  
5 1     1   5 use warnings FATAL => 'all';
  1         6  
  1         51  
6 1     1   7 use Carp;
  1         1  
  1         104  
7 1     1   7 use base qw(Exporter);
  1         1  
  1         112  
8 1     1   1216 use Data::Dumper;
  1         12053  
  1         3831  
9            
10             our @EXPORT = qw( walkdir mapdir );
11            
12             =head1 NAME
13            
14             Tree::Walker - Iterate along hierarchical structures
15            
16             =head1 VERSION
17            
18             Version 0.01
19            
20             =cut
21            
22             our $VERSION = '0.01';
23            
24            
25             =head1 SYNOPSIS
26            
27             C provides an iterator framework for hierarchical things, starting with but not limited to the filesystem.
28             It returns its results in the form of a L, so there are plenty of handy tools available.
29             It can be subclassed for things other than the filesystem, or you can tell it to use another class - either way.
30            
31             =head1 UNIVERSAL METHODS
32            
33             These methods constitute the API for C and are written in a universal fashion.
34            
35             =head2 new
36            
37             The C method sets up a walk. [possibly a walk method just to set one up and run it?]
38            
39             The components of a walk are:
40             =over
41             =item The starting point (for the filesystem, a string representing the directory to start walking in)
42             =item Restrictions on the walk (for the filesystem, extensions to be looked for or a pattern to match)
43             =item A general set of handlers to be taken if some specific item is matched
44             =item What information to be returned for each node (for the filesystem, the name, type, full path, timestamp, and size of each file/directory)
45             =back
46            
47             The walker is designed to be subclassed for walking different hierarchical structures; see L for
48             information about how that works.
49            
50             =cut
51            
52             sub new {
53 0     0 1   my $class = shift;
54 0           my $self = bless ({
55             filters => [],
56             }, $class);
57 0 0         $self->{select} = [$self->data_available()] unless defined $self->{select};
58 0           $self->interpret_parameters (@_);
59            
60 0           $self;
61             }
62            
63             =head2 walk, walk_all, walk_all_simple
64            
65             C returns an iterator that will return one item from the walk each time it's called. The returns
66             are in the form of an arrayref of fields as specified in the walker query.
67            
68             C runs that iterator until it's done, returning the list of results.
69            
70             C is a walk_all that only returns the list of first result elements (probably the tag, you see; good for quick filtering)
71            
72             =cut
73            
74             sub walk {
75 0     0 1   my $self = shift;
76 0           my @stack; # Yeah, isn't that cool? We can't go recursive because I want an iterator.
77 0 0         if (ref ($self->{start}) eq 'ARRAY') {
78 0           push @stack, { tag=> '-', list => $self->{start} };
79             } else {
80 0           push @stack, { tag => $self->{start}, list => [$self->{start}] };
81             }
82 0           $self->walk_init;
83            
84 0           my $current_iterator = undef;
85            
86             return sub {
87             NEXT:
88 0 0   0     if (defined $current_iterator) {
89 0           my $potential = $current_iterator->();
90 0 0         return $potential if defined $potential;
91 0           $current_iterator = undef;
92             }
93 0 0         return undef unless @stack;
94            
95 0           my $curframe = $stack[-1]; # Current frame is last on stack.
96 0           while (!@{$curframe->{list}}) { # Pop frames as long as the last one is empty.
  0            
97 0           pop @stack;
98 0 0         return undef unless @stack; # If we're out of frames, we're done with the walk.
99 0           $curframe = $stack[-1];
100             }
101            
102 0           my $current = shift @{$curframe->{list}};
  0            
103 0 0         return $current->() if ref $current eq 'CODE'; # This lets us represent the parent as a node easily.
104 0 0 0       if (ref $current and $current->can('walk')) {
105 0           $current_iterator = $current->walk;
106 0           goto NEXT;
107             }
108            
109 0           my $type = $self->type ($current, @stack); # The type can be undef - a leaf - or anything else - expandable.
110 0 0         if (not defined $type) {
111 0 0         goto NEXT if $self->{suppress_leaves};
112 0           my $data = $self->get_data($current, undef, @stack); # Context frame is undef for a leaf
113 0           foreach my $test (@{$self->{filters}}) {
  0            
114 0           my ($code, @args) = @$test;
115 0 0         goto NEXT unless $code->(_access_hash($data, @args));
116             }
117 0           return [_access_hash ($data, @{$self->headers})];
  0            
118             }
119            
120             # We have an expandable node. Let's build a new frame! (Unless this node is pruned, anyway.)
121 0 0         if ($self->{prune}) {
122 0           foreach my $p (@{$self->{prune}}) {
  0            
123 0 0         goto NEXT if $p eq $current;
124             }
125             }
126 0           my $this_frame;
127 0 0         $this_frame = { tag=> $current,
128             list => [$self->get_left ($type, $current, @stack),
129             $self->{suppress_nodes} ? () : $self->_wrap_current ($current, \$this_frame, @stack), # Context frame is this frame for a node.
130             $self->get_right ($type, $current, @stack)]
131             };
132 0           push @stack, $this_frame;
133 0           goto NEXT; # And then continue the walk.
134             }
135 0           }
136             sub _access_hash {
137 0     0     my $hash = shift;
138 0           map {$hash->{$_}} @_;
  0            
139             }
140             sub _wrap_current {
141 0     0     my $self = shift;
142 0           my $current = shift;
143 0           my $context_frame = shift;
144 0           my @stack = @_;
145             return sub {
146 0     0     my $data = $self->get_data($current, $$context_frame, @stack);
147 0           return [_access_hash ($data, @{$self->headers})];
  0            
148             }
149 0           }
150            
151             sub walk_all {
152 0     0 1   my $self = shift;
153 0           my $iterator = $self->walk(@_);
154 0           my @return = ();
155 0           while (my $r = $iterator->()) {
156 0           push @return, $r;
157             }
158 0           @return;
159             }
160             sub walk_all_simple {
161 0     0 1   my $self = shift;
162 0           my $iterator = $self->walk(@_);
163 0           my @return = ();
164 0           while (my $r = $iterator->()) {
165 0           push @return, $r->[0];
166             }
167 0           @return;
168             }
169            
170             =head2 walk_table
171            
172             Returns a L table encapsulating a walk iterator. Only works if that module
173             is installed; otherwise croaks.
174            
175             =cut
176            
177             sub walk_table {
178 0     0 1   my $self = shift;
179 0           eval { require Data::Table::Lazy; };
  0            
180 0 0         croak "walk_table requires Data::Table::Lazy - not installed" if $@;
181 0           Data::Table::Lazy->new ($self->walk, $self->headers);
182             }
183            
184             =head2 walkdir (start, parameters, action)
185            
186             Called with a string, an arrayref, and a subroutine, this function will build and call a walker, then
187             run the iteration by repeated calls to the subroutine, like this:
188            
189             use Tree::Walker;
190            
191             my @file_list;
192             walkdir '.', [suppress_nodes => 1], sub {
193             push @file_list, $_[2];
194             }
195            
196             =cut
197            
198             sub walkdir ($$;&) {
199 0     0 1   my $directory = shift;
200 0           my $parameters = shift;
201 0           my $action;
202 0 0         if (ref $parameters eq 'CODE') {
203 0           $action = $parameters;
204 0           $parameters = {};
205             } else {
206 0           $action = shift;
207             }
208 0 0         if (ref $parameters eq 'ARRAY') {
209 0           my %p = @$parameters;
210 0           $parameters = \%p;
211             }
212            
213 0           my $walker = Tree::Walker->new ($directory, $parameters);
214            
215 0           my $iterator = $walker->walk;
216 0           while (my $result = $iterator->()) {
217 0           $action->(@$result);
218             }
219             }
220            
221             =head2 mapdir
222            
223             Another little quickie, this one allows even briefer syntax if your subroutine is small.
224            
225             use Tree::Walker;
226            
227             my @pm_list = mapdir { $_[2] } '.', '.pm';
228            
229             =cut
230            
231             sub mapdir (&;$$) {
232 0     0 1   my $action = shift;
233 0   0       my $directory = shift || '.';
234 0   0       my $parameters = shift || {};
235 0 0         if (ref $parameters eq 'ARRAY') {
236 0           my %p = @$parameters;
237 0           $parameters = \%p;
238             }
239            
240 0           my @results = ();
241 0           my $walker = Tree::Walker->new ($directory, $parameters);
242            
243 0           my $iterator = $walker->walk;
244 0           while (my $result = $iterator->()) {
245 0           push @results, $action->(@$result);
246             }
247 0           return @results;
248             }
249            
250             =head2 interpret_parameters
251            
252             The C method sets up the parameters for the walk. Most of the work is done by C, which can be overridden, but
253             the basic behavior is provided by the base class.
254            
255             =head1 OVERRIDABLE OR PARTLY OVERRIDABLE METHODS
256            
257             These methods work with the filesystem in the unadorned C but are overridden
258             in subclasses (for example see L).
259            
260             =head2 interpret_parameters
261            
262             The C methods interprets the parameters passed to ->new and sets up the walk environment.
263            
264             The base class provides three different modes:
265             =over
266             =item Directory walking is the core functionality; you provide a start directory as the first parameter.
267             =item Explicit file check; the first parameter is a string that points to a file, not a directory. This filespec can be
268             a full relative path; it doesn't just have to be a name.
269             =item List walk; the first parameter is an arrayref of either strings or arrayrefs. If the latter,
270             then the first member of each child arrayref is the type tag for the rest, and the rest are interpreted
271             recursively as subwalks.
272             =back
273            
274             The base class provides list (composite) walking,
275            
276             The rest of the parameters mostly just apply to directory walks, which can be restricted in a number of different ways.
277             There are four types of parameters: walk parameters, filter parameters, additional fields, and field selection. Field
278             selection obviously applies to all types of walk, not just directory walks, as it determines what fields are actually
279             returned by the call. Let's look at the four types separately.
280            
281             There is actually only one walk parameter, C. If this is false, then it is a prefixed walk, and each node
282             will appear in the results list before its children. If it's true, then nodes follow their children (this is necessary
283             if you want a total-size number for each directory).
284            
285             Parameters for filtering the results of filesystem walking are as follows, for filters applied
286             to filenames (not directory names):
287             =over
288             =item ext - an extension that files must match to be returned
289             =item ext_list - a list (arrayref) of extensions, one of which must be matched by a file to be returned
290             =item pattern - a regexp that filenames must match for the file to be returned
291             =item exists - return only existing files or non-existing files, for any files that have been specified explicitly
292             =item filter - if all else fails, you can write your own filters here
293             =back
294            
295             The C parameter contains either a coderef that will be passed the entire list of headers below and returns
296             a boolean (false = don't return this row, true = return this row) or an arrayref C<[, field, field, field...]>
297             that specifies which fields the coderef wants to see I an arrayref of such arrayrefs, e.g.
298             C<[[, field, ...], [, field, ...], ...]>
299            
300             In the end, all the other filters go into the same filter structure anyway, so this part is very easy to subclass.
301            
302             To select whether or not to return directories, or files, use:
303             =over
304             =item suppress_leaves - (at the abstract level) if set, non-expandable nodes will not be returned
305             =item suppress_nodes - (at the abstract level) if set, expandable nodes will not be returned - doesn't affect the walk
306             =item prune - a name or list of names that, if encountered, will not be walked at all
307             =back
308            
309             There's a shortcut for filesystem queries (or rather, a set of shortcuts). If the second parameter is not a hashref but
310             rather a string, then:
311             =over
312             =item If it starts with a period but doesn't have a vertical bar | it will be understood as C.
313             =item If it starts with a period but does have at least one vertical bar | it will be C.
314             =item Otherwise, it will be taken as a pattern, which is a crippled regexp but quick and easy.
315             =back
316            
317             If one of these options is taken, C is also set because the idea is fast, easy ways to get data,
318             and you probably just want file information. And of course you're locked into the defaults for everything else.
319            
320             To add fields to the list of result fields, you can pass in a C parameter that consists of an arrayref:
321             C<[[, field, field, ...], ...]>. After the normal fields are generated, each of these field generators is called
322             in sequence, and each returns a list of values to be named according to the list following the coderef.
323            
324             Finally, to restrict the list of fields actually returned on each call to the generator, simply pass in a list
325             of names under C
326            
327             =cut
328            
329             sub _interpret_sub {
330 0     0     my $self = shift;
331 0           my $sub = shift;
332            
333 0 0         if (ref $sub eq 'ARRAY') {
334 0           my ($role, @rest) = @$sub;
335 0           return Tree::Walker->new(@rest, {role=>$role}, @_);
336             }
337 0           Tree::Walker->new($sub, @_);
338             }
339            
340             sub _interp_one {
341 0     0     my $p = shift;
342 0 0         return unless defined $p;
343 0 0         return $p if ref $p;
344 0           _interp_one_class($p); # Class-specific ways of dealing with string parameters
345             }
346             sub _interp_one_class {
347 0     0     my $p = shift;
348 0           my $r = { suppress_nodes => 1 };
349 0 0         if ($p =~ /^\./) {
350 0 0         if ($p =~ /\|/) {
351 0           $r->{ext_list} = [split / *\| */, $p];
352             } else {
353 0           $r->{ext} = $p;
354             }
355             } else {
356 0           $r->{pattern} = $p;
357             }
358 0           return $r;
359             }
360            
361             sub interpret_parameters {
362 0     0 1   my $self = shift;
363 0           $self->{start} = shift;
364 0           my @rest = @_;
365 0           $self->{filters} = [];
366 0           $self->{added_fields} = [];
367            
368 0 0         if (ref ($self->{start}) eq 'ARRAY') {
369 0           my @subs = map { $self->_interpret_sub($_, @rest) } @{$self->{start}};
  0            
  0            
370 0           $self->{start} = \@subs;
371 0           return;
372             }
373            
374 0           while (my $p = _interp_one(shift)) {
375 0 0         return unless defined $p;
376 0 0         if (ref $p eq 'HASH') {
377 0           while (my ($k,$v) = each %$p) {
378 0 0         if ($k eq 'filter') {
    0          
379 0           push @{$self->{filters}}, $v;
  0            
380             } elsif ($k eq 'field') {
381 0           push @{$self->{added_fields}}, $v;
  0            
382             } else {
383 0           $self->{$k} = $v;
384             }
385             }
386             } else {
387 0           croak "full parameters for walker must be string or hashref";
388             }
389             }
390 0 0         if ($self->{prune}) {
391 0 0         $self->{prune} = [$self->{prune}] unless ref $self->{prune};
392             }
393            
394 0           $self->interpret_parameters_class;
395             }
396            
397             sub _total_size_callee {
398 0     0     my $tag = shift;
399 0           my $values = shift;
400 0           my $context_frame = shift;
401 0           my @stack = @_;
402 0 0 0       my $size = $values->{size} + (defined $context_frame ? ($context_frame->{total_size} || 0) : 0);
403 0           $stack[-1]->{total_size} += $size;
404 0           return $size;
405             }
406            
407             sub interpret_parameters_class {
408 0     0 0   my $self = shift;
409            
410 0 0         if ($self->{ext}) {
411 0           my $ext = $self->{ext};
412 0           $ext =~ s/\./\\./g;
413 0     0     push @{$self->{filters}}, [sub { shift =~ /$ext$/; }, 'name'];
  0            
  0            
414             }
415 0 0         if ($self->{ext_list}) {
416 0           my @list = (@{$self->{ext_list}});
  0            
417 0           foreach (@list) {
418 0           s/\./\\./g;
419             }
420 0           my $pat = join ('$|', @list);
421 0     0     push @{$self->{filters}}, [sub { shift =~ /$pat$/; }, 'name'];
  0            
  0            
422             }
423 0 0         if ($self->{pattern}) {
424 0     0     push @{$self->{filters}}, [sub { shift =~ /$self->{pattern}/; }, 'name'];
  0            
  0            
425             }
426 0 0         $self->{postfix} = 0 unless defined $self->{postfix};
427 0 0         if (defined $self->{exists}) {
428 0 0         if ($self->{exists}) {
429 0     0     push @{$self->{filters}}, [sub { shift ne '!' }, 'type'];
  0            
  0            
430             } else {
431 0     0     push @{$self->{filters}}, [sub { shift eq '!' }, 'type'];
  0            
  0            
432             }
433             }
434            
435 0 0         if (grep { $_ eq 'total_size' } @{$self->{select}}) {
  0            
  0            
436 0           push @{$self->{added_fields}}, [\&_total_size_callee, 'total_size'];
  0            
437 0           $self->{postfix} = 1;
438             }
439             }
440            
441             =head2 walk_init ()
442            
443             Initializes a walk. Doesn't do anything in the filesystem.
444            
445             =cut
446            
447 0     0 1   sub walk_init {}
448            
449             =head2 qualify (tag, stack)
450            
451             Given the tag for a node and the stack above it, fully qualify the tag as a locator.
452            
453             =cut
454            
455             sub qualify {
456 0     0 1   my $shift = shift;
457 0           my $tag = shift;
458 0           require File::Spec;
459 0           my @parents = map {$_->{tag}} @_[1..$#_];
  0            
460 0           File::Spec->catdir (@parents, $tag);
461             }
462            
463             =head2 type (tag, stack)
464            
465             Given the tag for a node, visits it (does initial retrieval) and tells us its type.
466            
467             =cut
468            
469             sub type {
470 0     0 1   my $self = shift;
471 0 0         return 'd' if -d $self->qualify (@_);
472 0           return undef;
473             }
474            
475             =head2 data_available
476            
477             Returns a list of the fields the walker can return (i.e. the fields the driver knows about) and the default
478             order in which they'll be returned.
479            
480             For the filesystem, these are:
481             =over
482             =item name - the name of the file or directory
483             =item role - the role of the node (specified at the outset)
484             =item indent - the indentation level
485             =item path - the path of the file or directory, built for the host OS using File::Spec
486             =item dev - device number of the filesystem (this and the next 12 are the standard perl 'stat' fields)
487             =item ino - inode number
488             =item mode - file mode as integer
489             =item nlink - number of (hard) links to the file
490             =item uid - numeric user ID of owner
491             =item gid - numeric group ID of owner
492             =item rdev - device identifier for special files
493             =item size - total size of file in bytes
494             =item atime - last access time
495             =item mtime - last modify time
496             =item ctime - inode change time (these three all in seconds since 00:00 January 1, 1970 GMT)
497             =item blksize - block size of filesystem
498             =item blocks - actual number of blocks allocated to the file
499             =item modestr - file mode as interpreted Unix-style mode string
500             =item type - the first character of the modestr (for convenience)
501             =back
502            
503            
504             =cut
505            
506             sub data_available {
507 0     0 1   qw(name role indent path dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks modestr type);
508             }
509            
510             =head2 get_data, get_data_class
511            
512             Given the context and a node, gets the configured data for that node. Again, class-specific fields are handled
513             in the C function.
514            
515             =cut
516            
517             sub get_data {
518 0     0 1   my $self = shift;
519 0           my $tag = shift;
520 0           my $context_frame = shift;
521 0           my @stack = @_;
522 0           my $values = {};
523 0           $values->{name} = $tag;
524 0   0       $values->{role} = $self->{role} || '';
525 0           $values->{indent} = scalar @_ - 1;
526 0           my $path = $self->qualify($tag, @_);
527            
528 0           $self->get_data_class ($tag, $path, $values, $context_frame, @stack);
529            
530 0           foreach my $added_field (@{$self->{added_fields}}) {
  0            
531 0           my ($code, @rest) = @$added_field;
532             #print STDERR Dumper (\@stack);
533 0           my @values = $code->($tag, $values, $context_frame, @stack);
534 0           foreach my $field (@rest) {
535 0           $values->{$field} = shift @values;
536             }
537             }
538            
539 0           $values;
540             }
541            
542             sub get_data_class {
543 0     0 1   my $self = shift;
544 0           my $tag = shift;
545 0           my $path = shift;
546 0           my $values = shift;
547            
548 0           $values->{path} = $path;
549            
550 0           my @stat = stat($path);
551 0 0         if (not @stat) {
552 0           $values->{type} = '!';
553 0           $values->{modestr} = '!---------';
554 0           foreach my $statfield (qw(dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks)) {
555 0           $values->{$statfield} = 0;
556             }
557 0           return $values;
558             }
559            
560 0           foreach my $statfield (qw(dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks)) {
561 0           $values->{$statfield} = shift @stat;
562             }
563            
564             # This bit is shamelessly stolen from Stat::lsMode because I don't want all its overhead.
565             # Not to mention it was written in 1998 and doesn't pass smoke on Windows.
566 0           my $mode = $values->{mode};
567 0           my $setids = ($mode & 07000)>>9;
568 0           my @permstrs = qw(--- --x -w- -wx r-- r-x rw- rwx)[($mode&0700)>>6, ($mode&0070)>>3, $mode&0007];
569 0           my $ftype = qw(. p c ? d ? b ? - ? l ? s ? ? ?)[($mode & 0170000)>>12];
570 0           $values->{type} = $ftype;
571 0 0         if ($setids) {
572 0 0         if ($setids & 01) { # Sticky bit
573 0 0         $permstrs[2] =~ s/([-x])$/$1 eq 'x' ? 't' : 'T'/e;
  0            
574             }
575 0 0         if ($setids & 04) { # Setuid bit
576 0 0         $permstrs[0] =~ s/([-x])$/$1 eq 'x' ? 's' : 'S'/e;
  0            
577             }
578 0 0         if ($setids & 02) { # Setgid bit
579 0 0         $permstrs[1] =~ s/([-x])$/$1 eq 'x' ? 's' : 'S'/e;
  0            
580             }
581             }
582 0           $values->{modestr} = join ('', $ftype, @permstrs);
583             }
584            
585             =head2 headers
586            
587             Returns names for the fields in each returned line.
588            
589             =cut
590            
591 0     0 1   sub headers { shift->{select} }
592            
593             =head2 get_children, get_left, get_right
594            
595             The C method, called on a node, returns a list of its children (to be interpreted in turn by C
596             and C). The C and C functions take that list and divide it according to the walk type.
597            
598             =cut
599            
600 0 0   0 1   sub get_left { return $_[0]->{postfix} ? get_children(@_) : (); }
601 0 0   0 1   sub get_right { return $_[0]->{postfix} ? () : get_children(@_); }
602             sub get_children {
603 0     0 1   my $self = shift;
604 0           my $type = shift;
605 0           opendir D, $self->qualify (@_);
606 0           require File::Spec;
607 0           my @children = File::Spec->no_upwards(readdir(D));
608 0           closedir D;
609 0           @children;
610             }
611            
612             =head1 AUTHOR
613            
614             Michael Roberts, C<< >>
615            
616             =head1 BUGS
617            
618             Please report any bugs or feature requests to C, or through
619             the web interface at L. I will be notified, and then you'll
620             automatically be notified of progress on your bug as I make changes.
621            
622            
623            
624            
625             =head1 SUPPORT
626            
627             You can find documentation for this module with the perldoc command.
628            
629             perldoc Tree::Walker
630            
631            
632             You can also look for information at:
633            
634             =over 4
635            
636             =item * RT: CPAN's request tracker (report bugs here)
637            
638             L
639            
640             =item * AnnoCPAN: Annotated CPAN documentation
641            
642             L
643            
644             =item * CPAN Ratings
645            
646             L
647            
648             =item * Search CPAN
649            
650             L
651            
652             =back
653            
654            
655             =head1 ACKNOWLEDGEMENTS
656            
657            
658             =head1 LICENSE AND COPYRIGHT
659            
660             Copyright 2012 Michael Roberts.
661            
662             This program is free software; you can redistribute it and/or modify it
663             under the terms of the the Artistic License (2.0). You may obtain a
664             copy of the full license at:
665            
666             L
667            
668             Any use, modification, and distribution of the Standard or Modified
669             Versions is governed by this Artistic License. By using, modifying or
670             distributing the Package, you accept this license. Do not use, modify,
671             or distribute the Package, if you do not accept this license.
672            
673             If your Modified Version has been derived from a Modified Version made
674             by someone other than you, you are nevertheless required to ensure that
675             your Modified Version complies with the requirements of this license.
676            
677             This license does not grant you the right to use any trademark, service
678             mark, tradename, or logo of the Copyright Holder.
679            
680             This license includes the non-exclusive, worldwide, free-of-charge
681             patent license to make, have made, use, offer to sell, sell, import and
682             otherwise transfer the Package with respect to any patent claims
683             licensable by the Copyright Holder that are necessarily infringed by the
684             Package. If you institute patent litigation (including a cross-claim or
685             counterclaim) against any party alleging that the Package constitutes
686             direct or contributory patent infringement, then this Artistic License
687             to you shall terminate on the date that such litigation is filed.
688            
689             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
690             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
691             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
692             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
693             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
694             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
695             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
696             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
697            
698            
699             =cut
700            
701             1; # End of Tree::Walker