lib/licensed/commands/status.rb in licensed-4.3.1 vs lib/licensed/commands/status.rb in licensed-4.4.0
- old
+ new
@@ -21,16 +21,54 @@
# report - A Licensed::Report object for this command
#
# Returns whether the command succeeded based on the call to super
def run_command(report)
super do |result|
- next if result
+ stale_records = stale_cached_records
+ if stale_records.any?
+ messages = stale_records.map { |f| "Stale dependency record found: #{f}" }
+ messages << "Please run the licensed cache command to clean up stale records"
+ case config["stale_records_action"].to_s
+ when "error"
+ report.errors.concat messages
+ result = false
+ when "warn", ""
+ report.warnings.concat messages
+ end
+ end
+
+ next result if result
+
report.errors << "Licensed found errors during source enumeration. Please see https://github.com/github/licensed/tree/master/docs/commands/status.md#status-errors-and-resolutions for possible resolutions."
+
+ result
end
+ ensure
+ cache_paths.clear
+ files.clear
end
+ # Run the command for all enumerated dependencies found in a dependency source,
+ # recording results in a report.
+ # Enumerating dependencies in the source is skipped if a :sources option
+ # is provided and the evaluated `source.class.type` is not in the :sources values
+ #
+ # app - The application configuration for the source
+ # source - A dependency source enumerator
+ #
+ # Returns whether the command succeeded for the dependency source enumerator
+ def run_source(app, source, report)
+ result = super
+
+ # add the full cache path to the list of cache paths
+ # that should be checked for extra files after the command run
+ cache_paths << app.cache_path.join(source.class.type) unless result == :skipped
+
+ result
+ end
+
# Evaluates a dependency for any compliance errors.
# Checks a dependency against either a cached metadata record or
# reviewed entries in the configuration file.
#
# app - The application configuration for the dependency
@@ -47,10 +85,13 @@
record = dependency.record
else
filename = app.cache_path.join(source.class.type, "#{dependency.name}.#{DependencyRecord::EXTENSION}")
report["filename"] = filename
record = cached_record(filename)
+
+ # add the absolute dependency file path to the list of files seen during this licensed run
+ files << filename.to_s
end
if record.nil?
report["license"] = nil
report.errors << "cached dependency record not found"
@@ -130,9 +171,29 @@
Licensee::ProjectFiles::ReadmeFile.new(text).license&.key,
"other"
].compact
licenses.sort_by { |license| license != "other" ? 0 : 1 }.first
+ end
+
+ # Check for cached files that don't match current dependencies
+ #
+ # Returns an array of any cached records that do not match a currently used dependency
+ def stale_cached_records
+ cache_paths.flat_map do |cache_path|
+ record_search_glob_pattern = cache_path.join("**/*.#{DependencyRecord::EXTENSION}")
+ Dir.glob(record_search_glob_pattern).select { |file| !files.include?(file) }
+ end.uniq
+ end
+
+ # Set of unique cache paths that are evaluted during the run
+ def cache_paths
+ @cache_paths ||= Set.new
+ end
+
+ # Set of unique absolute file paths of cached records evaluted during the run
+ def files
+ @files ||= Set.new
end
end
end
end