Rakefile 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. # FreeBSD Ports
  2. #
  3. # Douglas Thrift
  4. #
  5. # Rakefile
  6. require 'date'
  7. require 'ostruct'
  8. require 'pathname'
  9. require 'pry'
  10. require 'set'
  11. Color = Pry::Helpers::Text
  12. def in_portdir(&block)
  13. portdir = Pathname.new(Rake.original_dir)
  14. raise "#{portdir} is not a port directory" unless portdir.relative_path_from(@portsdir).to_s =~ %r{[^/]+/[^/]+}
  15. Dir.chdir(portdir) do
  16. block.call(portdir)
  17. end
  18. end
  19. def in_portstree(portstree, &block)
  20. portstree_zfs = `zfs get -H -o name mountpoint #{portstree.path}`.chomp
  21. sh "sudo zfs snapshot #{portstree_zfs}@clean"
  22. Dir.chdir(portstree.path) do
  23. block.call(portstree.path)
  24. end
  25. ensure
  26. sh "sudo zfs rollback #{portstree_zfs}@clean"
  27. sh "sudo zfs destroy #{portstree_zfs}@clean"
  28. end
  29. def update_portstree_map(map = {})
  30. `poudriere ports -l -q`.each_line do |line|
  31. line.chomp!
  32. if line =~ /^([^ ]+) +([^ ]+) +([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}) +([^ ]+)$/
  33. map[$1.to_sym] = OpenStruct.new(method: $2, timestamp: DateTime.parse($3), path: Pathname.new($4))
  34. else
  35. raise "unexpected line: #{line}"
  36. end
  37. end
  38. map
  39. end
  40. def clean_version(version)
  41. if version =~ /^(\d+\.\d+-RELEASE)(?:-p\d+)$/
  42. $1
  43. else
  44. version
  45. end
  46. end
  47. portstree_map = update_portstree_map
  48. portsdir = @portsdir = Pathname.pwd
  49. distdir = portsdir.join('distfiles')
  50. task default: %i(update_githead update_svnhead)
  51. desc 'Create or update the port checksum file (distinfo)'
  52. task :makesum do
  53. in_portdir do
  54. sh "make makesum DEV_WARNING_WAIT=0 DISTDIR=#{distdir}"
  55. end
  56. end
  57. %w(md5 sha1 sha256).each do |sum|
  58. desc "Show the #{sum.upcase} sums of the distfiles"
  59. task sum do
  60. sh "mkdir -p #{distdir}" unless distdir.exist?
  61. files = distdir.glob('**/*').select {|dist| dist.file?}.map {|dist| dist.relative_path_from(portsdir)}
  62. sh "#{sum} #{files.join(' ')}" unless files.empty?
  63. end
  64. end
  65. desc 'Remove the ports distfiles'
  66. task :distclean do
  67. in_portdir do
  68. sh "make distclean DISTDIR=#{distdir}"
  69. end
  70. end
  71. desc 'Verify the port using portlint'
  72. task portlint: :update_githead do
  73. in_portdir do |portdir|
  74. if githead_portstree.path.join(portdir.relative_path_from(portsdir), 'Makefile').exist?
  75. sh "portlint -C"
  76. else
  77. sh "portlint -A"
  78. end
  79. end
  80. end
  81. desc 'Show the port differences'
  82. task diff: :update_svnhead do |_, args|
  83. patch = args.extras.find {|arg| arg == 'patch'}
  84. in_portdir do |portdir|
  85. new_files = Set.new(`git ls-files`.each_line.map {|line| Pathname.new(line.chomp)})
  86. in_portstree(svnhead_portstree) do |path|
  87. rel_portdir = portdir.relative_path_from(portsdir)
  88. svnhead_portdir = path.join(rel_portdir)
  89. if svnhead_portdir.exist?
  90. old_files = Set.new(`svn ls -R #{svnhead_portdir}`.each_line.reject {|line| line =~ %r{/$}}.map {|line| Pathname.new(line.chomp)})
  91. else
  92. old_files = Set.new
  93. end
  94. sh "sudo mkdir -p #{svnhead_portdir}"
  95. Dir.chdir(svnhead_portdir) do
  96. new_files.each do |file|
  97. portdir_file = portdir.join(file)
  98. sh "sudo mkdir -p #{file.dirname}" unless file.dirname.exist?
  99. sh "sudo cp #{portdir_file} #{file}"
  100. end
  101. (new_files - old_files).each do |file|
  102. sh "sudo svn add --parents #{file}"
  103. end
  104. (old_files - new_files).each do |file|
  105. sh "sudo svn remove #{file}"
  106. end
  107. unless old_files.empty?
  108. if patch
  109. sh "svn diff > #{portdir.dirname.join("#{`make -V PKGNAME`.chomp}.diff")}"
  110. else
  111. sh "svn diff"
  112. end
  113. end
  114. end
  115. if old_files.empty?
  116. if patch
  117. sh "svn diff #{rel_portdir} > #{portsdir.join("#{portdir.basename}.diff")}"
  118. else
  119. sh "svn diff #{rel_portdir}"
  120. end
  121. end
  122. end
  123. end
  124. end
  125. desc 'Test the port with poudriere'
  126. task :testport, %i(jailname flavor) => :update_githead do |_, args|
  127. this_version = clean_version(`uname -r`.chomp)
  128. this_arch = `uname -m`.chomp
  129. this_jailname = nil
  130. `poudriere jail -l -q`.each_line do |line|
  131. line.chomp!
  132. if line =~ /^([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+).+$/
  133. jailname, version, arch, method = $1, $2, $3, $4
  134. if clean_version(version) == this_version && arch == this_arch && method == 'ftp'
  135. this_jailname = jailname
  136. break
  137. end
  138. else
  139. raise "unexpected line: #{line}"
  140. end
  141. end
  142. args.with_defaults(jailname: this_jailname)
  143. in_portdir do |portdir|
  144. files = `git ls-files`.each_line.map {|line| Pathname.new(line.chomp)}
  145. in_portstree(githead_portstree) do |path|
  146. rel_portdir = portdir.relative_path_from(portsdir)
  147. githead_portdir = path.join(rel_portdir)
  148. sh "sudo mkdir -p #{githead_portdir}"
  149. Dir.chdir(githead_portdir) do
  150. files.each do |file|
  151. portdir_file = portdir.join(file)
  152. sh "sudo mkdir -p #{file.dirname}" unless file.dirname.exist?
  153. sh "sudo cp #{portdir_file} #{file}"
  154. end
  155. end
  156. sh "sudo poudriere testport -j #{args.jailname} -o #{rel_portdir}#{args.flavor && "@#{args.flavor}"} -p githead"
  157. end
  158. end
  159. end
  160. {githead: 'git+https', svnhead: 'svn+https'}.each do |name, method|
  161. define_method("#{name}_portstree") do
  162. portstree_map[name]
  163. end
  164. desc "Create or update the #{name} portstree"
  165. task "update_#{name}" do |_, args|
  166. force = args.extras.find {|arg| arg == 'force'}
  167. portstree = portstree_map[name]
  168. if portstree
  169. raise "unexpected portstree method for #{name}: #{portstree[:method]} (expected: #{method})" if portstree[:method] != method
  170. if force || portstree.timestamp < Date.today
  171. sh "sudo poudriere ports -u -p #{name}"
  172. end
  173. else
  174. sh "sudo poudriere ports -c -m #{method} -p #{name}"
  175. update_portstree_map(portstree_map)
  176. end
  177. end
  178. end