pmdtester 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.ci/build.sh +91 -0
  3. data/.ci/files/env.gpg +1 -0
  4. data/.github/workflows/build.yml +39 -0
  5. data/.gitignore +9 -0
  6. data/.hoerc +1 -1
  7. data/.rubocop.yml +6 -2
  8. data/.ruby-version +1 -0
  9. data/History.md +40 -0
  10. data/Manifest.txt +24 -9
  11. data/README.rdoc +45 -30
  12. data/Rakefile +5 -3
  13. data/config/all-java.xml +1 -1
  14. data/config/design.xml +1 -1
  15. data/config/projectlist_1_0_0.xsd +2 -1
  16. data/config/projectlist_1_1_0.xsd +31 -0
  17. data/lib/pmdtester.rb +8 -7
  18. data/lib/pmdtester/builders/liquid_renderer.rb +73 -0
  19. data/lib/pmdtester/builders/pmd_report_builder.rb +102 -78
  20. data/lib/pmdtester/builders/project_builder.rb +100 -0
  21. data/lib/pmdtester/builders/project_hasher.rb +126 -0
  22. data/lib/pmdtester/builders/rule_set_builder.rb +92 -47
  23. data/lib/pmdtester/builders/simple_progress_logger.rb +4 -4
  24. data/lib/pmdtester/builders/summary_report_builder.rb +62 -131
  25. data/lib/pmdtester/collection_by_file.rb +55 -0
  26. data/lib/pmdtester/parsers/options.rb +19 -0
  27. data/lib/pmdtester/parsers/pmd_report_document.rb +74 -29
  28. data/lib/pmdtester/parsers/projects_parser.rb +2 -4
  29. data/lib/pmdtester/pmd_branch_detail.rb +29 -19
  30. data/lib/pmdtester/pmd_configerror.rb +23 -24
  31. data/lib/pmdtester/pmd_error.rb +34 -34
  32. data/lib/pmdtester/pmd_report_detail.rb +9 -12
  33. data/lib/pmdtester/pmd_tester_utils.rb +55 -0
  34. data/lib/pmdtester/pmd_violation.rb +66 -28
  35. data/lib/pmdtester/project.rb +21 -48
  36. data/lib/pmdtester/report_diff.rb +179 -111
  37. data/lib/pmdtester/resource_locator.rb +4 -0
  38. data/lib/pmdtester/runner.rb +66 -64
  39. data/pmdtester.gemspec +27 -36
  40. data/resources/_includes/diff_pill_row.html +6 -0
  41. data/resources/css/bootstrap.min.css +7 -0
  42. data/resources/css/datatables.min.css +36 -0
  43. data/resources/css/pmd-tester.css +131 -0
  44. data/resources/js/bootstrap.min.js +7 -0
  45. data/resources/js/code-snippets.js +66 -0
  46. data/resources/js/datatables.min.js +726 -0
  47. data/resources/js/jquery-3.2.1.slim.min.js +4 -0
  48. data/resources/js/jquery.min.js +2 -0
  49. data/resources/js/popper.min.js +5 -0
  50. data/resources/js/project-report.js +136 -0
  51. data/resources/project_diff_report.html +205 -0
  52. data/resources/project_index.html +102 -0
  53. metadata +64 -20
  54. data/.travis.yml +0 -40
  55. data/lib/pmdtester/builders/diff_builder.rb +0 -31
  56. data/lib/pmdtester/builders/diff_report/configerrors.rb +0 -50
  57. data/lib/pmdtester/builders/diff_report/errors.rb +0 -71
  58. data/lib/pmdtester/builders/diff_report/violations.rb +0 -77
  59. data/lib/pmdtester/builders/diff_report_builder.rb +0 -99
  60. data/lib/pmdtester/builders/html_report_builder.rb +0 -56
  61. data/resources/css/maven-base.css +0 -155
  62. data/resources/css/maven-theme.css +0 -171
@@ -1,4 +1,5 @@
1
1
  <?xml version="1.0" ?>
2
+ <!-- version 1.0.0 -->
2
3
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3
4
  <xs:element name="projectlist">
4
5
  <xs:complexType>
@@ -25,4 +26,4 @@
25
26
  <xs:element name="exclude-pattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
26
27
  </xs:sequence>
27
28
  </xs:complexType>
