Rakefile 15.5 KB
Newer Older
Patrick J Cherry's avatar
Patrick J Cherry committed
1
2
3
4
#!/usr/bin/ruby

require 'fileutils'
require 'rake/clean'
5
require 'digest'
Patrick J Cherry's avatar
Patrick J Cherry committed
6
7
8
9
require 'pp'

DEBEMAIL=ENV["DEBEMAIL"] || "symbiosis@bytemark.co.uk"
DEB_BUILD_ARCH=`dpkg-architecture -qDEB_BUILD_ARCH`.chomp
10
# REPONAME, DISTRO = File.dirname(File.expand_path(__FILE__)).split("/").last(2)
11
DISTRO="oldoldstable"
12
REPONAME="symbiosis"
Patrick J Cherry's avatar
Patrick J Cherry committed
13

Patrick J Cherry's avatar
Patrick J Cherry committed
14
15
16
17
18
19
20
21
22
23
#
# Monkey patch rake to output on stdout like normal people
#
module RakeFileUtils
  # Send the message to the default rake output (which is $stderr).
  def rake_output_message(message)
    $stdout.puts(message)
  end
end

24
25
def has_sautobuild?
  return @has_sautobuild if defined? @has_sautobuild
26
  @has_sautobuild = ( !ENV.has_key?("NO_SAUTOBUILD") and File.executable?("/usr/bin/sautobuild") )
27
28
29
30
31
32
end

def available_build_archs
  return @available_build_archs if defined? @available_build_archs

  if has_sautobuild?
Patrick J Cherry's avatar
Patrick J Cherry committed
33
    chroots = `/usr/bin/schroot -l`.to_s.split
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
    return (@available_build_archs = [DEB_BUILD_ARCH]) unless 0 == $?
  else
    return (@available_build_archs = [DEB_BUILD_ARCH])
  end

  #
  # We only build/test on amd64/i386.
  #
  possibles = %w(amd64 i386)

  archs = chroots.collect do |chroot|
    if chroot =~ /^(?:chroot:)?#{DISTRO}-(#{possibles.join("|")})$/
      $1
    else
      nil
    end
  end.compact.sort.uniq

  if archs.empty?
    warn "Could not find any schroots for the #{DISTRO} (#{possibles.join(", ")}).  Not using sautobuild"
    @has_sautobuild = false
    archs = [DEB_BUILD_ARCH] 
  end

  @available_build_archs = archs
end

Patrick J Cherry's avatar
Patrick J Cherry committed
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#
# This returns a list of all packages with the following format:
#
#  [name, Debian version, distro, architecture]
#
def all_packages
  #
  # Cache the answer, since this is a costly question.
  #
  return @all_packages unless @all_packages.nil?

  @all_packages = Dir["*"].collect do |pkgdir|

    next unless File.exists?(pkgdir+"/debian/changelog")

76
77
78
79
    bin_pkgs = []
    source = pkg = arch = version = distro = nil
    arch_dependent = false

Patrick J Cherry's avatar
Patrick J Cherry committed
80
81
82
83
    File.open(pkgdir+"/debian/changelog","r") do |fh|
      while !fh.eof? do
        fh.gets
        next unless $_ =~ /^([^ ]+) \((?:[0-9]+:)?([^\)]+)\) ([^;]+); /
84
        source, version, distro = [$1, $2, $3]
Patrick J Cherry's avatar
Patrick J Cherry committed
85
86
87
88
89
90
91
        break
      end
    end

    #
    # Assume all architectures
    #
92
    bin_pkgs = []
Patrick J Cherry's avatar
Patrick J Cherry committed
93
94
    arch = "all"
    File.open(File.join(pkgdir,"debian","control")){|fh| fh.readlines}.each do |l|
95
96
97
98
99
100
101
102
103
104
105
      case l
        when /^Package: (.*)/
          pkg = $1
        when /^Architecture: (.*)/
          this_arch = $1
          arch_dependent = (arch_dependent or this_arch != "all")
          (this_arch == "any" ? available_build_archs : %w(all)).collect do |a|
            bin_pkgs << "#{pkg}_#{version}_#{a}.deb"
          end
          pkg = nil
      end
Patrick J Cherry's avatar
Patrick J Cherry committed
106
107
    end

