summaryrefslogtreecommitdiff
path: root/infrastructure/makedistribution.pl.in
blob: 0ccd92be806c907806f3f04b81e9a15d6745d3af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
#!@PERL@

use strict;
use Symbol;

# comment string for various endings
my %comment_chars = ('cpp' => '// ', 'h' => '// ', 'pl' => '# ', 'pm' => '# ', '' => '# ');

# other extensions which need text copying, just to remove the private stuff
# .in is included here, as these could be any kind of source, but clearly
# they have text substitutions run on them by autoconf, so we can too :)
my %text_files = ('txt' => 1, 'spec' => 1, 'in' => 1);

# files which don't get the license added
# my %file_license = (); # 'filename' => 'GPL', 'DUAL' or 'none'

# ----------------------------------------------

# filled in from the manifest file
# my %dir_license = (); # 'dir' => 'GPL', 'DUAL' or 'none'
#
# most recently specified LICENSE become default until overridden
my $current_license; # 'GPL', 'DUAL' or 'none'

# distribution name
my $distribution = $ARGV[0];
die "No distribution name specified on the command line" if $distribution eq '';
my $dist_root = "distribution/$distribution";

# check distribution exists
die "Distribution '$distribution' does not exist" unless -d $dist_root;

# get version
open VERSION,"$dist_root/VERSION.txt" or die "Can't open $dist_root/VERSION.txt";
my $version = <VERSION>;
chomp $version;
my $archive_name = <VERSION>;
chomp $archive_name;
close VERSION;

# consistency check
die "Archive name '$archive_name' is not equal to the distribution name '$distribution'"
	unless $archive_name eq $distribution;

my $svnversion = `svnversion .`;
chomp $svnversion;
$svnversion =~ tr/0-9A-Za-z/_/c;

if($version =~ /USE_SVN_VERSION/)
{
	# for developers, use SVN version
	open INFO,'svn info . |';
	my $svnurl;
	while(<INFO>)
	{
		if(m/^URL: (.+?)[\n\r]+/)
		{
			$svnurl = $1;
		}
	}
	close INFO;
	$svnurl =~ m'box/(.+)$';
	my $svndir = $1;
	$svndir =~ tr/0-9A-Za-z/_/c;
	$version =~ s/USE_SVN_VERSION/$svndir.'_'.$svnversion/e;
}

# make initial directory
my $base_name = "$archive_name-$version";
system "rm -rf $base_name";
system "rm $base_name.tgz";
mkdir $base_name,0755;

# get license files
my %license_text; # name of license => array of lines of license text
foreach my $license ("GPL", "DUAL")
{
	my $file = "./LICENSE-$license.txt";
	open LICENSE, $file or die "Can't open $file: $!";
	my @lines = <LICENSE>;
	close LICENSE;
	unshift @lines, "distribution $base_name (svn version: $svnversion)\n";
	$license_text{$license} = \@lines;
}

# copy files, make a note of all the modules included
my %modules_included;
my $private_sections_removed = 0;
my $non_distribution_sections_removed = 0;
sub copy_from_list
{
	my $list = $_[0];
	open LIST,$list or die "Can't open $list";
	
	while(my $line = <LIST>)
	{
		next unless $line =~ m/\S/;
		chomp $line;
		my @words = split /\s+/, $line;
		my ($src,$dst,$other) = @words;
		$dst = $src if $dst eq '';
		if($src eq 'MKDIR')
		{
			# actually we just need to make a directory here
			mkdir "$base_name/$dst",0755;
		}
		elsif($src eq 'LICENSE')
		{
			$current_license = $dst;
		}
		elsif($src eq 'REPLACE-VERSION-IN')
		{
			replace_version_in($dst);
		}
		elsif($src eq 'RUN')
		{
			my ($junk,$cmd) = split /\s+/, $line, 2;
			print "Running $cmd...\n";
			if(system($cmd) != 0)
			{
				print "Error running $cmd. Aborting.\n";
				exit(1);
			}
		}
		elsif(-d $src)
		{
			$modules_included{$line} = 1;
			copy_dir($src,$dst);
		}
		else
		{
			copy_file($src,$dst);
		}
	}
	
	close LIST;
}
copy_from_list("distribution/COMMON-MANIFEST.txt");
copy_from_list("$dist_root/DISTRIBUTION-MANIFEST.txt");

# Copy in the root directory and delete the DISTRIBUTION-MANIFEST file
(system("cp $dist_root/*.* $base_name/") == 0)
	or die "Copy of root extra files failed";
unlink "$base_name/DISTRIBUTION-MANIFEST.txt"
	or die "Delete of DISTRIBUTION-MANIFEST.txt file failed";
replace_version_in("VERSION.txt");

# produce a new modules file
my $modules = gensym;
open $modules,"modules.txt" or die "Can't open modules.txt for reading";
open MODULES_OUT,">$base_name/modules.txt";

while(<$modules>)
{
	# skip lines for modules which aren't included
	next if m/\A(\w+\/\w+)\s/ && !exists $modules_included{$1};
	
	# skip private sections
	unless(skip_non_applicable_section($_, $modules, 'modules.txt'))
	{
		# copy line to out files
		print MODULES_OUT
	}
}