28
- </xs:schema>
29
+ </xs:schema>
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" ?>
2
+ <!-- version 1.1.0 -->
3
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
4
+ <xs:element name="projectlist">
5
+ <xs:complexType>
6
+ <xs:sequence>
7
+ <xs:element name="description" type="xs:string" minOccurs="1" maxOccurs="1"/>
8
+ <xs:element name="project" type="project" minOccurs="1" maxOccurs="unbounded"/>
9
+ </xs:sequence>
10
+ </xs:complexType>
11
+ </xs:element>
12
+ <xs:complexType name="project">
13
+ <xs:sequence>
14
+ <xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1"/>
15
+ <xs:element name="type" minOccurs="1" maxOccurs="1">
16
+ <xs:simpleType>
17
+ <xs:restriction base="xs:string">
18
+ <xs:enumeration value="git"/>
19
+ <xs:enumeration value="hg"/>
20
+ </xs:restriction>
21
+ </xs:simpleType>
22
+ </xs:element>
23
+ <xs:element name="connection" type="xs:string" minOccurs="1" maxOccurs="1"/>
24
+ <xs:element name="webview-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
25
+ <xs:element name="tag" type="xs:string" minOccurs="0" maxOccurs="1"/>
26
+ <xs:element name="exclude-pattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
27
+ <xs:element name="build-command" type="xs:string" minOccurs="0" maxOccurs="1"/>
28
+ <xs:element name="auxclasspath-command" type="xs:string" minOccurs="0" maxOccurs="1"/>
29
+ </xs:sequence>
30
+ </xs:complexType>
31
+ </xs:schema>
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'logger'
4
+ require 'logger/colors'
4
5
 
5
6
  require_relative 'pmdtester/cmd'
7
+ require_relative 'pmdtester/collection_by_file'
6
8
  require_relative 'pmdtester/pmd_branch_detail'
7
9
  require_relative 'pmdtester/pmd_configerror'
8
10
  require_relative 'pmdtester/pmd_error'
9
11
  require_relative 'pmdtester/pmd_report_detail'
12
+ require_relative 'pmdtester/pmd_tester_utils'
10
13
  require_relative 'pmdtester/pmd_violation'
11
14
  require_relative 'pmdtester/project'
12
15
  require_relative 'pmdtester/report_diff'
@@ -14,13 +17,10 @@ require_relative 'pmdtester/resource_locator'
14
17
  require_relative 'pmdtester/runner'
15
18
 
16
19
  require_relative 'pmdtester/builders/simple_progress_logger'
17
- require_relative 'pmdtester/builders/html_report_builder'
18
- require_relative 'pmdtester/builders/diff_builder'
19
- require_relative 'pmdtester/builders/diff_report/violations'
20
- require_relative 'pmdtester/builders/diff_report/configerrors'
21
- require_relative 'pmdtester/builders/diff_report/errors'
22
- require_relative 'pmdtester/builders/diff_report_builder'
20
+ require_relative 'pmdtester/builders/project_builder'
21
+ require_relative 'pmdtester/builders/project_hasher'
23
22
  require_relative 'pmdtester/builders/pmd_report_builder'
23
+ require_relative 'pmdtester/builders/liquid_renderer'
24
24
  require_relative 'pmdtester/builders/rule_set_builder'
25
25
  require_relative 'pmdtester/builders/summary_report_builder'
26
26
 
@@ -32,9 +32,10 @@ require_relative 'pmdtester/parsers/projects_parser'
32
32
  # and unexpected behaviors will not be introduced to PMD project
33
33
  # after fixing an issue and new rules can work as expected.
34
34
  module PmdTester
35
- VERSION = '1.0.1'
35
+ VERSION = '1.1.0'
36
36
  BASE = 'base'
37
37
  PATCH = 'patch'
38
+ PR_NUM_ENV_VAR = 'PMD_CI_PULL_REQUEST_NUMBER' # see PmdBranchDetail
38
39
 
39
40
  def logger