108
109
110
111
112
113
114
115
116
117
118
119
120
    source_version = "#{source}_#{version}"

    {:dir => pkgdir,
     :source => source,
     :source_changes => "#{source_version}_source.changes",
     :changes => (arch_dependent ? available_build_archs : [DEB_BUILD_ARCH]).collect do |this_arch|
        "#{source_version}_#{this_arch}.changes"
     end,
     :builds => (arch_dependent ? available_build_archs : [DEB_BUILD_ARCH]).collect do |this_arch|
        "#{source_version}_#{this_arch}.build"
     end,
     :packages => bin_pkgs,
     :version => version,
121
     :distro  => DISTRO, 
122
123
124
125
126
127
128
129
130
131
132
133
     :targz   => source_version+".tar.gz",
     :diffgz  => source_version+".diff.gz",
     :dsc     => source_version+".dsc",
     :arch_dependent => arch_dependent }
  end.compact
end

def package_changess(source = nil)
  all_packages.select do |pkg| 
    source.nil? or pkg[:source] == source
  end.collect { |pkg| pkg[:changes] }.flatten
end
Patrick J Cherry's avatar
Patrick J Cherry committed
134

135
136
137
138
def source_changess(source = nil)
  all_packages.select do |pkg|
    source.nil? or pkg[:source] == source
  end.collect{|pkg| pkg[:source_changes] }
Patrick J Cherry's avatar
Patrick J Cherry committed
139
140
end

141
142
143
144
def dscs(source = nil)
  all_packages.select do |pkg|
    source.nil? or pkg[:source] == source
  end.collect{|pkg| pkg[:dsc] }
Patrick J Cherry's avatar
Patrick J Cherry committed
145
146
end

147
148
149
150
def source_dirs(source= nil)
  all_packages.select do |pkg|
    source.nil? or pkg[:source] == source
  end.collect{|pkg| pkg[:dir] }
Patrick J Cherry's avatar
Patrick J Cherry committed
151
152
end

153
154
155
156
def packages(source = nil)
  all_packages.select do |pkg|
    source.nil? or pkg[:source] == source
  end.collect{|pkg| pkg[:packages] }.flatten
Patrick J Cherry's avatar
Patrick J Cherry committed
157
158
end

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
def targzs(source = nil)
  all_packages.select do |pkg|
    source.nil? or pkg[:source] == source
  end.collect{|pkg| pkg[:targz] }
end

def builds(source = nil)
  all_packages.select do |pkg|
    source.nil? or pkg[:source] == source
  end.collect{|pkg| pkg[:builds] }.flatten
end

def find_package_by_filename(fn)
  return nil unless fn =~ /\./

  all_packages.find do |pkg|
    pkg.values.any? do |val|
      (val.is_a?(Array) ?  val.include?(fn) : val == fn)
    end
  end
Patrick J Cherry's avatar
Patrick J Cherry committed
179
180
181
182
183
184
185
186
187
188
end

#
# This converts a debian version into an upstream one.
#
def upstream_version(debian_version)
  raise "bad version number (#{debian_version})" unless debian_version =~ /^([0-9]+:)?([^-]+)(-.*)?$/
  $2
end

189
190
191
#
# Works out the mercurial identity for the current RCS repo.
#
Patrick J Cherry's avatar
Patrick J Cherry committed
192
193
def git_id
  return @git_id if defined? @git_id
Patrick J Cherry's avatar
Patrick J Cherry committed
194

Patrick J Cherry's avatar
Patrick J Cherry committed
195
196
197
  @git_id = `git log -n 1 --format=%h`.chomp
  @git_id = nil if 0 != $?
  @git_id
198
end
Patrick J Cherry's avatar
Patrick J Cherry committed
199

200
201
202
203
#
# Returns the name of the repository directory.
#
def repo_dir 
Patrick J Cherry's avatar
Patrick J Cherry committed
204
  if git_id.nil?
205
206
    File.join("repo", distro)
  else
Patrick J Cherry's avatar
Patrick J Cherry committed
207
    File.join("repo", git_id)
208
209
  end
end
Patrick J Cherry's avatar
Patrick J Cherry committed
210

