autoproj-jenkins 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +41 -0
  6. data/Rakefile +11 -0
  7. data/autoproj-jenkins.gemspec +28 -0
  8. data/lib/autoproj/cli/jenkins.rb +100 -0
  9. data/lib/autoproj/cli/main_jenkins.rb +123 -0
  10. data/lib/autoproj/cli/test_postprocessing.rb +85 -0
  11. data/lib/autoproj/jenkins/credentials.rb +67 -0
  12. data/lib/autoproj/jenkins/exceptions.rb +7 -0
  13. data/lib/autoproj/jenkins/relativize.rb +74 -0
  14. data/lib/autoproj/jenkins/render_template.rb +92 -0
  15. data/lib/autoproj/jenkins/server.rb +79 -0
  16. data/lib/autoproj/jenkins/templates/abort-if-upstream-failed.pipeline.erb +18 -0
  17. data/lib/autoproj/jenkins/templates/bootstrap.pipeline.erb +27 -0
  18. data/lib/autoproj/jenkins/templates/buildconf-Gemfile +3 -0
  19. data/lib/autoproj/jenkins/templates/buildconf-config.yml.erb +12 -0
  20. data/lib/autoproj/jenkins/templates/buildconf-vagrant-Gemfile +4 -0
  21. data/lib/autoproj/jenkins/templates/buildconf.pipeline.erb +43 -0
  22. data/lib/autoproj/jenkins/templates/buildconf.xml.erb +24 -0
  23. data/lib/autoproj/jenkins/templates/handle-downstream.pipeline.erb +20 -0
  24. data/lib/autoproj/jenkins/templates/import-archive.pipeline.erb +2 -0
  25. data/lib/autoproj/jenkins/templates/import-git.pipeline.erb +16 -0
  26. data/lib/autoproj/jenkins/templates/import-svn.pipeline.erb +13 -0
  27. data/lib/autoproj/jenkins/templates/jenkins_dependency_overrides.rb.erb +5 -0
  28. data/lib/autoproj/jenkins/templates/package-Gemfile +2 -0
  29. data/lib/autoproj/jenkins/templates/package.pipeline.erb +102 -0
  30. data/lib/autoproj/jenkins/templates/package.xml.erb +23 -0
  31. data/lib/autoproj/jenkins/templates/setup-git-credentials.pipeline.erb +8 -0
  32. data/lib/autoproj/jenkins/templates/wait-upstream.pipeline.erb +160 -0
  33. data/lib/autoproj/jenkins/test_format_converters/boost-test.xsl +347 -0
  34. data/lib/autoproj/jenkins/updater.rb +214 -0
  35. data/lib/autoproj/jenkins/version.rb +5 -0
  36. data/lib/autoproj/jenkins.rb +19 -0
  37. data/lib/autoproj-jenkins.rb +8 -0
  38. metadata +179 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f5d96120cc78350275e92584c61af35c413bcafb