40
41
  PmdTester.logger
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'liquid'
4
+ require 'json'
5
+
6
+ module PmdTester
7
+ # A module to include in classes that use a Liquid template
8
+ # to generate content.
9
+ module LiquidRenderer
10
+ include PmdTester
11
+
12
+ def render_liquid(template_path, env)
13
+ to_render = File.read(ResourceLocator.resource(template_path))
14
+ includes = Liquid::LocalFileSystem.new(ResourceLocator.resource('_includes'), '%s.html')
15
+ Liquid::Template.file_system = includes
16
+ template = Liquid::Template.parse(to_render, error_mode: :strict)
17
+ template.render!(env, { strict_variables: true })
18
+ end
19
+
20
+ def render_and_write(template_path, target_file, env)
21
+ write_file(target_file, render_liquid(template_path, env))
22
+ end
23
+
24
+ def write_file(target_file, contents)
25
+ dir = File.dirname(target_file)
26
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
27
+
28
+ index = File.new(target_file, 'w')
29
+ index&.puts contents # may be nil when stubbing
30
+ logger&.info "Written #{target_file}"
31
+ ensure
32
+ index&.close
33
+ end
34
+
35
+ def copy_resource(dir, to_root)
36
+ src = ResourceLocator.resource(dir)
37
+ dest = "#{to_root}/#{dir}"
38
+ FileUtils.copy_entry(src, dest)
39
+ end
40
+ end
41
+
42
+ # Renders the index of a project diff report.
43
+ class LiquidProjectRenderer
44
+ include PmdTester
45
+ include ProjectHasher
46
+ include LiquidRenderer
47
+
48
+ def write_project_index(project, root)
49
+ liquid_env = {
50
+ 'diff' => report_diff_to_h(project.report_diff),
51
+ 'error_diffs' => errors_to_h(project),
52
+ 'configerror_diffs' => configerrors_to_h(project),
53
+ 'project_name' => project.name
54
+ }
55
+
56
+ # Renders index.html using liquid
57
+ write_file("#{root}/index.html", render_liquid('project_diff_report.html', liquid_env))
58
+ # generate array of violations in json
59
+ write_file("#{root}/project_data.js", dump_violations_json(project))
60
+ end
61
+
62
+ def dump_violations_json(project)
63
+ h = {
64
+ 'source_link_base' => project.webview_url,
65
+ 'source_link_template' => link_template(project),
66
+ **violations_to_hash(project)
67
+ }
68
+
69
+ project_data = JSON.fast_generate(h)
70
+ "let project = #{project_data}"
71
+ end
72
+ end
73
+ end
@@ -8,92 +8,70 @@ module PmdTester
8
8
  # projects and branch of pmd source code
9
9
  class PmdReportBuilder
10
10
  include PmdTester
11
- def initialize(branch_config, projects, local_git_repo, pmd_branch_name, threads = 1)
12
- @branch_config = branch_config
11
+
12
+ def initialize(projects, options, branch_config, branch_name)
13
13
  @projects = projects
14
- @local_git_repo = local_git_repo
15
- @pmd_branch_name = pmd_branch_name
16
- @threads = threads
14
+ @local_git_repo = options.local_git_repo
15
+ @threads = options.threads
16
+ @error_recovery = options.error_recovery
17
+ @branch_config = branch_config
18
+ @pmd_branch_name = branch_name
17
19
  @pwd = Dir.getwd
18
20
 
19
- @pmd_branch_details = PmdBranchDetail.new(pmd_branch_name)
20
- end
21
-
22
- def execute_reset_cmd(type, tag)
23
- case type
24
- when 'git'
25
- reset_cmd = "git reset --hard #{tag}"
26
- when 'hg'
27
- reset_cmd = "hg up #{tag}"
28
- end
29
-
30
- Cmd.execute(reset_cmd)
31
- end
32
-
33
- def clone_projects
34
- logger.info 'Cloning projects started'
35
-
36
- @projects.each do |project|
37
- logger.info "Start cloning #{project.name} repository"
38
- path = project.local_source_path
39
- clone_cmd = "#{project.type} clone #{project.connection} #{path}"
40
- if File.exist?(path)
41
- logger.warn "Skipping clone, project path #{path} already exists"
42
- else
43
- Cmd.execute(clone_cmd)
44
- end
45
-
46
- Dir.chdir(path) do
47
- execute_reset_cmd(project.type, project.tag)
48
- end
49
- logger.info "Cloning #{project.name} completed"
50
- end
51
-
52
- logger.info 'Cloning projects completed'
21
+ @pmd_branch_details = PmdBranchDetail.new(@pmd_branch_name)
22
+ @project_builder = ProjectBuilder.new(@projects)
53
23
  end
54
24
 
55
25
  def get_pmd_binary_file
56
26
  logger.info "#{@pmd_branch_name}: Start packaging PMD"
57
27
  Dir.chdir(@local_git_repo) do