211
212
213
214
215
216
217
218
219
220
221
222
#####################################################################
#
# TASKS
#
#####################################################################

# The default task if nothing is specified
task :default => "Release"

#
# Generate the Release file
#
Patrick J Cherry's avatar
Patrick J Cherry committed
223
file "Release" => ["Sources.gz", "Sources", "Packages.gz", "Packages"] do |t|
224
225
  require 'socket'

Patrick J Cherry's avatar
Patrick J Cherry committed
226
227
228
229
230
  # 
  # Standard headers
  #
  release =<<EOF
Archive: #{DISTRO}
231
232
233
Label: #{REPONAME}
Origin: #{Socket.gethostname}
Architectures: #{available_build_archs.join(" ")} source
Patrick J Cherry's avatar
Patrick J Cherry committed
234
235
236
237
EOF
  #
  # Add the md5sums for each prereq.
  #
238
  hashes = Hash.new{|h,k| h[k] = []}
Patrick J Cherry's avatar
Patrick J Cherry committed
239
  t.prerequisites.each do |prereq|
240
241
242
243
244
    data = File.read(prereq)
    size = File.stat(prereq).size
    [Digest::MD5, Digest::SHA1, Digest::SHA256].each do |klass|
      hashes[klass] << [klass.hexdigest(data), size, prereq]
    end
Patrick J Cherry's avatar
Patrick J Cherry committed
245
  end
246
247
248
  release << "MD5Sum: \n " + hashes[Digest::MD5].collect{|m| m.join(" ")}.join("\n ")+"\n"
  release << "SHA1: \n "   + hashes[Digest::SHA1].collect{|m| m.join(" ")}.join("\n ")+"\n"
  release << "SHA256: \n " + hashes[Digest::SHA256].collect{|m| m.join(" ")}.join("\n ")+"\n"
Patrick J Cherry's avatar
Patrick J Cherry committed
249
250
251
252
253

  File.open(t.name+".new","w+"){|fh| fh.puts release}
  FileUtils.mv("#{t.name}.new", t.name, :force => true)
end

254
255
256
257
258
259
#
# Generate the Packages file
#
file "Packages" => packages do |t|
  sh "dpkg-scanpackages -m . /dev/null > #{t.name}.new"
  FileUtils.mv("#{t.name}.new", t.name, :force => true)
Patrick J Cherry's avatar
Patrick J Cherry committed
260
261
end

262
263
264
265
266
267
#
# Generate the Sources file
#
file "Sources" => source_changess + dscs do |t| 
  sh "dpkg-scansources . /dev/null > #{t.name}.new"
  FileUtils.mv("#{t.name}.new", t.name, :force => true)
Patrick J Cherry's avatar
Patrick J Cherry committed
268
269
end

270
271
desc "Sign the repository"
task :sign  => ["all", "Release.gpg" ] 
Patrick J Cherry's avatar
Patrick J Cherry committed
272

273
274
desc "Build all packages and documentation"
task :all   => ["Release"]
Patrick J Cherry's avatar
Patrick J Cherry committed
275

276
277
278
279
280
281
desc "Check all build dependencies."
task :dependencies  => "pkg:dependencies" 

desc "Remove any temporary products."
task :clean => "pkg:clean" do
 rm_f  %w(Release.asc Packages.new Sources.new Release.new *-stamp)
Patrick J Cherry's avatar
Patrick J Cherry committed
282
283
end

284
285
286
desc "Remove any generated file."
task :clobber => %w(clean pkg:clobber) do
 rm_f %w(Packages Sources Packages.gz Sources.gz Release Release.gpg)
Patrick J Cherry's avatar
Patrick J Cherry committed
287
288
end

289
290
291
desc "Verify integrity of packages using lintian"
task :lintian => ["lintian-stamp"]

Patrick J Cherry's avatar
Patrick J Cherry committed
292
file "lintian-stamp" => source_changess + package_changess do |t| 
293
294
295
296
297
  if has_sautobuild?
    sh "schroot -c #{DISTRO} -- lintian -X cpy -I #{t.prerequisites.join(" ")}"
  else
    sh "lintian -X cpy -I #{t.prerequisites.join(" ")}"
  end
Patrick J Cherry's avatar
Patrick J Cherry committed
298
299
300
  FileUtils.touch t.name