close MODULES_OUT;
close $modules;

# report on how many private sections were removed
print "Private sections removed: $private_sections_removed\nNon-distribution sections removed: $non_distribution_sections_removed\n";

# tar it up
system "tar cf - $base_name | gzip -9 - > $base_name.tgz";

sub copy_file
{
	my ($fn,$dst_fn) = @_;
	
	my $ext;
	$ext = $1 if $fn =~ m/\.(\w+)\Z/;
	$dst_fn =~ m~\A(.+)/[^/]+?\Z~;
	
	# licensed or not?
	if(exists $comment_chars{$ext} && $current_license ne "none")
	{
		# copy as text, inserting license
		# print "source copy $fn to $base_name/$dst_fn\n";

		my $in = gensym;
		open $in,$fn or die "$fn: $!";
		open OUT,">$base_name/$dst_fn" or die "$base_name/$dst_fn: $!";
		
		my $first = <$in>;
		if($first =~ m/\A#!/)
		{
			print OUT $first;
			$first = '';
		}
		
		# write license
		my $b = $comment_chars{$ext};
		my $this_license = $license_text{$current_license};
		for (@$this_license)
		{
			print OUT $b, $_;
		}
		
		if($first ne '')
		{
			print OUT $first;
		}
		
		while(<$in>)
		{
			unless(skip_non_applicable_section($_, $in, $fn))
			{
				print OUT
			}
		}	
		
		close OUT;
		close $in;
	}
	elsif(exists $text_files{$ext})
	{
		# copy this as text, to remove private stuff
		# print "text copy $fn to $base_name/$dst_fn\n";

		my $in = gensym;
		open $in,$fn or die "$fn: $!";
		open OUT,">$base_name/$dst_fn" or die "$base_name/$dst_fn: $!";

		while(<$in>)
		{
			unless(skip_non_applicable_section($_, $in, $fn))
			{
				print OUT
			}
		}	

		close OUT;
		close $in;
	}
	else
	{
		# copy as binary
		# print "binary copy $fn to $base_name/$dst_fn\n";
		my $cmd = "cp -p $fn $base_name/$dst_fn";
		system($cmd) == 0 or die "copy failed: $cmd";
	}
	
	# copy executable bit from src
	if(-x $fn)
	{
		system 'chmod','a+x',"$base_name/$dst_fn"
	}
	else
	{
		system 'chmod','a-x',"$base_name/$dst_fn"
	}
}

sub skip_non_applicable_section
{
	my ($l, $filehandle, $filename) = @_;
	if($l =~ m/BOX_PRIVATE_BEGIN/)
	{
		# skip private section
		print "Removing private section from $filename\n";
		$private_sections_removed++;
		while(<$filehandle>) {last if m/BOX_PRIVATE_END/}
		
		# skipped something
		return 1;
	}
	elsif($l =~ m/IF_DISTRIBUTION\((.+?)\)/)
	{
		# which distributions does this apply to?
		my $applies = 0;
		for(split /,/,$1)
		{
			$applies = 1 if $_ eq $distribution
		}
		unless($applies)
		{
			# skip section?
			print "Removing distribution specific section from $filename\n";
			$non_distribution_sections_removed++;
			while(<$filehandle>) {last if m/END_IF_DISTRIBUTION/}
		}
		# hide this line
		return 1;
	}
	elsif($l =~ m/END_IF_DISTRIBUTION/)
	{
		# hide these lines
		return 1;
	}
	else
	{
		# no skipping, return this line
		return 0;
	}
}

sub copy_dir
{
	my ($dir,$dst_dir) = @_;

	# copy an entire directory... first make sure it exists
	my @n = split /\//,$dst_dir;
	my $d = $base_name;
	for(@n)
	{
		$d .= '/';
		$d .= $_;
		mkdir $d,0755;
	}
	
	# then do each of the files within in
	opendir DIR,$dir;
	my @items = readdir DIR;
	closedir DIR;
	
	for(@items)
	{
		next if m/\A\./;
		next if m/\A_/;
		next if m/\AMakefile\Z/;
		next if m/\Aautogen/;
		next if m/-smf-method\Z/; # copy only the .in versions
		next if m/-manifest.xml\Z/; # copy only the .in versions
		if($dir eq 'docs') {
			next if m/.(x[sm]l|tmpl)\Z/; # don't include doc sources
			next if m/generate_except_xml.pl/;
		}
		next if !-f "$dir/$_";
		
		copy_file("$dir/$_","$dst_dir/$_");
	}
}

sub replace_version_in
{
	my ($file) = @_;
	
	my $fn = $base_name . '/' . $file;
	open IN,$fn or die "Can't open $fn";
	open OUT,'>'.$fn.'.new' or die "Can't open $fn.new for writing";
	
	while(<IN>)
	{
		s/###DISTRIBUTION-VERSION-NUMBER###/$version/g;
		s/.*USE_SVN_VERSION.*/$version/g;
		print OUT
	}
	
	close OUT;
	close IN;

	rename($fn.'.new', $fn) or die "Can't rename in place $fn";
}