58
- current_head_sha = Cmd.execute('git rev-parse HEAD')
59
- current_branch_sha = Cmd.execute("git rev-parse #{@pmd_branch_name}")
28
+ build_branch_sha = Cmd.execute("git rev-parse #{@pmd_branch_name}^{commit}")
29
+
30
+ checkout_build_branch # needs a clean working tree, otherwise fails
60
31
 
61
- @pmd_version = determine_pmd_version
32
+ raise "Wrong branch #{get_last_commit_sha}" unless build_branch_sha == get_last_commit_sha
62
33
 
63
- # in case we are already on the correct branch
64
- # and a binary zip already exists...
65
- if current_head_sha == current_branch_sha &&
66
- File.exist?("pmd-dist/target/pmd-bin-#{@pmd_version}.zip")
67
- logger.warn "#{@pmd_branch_name}: Skipping packaging - zip for " \
68
- "#{@pmd_version} already exists"
34
+ logger.debug "#{@pmd_branch_name}: PMD Version is #{@pmd_version} " \
35
+ "(sha=#{build_branch_sha})"
36
+ distro_path = saved_distro_path(build_branch_sha)
37
+ if File.directory?(distro_path)
38
+ logger.info "#{@pmd_branch_name}: Skipping packaging - saved version exists " \
39
+ " in #{distro_path}"
69
40
  else
70
- build_pmd
41
+ build_pmd(into_dir: distro_path)
71
42
  end
72
43
 
73
- @pmd_branch_details.branch_last_sha = get_last_commit_sha
44
+ # we're still on the build branch
45
+ @pmd_branch_details.branch_last_sha = build_branch_sha
74
46
  @pmd_branch_details.branch_last_message = get_last_commit_message
75
-
76
- logger.info "#{@pmd_branch_name}: Extracting the zip"
77
- unzip_cmd = "unzip -qo pmd-dist/target/pmd-bin-#{@pmd_version}.zip -d #{@pwd}/target"
78
- Cmd.execute(unzip_cmd)
79
47
  end
80
48
  logger.info "#{@pmd_branch_name}: Packaging PMD completed"
81
49
  end
82
50
 
83
- def build_pmd
84
- logger.info "#{@pmd_branch_name}: Checking out the branch"
85
- checkout_cmd = "git checkout #{@pmd_branch_name}"
86
- Cmd.execute(checkout_cmd)
87
-
88
- # determine the version again - it might be different in the other branch
89
- @pmd_version = determine_pmd_version
51
+ # builds pmd on currently checked out branch
52
+ def build_pmd(into_dir:)
53
+ # in CI there might have been a build performed already. In that case
54
+ # we reuse the build result, otherwise we build PMD freshly
55
+ pmd_dist_target = "pmd-dist/target/pmd-bin-#{@pmd_version}.zip"
56
+ if File.exist?("#{@local_git_repo}/#{pmd_dist_target}")
57
+ # that's a warning, because we don't know, whether this build really
58
+ # belongs to the current branch or whether it's from a previous branch.
59
+ # In CI, that's not a problem, because the workspace is always fresh.
60
+ logger.warn "#{@pmd_branch_name}: Reusing already existing #{pmd_dist_target}"
61
+ else
62
+ logger.info "#{@pmd_branch_name}: Building PMD #{@pmd_version}..."
63
+ package_cmd = './mvnw clean package' \
64
+ ' -Dmaven.test.skip=true' \
65
+ ' -Dmaven.javadoc.skip=true' \
66
+ ' -Dmaven.source.skip=true' \
67
+ ' -Dcheckstyle.skip=true' \
68
+ ' -T1C'
69
+ Cmd.execute(package_cmd)
70
+ end
90
71
 
91
- logger.info "#{@pmd_branch_name}: Building PMD #{@pmd_version}..."
92
- package_cmd = './mvnw clean package' \
93
- ' -Dmaven.test.skip=true' \
94
- ' -Dmaven.javadoc.skip=true' \
95
- ' -Dmaven.source.skip=true'
96
- Cmd.execute(package_cmd)
72
+ logger.info "#{@pmd_branch_name}: Extracting the zip"
73
+ Cmd.execute("unzip -qo #{pmd_dist_target} -d pmd-dist/target/exploded")
74
+ Cmd.execute("mv pmd-dist/target/exploded/pmd-bin-#{@pmd_version} #{into_dir}")
97
75
  end
98
76
 
99
77
  def determine_pmd_version
@@ -103,7 +81,7 @@ module PmdTester
103
81
  end
104
82
 