end

301
302
303
304
desc "Verify package signatures"
task :verify => ["verify-stamp"] 

file "verify-stamp" => source_changess + packages + ["Release.gpg"] do |t| 
Patrick J Cherry's avatar
Patrick J Cherry committed
305
306
307
308
309
310
  t.prerequisites.each do |prereq|
    sh "gpg --verify #{prereq}"
  end
  FileUtils.touch t.name
end

311
312
313
314

desc "Check which packages need their changelogs updating"
task "check_changelogs" do
  need_updating = []
Patrick J Cherry's avatar
Patrick J Cherry committed
315
  br = `git branch`.split($/).find{|b| b =~ /^\* /}.sub(/^\* +/,"")
316
  source_dirs.each do |d|
Patrick J Cherry's avatar
Patrick J Cherry committed
317
318
319
320
321
    ch_t = `git log -n 1 --format='%at' #{br} #{d}/debian/changelog`.to_i
    d_t  = `git log -n 1 --format='%at' #{br} #{d}/**`.to_i
    if ch_t < d_t
      ch_ch = `git log -n 1 --format='changelog: %h: %an: %ai' #{br} #{d}/debian/changelog`.chomp
      d_ch =  `git log -n 1 --format='directory: %h: %an: %ai' #{br} #{d}/**`.chomp
322
      need_updating << d + "\n    " + ch_ch + "\n    " + d_ch
Patrick J Cherry's avatar
Patrick J Cherry committed
323
324
    end
  end
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344

  if need_updating.length > 0
    puts "The following packages _probably_ need new changelog entries:"
    puts " * "+need_updating.join("\n * ")
    puts "Note that this is only a very rough check!"
  else
    puts "All package changelogs are up-to-date."
  end
end

desc "Build a repository suitable for testing."
task "repo" => "Release" do
  mkdir_p repo_dir
  cp packages, repo_dir
  cp targzs, repo_dir
  cp source_changess, repo_dir
  cp package_changess, repo_dir
  cp dscs, repo_dir
  cp builds, repo_dir
  cp %w(Release Sources.gz Sources Packages.gz Packages), repo_dir
Patrick J Cherry's avatar
Patrick J Cherry committed
345
346
end

347
348
desc "Generate API documentation."
task "rdoc" => "doc/html/created.rid"
Patrick J Cherry's avatar
Patrick J Cherry committed
349
350

#
351
352
# This rule makes sure the docs are rebuild if there is a change to any of the
# ruby code.
Patrick J Cherry's avatar
Patrick J Cherry committed
353
#
354
355
356
357
358
rule("doc/html/created.rid" => 
  proc do
    source_files = Dir.glob(File.join("*","lib","**","*")).select{|f| File.file?(f)}
    source_files += Dir.glob(File.join("*","ext","**","*")).select{|f| File.file?(f)}
    source_files
Patrick J Cherry's avatar
Patrick J Cherry committed
359
  end
360
361
) do
  Rake::Task["rdoc:all"].invoke
Patrick J Cherry's avatar
Patrick J Cherry committed
362
363
end

364
namespace :rdoc do
Patrick J Cherry's avatar
Patrick J Cherry committed
365
366

  #
367
  # Build all the documentation, removing any existing.
Patrick J Cherry's avatar
Patrick J Cherry committed
368
  #
369
370
371
  task :all => ["dependencies", "clobber"] do
    sh "rdoc1.8 --diagram --op doc/html */lib/ */ext/"
  end
Patrick J Cherry's avatar
Patrick J Cherry committed
372
373

  #
374
  # Make sure we've got the correct dependencies for building rdoc.
Patrick J Cherry's avatar
Patrick J Cherry committed
375
  #
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
  task :dependencies do 
    missing_build_deps = []
    [
      %w(/usr/bin/rdoc1.8 rdoc1.8),
      %w(/usr/bin/dot graphviz)
    ].each do |executable, package|
      missing_build_deps << package unless File.executable?(executable)
    end
  
    raise "Need to install the following packages to build documentation:\n  #{missing_build_deps.join(" ")}" unless missing_build_deps.empty?
  end 

  task :clean do
    # no op
  end
  
  task :clobber do
    rm_rf "doc/html"
  end

