Commit b2c7fbfc authored by anonym's avatar anonym
Browse files

Merge remote-tracking branch 'origin/web/release-4.8'

Closes #17306.
parents e8f4f42e 6ebd335f
# This file (.rubocop.yml) encodes consciously chosen deviation from Rubocop's
# default configuration. The jury is still out regarding other checks, which are
# disabled or tweaked in .rubocop_todo.yml.
inherit_from: .rubocop_todo.yml
AllCops:
Exclude:
# Let's ignore this script until we start using it and maintaining
# the corresponding doc-source-relationships.yml
- 'bin/doc-impacted-by'
# XXX:Buster: bump to 2.5 once we require Buster to build Tails and to run our
# test suite
TargetRubyVersion: 2.3
Layout/HashAlignment:
EnforcedHashRocketStyle: table
EnforcedColonStyle: table
Lint/SuppressedException:
AllowComments: true
Metrics/AbcSize:
Max: 30
Metrics/BlockLength:
Max: 27
ExcludedMethods:
# Rake
- 'namespace'
- 'task'
# Vagrant
- 'Vagrant.configure'
Metrics/ClassLength:
Max: 200
Metrics/CyclomaticComplexity:
Max: 9
Metrics/MethodLength:
Max: 30
Metrics/ParameterLists:
CountKeywordArgs: false
Metrics/PerceivedComplexity:
Max: 10
Naming/BlockParameterName:
AllowedNames:
- expected_patterns_MiB
- size_MiB
- size_in_MiB_of_destination_disk
Naming/MethodName:
IgnoredPatterns:
# Cucumber
- \A(After|Before)Feature\z
# Case matters: bit vs. byte
- _(kB|MiB)\z
# Stay close to Dogtail's API
- \A(pressKey|roleName|typeText)\z
# Stay close to OpenCV's API
- \AmatchTemplate\z
Naming/MethodParameterName:
AllowedNames:
- h
- to
- vm
- w
- x
- y
Style/AccessModifierDeclarations:
EnforcedStyle: inline
Style/AsciiComments:
Enabled: false
Style/AutoResourceCleanup:
Enabled: true
Style/ClassAndModuleChildren:
EnforcedStyle: compact
Style/ClassVars:
Exclude:
- 'features/support/helpers/dogtail.rb'
- 'features/support/helpers/remote_shell.rb'
Style/CollectionMethods:
Enabled: true
Style/ConstantVisibility:
Enabled: true
Style/FrozenStringLiteralComment:
Enabled: false
Style/GlobalVars:
Exclude:
- 'Rakefile'
Style/GuardClause:
MinBodyLength: 3
Style/HashEachMethods:
Enabled: true
Style/HashTransformKeys:
Enabled: true
Style/HashTransformValues:
Enabled: true
Style/HashSyntax:
EnforcedStyle: ruby19_no_mixed_keys
Style/MethodCallWithArgsParentheses:
Enabled: true
IgnoredMethods:
- abort
- assert
- basename
- chdir
- debug_log
- define
- delete
- desc
- exist?
- exit
- fatal_system
- include
- include?
- mkdir
- mktmpdir
- puts
- raise
- remove_entry_secure
- require
- require_relative
- returncode
- separator
- should
- should_not
- sleep
- start_with?
- step
- task
- wait
- warn
- write
- yield
Style/MethodCalledOnDoEndBlock:
Enabled: true
Style/NumericLiterals:
MinDigits: 6
Style/OptionHash:
Enabled: true
Style/ReturnNil:
Enabled: true
Style/Send:
Enabled: true
Style/SingleLineBlockParams:
Enabled: true
Style/StringMethods:
Enabled: true
Style/SymbolArray:
EnforcedStyle: brackets
Style/TrailingCommaInArguments:
EnforcedStyleForMultiline: no_comma
Style/TrailingCommaInArrayLiteral:
EnforcedStyleForMultiline: consistent_comma
Style/TrailingCommaInHashLiteral:
EnforcedStyleForMultiline: consistent_comma
Style/WordArray:
EnforcedStyle: brackets
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2020-05-10 17:29:26 +0200 using RuboCop version 0.80.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: runtime_error, standard_error
Lint/InheritException:
Exclude:
- 'features/support/helpers/misc_helpers.rb'
# Offense count: 11
Naming/AccessorMethodName:
Exclude:
- 'features/scripts/vm-execute'
- 'features/step_definitions/ssh.rb'
- 'features/support/helpers/vm_helper.rb'
# Offense count: 20
Style/Documentation:
Exclude:
- 'spec/**/*'
- 'test/**/*'
- 'Rakefile'
- 'features/scripts/vm-execute'
- 'features/support/extra_hooks.rb'
- 'features/support/helpers/chatbot_helper.rb'
- 'features/support/helpers/display_helper.rb'
- 'features/support/helpers/dogtail.rb'
- 'features/support/helpers/opencv.rb'
- 'features/support/helpers/remote_shell.rb'
- 'features/support/helpers/screen.rb'
- 'features/support/helpers/sniffing_helper.rb'
- 'features/support/helpers/sshd_helper.rb'
- 'features/support/helpers/storage_helper.rb'
- 'features/support/helpers/vm_helper.rb'
This diff is collapsed.
......@@ -5,10 +5,10 @@
require 'json'
usage_str = "Usage: apt-snapshots-serials-cat-json APT_SNAPSHOTS_CONFIG_DIR"
!ARGV.empty? or raise usage_str
usage_str = 'Usage: apt-snapshots-serials-cat-json APT_SNAPSHOTS_CONFIG_DIR'
!ARGV.empty? || raise(usage_str)
config_dir = ARGV[0]
!config_dir.empty? or raise usage_str
!config_dir.empty? || raise(usage_str)
serials = {}
......@@ -17,7 +17,8 @@ origins = Dir.glob("#{config_dir}/*").map do |origin_dir|
end
origins.map do |origin|
serials[origin] = File.open("#{config_dir}/#{origin}/serial") { |f| f.read.chomp }
serial_file = "#{config_dir}/#{origin}/serial"
serials[origin] = File.open(serial_file) { |f| f.read.chomp }
end
puts JSON.dump(serials)
......@@ -7,15 +7,15 @@
# Example:
#
# apt-snapshots-serials-load-json \
# '{"torproject":"2017120803","debian-security":"2017120902","debian":"2017120903"}'
# '{"torproject":"2017120803","debian":"2017120903"}'
require 'json'
usage_str = "Usage: apt-snapshots-serials-load-json SERIALS_JSON"
ARGV.size == 1 or raise usage_str
serials = JSON.load(ARGV[0])
usage_str = 'Usage: apt-snapshots-serials-load-json SERIALS_JSON'
(ARGV.size == 1) || raise(usage_str)
serials = JSON.parse(ARGV[0])
serials.each { |origin, serial|
serial != 'latest' or raise "Only numeric serials are supported"
serials.each do |origin, serial|
(serial != 'latest') || raise('Only numeric serials are supported')
puts "#{origin}: #{serial}\n"
}
end
#!/usr/bin/env ruby
# coding: utf-8
require 'deep_merge'
require 'English'
require 'git'
require 'optparse'
require 'yaml'
require 'test/unit'
Test::Unit.run = true
include Test::Unit::Assertions
# Make all the assert_* methods easily accessible.
include Test::Unit::Assertions # rubocop:disable Style/MixinUsage
# The Ruby Git module we use needs the Git root directory, and this
# prevents it from being able to run the command below.
GIT_DIR = `git rev-parse --show-toplevel`.chomp
assert_equal(0, $?.exitstatus)
DEFAULT_RELATIONSHIP_FILE = "#{GIT_DIR}/doc-source-relationships.yml"
assert_equal(0, $CHILD_STATUS.exitstatus)
DEFAULT_RELATIONSHIP_FILE = "#{GIT_DIR}/doc-source-relationships.yml".freeze
class Object
def arrayify
self.instance_of?(Array) ? self : [self]
instance_of?(Array) ? self : [self]
end
end
......@@ -30,36 +31,36 @@ class Array
end
def parse_argv!
options = Hash.new
options = {}
opt_parser = OptionParser.new do |opts|
opts.banner = "Usage: [OPTION]... COMMITISH1 COMMITISH2 MANIFEST1 MANIFEST2"
opts.separator ""
opts.separator "Produces a list of documentation pages that might need " \
"attention due to the changes from COMMITISH1 to " \
"COMMITISH2. The corresponding .build-manifest files must " \
"be passed as MANIFEST1 and MANIFEST2."
opts.separator ""
opts.separator "Example:"
opts.separator " bin/doc-impacted-by 3.0 3.2 " \
"tails-amd64-3.0.build-manifest " \
"tails-amd64-3.2.build-manifest"
opts.separator ""
opts.separator "Options:"
opts.banner = 'Usage: [OPTION]... COMMITISH1 COMMITISH2 MANIFEST1 MANIFEST2'
opts.separator ''
opts.separator 'Produces a list of documentation pages that might need ' \
'attention due to the changes from COMMITISH1 to ' \
'COMMITISH2. The corresponding .build-manifest files must ' \
'be passed as MANIFEST1 and MANIFEST2.'
opts.separator ''
opts.separator 'Example:'
opts.separator ' bin/doc-impacted-by 3.0 3.2 ' \
'tails-amd64-3.0.build-manifest ' \
'tails-amd64-3.2.build-manifest'
opts.separator ''
opts.separator 'Options:'
opts.on("-h", "--help", "Show this message") do
opts.on('-h', '--help', 'Show this message') do
puts opts
exit
end
opts.on("-f PATH", "--relationship-file=PATH",
"Use a custom PATH for the doc-source relationship description " +
"file (default: #{File.basename(DEFAULT_RELATIONSHIP_FILE)} in " +
"the Git root)") do |path|
opts.on('-f PATH', '--relationship-file=PATH',
'Use a custom PATH for the doc-source relationship description ' \
"file (default: #{File.basename(DEFAULT_RELATIONSHIP_FILE)} in " \
'the Git root)') do |path|
options['relationship-file'] = path
end
opts.on("-s", "--skip-packages", "Skip looking at packages, " +
"only look at Git") do
opts.on('-s', '--skip-packages', 'Skip looking at packages, ' \
'only look at Git') do
options['skip-packages'] = true
end
end
......@@ -67,20 +68,21 @@ def parse_argv!
req_nr_parameters = options['skip-packages'] ? 2 : 4
assert_equal(req_nr_parameters, parameters.size,
"You must pass exactly #{req_nr_parameters} parameters")
return [options, parameters]
[options, parameters]
end
# From a .build-manifest, from its list of packages, generate a
# Hash mapping `package` to a Hash containing the remaining package
# fields from the .build-manifest (e.g. `arch`, `version`).
def read_package_manifest_file_as_package_map(path)
package_manifest = YAML.load(File.read(path))
package_manifest = YAML.safe_load(File.read(path))
packages = package_manifest['packages']['binary'] +
package_manifest['packages']['source']
packages.map do |entry|
packages
.map do |entry|
[
entry['package'],
entry.clone.delete_if { |k, _| k == 'package' }
entry.clone.delete_if { |k, _| k == 'package' },
]
end
.to_h
......@@ -96,14 +98,15 @@ def canonicalize_relationship(orig_entry)
}
fields = field_abbreviations.values
field_abbreviations.each do |short, long|
next unless entry.has_key?(short)
assert(not(entry.has_key?(long)),
"contains both '#{long}' and its abbreviation '#{short}'")
next unless entry.key?(short)
assert(!entry.key?(long),
"contains both '#{long}' and its abbreviation '#{short}'")
v = entry[short]
entry.delete(short)
entry[long] = v
end
assert(entry.has_key?('pages'),
assert(entry.key?('pages'),
"lacks the obligatory 'pages' field")
assert(entry.keys.size > 1,
"entries with only a 'pages' field are meaningless")
......@@ -111,13 +114,14 @@ def canonicalize_relationship(orig_entry)
assert((entry.keys - fields).empty?,
"contains invalid fields: #{entry.keys - fields}")
fields.each do |field|
next unless entry.has_key?(field)
next unless entry.key?(field)
entry[field] = entry[field].arrayify
end
return entry
entry
rescue Exception => e
STDERR.puts 'Problematic entry:'
STDERR.puts YAML.dump([orig_entry])
warn 'Problematic entry:'
warn YAML.dump([orig_entry])
STDERR.puts
raise e
end
......@@ -126,15 +130,15 @@ end
# map", a Hash which maps all documentation pages to the sources it is
# impacted by.
def read_relationship_file_as_impact_map(relationship_file)
impact_map = Hash.new
relationships = YAML.load(File.read(relationship_file))
impact_map = {}
relationships = YAML.safe_load(File.read(relationship_file))
relationships.map { |e| canonicalize_relationship(e) } .each do |entry|
entry['pages'].each do |page|
source_files = entry.clone.delete_if { |k, _| k == 'pages' }
impact_map.deep_merge({page => source_files})
impact_map.deep_merge({ page => source_files })
end
end
return impact_map
impact_map
end
# Given the "documentation impact map" and the "old" and "new" state,
......@@ -153,20 +157,20 @@ def find_impacted_docs(impact_map,
# something like `git.object(new_commit).path('wiki/src')` but the
# Git module we use seem to not support listing files at a certain
# commit.
git_cmd_wiki_files = "git ls-tree -r --full-tree " +
git_cmd_wiki_files = 'git ls-tree -r --full-tree ' \
"--name-only #{new_commit} -- wiki/src"
doc_pages = `#{git_cmd_wiki_files}`.chomp.split("\n")
assert_equal(0, $?.exitstatus, "Error: `git ls-tree` failed")
assert_equal(0, $CHILD_STATUS.exitstatus, 'Error: `git ls-tree` failed')
old_packages = old_manifest.keys
new_packages = new_manifest.keys
removed_packages = old_packages - new_packages
introduced_packages = new_packages - old_packages
updated_packages = (new_packages & old_packages).select do |package|
old_manifest[package] != new_manifest[package]
updated_packages = (new_packages & old_packages).reject do |package|
old_manifest[package] == new_manifest[package]
end
impacted_docs = Hash.new
impacted_docs = {}
impact_map.each do |page, sources|
file_paths = []
package_globs = []
......@@ -180,9 +184,9 @@ def find_impacted_docs(impact_map,
when 'files'
file_paths = source
else
raise "Unknown field '#{type}' in impact map; this should not " +
"happen, and probably means canonicalize_relationship() " +
"is buggy"
raise "Unknown field '#{type}' in impact map; this should not " \
'happen, and probably means canonicalize_relationship() ' \
'is buggy'
end
end
all_source_file_paths = file_paths + test_paths
......@@ -190,15 +194,14 @@ def find_impacted_docs(impact_map,
all_source_file_paths.each do |source_path|
# Git::Diff#path() alters the object so it cannot be used for a
# successive call for another path.
_git_diff = git_diff.clone
source_path_diff = _git_diff.path(source_path)
if source_path_diff.size > 0
changed_files = source_path_diff.map { |file| file.path }
reasons = changed_files.map do |path|
"Changes in source file: #{path}"
end
impacted_docs.deep_merge({page_path => reasons})
source_path_diff = git_diff.clone.path(source_path)
next if source_path_diff.empty?
changed_files = source_path_diff.map(&:path)
reasons = changed_files.map do |path|
"Changes in source file: #{path}"
end
impacted_docs.deep_merge({ page_path => reasons })
end
package_globs.each do |package_glob|
reasons = []
......@@ -216,22 +219,23 @@ def find_impacted_docs(impact_map,
new = new_manifest[package]
assert_not_equal(
old, new,
"'#{package}' has identical data in both manifests so it is " +
"a bug that we ended up here"
"'#{package}' has identical data in both manifests so it is " \
'a bug that we ended up here'
)
package_changes = old_manifest[package].keys.sort.map do |key|
package_changes = old_manifest[package]
.keys.sort.map do |key|
old_val = old[key]
new_val = new[key]
old_val != new_val ? "#{old_val}#{new_val}" : nil
end
.compact.join(', ')
.compact.join(', ')
"Updated package: #{package} (#{package_changes})"
end
impacted_docs.deep_merge({page_path => reasons}) unless reasons.empty?
impacted_docs.deep_merge({ page_path => reasons }) unless reasons.empty?
end
end
end
return impacted_docs
impacted_docs
end
# Main
......@@ -242,8 +246,8 @@ old_commit, new_commit, old_manifest_path, new_manifest_path = parameters
impact_map = read_relationship_file_as_impact_map(relationship_file)
if options['skip-packages']
old_manifest = Hash.new
new_manifest = Hash.new
old_manifest = {}
new_manifest = {}
else
old_manifest = read_package_manifest_file_as_package_map(old_manifest_path)
new_manifest = read_package_manifest_file_as_package_map(new_manifest_path)
......@@ -254,22 +258,25 @@ impacted_docs = find_impacted_docs(
old_manifest, new_manifest
)
if impacted_docs.size > 0
unless impacted_docs.empty?
result =
impacted_docs.sort.map do |page, reasons|
impacted_docs
.sort
.map do |page, reasons|
"#{page}\n" +
reasons.sort.map do |reason|
reasons
.sort.map do |reason|
"- #{reason}"
end
.join("\n")
.join("\n")
end
.join("\n\n")
.join("\n\n")
puts "The following documentation pages need investigation:"
puts 'The following documentation pages need investigation:'
puts
puts result
end
if options['skip-packages']
STDERR.puts "Warning! The --skip-packages option makes this " +
"report incomplete!"
warn 'Warning! The --skip-packages option makes this ' \
'report incomplete!'
end
#!/usr/bin/env ruby
require 'date'
require 'English'
require 'test/unit'
Test::Unit.run = true
include Test::Unit::Assertions
# Make all the assert_* methods easily accessible.
include Test::Unit::Assertions # rubocop:disable Style/MixinUsage
# Force UTF-8. Ruby will default to the system locale, and if it is
# non-UTF-8, String-methods will fail when operating on non-ASCII
......@@ -11,15 +13,15 @@ include Test::Unit::Assertions
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8
GIT_DIR=`git rev-parse --show-toplevel`
GIT_DIR = `git rev-parse --show-toplevel`.freeze
assert_equal(
0, $?.exitstatus,
"Failed to find Tails' Git root; this command must be run " +
"inside Tails Git repo"
0, $CHILD_STATUS.exitstatus,
"Failed to find Tails' Git root; this command must be run " \
'inside Tails Git repo'
)
def rfc2822_date?(date)
!!DateTime.rfc2822(date)
!DateTime.rfc2822(date).nil?
rescue ArgumentError
false
end
......@@ -30,20 +32,20 @@ def page_meta_date_is_ok?(path)
content_lines = File.new(path).read.split("\n")
matches = content_lines.grep(meta_date_post_re)
if matches.size != 1