105
83
  def get_last_commit_sha
106
- get_last_commit_sha_cmd = 'git rev-parse HEAD'
84
+ get_last_commit_sha_cmd = 'git rev-parse HEAD^{commit}'
107
85
  Cmd.execute(get_last_commit_sha_cmd)
108
86
  end
109
87
 
@@ -113,27 +91,39 @@ module PmdTester
113
91
  end
114
92
 
115
93
  def generate_pmd_report(project)
116
- run_path = "target/pmd-bin-#{@pmd_version}/bin/run.sh"
117
- pmd_cmd = "#{run_path} pmd -d #{project.local_source_path} -f xml " \
94
+ error_recovery_options = @error_recovery ? 'PMD_JAVA_OPTS="-Dpmd.error_recovery -ea" ' : ''
95
+ run_path = "#{saved_distro_path(@pmd_branch_details.branch_last_sha)}/bin/run.sh"
96
+ pmd_cmd = "#{error_recovery_options}" \
97
+ "#{run_path} pmd -d #{project.local_source_path} -f xml " \
118
98
  "-R #{project.get_config_path(@pmd_branch_name)} " \
119
99
  "-r #{project.get_pmd_report_path(@pmd_branch_name)} " \
120
- "-failOnViolation false -t #{@threads}"
100
+ "-failOnViolation false -t #{@threads} " \
101
+ "#{project.auxclasspath}"
121
102
  start_time = Time.now
122
- Cmd.execute(pmd_cmd)
103
+ if File.exist?(project.get_pmd_report_path(@pmd_branch_name))
104
+ logger.warn "#{@pmd_branch_name}: Skipping PMD run - report " \
105
+ "#{project.get_pmd_report_path(@pmd_branch_name)} already exists"
106
+ else
107
+ Cmd.execute(pmd_cmd)
108
+ end
123
109
  end_time = Time.now
124
110
  [end_time - start_time, end_time]
125
111
  end
126
112
 
127
113
  def generate_config_for(project)
114
+ logger.debug "Generating ruleset with excludes from #{@branch_config}"
128
115
  doc = Nokogiri::XML(File.read(@branch_config))
129
116
  ruleset = doc.at_css('ruleset')
117
+ ruleset.add_child("\n")
130
118
  project.exclude_pattern.each do |exclude_pattern|
131
- ruleset.add_child("<exclude-pattern>#{exclude_pattern}</exclude-pattern>")
119
+ ruleset.add_child(" <exclude-pattern>#{exclude_pattern}</exclude-pattern>\n")
132
120
  end
133
121
 
134
122
  File.open(project.get_config_path(@pmd_branch_name), 'w') do |x|
135
123
  x << doc.to_s
136
124
  end
125
+
126
+ logger.debug "Created file #{project.get_config_path(@pmd_branch_name)}"
137
127
  end
138
128
 
139
129
  def generate_pmd_reports
@@ -141,16 +131,14 @@ module PmdTester
141
131
 
142
132
  sum_time = 0
143
133
  @projects.each do |project|
144
- progress_logger = SimpleProgressLogger.new(project.name)
134
+ progress_logger = SimpleProgressLogger.new("generating #{project.name}'s PMD report")
145
135
  progress_logger.start
146
136
  generate_config_for(project)
147
137
  execution_time, end_time = generate_pmd_report(project)
148
138
  progress_logger.stop
149
139
  sum_time += execution_time
150
140
 
151
- report_details = PmdReportDetail.new
152
- report_details.execution_time = execution_time
153
- report_details.timestamp = end_time
141
+ report_details = PmdReportDetail.new(execution_time: execution_time, timestamp: end_time)
154
142
  report_details.save(project.get_report_info_path(@pmd_branch_name))
155
143
  logger.info "#{project.name}'s PMD report was generated successfully"
156
144
  end
@@ -161,10 +149,46 @@ module PmdTester
161
149
  @pmd_branch_details
162
150
  end
163
151
 
152
+ # returns the branch details
164
153
  def build
165
- clone_projects
154
+ @project_builder.clone_projects
155
+ @project_builder.build_projects
166
156
  get_pmd_binary_file
167
157
  generate_pmd_reports
168
158
  end