end
Patrick J Cherry's avatar
Patrick J Cherry committed
397

398
399
desc "Upload packages to the local tree" 
task "upload" => "repo" do
Patrick J Cherry's avatar
Patrick J Cherry committed
400
  #
401
  # TODO
Patrick J Cherry's avatar
Patrick J Cherry committed
402
403
404
  #
end

405

Patrick J Cherry's avatar
Patrick J Cherry committed
406
#
407
# Create a namespace for all the packaging tasks
Patrick J Cherry's avatar
Patrick J Cherry committed
408
#
409
namespace :pkg do
Patrick J Cherry's avatar
Patrick J Cherry committed
410
411

  #
412
  # Create a namespace per package.
Patrick J Cherry's avatar
Patrick J Cherry committed
413
  #
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  all_packages.each do |pkg|
    
    #
    # Task to build our package -- an easy to remember name
    #
    desc "Build #{pkg[:source]}"
    task pkg[:source]   => "pkg:#{pkg[:source]}:all"
    
    #
    # Add the package specific tasks to the generic build tasks -- these are
    # used in the top-level tasks.
    #
    task :all           => "pkg:#{pkg[:source]}:all"
    task :genchanges    => "pkg:#{pkg[:source]}:genchanges"
    task :source        => "pkg:#{pkg[:source]}:source"
    task :buildpackage  => "pkg:#{pkg[:source]}:buildpackage"
    task :clean         => "pkg:#{pkg[:source]}:clean"
    task :clobber       => "pkg:#{pkg[:source]}:clobber"
    task :dependencies  => "pkg:#{pkg[:source]}:dependencies"

    namespace pkg[:source] do
      
      task :source => ["clean"] do |t|
        #
        # Make sure the documentation is build before creating the source tgz
        # for any documentation package.
        #
        Rake::Task["rdoc"].invoke if "doc" == pkg[:dir]
        sh "dpkg-source -b #{pkg[:dir]}"
      end
Patrick J Cherry's avatar
Patrick J Cherry committed
444

445
446
447
      task :genchanges => ["clean", pkg[:dsc]] do 
        sh "cd #{pkg[:dir]} && dpkg-genchanges -S > ../#{pkg[:source_changes]}"
      end
Patrick J Cherry's avatar
Patrick J Cherry committed
448

449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
      task :buildpackage => ["dependencies", pkg[:dsc], pkg[:source_changes]].flatten do
        #
        # Now call sautobuild and debsign
        #
        if has_sautobuild?
          sh "/usr/bin/sautobuild --no-repo --dist=#{pkg[:distro]} #{pkg[:dir]}"
        else
          sh "cd #{pkg[:dir]} && debuild -us -uc -sa"
        end
      end

      task :clean do
        Rake::Task["rdoc:clean"].invoke if "doc" == pkg[:dir]
        begin
          unless has_sautobuild?
            File.chmod(0755, "#{pkg[:dir]}/debian/rules")
            sh "cd #{pkg[:dir]} && fakeroot debian/rules clean"
Patrick J Cherry's avatar
Patrick J Cherry committed
466
          end
467
468
469
470
471
        rescue => err
          # do nothing because because this rules clean cannot be expected to
          # work for every package outside of a chroot.
        end
      end
Patrick J Cherry's avatar
Patrick J Cherry committed
472

473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
      task :clobber => "clean" do
        Rake::Task["rdoc:clobber"].invoke if "doc" == pkg[:dir]

        rm_f pkg[:packages] + pkg[:builds] + pkg[:changes] + [pkg[:dsc], pkg[:targz], pkg[:diffgz], pkg[:source_changes]]
      end

      task :dependencies => [File.join(pkg[:dir],"debian","control")] do |t|
        Rake::Task["rdoc:dependencies"].invoke if "doc" == pkg[:dir]

        missing_build_deps = if has_sautobuild?
          []
        else
          pkg_depends = `cd #{pkg[:dir]} && dpkg-checkbuilddeps 2>&1`.chomp
          if 0 != $? 
            if pkg_depends =~ /^dpkg-checkbuilddeps: Unmet build dependencies: (.*)/i
              $1.gsub(/\([^\)]+\)/,'').split(" ")
            else
              raise "dpkg-checkbuilddeps returned unrecognised output:\n#{pkg_depends}"
            end
          else
            []
          end
        end

        raise "Need to install the following packages to build #{pkg[:source]}:\n  #{missing_build_deps.join(" ")}" unless missing_build_deps.empty?
      end 

      task :all  => %w(dependencies clean)+pkg[:packages]
