Commits

Cintia Del Rio Calvo committed efe2c08

NONE: adding a helper to extract license files from jars

Comments (0)

Files changed (1)

bin/licensing_helper

+#!/usr/bin/env ruby
+
+# This script was made originally to Stash https://stash.atlassian.com/projects/STASH/repos/stash/browse/etc/licensing/licensing_tool
+
+require 'rubygems'
+
+%w(fileutils colorize commander/import).each do |gem|
+  begin
+    require gem
+  rescue LoadError => e
+    puts "Failed to load '#{gem}' - please install this gem first"
+    puts ""
+    puts "\t[sudo] gem install #{gem}"
+    puts ""
+    exit -1
+  end
+end
+
+program :name, 'license_tool'
+program :version, '1.0.0'
+program :description, 'Make looking up license information easier'
+
+class Jar
+  class << self
+    def read_file(path, file)
+      `unzip -p #{file} #{path}`
+    end
+  end
+
+  def valid_jar_file?(file)
+    `jar tf #{file} &> /dev/null`
+    $?.to_i.eql?(0)
+  end
+end
+
+class License
+
+  def write_license(gav, license_dir)
+    file = gav.path
+    puts "file is nil -> #{gav}".red && return unless file
+    unless File.file?(File.expand_path(file))
+      puts "File '#{file}' not found"
+      return
+    end
+    license_information = `jar tf #{file}`.split("\n").grep(/(LICENSE|NOTICE)/i).sort.reverse.reject {|f| f =~ /(\.class$|\/$)/}
+    unless license_information.empty?
+      puts "Found #{license_information.join(", ")}"
+      local_file = gav.license_file_name
+      puts "Writing combined license to #{local_file}".green
+      File.open(File.join(license_dir, local_file), "w") do |f|
+        f << license_information.map {|path| Jar.read_file(path, file)}.join("\n\n")
+      end
+    else
+      puts "No license information found for #{File.basename(file)}".yellow
+    end
+  end
+end
+
+Gav = Struct.new(:group, :artifact, :version, :path) do
+  def name
+    gav_name = [group,artifact, version].compact
+    if (gav_name.size == 2)
+      gav_name.join('--').gsub(/[^A-Za-z0-9.-]/,'')
+    else
+      gav_name.join('--')
+    end
+  end
+  alias_method :to_s, :name
+
+  def license_file_name
+    "#{name}.txt"
+  end
+end
+
+class Maven
+
+  def repo_prefix; File.expand_path("~/.m2/repository"); end
+
+  # Example entries:
+  # A Hibernate Core Module,org.hibernate:hibernate-core:jar:4.1.9.Final,GNU Lesser General Public License,http://hibernate.org,binary
+  # zepto,1.0rc1,MIT License,http://zeptojs.com/,binary
+
+  # M2 repository paths
+  # ~/.m2/repository/org/apache/felix/org.apache.felix.framework/3.0.2/org.apache.felix.framework-3.0.2.jar
+  # ~/.m2/repository/org/hibernate/hibernate-core/4.1.9.Final/hibernate-core-4.1.9.Final.jar
+
+  # org.hibernate:hibernate-core:jar:4.1.9.Final
+  def to_path(name, gav)
+    if gav =~ /:/
+      gav_to_path(gav)
+    else
+      name_to_path(name, gav)
+    end
+  end
+
+  private
+    def name_to_path(name, version)
+      Gav.new(nil, name, version, nil)
+    end
+
+    def gav_to_path(gav)
+      group, artifact, packaging, version = gav.split(":")
+      path_group = group.split(".").join("/")
+      Gav.new(group, artifact, version, File.join(repo_prefix, *[path_group, artifact, version, "#{artifact}-#{version}.jar"].compact))
+    end
+end
+
+def pretty_print_license_files(lst)
+  lst.each do |f|
+    a = block_given? ? yield(f) : ""
+    puts "\t* #{f.yellow} #{a}"
+  end
+end
+
+def fuzzy_find_license_entry(bom_list, license_file_name)
+  needle = license_file_name.split("-").first
+  res = bom_list.select do |gav|
+    gav if gav.artifact =~ /.*#{needle}.*/i
+  end
+end
+
+def read_bom(file, scope = nil)
+  entries = scope ? IO.readlines(file).grep(/#{scope}$/) : IO.readlines(file)
+  entries.map do |rec|
+    name, gav, *rest = rec.split(",")
+    Maven.new.to_path name, gav
+  end
+end
+
+def get_existing_license_files(licenses_dir)
+  Dir["#{licenses_dir}/*.txt"].map {|path| File.basename path}
+end
+
+
+DEFAULT_LICENSE_DIR = File.join("distribution", "licenses", "src", "main", "resources", "licenses")
+
+def get_dir_from_arguments(args)
+  if (args.length == 0)
+    license_dir_path = DEFAULT_LICENSE_DIR
+  else
+    license_dir_path = File.join(args)
+  end
+end
+
+
+binary_deps = read_bom("./third-party-licensing/bom.csv", "binary")
+all_deps = read_bom("./third-party-licensing/bom.csv")
+required_license_files = binary_deps.map {|gav| gav.license_file_name}
+
+command :show_unused_license_files do |c|
+  c.syntax = 'license_tool show_unused_license_files ./path/to/license/folder'
+  c.description = 'Show license files that don\'t have a corresponding entry in the BOM'
+  c.action do |args, options|
+    license_dir_path = get_dir_from_arguments(args)
+    unused_license_files = get_existing_license_files(license_dir_path) - required_license_files
+    puts "The following license file exist but don't have corresponding entries in the bom"
+    pretty_print_license_files(unused_license_files) do |gav|
+      matches = fuzzy_find_license_entry(all_deps, gav)
+      "\n\t\tpotential matching licenses in the bom: #{matches.join(', ').green}" unless matches.empty?
+    end
+  end
+end
+
+command :show_missing_license_files do |c|
+  c.syntax = 'license_tool show_missing_license_files ./path/to/license/folder'
+  c.description = 'Show missing license files for entries that exist in the BOM'
+  c.option '--create', 'Create empty license files'
+
+  c.action do |args, options|
+    license_dir_path = get_dir_from_arguments(args)
+
+    missing_license_files = required_license_files - get_existing_license_files(license_dir_path)
+    unless missing_license_files.empty?
+      puts "The following license files are missing"
+      pretty_print_license_files missing_license_files
+    else
+      puts "No missing license files".green
+    end
+    if options.create
+      missing_license_files.each do |license_file|
+        puts "Creating license file for #{license_file}".green
+        File.open(File.join(license_dir_path, license_file), "w") do |f|
+          f << ""
+        end
+      end
+    end
+  end
+end
+
+
+command :bulk_write do |c|
+  c.syntax = 'license_tool bulk_write ./path/to/license/folder'
+  c.description = 'Bulk create license files using the artifacts in the local Maven repository'
+  c.action do |args, options|
+    license_dir_path = get_dir_from_arguments(args)
+    license_tool = License.new
+
+    binary_deps.each do |info|
+      group, artifact, version, path = info.group, info.artifact, info.version, info.path
+      puts "Trying to retrieve license for #{group}, #{artifact}, #{version}"
+      puts info.to_s
+      license_tool.write_license(info, license_dir_path)
+      puts ""
+    end
+  end
+end
+
+
+default_command :help