159
+
160
+ private
161
+
162
+ def checkout_build_branch
163
+ logger.info "#{@pmd_branch_name}: Checking out the branch"
164
+ # note that this would fail if the tree is dirty
165
+ Cmd.execute("git checkout #{@pmd_branch_name}")
166
+
167
+ # determine the version
168
+ @pmd_version = determine_pmd_version
169
+
170
+ return unless wd_has_dirty_git_changes
171
+
172
+ # working dir is dirty....
173
+ # we don't allow this because we need the SHA to address the zip file
174
+ logger.error "#{@pmd_branch_name}: Won\'t build without a clean working tree, " \
175
+ 'commit your changes'
176
+ end
177
+
178
+ def work_dir
179
+ "#{@pwd}/target"
180
+ end
181
+
182
+ # path to the unzipped distribution
183
+ # e.g. <cwd>/pmd-bin-<version>-<branch>-<sha>
184
+ def saved_distro_path(build_sha)
185
+ "#{work_dir}/pmd-bin-#{@pmd_version}" \
186
+ "-#{PmdBranchDetail.branch_filename(@pmd_branch_name)}" \
187
+ "-#{build_sha}"
188
+ end
189
+
190
+ def wd_has_dirty_git_changes
191
+ !Cmd.execute('git status --porcelain').empty?
192
+ end
169
193
  end
170
194
  end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'tempfile'
5
+
6
+ module PmdTester
7
+ # Clones and builds the projects, that are configured in the project-list.xml
8
+ class ProjectBuilder
9
+ include PmdTester
10
+
11
+ def initialize(projects)
12
+ @projects = projects
13
+ end
14
+
15
+ def clone_projects
16
+ logger.info 'Cloning projects started'
17
+
18
+ @projects.each do |project|
19
+ logger.info "Start cloning #{project.name} repository"
20
+ path = project.local_source_path
21
+ clone_cmd = "#{project.type} clone #{project.connection} #{path}"
22
+ if File.exist?(path)
23
+ logger.warn "Skipping clone, project path #{path} already exists"
24
+ else
25
+ Cmd.execute(clone_cmd)
26
+ end
27
+
28
+ Dir.chdir(path) do
29
+ execute_reset_cmd(project.type, project.tag)
30
+ end
31
+ logger.info "Cloning #{project.name} completed"
32
+ end
33
+
34
+ logger.info 'Cloning projects completed'
35
+ end
36
+
37
+ def build_projects
38
+ logger.info 'Building projects started'
39
+
40
+ @projects.each do |project|
41
+ path = project.local_source_path
42
+ Dir.chdir(path) do
43
+ progress_logger = SimpleProgressLogger.new("building #{project.name} in #{path}")
44
+ progress_logger.start
45
+ prepare_project(project)
46
+ progress_logger.stop
47
+ end
48
+ logger.info "Building #{project.name} completed"
49
+ end
50
+
51
+ logger.info 'Building projects completed'
52
+ end
53
+
54
+ private
55
+
56
+ def prepare_project(project)
57
+ # Note: current working directory is the project directory,
58
+ # where the source code has been cloned to
59
+ if project.build_command
60
+ logger.debug "Executing build-command: #{project.build_command}"
61
+ run_as_script(Dir.getwd, project.build_command)
62
+ end
63
+ if project.auxclasspath_command
64
+ logger.debug "Executing auxclasspath-command: #{project.auxclasspath_command}"
65
+ auxclasspath = run_as_script(Dir.getwd, project.auxclasspath_command)
66
+ project.auxclasspath = "-auxclasspath #{auxclasspath}"
67
+ else
68
+ project.auxclasspath = ''
69
+ end
70
+ end
71
+
72
+ def run_as_script(path, command)
73
+ script = Tempfile.new(['pmd-regression-', '.sh'], path)
74
+ logger.debug "Creating script #{script.path}"
75
+ begin
76
+ script.write(command)
77
+ script.close
78
+ shell = 'sh -xe'
79
+ if command.start_with?('#!')
80
+ shell = command.lines[0].chomp[2..] # remove leading "#!"
81
+ end
82
+ stdout = Cmd.execute("#{shell} #{script.path}")
83
+ ensure
84
+ script.unlink
85
+ end
86
+ stdout
87
+ end
88
+
89
+ def execute_reset_cmd(type, tag)
90
+ case type
91
+ when 'git'
92
+ reset_cmd = "git checkout #{tag}; git reset --hard #{tag}"
93
+ when 'hg'
94
+ reset_cmd = "hg up #{tag}"
95
+ end
96
+
97
+ Cmd.execute(reset_cmd)
98
+ end
99
+ end
100
+ end