Patrick J Cherry's avatar
Patrick J Cherry committed
501
502
503
504
505
506
    end

  end

end

507
508
509
510
511
#####################################################################
# 
# RULES
#
#####################################################################
512

513
514
515
516
517
518
519
520
desc "Generic rule to create a detached signature for something."
rule '.gpg' => [ proc {|t| t.sub(/.gpg$/,"") } ] do |t|
  sh "gpg --armor --sign-with #{DEBEMAIL} --detach-sign --output - #{t.source} > #{t.name}"
end

desc "Generic rule to sign something with a cleartext signature"
rule '.asc' => [ proc {|t| t.sub(/.asc$/,"") } ] do |t|
  sh "gpg --armor --sign-with #{DEBEMAIL} --clearsign --output - #{t.source} > #{t.name}"
521
522
end

523
524
525
desc "Generic rule to zip things up, keeping a copy."
rule '.gz' => [ proc {|t| t.sub(/.gz$/,"") } ] do |t|
  sh "cat #{t.source} | gzip -9c > #{t.name}"
Patrick J Cherry's avatar
Patrick J Cherry committed
526
527
end

528
529
530
# dsc/targz => source
# source.changes => dsc
# deb/build/changes => source.changes
Patrick J Cherry's avatar
Patrick J Cherry committed
531

532
533
534
535
desc "Generic rule to call the :source task for a package given a filename."
rule(/^[^\/]+\.(tar\.gz|diff\.gz|dsc)$/ =>
  proc do |task_name|
    pkg = find_package_by_filename(task_name)
Patrick J Cherry's avatar
Patrick J Cherry committed
536

537
538
539
    if pkg.nil?
      raise "Could not find package to build for #{task_name}"
    end
Patrick J Cherry's avatar
Patrick J Cherry committed
540

541
542
    source_files = Dir.glob(File.join(pkg[:dir],"**", "*")).select{|f| File.file?(f)}
    source_files << 'doc/html/created.rid' if pkg[:dir] == "doc"
Patrick J Cherry's avatar
Patrick J Cherry committed
543

544
    source_files
Patrick J Cherry's avatar
Patrick J Cherry committed
545
  end
546
547
) do |t|
  pkg = find_package_by_filename(t.name)
Patrick J Cherry's avatar
Patrick J Cherry committed
548

549
  Rake::Task["pkg:#{pkg[:source]}:source"].invoke
Patrick J Cherry's avatar
Patrick J Cherry committed
550
551
end

552
553
554
555
556
557
desc "Generic rule to call the :genchanges task for a package given a filename."
rule(/^[^\/]+_source\.changes$/ =>
  proc do |task_name|
    pkg = find_package_by_filename(task_name)
    raise "Could not find package to build for #{task_name}" if pkg.nil?
    pkg[:dsc]
Patrick J Cherry's avatar
Patrick J Cherry committed
558
  end
559
560
) do |t|
  pkg = find_package_by_filename(t.name)
Patrick J Cherry's avatar
Patrick J Cherry committed
561

562
563
564
565
566
567
568
569
570
571
572
573
  Rake::Task["pkg:#{pkg[:source]}:genchanges"].invoke
end

desc "Generic rule to call the :buildpackage task for a package given a filename."
rule(/^[^\/]+(_(#{available_build_archs.join("|")})\.(build|changes)|\.deb)$/ =>
  proc do |task_name|
    pkg = find_package_by_filename(task_name)
    raise "Could not find package to build for #{task_name}" if pkg.nil?
    pkg[:source_changes]
  end  
) do |t|
  pkg = find_package_by_filename(t.name)
574

575
  Rake::Task["pkg:#{pkg[:source]}:buildpackage"].invoke
Patrick J Cherry's avatar
Patrick J Cherry committed
576
end
Patrick J Cherry's avatar
Patrick J Cherry committed
577

578