4
+ data.tar.gz: d1bd6d3060ea76972df27145c9fceed592354ba9
5
+ SHA512:
6
+ metadata.gz: 6d3f538eac2dd5471fb6bcf43f5f788e7babbe67ce8ced5edc8cc73a10eefeeece7e57dc9c55eacf37c2ebbac9b38ee27b2eec1e8112a78ef14fd28ad883e80d
7
+ data.tar.gz: 31525d9641c6df34e2b1b41af1700d3436381ca40bdacb3a4ec1b8b145598babbee284c4def436bb58d686ef721c3e89cf2f7d11da01be6e5682642846bd5e3e
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.sw?
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in autoproj-jenkins.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Sylvain Joyeux
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Autoproj::Jenkins
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/autoproj/jenkins`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'autoproj-jenkins'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install autoproj-jenkins
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/autoproj-jenkins.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ t.warning = false
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'autoproj/jenkins/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "autoproj-jenkins"
8
+ spec.version = Autoproj::Jenkins::VERSION
9
+ spec.authors = ["Sylvain Joyeux"]
10
+ spec.email = ["sylvain.joyeux@m4x.org"]
11
+
12
+ spec.summary = %q{Exporting an autoproj build to a jenkins server}
13
+ spec.homepage = "https://github.com/doudou/autoproj-jenkins"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'jenkins_api_client'
22
+ spec.add_dependency 'autoproj', '>= 2.0.0.rc20'
23
+ spec.add_development_dependency "bundler", "~> 1.12"
24
+ spec.add_development_dependency "rake", "~> 11.0"
25
+ spec.add_development_dependency "minitest", "~> 5.0"
26
+ spec.add_development_dependency "simplecov"
27
+ spec.add_development_dependency "flexmock"
28
+ end
@@ -0,0 +1,100 @@
1
+ require 'autoproj/cli/inspection_tool'
2
+ require 'autoproj/jenkins'
3
+
4
+ module Autoproj
5
+ module CLI
6
+ class Jenkins < Autoproj::CLI::InspectionTool
7
+ attr_reader :server
8
+ attr_reader :updater
9
+
10
+ def initialize(ws, job_prefix: '', **options)
11
+ super(ws)
12
+ @server = Autoproj::Jenkins::Server.new(**options)
13
+ @updater = Autoproj::Jenkins::Updater.new(ws, server, job_prefix: job_prefix)
14
+ end
15
+
16
+ def parse_vcs_credentials(credentials)
17
+ results = Autoproj::Jenkins::Credentials.new
18
+ credentials.each do |argument|
19
+ credential = Autoproj::Jenkins::Credentials.parse(argument)
20
+ results.add(credential)
21
+ end
22
+ results
23
+ end
24
+
25
+ def create_or_update_buildconf_job(*package_names, force: false, dev: false, credentials_id: nil, vcs_credentials: [])
26
+ initialize_and_load
27
+
28
+ if dev
29
+ gemfile = 'buildconf-vagrant-Gemfile'
30
+ autoproj_install_path = '/opt/autoproj/bin/autoproj_install'
31
+ else
32
+ gemfile = 'buildconf-Gemfile'
33
+ autoproj_install_path = nil
34
+ end
35
+
36
+ finalize_setup(package_names, recursive: false, non_imported_packages: :return)
37
+ updater.create_or_update_buildconf_job(*package_names, gemfile: gemfile,
38
+ autoproj_install_path: autoproj_install_path, dev: dev,
39
+ credentials_id: credentials_id,
40
+ vcs_credentials: parse_vcs_credentials(vcs_credentials))
41
+ end
42
+
43
+ def add_or_update_packages(*package_names, dev: false, vcs_credentials: [])
44
+ initialize_and_load
45
+ source_packages, _ = finalize_setup(package_names, non_imported_packages: nil)
46
+ source_packages = source_packages.map do |package_name|
47
+ ws.manifest.package_definition_by_name(package_name)
48
+ end
49
+
50
+ if dev
51
+ gemfile = 'buildconf-vagrant-Gemfile'
52
+ autoproj_install_path = '/opt/autoproj/bin/autoproj_install'
53
+ else
54
+ gemfile = 'buildconf-Gemfile'
55
+ autoproj_install_path = nil
56
+ end
57
+
58
+ updater.update(
59
+ *source_packages,
60
+ gemfile: gemfile,
61
+ autoproj_install_path: autoproj_install_path,
62
+ vcs_credentials: parse_vcs_credentials(vcs_credentials))
63
+ end
64
+
65
+ # Returns the "roots" in the trigger graph
66
+ #
67
+ # The trigger graph is the inverse of the dependency graph
68
+ # (a package's dependencies are built before the package itself)
69
+ #
70
+ # @param [Array<String>] package_names the packages whose trigger
71
+ # roots we want to find
72
+ # @return [Array<String>] the trigger root packages
73
+ def trigger_root_packages(*package_names)
74
+ package_names.find_all do |pkg_name|
75
+ pkg = ws.manifest.find_autobuild_package(pkg_name)
76
+ if !pkg
77
+ raise ArgumentError, "#{pkg_name} is not a known package"
78
+ end
79
+ pkg.dependencies.all? do |dep_name|
80
+ !package_names.include?(dep_name)
81
+ end
82
+ end
83
+ end
84
+
85
+ # Trigger the build of the given packages
86
+ #
87
+ # It actually only triggers the jobs that are roots in the trigger
88
+ # graph
89
+ #
90
+ # @param [Array<String>] package_names the names of the packages to
91
+ # build
92
+ def trigger_packages(*package_names)
93
+ trigger_root_packages(*package_names).each do |pkg_name|
94
+ server.trigger_job(updater.job_name_from_package_name(pkg_name))
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+
@@ -0,0 +1,123 @@
1
+ module Autoproj
2
+ module CLI
3
+ # The 'jenkins' subcommand for autoproj
4
+ class MainJenkins < Thor
5
+ class_option :username, desc: 'username to the Jenkins CLI (a password will be requested if --password is not given)'
6
+ class_option :password, desc: 'password to the Jenkins CLI (needs --username)'
7
+ class_option :job_prefix, desc: 'string that should be used as prefix to all generated job names',
8
+ type: :string, default: ''
9
+
10
+ namespace 'jenkins'
11
+
12
+ no_commands do
13
+ def request_password
14
+ STDOUT.print "Password: "
15
+ STDOUT.flush
16
+ STDIN.noecho do |io|
17
+ io.readline.chomp
18
+ end
19
+ end
20
+
21
+ def create_ops(url, target_os: nil)
22
+ if username = options[:username]
23
+ password = options[:password] || request_password
24
+ auth = Hash[username: username,
25
+ password: password]
26
+ elsif options[:password]
27
+ raise ArgumentError, "--password given without --username"
28
+ else
29
+ auth = Hash.new
30
+ end
31
+
32
+ workspace_options = Hash.new
33
+ if target_os
34
+ names, versions = target_os.split(':')
35
+ names = names.split(',')
36
+ names << 'default'
37
+ versions = versions.split(',')
38
+ versions << 'default'
39
+ workspace_options[:os_package_resolver] = OSPackageResolver.new(operating_system: [names, versions])
40
+ end
41
+ ws = Autoproj::Workspace.default(**workspace_options)
42
+
43
+ STDERR.puts "connecting to jenkins '#{url}' with prefix '#{options[:prefix]}'"
44
+ Jenkins.new(ws,
45
+ job_prefix: options[:job_prefix],
46
+ server_url: url,
47
+ **auth)
48
+ end
49
+ end
50
+
51
+ desc 'init URL [PACKAGE NAMES]', 'initialize the jenkins server by creating the base build job, optionally restricting the build to certain packages'
52
+ option :force, desc: 'if set, delete any existing job'
53
+ option :trigger, desc: 'trigger the job once created',
54
+ type: :boolean, default: false
55
+ option :dev, desc: 'assume that the jenkins instance is a development instance under vagrant and that autoproj-jenkins is made available as /opt/autoproj-jenkins',
56
+ type: :boolean, default: false
57
+ option :target_os, desc: "the autoproj definition for the target OS as name0,name1:version0,version1",
58
+ default: nil
59
+ option :credentials_id, desc: "the credentials ID of the username/password credentials that autoproj-jenkins should use to access the jenkins CLI",
60
+ default: 'autoproj-jenkins-cli'
61
+ option :vcs_credentials, desc: 'list of vcs_type:URLs for which credentials should be provided (see documentation)',
62
+ type: :array, default: []
63
+ def init(url, *package_names)
64
+ require 'autoproj/cli/jenkins'
65
+ ops = create_ops(url, target_os: options[:target_os])
66
+
67
+ ops.create_or_update_buildconf_job(
68
+ *package_names,
69
+ credentials_id: options[:credentials_id],
70
+ force: options[:force],
71
+ vcs_credentials: options[:vcs_credentials],
72
+ dev: options[:dev])
73
+ if options[:trigger]
74
+ ops.trigger_buildconf_job
75
+ end
76
+ end
77
+
78
+
79
+ desc 'update [PACKAGE_NAMES]', 'add the following package and its dependencies to the jenkins build'
80
+ option :force, desc: 'ignore the current state, generate jobs as if nothing was ever done'
81
+ option :dev, desc: 'assume that the jenkins instance is a development instance under vagrant and that autoproj-jenkins is made available as /opt/autoproj-jenkins',
82
+ type: :boolean, default: false
83
+ option :vcs_credentials, desc: 'list of vcs_type:URLs for which credentials should be provided (see documentation)',
84
+ type: :array, default: []
85
+ def update(url, *package_names)
86
+ require 'autoproj/cli/jenkins'
87
+ ops = create_ops(url)
88
+ Autoproj.report(silent: !options[:debug], debug: options[:debug]) do
89
+ updated_jobs = ops.add_or_update_packages(*package_names, dev: options[:dev], vcs_credentials: options[:vcs_credentials])
90
+ updated_jobs.sort.each do |job_name|
91
+ puts job_name
92
+ end
93
+ end
94
+ end
95
+
96
+ desc 'postprocess-tests OUTPUT_DIR [PACKAGE_NAME]', 'postprocesses test result formatted in various formats to convert them into the JUnit XML format understood by Jenkins',
97
+ hide: true
98
+ option :after, desc: "if provided, any report file that is older than this file will be ignored",
99
+ default: nil
100
+ def postprocess_tests(output_dir, *package_names)
101
+ require 'autoproj/cli/test_postprocessing'
102
+ ops = TestPostprocessing.new(Workspace.default)
103
+ if options[:after]
104
+ reference_time = File.stat(options[:after]).mtime
105
+ end
106
+ ops.process(output_dir, *package_names, after: reference_time)
107
+ end
108
+
109
+ desc 'relativize ROOT_DIR INPUT_TEXT OUTPUT_TEXT', 'replaces INPUT_TEXT by OUTPUT_TEXT in all files that can contain absolute paths',
110
+ hide: true
111
+ def relativize(root_dir, input_text, output_text)
112
+ require 'autoproj/jenkins'
113
+ relativize = Autoproj::Jenkins::Relativize.new(Pathname.new(root_dir), input_text, output_text)
114
+ processed_paths = relativize.process
115
+ puts "modified #{processed_paths.size} file"
116
+ processed_paths.each do |p|
117
+ puts " #{p}"
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+
@@ -0,0 +1,85 @@
1
+ require 'autoproj/cli/inspection_tool'
2
+
3
+ module Autoproj
4
+ module CLI
5
+ class TestPostprocessing < Autoproj::CLI::InspectionTool
6
+ attr_reader :convertions
7
+
8
+ def self.test_format_converter_dir
9
+ File.expand_path(
10
+ File.join('..', 'jenkins', 'test_format_converters'),
11
+ __dir__)
12
+ end
13
+
14
+ TEST_RESULT_CONVERTERS = Hash[
15
+ '*.boost.xml' => File.join(test_format_converter_dir, 'boost-test.xsl'),
16
+ '*.junit.xml' => nil
17
+ ]
18
+
19
+ def initialize(ws, convertions: TEST_RESULT_CONVERTERS)
20
+ super(ws)
21
+ @convertions = convertions
22
+ end
23
+
24
+ class ConvertionFailed < RuntimeError; end
25
+
26
+ def process(output_dir, *package_names, after: nil)
27
+ initialize_and_load
28
+ source_packages, _ = finalize_setup(package_names, recursive: false)
29
+ source_packages = source_packages.map do |package_name|
30
+ ws.manifest.package_definition_by_name(package_name)
31
+ end
32
+
33
+ has_failures = false
34
+ source_packages.each do |pkg|
35
+ utility = pkg.autobuild.test_utility
36
+ found_something = false
37
+ convertions.each do |glob, xsl|
38
+ Dir.glob(File.join(utility.target_dir, glob)) do |input_file|
39
+ input_mtime = File.stat(input_file).mtime
40
+ if after && input_mtime < after
41
+ Autoproj.message " ignoring #{input_file}, its modification time is #{input_mtime} which is after #{after}"
42
+ next
43
+ end
44
+
45
+ found_something = true
46
+ FileUtils.mkdir_p output_dir
47
+ output_file = File.join(output_dir, File.basename(input_file))
48
+ begin
49
+ if xsl
50
+ xsl_process(input_file, xsl, output_file)
51
+ else
52
+ FileUtils.copy_file input_file, output_file
53
+ end
54
+ Autoproj.message " generated #{output_file} from #{input_file} for #{pkg.name}"
55
+ rescue Exception => e
56
+ Autoproj.error e.message
57
+ has_failures = true
58
+ end
59
+ end
60
+ end
61
+
62
+ if !found_something
63
+ Autoproj.message "found no test results for #{pkg.name}"
64
+ end
65
+ end
66
+ ensure
67
+ if has_failures
68
+ raise ConvertionFailed, "some files failed to convert, see output for more details"
69
+ end
70
+ end
71
+
72
+ def xsl_process(input_file, stylesheet, output_file)
73
+ if File.read(input_file).strip.empty?
74
+ return
75
+ end
76
+
77
+ if !system('saxonb-xslt', "-o:#{output_file}", "-xsl:#{stylesheet}", "-s:#{input_file}")
78
+ raise ArgumentError, "failed to convert #{input_file} using #{stylesheet}"
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+
@@ -0,0 +1,67 @@
1
+ module Autoproj::Jenkins
2
+ # Management of the mapping from a VCS description to the corresponding
3
+ # Jenkins credential
4
+ class Credentials
5
+ Credential = Struct.new :vcs, :protocol, :host do
6
+ # Whether this credential object matches the given VCS
7
+ #
8
+ # @param [Autoproj::VCSDefinition] vcs
9
+ def matches?(vcs)
10
+ return if vcs.type.to_sym != self.vcs
11
+ vcs_url = URI.parse(vcs.url)
12
+ vcs_url.scheme == protocol &&
13
+ vcs_url.host == host
14
+ end
15
+
16
+ # The ID of the jenkins credential
17
+ def jenkins_id
18
+ "autoproj-#{vcs}-#{protocol}-#{host}"
19
+ end
20
+ end
21
+
22
+ # Parse a string that represents a single credential and return it
23
+ #
24
+ # @param [String] string a string of the form "vcs_type:URI", e.g.
25
+ # "git:https://github.com"
26
+ # @return [Credential]
27
+ def self.parse(string)
28
+ vcs, *uri = string.split(':')
29
+ if !vcs || vcs.empty? || uri.empty?
30
+ raise ArgumentError, "expected VCS:URL but got #{string}"
31
+ elsif !Autoproj::Jenkins.vcs_supported?(vcs)
32
+ raise UnhandledVCS, "#{vcs} is not a supported VCS"
33
+ end
34
+ uri = URI.parse(uri.join(':'))
35
+ Credential.new(vcs.to_sym, uri.scheme, uri.host)
36
+ end
37
+
38
+ attr_reader :credentials
39
+
40
+ def initialize
41
+ @credentials = Hash.new
42
+ end
43
+
44
+ def empty?
45
+ credentials.empty?
46
+ end
47
+
48
+ def [](vcs)
49
+ credentials[vcs.to_sym] || Array.new
50
+ end
51
+
52
+ def add(credential)
53
+ (credentials[credential.vcs] ||= Array.new) << credential
54
+ end
55
+
56
+ # Return the credential description for the given VCS
57
+ #
58
+ # @param [Autoproj::VCSDefinition] vcs
59
+ # @return [nil,Credential]
60
+ def for(vcs)
61
+ self[vcs.type].find do |c|
62
+ c.matches?(vcs)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
@@ -0,0 +1,7 @@
1
+ module Autoproj::Jenkins
2
+ # Exception raised when trying to handle a package whose VCS we don't
3
+ # integrate
4
+ class UnhandledVCS < RuntimeError
5
+ end
6
+ end
7
+
@@ -0,0 +1,74 @@
1
+ module Autoproj
2
+ module Jenkins
3
+ # Process files that might contain full paths and transform them by
4
+ # replacing the original path with a new one
5
+ class Relativize
6
+ FILE_PATTERN = Regexp.union(
7
+ /\/pkgconfig\/.*.pc$/,
8
+ /\.cmake$/,
9
+ /\.txt$/
10
+ )
11
+
12
+ # The path of the root to be filtered
13
+ #
14
+ # @return [Pathname]
15
+ attr_reader :root_path
16
+
17
+ # The text to be replaced
18
+ #
19
+ # @return [String]
20
+ attr_reader :original_text
21
+
22
+ # The text replacing {#original_text}
23
+ #
24
+ # @return [String]
25
+ attr_reader :replacement_text
26
+
27
+ # A pattern used to filter which files should be filtered
28
+ #
29
+ # @return [#===]
30
+ attr_reader :file_pattern
31
+
32
+ def initialize(root_path, original_text, replacement_text, file_pattern: FILE_PATTERN)
33
+ @root_path = root_path
34
+ @original_text = original_text
35
+ @replacement_text = replacement_text
36
+ @file_pattern = file_pattern
37
+ end
38
+
39
+ # Process all files matching {#file_pattern} within {#root_path}
40
+ #
41
+ # @return [Array<Pathname>] the files that have been processed
42
+ def process
43
+ processed_files = Array.new
44
+ root_path.find do |candidate|
45
+ if candidate.file? && (file_pattern === candidate.to_s)
46
+ if process_file(candidate)
47
+ processed_files << candidate
48
+ end
49
+ end
50
+ end
51
+ processed_files
52
+ end
53
+
54
+ # @api private
55
+ #
56
+ # Replaces text in a given file
57
+ #
58
+ # @return [Boolean] true if the pattern was found
59
+ def process_file(path)
60
+ replaced = false
61
+ filtered = path.each_line.map do |line|
62
+ line.gsub(original_text) { replaced = true; replacement_text }
63
+ end
64
+ if replaced
65
+ path.open('w') do |io|
66
+ io.puts filtered.join
67
+ end
68
+ true
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+