packaging 0.99.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.
- checksums.yaml +7 -0
- data/LICENSE +17 -0
- data/README-Solaris.md +117 -0
- data/README.md +1031 -0
- data/lib/packaging.rb +32 -0
- data/lib/packaging/artifactory.rb +278 -0
- data/lib/packaging/config.rb +392 -0
- data/lib/packaging/config/params.rb +366 -0
- data/lib/packaging/deb.rb +28 -0
- data/lib/packaging/deb/repo.rb +263 -0
- data/lib/packaging/gem.rb +112 -0
- data/lib/packaging/ips.rb +57 -0
- data/lib/packaging/msi.rb +89 -0
- data/lib/packaging/nuget.rb +39 -0
- data/lib/packaging/osx.rb +36 -0
- data/lib/packaging/paths.rb +238 -0
- data/lib/packaging/platforms.rb +480 -0
- data/lib/packaging/repo.rb +55 -0
- data/lib/packaging/retrieve.rb +46 -0
- data/lib/packaging/rpm.rb +5 -0
- data/lib/packaging/rpm/repo.rb +257 -0
- data/lib/packaging/tar.rb +154 -0
- data/lib/packaging/util.rb +146 -0
- data/lib/packaging/util/date.rb +15 -0
- data/lib/packaging/util/execution.rb +85 -0
- data/lib/packaging/util/file.rb +125 -0
- data/lib/packaging/util/git.rb +174 -0
- data/lib/packaging/util/git_tags.rb +73 -0
- data/lib/packaging/util/gpg.rb +62 -0
- data/lib/packaging/util/jenkins.rb +95 -0
- data/lib/packaging/util/misc.rb +69 -0
- data/lib/packaging/util/net.rb +368 -0
- data/lib/packaging/util/os.rb +17 -0
- data/lib/packaging/util/platform.rb +40 -0
- data/lib/packaging/util/rake_utils.rb +111 -0
- data/lib/packaging/util/serialization.rb +19 -0
- data/lib/packaging/util/ship.rb +171 -0
- data/lib/packaging/util/tool.rb +41 -0
- data/lib/packaging/util/version.rb +326 -0
- data/spec/fixtures/config/ext/build_defaults.yaml +2 -0
- data/spec/fixtures/config/ext/project_data.yaml +2 -0
- data/spec/fixtures/config/params.yaml +2 -0
- data/spec/fixtures/configs/components/test_file.json +1 -0
- data/spec/fixtures/configs/components/test_file_2.json +0 -0
- data/spec/fixtures/configs/components/test_file_not_tagged.json +1 -0
- data/spec/fixtures/configs/components/test_file_wrong_ext.txt +0 -0
- data/spec/fixtures/configs/components/test_file_wrong_ext.wrong +0 -0
- data/spec/fixtures/util/pre_tasks.yaml +4 -0
- data/spec/lib/packaging/artifactory_spec.rb +171 -0
- data/spec/lib/packaging/config_spec.rb +556 -0
- data/spec/lib/packaging/deb/repo_spec.rb +148 -0
- data/spec/lib/packaging/deb_spec.rb +52 -0
- data/spec/lib/packaging/paths_spec.rb +153 -0
- data/spec/lib/packaging/platforms_spec.rb +153 -0
- data/spec/lib/packaging/repo_spec.rb +97 -0
- data/spec/lib/packaging/retrieve_spec.rb +61 -0
- data/spec/lib/packaging/rpm/repo_spec.rb +133 -0
- data/spec/lib/packaging/tar_spec.rb +122 -0
- data/spec/lib/packaging/util/execution_spec.rb +56 -0
- data/spec/lib/packaging/util/file_spec.rb +139 -0
- data/spec/lib/packaging/util/git_spec.rb +160 -0
- data/spec/lib/packaging/util/git_tag_spec.rb +36 -0
- data/spec/lib/packaging/util/gpg_spec.rb +64 -0
- data/spec/lib/packaging/util/jenkins_spec.rb +112 -0
- data/spec/lib/packaging/util/misc_spec.rb +31 -0
- data/spec/lib/packaging/util/net_spec.rb +239 -0
- data/spec/lib/packaging/util/os_spec.rb +31 -0
- data/spec/lib/packaging/util/rake_utils_spec.rb +70 -0
- data/spec/lib/packaging/util/ship_spec.rb +117 -0
- data/spec/lib/packaging/util/version_spec.rb +123 -0
- data/spec/lib/packaging_spec.rb +19 -0
- data/spec/spec_helper.rb +36 -0
- data/static_artifacts/PackageInfo.plist +3 -0
- data/tasks/00_utils.rake +216 -0
- data/tasks/30_metrics.rake +33 -0
- data/tasks/apple.rake +266 -0
- data/tasks/build.rake +12 -0
- data/tasks/clean.rake +5 -0
- data/tasks/config.rake +30 -0
- data/tasks/deb.rake +129 -0
- data/tasks/deb_repos.rake +28 -0
- data/tasks/deprecated.rake +130 -0
- data/tasks/doc.rake +20 -0
- data/tasks/education.rake +57 -0
- data/tasks/fetch.rake +57 -0
- data/tasks/gem.rake +146 -0
- data/tasks/jenkins.rake +494 -0
- data/tasks/jenkins_dynamic.rake +202 -0
- data/tasks/load_extras.rake +21 -0
- data/tasks/mock.rake +348 -0
- data/tasks/nightly_repos.rake +335 -0
- data/tasks/pe_deb.rake +12 -0
- data/tasks/pe_rpm.rake +13 -0
- data/tasks/pe_ship.rake +221 -0
- data/tasks/pe_sign.rake +13 -0
- data/tasks/pe_tar.rake +5 -0
- data/tasks/retrieve.rake +45 -0
- data/tasks/rpm.rake +66 -0
- data/tasks/rpm_repos.rake +29 -0
- data/tasks/ship.rake +752 -0
- data/tasks/sign.rake +226 -0
- data/tasks/tag.rake +8 -0
- data/tasks/tar.rake +34 -0
- data/tasks/update.rake +16 -0
- data/tasks/vanagon.rake +35 -0
- data/tasks/vendor_gems.rake +117 -0
- data/tasks/version.rake +33 -0
- data/tasks/z_data_dump.rake +65 -0
- data/templates/README +1 -0
- data/templates/downstream.xml.erb +47 -0
- data/templates/msi.xml.erb +197 -0
- data/templates/packaging.xml.erb +344 -0
- data/templates/repo.xml.erb +114 -0
- metadata +234 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
# Utility methods used by the various rake tasks
|
2
|
+
module Pkg::Util
|
3
|
+
require 'erb'
|
4
|
+
require 'benchmark'
|
5
|
+
require 'base64'
|
6
|
+
require 'io/console'
|
7
|
+
require 'packaging/util/date'
|
8
|
+
require 'packaging/util/execution'
|
9
|
+
require 'packaging/util/file'
|
10
|
+
require 'packaging/util/git'
|
11
|
+
require 'packaging/util/gpg'
|
12
|
+
require 'packaging/util/jenkins'
|
13
|
+
require 'packaging/util/misc'
|
14
|
+
require 'packaging/util/net'
|
15
|
+
require 'packaging/util/os'
|
16
|
+
require 'packaging/util/platform'
|
17
|
+
require 'packaging/util/serialization'
|
18
|
+
require 'packaging/util/ship'
|
19
|
+
require 'packaging/util/tool'
|
20
|
+
require 'packaging/util/rake_utils'
|
21
|
+
require 'packaging/util/version'
|
22
|
+
require 'packaging/util/git_tags'
|
23
|
+
|
24
|
+
def self.boolean_value(var)
|
25
|
+
return TRUE if var == TRUE || ( var.is_a?(String) && ( var.downcase == 'true' || var.downcase =~ /^y$|^yes$/))
|
26
|
+
FALSE
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.in_project_root(&blk)
|
30
|
+
result = nil
|
31
|
+
fail "Cannot execute in project root if Pkg::Config.project_root is not set" unless Pkg::Config.project_root
|
32
|
+
|
33
|
+
Dir.chdir Pkg::Config.project_root do
|
34
|
+
result = blk.call
|
35
|
+
end
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
# Utility to get the contents of an Environment variable
|
40
|
+
#
|
41
|
+
# @param var [String] The name of the environment variable to return
|
42
|
+
# @return [String, Boolean, Hash, Array, nil] The contents of ENV[var]
|
43
|
+
def self.get_var(var)
|
44
|
+
self.check_var(var, ENV[var])
|
45
|
+
ENV[var]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Utility to check if a variable is set
|
49
|
+
#
|
50
|
+
# @param varname [String] the name of the variable to be checked
|
51
|
+
# @param var [String, Boolean, Hash, Array, nil] the contents of the variable to be checked
|
52
|
+
# @return [String, Boolean, Hash, Array, nil] the contents of var
|
53
|
+
# @raise [RuntimeError] raises an exception if the variable is not set and is required
|
54
|
+
def self.check_var(varname, var)
|
55
|
+
fail "Requires #{varname} be set!" if var.nil?
|
56
|
+
var
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.require_library_or_fail(library, library_name = nil)
|
60
|
+
library_name ||= library
|
61
|
+
begin
|
62
|
+
require library
|
63
|
+
rescue LoadError
|
64
|
+
fail "Could not load #{library_name}. #{library_name} is required by the packaging repo for this task"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.base64_encode(string)
|
69
|
+
Base64.encode64(string).strip
|
70
|
+
end
|
71
|
+
|
72
|
+
# Utility to retrieve command line input
|
73
|
+
# @param noecho [Boolean, nil] if we are retrieving command line input with or without privacy. This is mainly
|
74
|
+
# for sensitive information like passwords.
|
75
|
+
def self.get_input(echo = true)
|
76
|
+
fail "Cannot get input on a noninteractive terminal" unless $stdin.tty?
|
77
|
+
|
78
|
+
system 'stty -echo' unless echo
|
79
|
+
$stdin.gets.chomp!
|
80
|
+
ensure
|
81
|
+
system 'stty echo'
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.rand_string
|
85
|
+
rand.to_s.split('.')[1]
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.ask_yes_or_no(force = false)
|
89
|
+
unless force
|
90
|
+
return Pkg::Util.boolean_value(Pkg::Config.answer_override) unless Pkg::Config.answer_override.nil?
|
91
|
+
end
|
92
|
+
|
93
|
+
answer = Pkg::Util.get_input
|
94
|
+
return true if answer =~ /^y$|^yes$/
|
95
|
+
return false if answer =~ /^n$|^no$/
|
96
|
+
puts "Nope, try something like yes or no or y or n, etc:"
|
97
|
+
Pkg::Util.ask_yes_or_no
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.confirm_ship(files)
|
101
|
+
$stdout.puts "Artifacts will be shipped to the following hosts:"
|
102
|
+
Pkg::Util.filter_configs('host').each { |key, value| puts "#{key}: #{value}" }
|
103
|
+
$stdout.puts "Does this look right?? [y,n]"
|
104
|
+
Pkg::Util.ask_yes_or_no(true)
|
105
|
+
$stdout.puts "The following files have been built and are ready to ship:"
|
106
|
+
files.each { |file| puts "\t#{file}\n" unless File.directory?(file) }
|
107
|
+
$stdout.puts "Ship these files?? [y,n]"
|
108
|
+
Pkg::Util.ask_yes_or_no(true)
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.filter_configs(filter = nil)
|
112
|
+
return Pkg::Config.instance_values.select { |key, _| key.match(/#{filter}/) } if filter
|
113
|
+
Pkg::Config.instance_values
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
# Construct a probably-correct (or correct-enough) URI for
|
118
|
+
# tools like ssh or rsync. Currently lacking support for intuitive
|
119
|
+
# joins, ports, protocols, fragments, or 75% of what Addressable::URI
|
120
|
+
# or URI would provide out of the box. The "win" here is that
|
121
|
+
# the returned String should "just work".
|
122
|
+
# @private pseudo_uri
|
123
|
+
# @return [String, nil] a string representing either a hostname:/path pair,
|
124
|
+
# a hostname without a path, or a path without a hostname. Returns nil
|
125
|
+
# if it is unable to construct a useful URI-like string.
|
126
|
+
# @param [Hash] opts fragments used to build the pseudo URI
|
127
|
+
# @option opts [String] :path URI-ish path component
|
128
|
+
# @option opts [String] :host URI-ish host component
|
129
|
+
def self.pseudo_uri(opts = {})
|
130
|
+
options = { path: nil, host: nil }.merge(opts)
|
131
|
+
|
132
|
+
# Prune empty values to determine what is returned
|
133
|
+
options.delete_if { |_, v| v.to_s.empty? }
|
134
|
+
return nil if options.empty?
|
135
|
+
|
136
|
+
[options[:host], options[:path]].compact.join(':')
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.deprecate(old_cmd, new_cmd = nil)
|
140
|
+
msg = "!! #{old_cmd} is deprecated."
|
141
|
+
if new_cmd
|
142
|
+
msg << " Please use #{new_cmd} instead."
|
143
|
+
end
|
144
|
+
$stdout.puts("\n#{msg}\n")
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Utilities for managing/querying date/time
|
2
|
+
|
3
|
+
module Pkg::Util::Date
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def timestamp(separator = nil)
|
7
|
+
if s = separator
|
8
|
+
format = "%Y#{s}%m#{s}%d#{s}%H#{s}%M#{s}%S"
|
9
|
+
else
|
10
|
+
format = "%Y-%m-%d %H:%M:%S"
|
11
|
+
end
|
12
|
+
Time.now.strftime(format)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Utility methods for handling system calls and interactions
|
2
|
+
|
3
|
+
module Pkg::Util::Execution
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Alias to $?.success? that makes success? slightly easier to test and stub
|
8
|
+
# If immediately run, $? will not be instanciated, so only call success? if
|
9
|
+
# $? exists, otherwise return nil
|
10
|
+
def success?(statusobject = $?)
|
11
|
+
return statusobject.success?
|
12
|
+
end
|
13
|
+
|
14
|
+
# ex combines the behavior of `%x{cmd}` and rake's `sh "cmd"`. `%x{cmd}` has
|
15
|
+
# the benefit of returning the standard out of an executed command, enabling us
|
16
|
+
# to query the file system, e.g. `contents = %x{ls}`. The drawback to `%x{cmd}`
|
17
|
+
# is that on failure of a command (something returned non-zero) the return of
|
18
|
+
# `%x{cmd}` is just an empty string. As such, we can't know if we succeeded.
|
19
|
+
# Rake's `sh "cmd"`, on the other hand, will raise a RuntimeError if a command
|
20
|
+
# does not return 0, but doesn't return any of the stdout from the command -
|
21
|
+
# only true or false depending on its success or failure. With `ex(cmd)` we
|
22
|
+
# purport to both return the results of the command execution (ala `%x{cmd}`)
|
23
|
+
# while also raising an exception if a command does not succeed (ala `sh "cmd"`).
|
24
|
+
def ex(command, debug = false)
|
25
|
+
puts "Executing '#{command}'..." if debug
|
26
|
+
ret = `#{command}`
|
27
|
+
unless Pkg::Util::Execution.success?
|
28
|
+
raise RuntimeError
|
29
|
+
end
|
30
|
+
|
31
|
+
if debug
|
32
|
+
puts "Command '#{command}' returned:"
|
33
|
+
puts ret
|
34
|
+
end
|
35
|
+
|
36
|
+
ret
|
37
|
+
end
|
38
|
+
|
39
|
+
# Turns out trying to change ex to use Open3 is SUPER DANGEROUS and destructive
|
40
|
+
# in ways I hadn't imagined. I'm going to add a new method here instead and start
|
41
|
+
# converting code to use that so I don't break more than I plan to.
|
42
|
+
def capture3(command, debug = false)
|
43
|
+
require 'open3'
|
44
|
+
puts "Executing '#{command}'..." if debug
|
45
|
+
stdout, stderr, ret = Open3.capture3(command)
|
46
|
+
unless Pkg::Util::Execution.success?(ret)
|
47
|
+
raise "#{stdout}#{stderr}"
|
48
|
+
end
|
49
|
+
|
50
|
+
if debug
|
51
|
+
puts "Command '#{command}' returned:"
|
52
|
+
puts stdout
|
53
|
+
end
|
54
|
+
|
55
|
+
return stdout, stderr, ret
|
56
|
+
end
|
57
|
+
|
58
|
+
# Loop a block up to the number of attempts given, exiting when we receive success
|
59
|
+
# or max attempts is reached. Raise an exception unless we've succeeded.
|
60
|
+
def retry_on_fail(args, &blk)
|
61
|
+
success = FALSE
|
62
|
+
exception = ''
|
63
|
+
|
64
|
+
if args[:times].respond_to?(:times) and block_given?
|
65
|
+
args[:times].times do |i|
|
66
|
+
if args[:delay]
|
67
|
+
sleep args[:delay]
|
68
|
+
end
|
69
|
+
|
70
|
+
begin
|
71
|
+
blk.call
|
72
|
+
success = TRUE
|
73
|
+
break
|
74
|
+
rescue => err
|
75
|
+
puts "An error was encountered evaluating block. Retrying.."
|
76
|
+
exception = err.to_s + "\n" + err.backtrace.join("\n")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
else
|
80
|
+
fail "retry_on_fail requires and arg (:times => x) where x is an Integer/Fixnum, and a block to execute"
|
81
|
+
end
|
82
|
+
fail "Block failed maximum of #{args[:times]} tries. Exiting..\nLast failure was: #{exception}" unless success
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# Utility methods for handling files and directories
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Pkg::Util::File
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def exist?(file)
|
8
|
+
::File.exist?(file)
|
9
|
+
end
|
10
|
+
alias_method :exists?, :exist?
|
11
|
+
|
12
|
+
def directory?(file)
|
13
|
+
::File.directory?(file)
|
14
|
+
end
|
15
|
+
|
16
|
+
def mktemp
|
17
|
+
mktemp = Pkg::Util::Tool.find_tool('mktemp', :required => true)
|
18
|
+
stdout, _, _ = Pkg::Util::Execution.capture3("#{mktemp} -d -t pkgXXXXXX")
|
19
|
+
stdout.strip
|
20
|
+
end
|
21
|
+
|
22
|
+
def empty_dir?(dir)
|
23
|
+
File.exist?(dir) and File.directory?(dir) and Dir["#{dir}/**/*"].empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns an array of all the directories at the top level of #{dir}
|
27
|
+
#
|
28
|
+
def directories(dir)
|
29
|
+
if File.directory?(dir)
|
30
|
+
Dir.chdir(dir) do
|
31
|
+
Dir.glob("*").select { |entry| File.directory?(entry) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns an array of all files with #{ext} inside #{dir}
|
37
|
+
def files_with_ext(dir, ext)
|
38
|
+
Dir.glob("#{dir}/**/*#{ext}")
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def file_exists?(file, args = { :required => false })
|
43
|
+
exists = File.exist? file
|
44
|
+
if !exists and args[:required]
|
45
|
+
fail "Required file #{file} could not be found"
|
46
|
+
end
|
47
|
+
exists
|
48
|
+
end
|
49
|
+
|
50
|
+
def file_writable?(file, args = { :required => false })
|
51
|
+
writable = File.writable? file
|
52
|
+
if !writable and args[:required]
|
53
|
+
fail "File #{file} is not writable"
|
54
|
+
end
|
55
|
+
writable
|
56
|
+
end
|
57
|
+
|
58
|
+
alias :get_temp :mktemp
|
59
|
+
|
60
|
+
def erb_string(erbfile, b = binding)
|
61
|
+
template = File.read(erbfile)
|
62
|
+
message = ERB.new(template, nil, "-")
|
63
|
+
message.result(b)
|
64
|
+
end
|
65
|
+
|
66
|
+
def erb_file(erbfile, outfile = nil, remove_orig = false, opts = { :binding => binding })
|
67
|
+
outfile ||= File.join(mktemp, File.basename(erbfile).sub(File.extname(erbfile), ""))
|
68
|
+
output = erb_string(erbfile, opts[:binding])
|
69
|
+
File.open(outfile, 'w') { |f| f.write output }
|
70
|
+
puts "Generated: #{outfile}"
|
71
|
+
FileUtils.rm_rf erbfile if remove_orig
|
72
|
+
outfile
|
73
|
+
end
|
74
|
+
|
75
|
+
def untar_into(source, target = nil, options = "")
|
76
|
+
tar = Pkg::Util::Tool.find_tool('tar', :required => true)
|
77
|
+
# We only accept a writable directory as a target
|
78
|
+
if target and !target.empty? and file_writable?(target) and File.directory?(target)
|
79
|
+
target_opts = "-C #{target}"
|
80
|
+
end
|
81
|
+
if file_exists?(source, :required => true)
|
82
|
+
stdout, _, _ = Pkg::Util::Execution.capture3(%Q(#{tar} #{options} #{target_opts} -xf #{source}))
|
83
|
+
stdout
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def install_files_into_dir(file_patterns, workdir)
|
88
|
+
install = []
|
89
|
+
# We need to add our list of file patterns from the configuration; this
|
90
|
+
# used to be a list of "things to copy recursively", which would install
|
91
|
+
# editor backup files and other nasty things.
|
92
|
+
#
|
93
|
+
# This handles that case correctly, with a deprecation warning, to augment
|
94
|
+
# our FileList with the right things to put in place.
|
95
|
+
#
|
96
|
+
# Eventually, when all our projects are migrated to the new standard, we
|
97
|
+
# can drop this in favour of just pushing the patterns directly into the
|
98
|
+
# FileList and eliminate many lines of code and comment.
|
99
|
+
Dir.chdir(Pkg::Config.project_root) do
|
100
|
+
file_patterns.each do |pattern|
|
101
|
+
if File.directory?(pattern) and !Pkg::Util::File.empty_dir?(pattern)
|
102
|
+
install << Dir[pattern + "/**/*"]
|
103
|
+
else
|
104
|
+
install << Dir[pattern]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
install.flatten!
|
108
|
+
|
109
|
+
# Transfer all the files and symlinks into the working directory...
|
110
|
+
install = install.select { |x| File.file?(x) or File.symlink?(x) or Pkg::Util::File.empty_dir?(x) }
|
111
|
+
|
112
|
+
install.each do |file|
|
113
|
+
if Pkg::Util::File.empty_dir?(file)
|
114
|
+
FileUtils.mkpath(File.join(workdir, file), :verbose => false)
|
115
|
+
else
|
116
|
+
FileUtils.mkpath(File.dirname(File.join(workdir, file)), :verbose => false)
|
117
|
+
FileUtils.cp(file, File.join(workdir, file), :verbose => false, :preserve => true)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
Pkg::Util::Version.versionbump(workdir) if Pkg::Config.update_version_file
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
# Utility methods for handling git
|
4
|
+
module Pkg::Util::Git
|
5
|
+
class << self
|
6
|
+
# Git utility to create a new git commit
|
7
|
+
def commit_file(file, message = 'changes')
|
8
|
+
fail_unless_repo
|
9
|
+
puts 'Commiting changes:'
|
10
|
+
puts
|
11
|
+
diff, = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} diff HEAD #{file}")
|
12
|
+
puts diff
|
13
|
+
stdout, = Pkg::Util::Execution.capture3(%(#{Pkg::Util::Tool::GIT} commit #{file} -m "Commit #{message} in #{file}" &> #{Pkg::Util::OS::DEVNULL}))
|
14
|
+
stdout
|
15
|
+
end
|
16
|
+
|
17
|
+
# Git utility to create a new git tag
|
18
|
+
def tag(version)
|
19
|
+
fail_unless_repo
|
20
|
+
stdout, = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} tag -s -u #{Pkg::Util::Gpg.key} -m '#{version}' #{version}")
|
21
|
+
stdout
|
22
|
+
end
|
23
|
+
|
24
|
+
# Git utility to create a new git bundle
|
25
|
+
# rubocop:disable Metrics/AbcSize
|
26
|
+
def bundle(treeish, appendix = Pkg::Util.rand_string, temp = Pkg::Util::File.mktemp)
|
27
|
+
fail_unless_repo
|
28
|
+
Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} bundle create #{temp}/#{Pkg::Config.project}-#{Pkg::Config.version}-#{appendix} #{treeish} --tags")
|
29
|
+
Dir.chdir(temp) do
|
30
|
+
Pkg::Util::Execution.capture3("#{Pkg::Util::Tool.find_tool('tar')} -czf #{Pkg::Config.project}-#{Pkg::Config.version}-#{appendix}.tar.gz #{Pkg::Config.project}-#{Pkg::Config.version}-#{appendix}")
|
31
|
+
FileUtils.rm_rf("#{Pkg::Config.project}-#{Pkg::Config.version}-#{appendix}")
|
32
|
+
end
|
33
|
+
"#{temp}/#{Pkg::Config.project}-#{Pkg::Config.version}-#{appendix}.tar.gz"
|
34
|
+
end
|
35
|
+
|
36
|
+
def pull(remote, branch)
|
37
|
+
fail_unless_repo
|
38
|
+
stdout, = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} pull #{remote} #{branch}")
|
39
|
+
stdout
|
40
|
+
end
|
41
|
+
|
42
|
+
# Check if we are currently working on a tagged commit.
|
43
|
+
def tagged?
|
44
|
+
ref_type == 'tag'
|
45
|
+
end
|
46
|
+
|
47
|
+
# Reports if a ref and its corresponding git repo points to
|
48
|
+
# a git tag.
|
49
|
+
#
|
50
|
+
# @param url [string] url of repo grabbed from json file
|
51
|
+
# @param ref [string] ref grabbed from json file
|
52
|
+
def remote_tagged?(url, ref)
|
53
|
+
reference = Pkg::Util::Git_tag.new(url, ref)
|
54
|
+
reference.tag?
|
55
|
+
end
|
56
|
+
|
57
|
+
# Checks out a specified ref. The ref must exist in the current repo.
|
58
|
+
# This also removes any uncommitted changes
|
59
|
+
def checkout(ref)
|
60
|
+
Pkg::Util.in_project_root do
|
61
|
+
_, _, ret = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} reset --hard ; #{Pkg::Util::Tool::GIT} checkout #{ref}")
|
62
|
+
Pkg::Util::Execution.success?(ret) || raise("Could not checkout #{ref} git branch to build package from...exiting")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the value of `git describe`. If this is not a git repo or
|
67
|
+
# `git describe` fails because there is no tag, this will return false
|
68
|
+
def describe(extra_opts = ['--tags', '--dirty'])
|
69
|
+
Pkg::Util.in_project_root do
|
70
|
+
stdout, _, ret = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} describe #{Array(extra_opts).join(' ')}")
|
71
|
+
if Pkg::Util::Execution.success?(ret)
|
72
|
+
stdout.strip
|
73
|
+
else
|
74
|
+
false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# return the sha of HEAD on the current branch
|
80
|
+
# You can specify the length you want from the sha. Default is 40, the
|
81
|
+
# length for sha1. If you specify anything higher, it will still return 40
|
82
|
+
# characters. Ideally, you're not going to specify anything under 7 characters,
|
83
|
+
# but I'll leave that discretion up to you.
|
84
|
+
def sha(length = 40)
|
85
|
+
Pkg::Util.in_project_root do
|
86
|
+
stdout, = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} rev-parse --short=#{length} HEAD")
|
87
|
+
stdout.strip
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Return the ref type of HEAD on the current branch
|
92
|
+
def ref_type
|
93
|
+
Pkg::Util.in_project_root do
|
94
|
+
stdout, = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} cat-file -t #{describe('')}")
|
95
|
+
stdout.strip
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# If HEAD is a tag, return the tag. Otherwise return the sha of HEAD.
|
100
|
+
def sha_or_tag(length = 40)
|
101
|
+
if ref_type == 'tag'
|
102
|
+
describe
|
103
|
+
else
|
104
|
+
sha(length)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Return true if we're in a git repo, otherwise false
|
109
|
+
def repo?
|
110
|
+
Pkg::Util.in_project_root do
|
111
|
+
_, _, ret = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} rev-parse --git-dir")
|
112
|
+
Pkg::Util::Execution.success?(ret)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# rubocop:disable Style/GuardClause
|
117
|
+
def fail_unless_repo
|
118
|
+
unless repo?
|
119
|
+
raise "Pkg::Config.project_root (#{Pkg::Config.project_root}) is not \
|
120
|
+
a valid git repository"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Return the basename of the project repo
|
125
|
+
def project_name
|
126
|
+
Pkg::Util.in_project_root do
|
127
|
+
stdout, = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} config --get remote.origin.url")
|
128
|
+
stdout.split('/')[-1].chomp('.git').chomp
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Return the name of the current branch
|
133
|
+
def branch_name
|
134
|
+
Pkg::Util.in_project_root do
|
135
|
+
stdout, = Pkg::Util::Execution.capture3("#{Pkg::Util::Tool::GIT} rev-parse --abbrev-ref HEAD")
|
136
|
+
stdout.strip
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def source_dirty?
|
141
|
+
describe.include?('dirty')
|
142
|
+
end
|
143
|
+
|
144
|
+
def fail_on_dirty_source
|
145
|
+
if source_dirty?
|
146
|
+
raise "The source tree is dirty, e.g. there are uncommited changes. \
|
147
|
+
Please commit/discard changes and try again."
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
##########################################################################
|
152
|
+
# DEPRECATED METHODS
|
153
|
+
#
|
154
|
+
def git_commit_file(file, message = "changes")
|
155
|
+
Pkg::Util.deprecate('Pkg::Util::Git.git_commit_file', 'Pkg::Util::Git.commit_file')
|
156
|
+
Pkg::Util::Git.commit_file(file, message)
|
157
|
+
end
|
158
|
+
|
159
|
+
def git_tag(version)
|
160
|
+
Pkg::Util.deprecate('Pkg::Util::Git.git_tag', 'Pkg::Util::Git.tag')
|
161
|
+
Pkg::Util::Git.tag(version)
|
162
|
+
end
|
163
|
+
|
164
|
+
def git_bundle(treeish, appendix = Pkg::Util.rand_string, temp = Pkg::Util::File.mktemp)
|
165
|
+
Pkg::Util.deprecate('Pkg::Util::Git.git_bundle', 'Pkg::Util::Git.bundle')
|
166
|
+
Pkg::Util::Git.bundle(treeish, appendix, temp)
|
167
|
+
end
|
168
|
+
|
169
|
+
def git_pull(remote, branch)
|
170
|
+
Pkg::Util.deprecate('Pkg::Util::Git.git_pull', 'Pkg::Util::Git.pull')
|
171
|
+
Pkg::Util::Git.pull(remote, branch)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|