Commit | Line | Data |
3fea05b9 |
1 | package Module::Install::Bundle; |
2 | |
3 | use strict; |
4 | use Cwd (); |
5 | use File::Find (); |
6 | use File::Copy (); |
7 | use File::Basename (); |
8 | use Module::Install::Base (); |
9 | |
10 | use vars qw{$VERSION @ISA $ISCORE}; |
11 | BEGIN { |
12 | $VERSION = '0.91'; |
13 | @ISA = 'Module::Install::Base'; |
14 | $ISCORE = 1; |
15 | } |
16 | |
17 | sub auto_bundle { |
18 | my $self = shift; |
19 | |
20 | # Flatten array of arrays into a single array |
21 | my @core = map @$_, map @$_, grep ref, $self->requires; |
22 | |
23 | $self->bundle(@core); |
24 | } |
25 | |
26 | sub bundle { |
27 | my $self = shift; |
28 | $self->admin->bundle(@_) if $self->is_admin; |
29 | |
30 | my $cwd = Cwd::cwd(); |
31 | my $bundles = $self->read_bundles; |
32 | my $bundle_dir = $self->_top->{bundle}; |
33 | $bundle_dir =~ s/\W+/\\W+/g; |
34 | |
35 | while (my ($name, $version) = splice(@_, 0, 2)) { |
36 | $version ||= 0; |
37 | |
38 | my $source = $bundles->{$name} or die "Cannot find bundle source for $name"; |
39 | my $target = File::Basename::basename($source); |
40 | $self->bundles($name, $target); |
41 | |
42 | next if eval "use $name $version; 1"; |
43 | mkdir $target or die $! unless -d $target; |
44 | |
45 | # XXX - clean those directories upon "make clean"? |
46 | File::Find::find({ |
47 | wanted => sub { |
48 | my $out = $_; |
49 | $out =~ s/$bundle_dir/./i; |
50 | mkdir $out if -d; |
51 | File::Copy::copy($_ => $out) unless -d; |
52 | }, |
53 | no_chdir => 1, |
54 | }, $source); |
55 | } |
56 | |
57 | chdir $cwd; |
58 | } |
59 | |
60 | sub read_bundles { |
61 | my $self = shift; |
62 | my %map; |
63 | |
64 | local *FH; |
65 | open FH, $self->_top->{bundle} . ".yml" or return {}; |
66 | while (<FH>) { |
67 | /^(.*?): (['"])?(.*?)\2$/ or next; |
68 | $map{$1} = $3; |
69 | } |
70 | close FH; |
71 | |
72 | return \%map; |
73 | } |
74 | |
75 | |
76 | sub auto_bundle_deps { |
77 | my $self = shift; |
78 | |
79 | # Flatten array of arrays into a single array |
80 | my @core = map @$_, map @$_, grep ref, $self->requires; |
81 | while (my ($name, $version) = splice(@core, 0, 2)) { |
82 | next unless $name; |
83 | $self->bundle_deps($name, $version); |
84 | $self->bundle($name, $version); |
85 | } |
86 | } |
87 | |
88 | sub bundle_deps { |
89 | my ($self, $pkg, $version) = @_; |
90 | my $deps = $self->admin->scan_dependencies($pkg) or return; |
91 | |
92 | foreach my $key (sort keys %$deps) { |
93 | $self->bundle($key, ($key eq $pkg) ? $version : 0); |
94 | } |
95 | } |
96 | |
97 | 1; |
98 | |
99 | __END__ |
100 | |
101 | =pod |
102 | |
103 | =head1 NAME |
104 | |
105 | Module::Install::Bundle - Bundle distributions along with your distribution |
106 | |
107 | =head1 SYNOPSIS |
108 | |
109 | Have your Makefile.PL read as follows: |
110 | |
111 | use inc::Module::Install; |
112 | |
113 | name 'Foo-Bar'; |
114 | all_from 'lib/Foo/Bar.pm'; |
115 | requires 'Baz' => '1.60'; |
116 | |
117 | # one of either: |
118 | bundle 'Baz' => '1.60'; |
119 | # OR: |
120 | auto_bundle; |
121 | |
122 | WriteAll; |
123 | |
124 | =head1 DESCRIPTION |
125 | |
126 | Module::Install::Bundle allows you to bundle a CPAN distribution within your |
127 | distribution. When your end-users install your distribution, the bundled |
128 | distribution will be installed along with yours, unless a newer version of |
129 | the bundled distribution already exists on their local filesystem. |
130 | |
131 | While bundling will increase the size of your distribution, it has several |
132 | benefits: |
133 | |
134 | Allows installation of bundled distributions when CPAN is unavailable |
135 | Allows installation of bundled distributions when networking is unavailable |
136 | Allows everything your distribution needs to be packaged in one place |
137 | |
138 | Bundling differs from auto-installation in that when it comes time to |
139 | install, a bundled distribution will be installed based on the distribution |
140 | bundled with your distribution, whereas with auto-installation the distibution |
141 | to be installed will be acquired from CPAN and then installed. |
142 | |
143 | =head1 METHODS |
144 | |
145 | =over 4 |
146 | |
147 | =item * auto_bundle() |
148 | |
149 | Takes no arguments, will bundle every distribution specified by a C<requires()>. |
150 | When you, as a module author, do a C<perl Makefile.PL> the latest versions of |
151 | the distributions to be bundled will be acquired from CPAN and placed in |
152 | F<inc/BUNDLES/>. |
153 | |
154 | =item * bundle($name, $version) |
155 | |
156 | Takes a list of key/value pairs specifying a distribution name and version |
157 | number. When you, as a module author, do a perl Makefile.PL the distributions |
158 | that you specified with C<bundle()> will be acquired from CPAN and placed in |
159 | F<inc/BUNDLES/>. |
160 | |
161 | =item * bundle_deps($name, $version) |
162 | |
163 | Same as C<bundle>, except that all dependencies of the bundled modules are |
164 | also detected and bundled. To use this function, you need to declare the |
165 | minimum supported perl version first, like this: |
166 | |
167 | requires( perl => 5.005 ); |
168 | |
169 | =item * auto_bundle_deps |
170 | |
171 | Same as C<auto_bundle>, except that all dependencies of the bundled |
172 | modules are also detected and bundled. This function has the same constraints as bundle_deps. |
173 | |
174 | =back |
175 | |
176 | =head1 BUGS |
177 | |
178 | Please report any bugs to (patches welcome): |
179 | |
180 | http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Module-Install |
181 | |
182 | =head1 AUTHORS |
183 | |
184 | Audrey Tang E<lt>autrijus@autrijus.orgE<gt> |
185 | |
186 | Documentation by Adam Foxson E<lt>afoxson@pobox.comE<gt> |
187 | |
188 | =head1 COPYRIGHT |
189 | |
190 | Copyright 2003, 2004, 2005 by Audrey Tang E<lt>autrijus@autrijus.orgE<gt>. |
191 | |
192 | This program is free software; you can redistribute it and/or modify it under |
193 | the same terms as Perl itself. |
194 | |
195 | =cut |