lapidarist 0.0.1
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/.gitignore +13 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/lapidarist +6 -0
- data/lapidarist.gemspec +26 -0
- data/lib/lapidarist.rb +29 -0
- data/lib/lapidarist/bundle_command.rb +49 -0
- data/lib/lapidarist/cli.rb +94 -0
- data/lib/lapidarist/configuration.rb +22 -0
- data/lib/lapidarist/gem.rb +137 -0
- data/lib/lapidarist/gems.rb +47 -0
- data/lib/lapidarist/git_command.rb +128 -0
- data/lib/lapidarist/level.rb +32 -0
- data/lib/lapidarist/logger.rb +76 -0
- data/lib/lapidarist/options.rb +79 -0
- data/lib/lapidarist/outdated.rb +37 -0
- data/lib/lapidarist/sha.rb +27 -0
- data/lib/lapidarist/shell.rb +57 -0
- data/lib/lapidarist/status.rb +16 -0
- data/lib/lapidarist/summary.rb +46 -0
- data/lib/lapidarist/test_command.rb +23 -0
- data/lib/lapidarist/update.rb +60 -0
- data/lib/lapidarist/version.rb +3 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 52a3f4f375bdf8923d629d74fbe00ebfb7e7dd84738ff6c8e3977d1be2dbcba0
|
4
|
+
data.tar.gz: f6b6ff542df51de84e710725b8a8d9bc53b9e39d529fb1c4e61cbf6eb4d1c40f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3ba56292233a696e78c23d274d8ab85d8ec04c5345d2991e2cbbae7f6b52b3dd08090c90af08eed8f63916676061f87415271dfeb6b2e6da020985cf07890f49
|
7
|
+
data.tar.gz: e09937e6620630a277868e27941fca69d893b3fb2513fa0ca24cbfdb06975c5ed238f33604297e6628d73edeaf3b185faed32ba83f55fef7043f0d255c2d25d3
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Mark Gangl
|
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,39 @@
|
|
1
|
+
# Lapidarist
|
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/lapidarist`. 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 'lapidarist'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install lapidarist
|
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 spec` 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/attack/lapidarist.
|
36
|
+
|
37
|
+
## License
|
38
|
+
|
39
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "lapidarist"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/lapidarist
ADDED
data/lapidarist.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "lapidarist/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "lapidarist"
|
7
|
+
spec.version = Lapidarist::VERSION
|
8
|
+
spec.authors = ["Mark Gangl"]
|
9
|
+
spec.email = ["mark@attackcorp.com"]
|
10
|
+
|
11
|
+
spec.summary = %q{Automatically update ruby gem dependencies.}
|
12
|
+
spec.description = %q{Sit back, relax, and allow Lapidarist to do the heavy lifiting and update your ruby gem dependencies for you.}
|
13
|
+
spec.homepage = "https://github.com/attack/lapidarist"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(spec)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
26
|
+
end
|
data/lib/lapidarist.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'lapidarist/version'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
require_relative 'lapidarist/configuration'
|
5
|
+
require_relative 'lapidarist/options'
|
6
|
+
require_relative 'lapidarist/level'
|
7
|
+
require_relative 'lapidarist/gem'
|
8
|
+
require_relative 'lapidarist/gems'
|
9
|
+
|
10
|
+
require_relative 'lapidarist/logger'
|
11
|
+
require_relative 'lapidarist/shell'
|
12
|
+
require_relative 'lapidarist/bundle_command'
|
13
|
+
require_relative 'lapidarist/git_command'
|
14
|
+
require_relative 'lapidarist/test_command'
|
15
|
+
require_relative 'lapidarist/update'
|
16
|
+
require_relative 'lapidarist/outdated'
|
17
|
+
require_relative 'lapidarist/sha'
|
18
|
+
|
19
|
+
require_relative 'lapidarist/summary'
|
20
|
+
require_relative 'lapidarist/status'
|
21
|
+
require_relative 'lapidarist/cli'
|
22
|
+
|
23
|
+
module Lapidarist
|
24
|
+
class << self
|
25
|
+
def config
|
26
|
+
@config ||= Lapidarist::Configuration.new
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class BundleCommand
|
3
|
+
def initialize
|
4
|
+
@shell = Shell.new
|
5
|
+
@logger = Logger.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def outdated
|
9
|
+
shell.run('cat Gemfile') if Lapidarist.config.debug
|
10
|
+
|
11
|
+
Enumerator.new do |y|
|
12
|
+
shell.run('bundle outdated --strict') do |std_out_err|
|
13
|
+
while line = std_out_err.gets
|
14
|
+
logger.std_out_err(line, 'bundle outdated')
|
15
|
+
gem = parse_gem_from(line)
|
16
|
+
y.yield(gem) if gem
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def update(gem, level: MAJOR)
|
23
|
+
shell.run("bundle update #{gem.name} --strict --#{level.to_s}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def version(gem)
|
27
|
+
stdout = shell.run('bundle list', "grep \" #{gem.name} \"")
|
28
|
+
result = stdout.match(/\((?<version>[0-9\.]+)\)/)
|
29
|
+
result[:version] if result
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_reader :shell, :logger
|
35
|
+
|
36
|
+
def parse_gem_from(line)
|
37
|
+
regex = / \* (.*) \(newest (\d[\d\.]*\d)[,\s] installed (\d[\d\.]*\d)[\),\s](.*groups \"(.*)\")?/.match line
|
38
|
+
|
39
|
+
unless regex.nil?
|
40
|
+
Gem.new(
|
41
|
+
name: regex[1],
|
42
|
+
newest_version: regex[2],
|
43
|
+
installed_version: regex[3],
|
44
|
+
groups: Array(regex[5]&.split(',')).map(&:strip)
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class CLI
|
3
|
+
def initialize(args)
|
4
|
+
@args = args
|
5
|
+
@git = GitCommand.new
|
6
|
+
@test = TestCommand.new
|
7
|
+
@outdated = Outdated.new
|
8
|
+
@update = Update.new
|
9
|
+
@sha = Sha.new
|
10
|
+
|
11
|
+
@logger = Logger.new
|
12
|
+
@logger.setup
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
Options.new(args).parse
|
17
|
+
logger.header('Starting lapidarist')
|
18
|
+
logger.debug("directory: #{Lapidarist.config.directory}", :options)
|
19
|
+
logger.debug("test_script: #{Lapidarist.config.test_script}", :options)
|
20
|
+
|
21
|
+
unless git.clean?
|
22
|
+
logger.footer('stopping, there are uncommitted changes')
|
23
|
+
return 1
|
24
|
+
end
|
25
|
+
|
26
|
+
sha.record_good
|
27
|
+
gems = outdated.run
|
28
|
+
|
29
|
+
status = nil
|
30
|
+
1.step do |attempt|
|
31
|
+
logger.header("Attempt ##{attempt}")
|
32
|
+
|
33
|
+
if gems.outdated.none?
|
34
|
+
logger.footer('stopping, there are no applicable outdated gems')
|
35
|
+
status = Status.new(gems, attempt)
|
36
|
+
break
|
37
|
+
end
|
38
|
+
|
39
|
+
updated_gems = update.run(gems, attempt)
|
40
|
+
|
41
|
+
if sha.new_commit_count.zero?
|
42
|
+
logger.footer('nothing updated, trying again')
|
43
|
+
gems = gems.merge(updated_gems)
|
44
|
+
next
|
45
|
+
end
|
46
|
+
|
47
|
+
logger.header("Testing gem updates")
|
48
|
+
if test.success?
|
49
|
+
logger.footer('test passed, nothing left to do')
|
50
|
+
gems = gems.merge(updated_gems)
|
51
|
+
status = Status.new(gems, attempt)
|
52
|
+
break
|
53
|
+
else
|
54
|
+
logger.footer('test failed, investigating failure')
|
55
|
+
end
|
56
|
+
|
57
|
+
failed_gem =
|
58
|
+
if updated_gems.one?
|
59
|
+
updated_but_failed_gem = updated_gems.first
|
60
|
+
git.reset_hard('HEAD^')
|
61
|
+
|
62
|
+
Gem.from(
|
63
|
+
updated_but_failed_gem,
|
64
|
+
attempt: attempt,
|
65
|
+
status: :failed,
|
66
|
+
updated_version: updated_but_failed_gem.latest_attempt[:version],
|
67
|
+
level: updated_but_failed_gem.latest_attempt[:level]
|
68
|
+
)
|
69
|
+
else
|
70
|
+
failed_gem_name = git.bisect(sha.last_good, test)
|
71
|
+
updated_but_failed_gem = updated_gems.detect { |g| g.name == failed_gem_name }
|
72
|
+
gems = gems.merge(updated_gems.take(sha.new_commit_count))
|
73
|
+
sha.record_good
|
74
|
+
|
75
|
+
Gem.from(
|
76
|
+
updated_but_failed_gem,
|
77
|
+
attempt: attempt,
|
78
|
+
status: :failed,
|
79
|
+
updated_version: updated_but_failed_gem.latest_attempt[:version],
|
80
|
+
level: updated_but_failed_gem.latest_attempt[:level]
|
81
|
+
)
|
82
|
+
end
|
83
|
+
gems = gems.merge(failed_gem)
|
84
|
+
end
|
85
|
+
|
86
|
+
Summary.new(gems, logger).display
|
87
|
+
return status.to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
attr_reader :args, :git, :test, :outdated, :update, :sha, :logger
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Lapidarist
|
4
|
+
class Configuration < OpenStruct
|
5
|
+
def initialize
|
6
|
+
super(
|
7
|
+
directory: Pathname.new('.'),
|
8
|
+
test_script: 'test.sh',
|
9
|
+
all: false,
|
10
|
+
quiet: false,
|
11
|
+
verbosity: 0,
|
12
|
+
commit_flags: '',
|
13
|
+
debug: false,
|
14
|
+
log_path: Pathname.new('./tmp/lapidarist.log'),
|
15
|
+
update_limit: nil,
|
16
|
+
groups: [],
|
17
|
+
version: MAJOR,
|
18
|
+
recursive: false
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class Gem
|
3
|
+
attr_reader :name, :newest_version, :installed_version, :attempts
|
4
|
+
|
5
|
+
def initialize(name:, newest_version:, installed_version:, groups: [], attempts: {})
|
6
|
+
@name = name
|
7
|
+
@newest_version = newest_version
|
8
|
+
@installed_version = installed_version
|
9
|
+
@groups = groups
|
10
|
+
@attempts = attempts
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from(gem, attempt: 0, status: nil, reason: nil, updated_version: nil, level: nil)
|
14
|
+
attempts = gem.attempts
|
15
|
+
|
16
|
+
if status
|
17
|
+
attempts = attempts.merge(
|
18
|
+
attempt => {
|
19
|
+
status: status,
|
20
|
+
reason: reason,
|
21
|
+
version: updated_version,
|
22
|
+
level: level
|
23
|
+
}
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
new(
|
28
|
+
name: gem.name,
|
29
|
+
newest_version: gem.newest_version,
|
30
|
+
installed_version: gem.installed_version,
|
31
|
+
groups: gem.groups,
|
32
|
+
attempts: attempts
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def ==(other_gem)
|
37
|
+
current_status == other_gem.current_status &&
|
38
|
+
name == other_gem.name &&
|
39
|
+
installed_version == other_gem.installed_version &&
|
40
|
+
newest_version == other_gem.newest_version &&
|
41
|
+
groups == other_gem.groups
|
42
|
+
end
|
43
|
+
|
44
|
+
def groups
|
45
|
+
@groups.sort
|
46
|
+
end
|
47
|
+
|
48
|
+
def dependency?
|
49
|
+
groups.any?
|
50
|
+
end
|
51
|
+
|
52
|
+
def current_status
|
53
|
+
latest_attempt&.fetch(:status, nil)
|
54
|
+
end
|
55
|
+
|
56
|
+
def current_level
|
57
|
+
latest_attempt&.fetch(:level, nil)
|
58
|
+
end
|
59
|
+
|
60
|
+
def outdated?(recursive: false)
|
61
|
+
current_status.nil? || (recursive && available_update_levels?)
|
62
|
+
end
|
63
|
+
|
64
|
+
def failed?
|
65
|
+
current_status == :failed
|
66
|
+
end
|
67
|
+
|
68
|
+
def skip?
|
69
|
+
current_status == :skipped
|
70
|
+
end
|
71
|
+
|
72
|
+
def updated?
|
73
|
+
current_status == :updated
|
74
|
+
end
|
75
|
+
|
76
|
+
def updated_version
|
77
|
+
updated_attempt&.fetch(:version, nil)
|
78
|
+
end
|
79
|
+
|
80
|
+
def what_changed
|
81
|
+
if version_changed?
|
82
|
+
"#{name} from #{installed_version} to #{updated_version}"
|
83
|
+
else
|
84
|
+
"#{name} dependencies"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def available_update_levels?
|
89
|
+
failed? && current_level > PATCH
|
90
|
+
end
|
91
|
+
|
92
|
+
def next_semver_level
|
93
|
+
if current_level
|
94
|
+
LEVELS.detect { |level| level < current_level }
|
95
|
+
else
|
96
|
+
MAJOR
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def log_s
|
101
|
+
[
|
102
|
+
"outdated gem: #{name}",
|
103
|
+
"installed: #{installed_version}",
|
104
|
+
"newest: #{newest_version}",
|
105
|
+
"updated: #{updated_version}"
|
106
|
+
].join(', ')
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_h
|
110
|
+
{
|
111
|
+
name: name,
|
112
|
+
newest_version: newest_version,
|
113
|
+
installed_version: installed_version,
|
114
|
+
groups: groups,
|
115
|
+
attempts: attempts.to_h
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
def latest_attempt_number
|
120
|
+
@latest_attempt_number ||= attempts.keys.last
|
121
|
+
end
|
122
|
+
|
123
|
+
def latest_attempt
|
124
|
+
@latest_attempt ||= attempts[latest_attempt_number] || {}
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def version_changed?
|
130
|
+
updated_version && installed_version != updated_version
|
131
|
+
end
|
132
|
+
|
133
|
+
def updated_attempt
|
134
|
+
@updated_attempt ||= attempts.values.detect { |a| a[:status] == :updated }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class Gems
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(gems)
|
6
|
+
@gems = gems
|
7
|
+
end
|
8
|
+
|
9
|
+
def each(&block)
|
10
|
+
gems.sort_by(&:name).each(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def outdated
|
14
|
+
entries.select do |gem|
|
15
|
+
if (Lapidarist.config.all || gem.dependency?) && gem.outdated?(recursive: Lapidarist.config.recursive)
|
16
|
+
gem
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def updated
|
22
|
+
entries.select(&:updated?)
|
23
|
+
end
|
24
|
+
|
25
|
+
def skipped
|
26
|
+
entries.select(&:skip?)
|
27
|
+
end
|
28
|
+
|
29
|
+
def failed
|
30
|
+
entries.select(&:failed?)
|
31
|
+
end
|
32
|
+
|
33
|
+
def merge(other_gems)
|
34
|
+
Gems.new(
|
35
|
+
Array(other_gems) + entries.select { |gem| !Array(other_gems).map(&:name).include?(gem.name) }
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def attempts
|
40
|
+
entries.map(&:latest_attempt_number).compact.max
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
attr_reader :gems
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class GitCommand
|
3
|
+
def initialize
|
4
|
+
@shell = Shell.new
|
5
|
+
@logger = Logger.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def head
|
9
|
+
shell.run('git rev-parse HEAD')[0].strip
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(*files)
|
13
|
+
shell.run("git add #{files.join(' ')}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def commit(message)
|
17
|
+
shell.run("git commit -m '#{message}' #{Lapidarist.config.commit_flags}".strip, label: 'git commit')
|
18
|
+
end
|
19
|
+
|
20
|
+
def bisect(start_sha, test)
|
21
|
+
logger.header('Starting bisect')
|
22
|
+
bisect_start(start_sha)
|
23
|
+
bisect_run(start_sha, test)
|
24
|
+
end
|
25
|
+
|
26
|
+
def log(sha)
|
27
|
+
shell.run("git log HEAD...#{sha}^ --no-color --oneline", label: 'git log')
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset_hard(ref)
|
31
|
+
shell.run("git reset --hard #{ref}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def clean?
|
35
|
+
shell.run('[ -z "$(git status --porcelain)" ]')[1] == 0
|
36
|
+
end
|
37
|
+
|
38
|
+
def count_commits(start_sha, end_sha)
|
39
|
+
shell.run("git rev-list #{end_sha} ^#{start_sha} --count")[0].to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :shell, :logger
|
45
|
+
|
46
|
+
def bisect_start(sha)
|
47
|
+
shell.run('git bisect start')
|
48
|
+
shell.run('git bisect bad')
|
49
|
+
shell.run("git bisect good #{sha}", label: 'git bisect good')
|
50
|
+
end
|
51
|
+
|
52
|
+
def bisect_run(start_sha, test)
|
53
|
+
failing_gem_name = nil
|
54
|
+
|
55
|
+
shell.run("git bisect run #{test}") do |std_out_err|
|
56
|
+
while line = std_out_err.gets
|
57
|
+
bisect_step = BisectStep.new(line, shell)
|
58
|
+
|
59
|
+
if bisect_step.failure?
|
60
|
+
failing_sha = bisect_step.failing_sha
|
61
|
+
failing_gem_name = bisect_step.failing_gem(failing_sha)
|
62
|
+
logger.info("... found failing gem update: #{failing_gem_name}")
|
63
|
+
end
|
64
|
+
|
65
|
+
if bisect_step.success?
|
66
|
+
bisect_reset
|
67
|
+
rewind_to_last_good_commit(failing_sha)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
unless failing_gem_name
|
72
|
+
logger.info("... last commit was failing commit")
|
73
|
+
end
|
74
|
+
|
75
|
+
logger.footer("bisect done")
|
76
|
+
end
|
77
|
+
|
78
|
+
if failing_gem_name && Lapidarist.config.debug
|
79
|
+
log(start_sha)
|
80
|
+
end
|
81
|
+
|
82
|
+
failing_gem_name
|
83
|
+
end
|
84
|
+
|
85
|
+
def bisect_reset
|
86
|
+
shell.run('git bisect reset')
|
87
|
+
end
|
88
|
+
|
89
|
+
def rewind_to_last_good_commit(sha)
|
90
|
+
reset_hard("#{sha}^")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class BisectStep
|
95
|
+
def initialize(line, shell)
|
96
|
+
@line = line
|
97
|
+
@shell = shell
|
98
|
+
end
|
99
|
+
|
100
|
+
def success?
|
101
|
+
line == "bisect run success\n"
|
102
|
+
end
|
103
|
+
|
104
|
+
def failure?
|
105
|
+
!failing_sha.nil?
|
106
|
+
end
|
107
|
+
|
108
|
+
def failing_sha
|
109
|
+
sha_regex = Regexp::new("(.*) is the first bad commit\n").match(line)
|
110
|
+
unless sha_regex.nil?
|
111
|
+
sha_regex[1]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def failing_gem(sha)
|
116
|
+
commit_message = shell.run("git log --format=%s -n 1 #{sha}", label: 'git log')[0]
|
117
|
+
|
118
|
+
sha_regex = Regexp::new('Update (.*) from').match(commit_message)
|
119
|
+
unless sha_regex.nil?
|
120
|
+
sha_regex[1]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
attr_reader :shell, :line
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class Level
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
attr_reader :index
|
6
|
+
|
7
|
+
def initialize(name:, index:)
|
8
|
+
@name = name
|
9
|
+
@index = index
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
name.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def <=>(other)
|
17
|
+
return 1 if index < other.index
|
18
|
+
return 0 if index == other.index
|
19
|
+
return -1 if index > other.index
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :name
|
25
|
+
end
|
26
|
+
|
27
|
+
MAJOR = Level.new(name: :major, index: 1)
|
28
|
+
MINOR = Level.new(name: :minor, index: 2)
|
29
|
+
PATCH = Level.new(name: :patch, index: 3)
|
30
|
+
|
31
|
+
LEVELS = [MAJOR, MINOR, PATCH].freeze
|
32
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class Logger
|
3
|
+
def header(message)
|
4
|
+
write '', 0
|
5
|
+
write "#{message} ...", 0
|
6
|
+
end
|
7
|
+
|
8
|
+
def smart_header(message)
|
9
|
+
if Lapidarist.config.verbosity > 0
|
10
|
+
header(message)
|
11
|
+
else
|
12
|
+
info(message, 0)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def footer(message)
|
17
|
+
write "... #{message}", 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def info(message, level = 0)
|
21
|
+
write message, level
|
22
|
+
end
|
23
|
+
|
24
|
+
def debug(message, label = nil)
|
25
|
+
return unless Lapidarist.config.debug
|
26
|
+
|
27
|
+
if label
|
28
|
+
puts " DEBUG (#{label}) > #{message}"
|
29
|
+
else
|
30
|
+
puts " DEBUG > #{message}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def std_out_err(message, command)
|
35
|
+
write "OUT_ERR (#{command}) > #{message.strip}", 2
|
36
|
+
end
|
37
|
+
|
38
|
+
def setup
|
39
|
+
if Lapidarist.config.log_path && !Lapidarist.config.log_path.empty?
|
40
|
+
Open3.capture2("mkdir -p #{Lapidarist.config.log_path.dirname}", chdir: Lapidarist.config.directory)
|
41
|
+
Open3.capture2("touch #{Lapidarist.config.log_path}", chdir: Lapidarist.config.directory)
|
42
|
+
clear_log_file
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def summary(message)
|
47
|
+
write_std_out(message, 0)
|
48
|
+
write_log_file(message)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def write(message, level)
|
54
|
+
log_line = "#{' ' * level}#{message}"
|
55
|
+
|
56
|
+
write_std_out(log_line, level)
|
57
|
+
write_log_file(log_line)
|
58
|
+
end
|
59
|
+
|
60
|
+
def write_std_out(message, level)
|
61
|
+
if level <= Lapidarist.config.verbosity && !Lapidarist.config.quiet
|
62
|
+
puts message
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def clear_log_file
|
67
|
+
Open3.capture2("cp /dev/null #{Lapidarist.config.log_path}", chdir: Lapidarist.config.directory)
|
68
|
+
end
|
69
|
+
|
70
|
+
def write_log_file(message)
|
71
|
+
if Lapidarist.config.log_path && !Lapidarist.config.log_path.empty?
|
72
|
+
Open3.capture2("echo \"#{message}\" >> #{Lapidarist.config.log_path}", chdir: Lapidarist.config.directory)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Lapidarist
|
4
|
+
class Options
|
5
|
+
def initialize(args)
|
6
|
+
@args = args
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse
|
10
|
+
opt_parser = OptionParser.new do |opts|
|
11
|
+
opts.on("-d", "--directory DIRECTORY", "Directory to run Lapidarist from.") do |d|
|
12
|
+
Lapidarist.config.directory = Pathname.new(d)
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on("-t", "--test TEST_SCRIPT", "Test script given to git bisect.") do |t|
|
16
|
+
Lapidarist.config.test_script = t
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on("-a", "--all", "Update gems that are sub-dependencies.") do |t|
|
20
|
+
Lapidarist.config.all = true
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("-q", "--quiet", "Do not print anything to stdout.") do |t|
|
24
|
+
Lapidarist.config.quiet = true
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-v", "Increase verbosity, repeat for more verbosity.") do |t|
|
28
|
+
Lapidarist.config.verbosity += 1
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-f", "--commit-flags flags", "Append flags to the commit command.") do |t|
|
32
|
+
Lapidarist.config.commit_flags = t
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("--debug", "Display debug output.") do |t|
|
36
|
+
Lapidarist.config.debug = true
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("-l LOG_PATH", "Path to log file") do |t|
|
40
|
+
Lapidarist.config.log_path = t
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("-n NUMBER_OF_GEMS", "Limit the number of gems to be updated.") do |t|
|
44
|
+
Lapidarist.config.update_limit = t.to_i
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on("--one", "Limit the number of gems to be updated to just one.") do |t|
|
48
|
+
Lapidarist.config.update_limit = 1
|
49
|
+
end
|
50
|
+
|
51
|
+
opts.on("-g GROUP_NAME", "--group GROUP_NAME", "Limit gems to be updated to a specified group(s).") do |g|
|
52
|
+
Lapidarist.config.groups << g
|
53
|
+
end
|
54
|
+
|
55
|
+
opts.on("--major", "Limit updates to major, minor and patch versions (essentially everything).") do |p|
|
56
|
+
Lapidarist.config.version = MAJOR
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on("--minor", "Limit updates to minor and patch versions.") do |p|
|
60
|
+
Lapidarist.config.version = MINOR
|
61
|
+
end
|
62
|
+
|
63
|
+
opts.on("--patch", "Limit updates to patch versions.") do |p|
|
64
|
+
Lapidarist.config.version = PATCH
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on("-r", "--recursive", "Try updating a the major version, minor version then patch version.") do |t|
|
68
|
+
Lapidarist.config.recursive = true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
opt_parser.parse!(args)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
attr_reader :args
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class Outdated
|
3
|
+
def initialize
|
4
|
+
@bundle = BundleCommand.new
|
5
|
+
@logger = Logger.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
logger.header('Detecting outdated gems')
|
10
|
+
|
11
|
+
gems = bundle.outdated.each_with_object([]) do |gem, results|
|
12
|
+
reason = reason_to_skip(gem)
|
13
|
+
if reason.nil?
|
14
|
+
logger.info(" + #{gem.log_s}")
|
15
|
+
results.push Gem.from(gem)
|
16
|
+
else
|
17
|
+
logger.info(" - (#{reason}) #{gem.log_s}")
|
18
|
+
results.push Gem.from(gem, status: :skipped, reason: reason)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Gems.new(gems)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :bundle, :logger
|
28
|
+
|
29
|
+
def reason_to_skip(gem)
|
30
|
+
if !Lapidarist.config.all && !gem.dependency?
|
31
|
+
:sub_dependency
|
32
|
+
elsif Lapidarist.config.groups.any? && (Lapidarist.config.groups & gem.groups).none?
|
33
|
+
:unmatched_group
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class Sha
|
3
|
+
def initialize
|
4
|
+
@good_shas = []
|
5
|
+
@git = GitCommand.new
|
6
|
+
@logger = Logger.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def record_good
|
10
|
+
good_sha = git.head
|
11
|
+
logger.debug("good sha: #{good_sha}")
|
12
|
+
@good_shas << good_sha
|
13
|
+
end
|
14
|
+
|
15
|
+
def last_good
|
16
|
+
good_shas.last
|
17
|
+
end
|
18
|
+
|
19
|
+
def new_commit_count
|
20
|
+
git.count_commits(last_good, 'HEAD')
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :good_shas, :git, :logger
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class Shell
|
3
|
+
def initialize
|
4
|
+
@logger = Logger.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def run(*commands, label: nil, &block)
|
8
|
+
if commands.one?
|
9
|
+
run_single_command(commands.first, label, &block)
|
10
|
+
else
|
11
|
+
pipe_multiple_commands(*commands, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_reader :logger
|
18
|
+
|
19
|
+
def run_single_command(command, label)
|
20
|
+
logger.info "COMMAND > `#{command}`", 1
|
21
|
+
|
22
|
+
if block_given?
|
23
|
+
Open3.popen2e(command, chdir: Lapidarist.config.directory) do |_std_in, std_out_err|
|
24
|
+
yield(std_out_err)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
out_err = []
|
28
|
+
|
29
|
+
status = Open3.popen2e(command, chdir: Lapidarist.config.directory) do |_std_in, std_out_err, wait_thr|
|
30
|
+
while line = std_out_err.gets
|
31
|
+
logger.std_out_err(line, label || command)
|
32
|
+
out_err << line
|
33
|
+
end
|
34
|
+
wait_thr.value
|
35
|
+
end
|
36
|
+
|
37
|
+
logger.info "STATUS > #{status}", 2
|
38
|
+
|
39
|
+
[out_err.join("\n"), status]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def pipe_multiple_commands(*commands)
|
44
|
+
if block_given?
|
45
|
+
Open3.pipeline_r(*commands, chdir: Lapidarist.config.directory) do |std_out, _ts|
|
46
|
+
yield(std_out)
|
47
|
+
end
|
48
|
+
else
|
49
|
+
output = ''
|
50
|
+
Open3.pipeline_r(*commands, chdir: Lapidarist.config.directory) do |std_out, _ts|
|
51
|
+
output = std_out.read
|
52
|
+
end
|
53
|
+
output
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class Summary
|
3
|
+
def initialize(gems, logger)
|
4
|
+
@gems = gems
|
5
|
+
@logger = logger
|
6
|
+
end
|
7
|
+
|
8
|
+
def display
|
9
|
+
logger.summary ''
|
10
|
+
logger.summary 'Summary'
|
11
|
+
logger.summary '-'*50
|
12
|
+
logger.summary "#{object_count(gems.updated, 'gem', 'gems')} updated, #{object_count(gems.failed, 'gem', 'gems')} failed and #{object_count(gems.skipped, 'gem', 'gems')} skipped in #{object_count(gems.attempts, 'attempt', 'attempts')}"
|
13
|
+
gems.each do |gem|
|
14
|
+
gem.attempts.each do |i, data|
|
15
|
+
case data[:status]
|
16
|
+
when :updated
|
17
|
+
logger.summary " + updated #{gem.name} from #{gem.installed_version} to #{data[:version]}"
|
18
|
+
when :failed
|
19
|
+
logger.summary " x failed #{gem.name} from #{gem.installed_version} to #{data[:version]}"
|
20
|
+
when :skipped
|
21
|
+
logger.summary " - skipped #{gem.name} (#{data[:reason]})"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :gems, :logger
|
30
|
+
|
31
|
+
def object_count(objects_or_length, singlular, plural)
|
32
|
+
length =
|
33
|
+
if objects_or_length.respond_to?(:length)
|
34
|
+
objects_or_length.length
|
35
|
+
else
|
36
|
+
objects_or_length
|
37
|
+
end
|
38
|
+
|
39
|
+
if length == 1
|
40
|
+
"1 #{singlular}"
|
41
|
+
else
|
42
|
+
"#{length} #{plural}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class TestCommand
|
3
|
+
def initialize
|
4
|
+
@shell = Shell.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def run
|
8
|
+
shell.run(to_s)[1]
|
9
|
+
end
|
10
|
+
|
11
|
+
def success?
|
12
|
+
run == 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
Lapidarist.config.test_script
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :shell
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Lapidarist
|
2
|
+
class Update
|
3
|
+
def initialize
|
4
|
+
@bundle = BundleCommand.new
|
5
|
+
@git = GitCommand.new
|
6
|
+
@logger = Logger.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(gems, attempt)
|
10
|
+
before_sha = git.head if Lapidarist.config.debug
|
11
|
+
|
12
|
+
logger.header('Updating outdated gems')
|
13
|
+
|
14
|
+
limit =
|
15
|
+
if Lapidarist.config.update_limit
|
16
|
+
[Lapidarist.config.update_limit - gems.updated.length, 0].max
|
17
|
+
else
|
18
|
+
gems.outdated.length
|
19
|
+
end
|
20
|
+
|
21
|
+
updated_gems = gems.outdated.take(limit).map do |outdated_gem|
|
22
|
+
update_gem(outdated_gem, attempt)
|
23
|
+
end
|
24
|
+
|
25
|
+
git.log(before_sha) if Lapidarist.config.debug
|
26
|
+
|
27
|
+
updated_gems
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :outdated_gems, :bundle, :git, :logger
|
33
|
+
|
34
|
+
def update_gem(outdated_gem, attempt)
|
35
|
+
logger.smart_header "Updating #{outdated_gem.name} from #{outdated_gem.installed_version}"
|
36
|
+
|
37
|
+
available_semver_levels = [Lapidarist.config.version]
|
38
|
+
available_semver_levels << outdated_gem.next_semver_level if Lapidarist.config.recursive
|
39
|
+
semver_level_restriction = available_semver_levels.compact.min
|
40
|
+
|
41
|
+
bundle.update(outdated_gem, level: semver_level_restriction)
|
42
|
+
updated_version = bundle.version(outdated_gem)
|
43
|
+
|
44
|
+
if git.clean?
|
45
|
+
skipped_gem = Gem.from(outdated_gem, attempt: attempt, status: :skipped, reason: :nothing_to_update)
|
46
|
+
logger.footer "nothing to update for #{skipped_gem.name}"
|
47
|
+
|
48
|
+
skipped_gem
|
49
|
+
else
|
50
|
+
updated_gem = Gem.from(outdated_gem, attempt: attempt, status: :updated, updated_version: updated_version, level: semver_level_restriction)
|
51
|
+
logger.footer "updated #{updated_gem.name} to #{updated_gem.updated_version}"
|
52
|
+
|
53
|
+
git.add('Gemfile', 'Gemfile.lock')
|
54
|
+
git.commit("Update #{updated_gem.what_changed}")
|
55
|
+
|
56
|
+
updated_gem
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lapidarist
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Gangl
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: Sit back, relax, and allow Lapidarist to do the heavy lifiting and update
|
56
|
+
your ruby gem dependencies for you.
|
57
|
+
email:
|
58
|
+
- mark@attackcorp.com
|
59
|
+
executables:
|
60
|
+
- lapidarist
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- ".gitignore"
|
65
|
+
- ".rspec"
|
66
|
+
- ".travis.yml"
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- bin/console
|
72
|
+
- bin/setup
|
73
|
+
- exe/lapidarist
|
74
|
+
- lapidarist.gemspec
|
75
|
+
- lib/lapidarist.rb
|
76
|
+
- lib/lapidarist/bundle_command.rb
|
77
|
+
- lib/lapidarist/cli.rb
|
78
|
+
- lib/lapidarist/configuration.rb
|
79
|
+
- lib/lapidarist/gem.rb
|
80
|
+
- lib/lapidarist/gems.rb
|
81
|
+
- lib/lapidarist/git_command.rb
|
82
|
+
- lib/lapidarist/level.rb
|
83
|
+
- lib/lapidarist/logger.rb
|
84
|
+
- lib/lapidarist/options.rb
|
85
|
+
- lib/lapidarist/outdated.rb
|
86
|
+
- lib/lapidarist/sha.rb
|
87
|
+
- lib/lapidarist/shell.rb
|
88
|
+
- lib/lapidarist/status.rb
|
89
|
+
- lib/lapidarist/summary.rb
|
90
|
+
- lib/lapidarist/test_command.rb
|
91
|
+
- lib/lapidarist/update.rb
|
92
|
+
- lib/lapidarist/version.rb
|
93
|
+
homepage: https://github.com/attack/lapidarist
|
94
|
+
licenses:
|
95
|
+
- MIT
|
96
|
+
metadata: {}
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubyforge_project:
|
113
|
+
rubygems_version: 2.7.6
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: Automatically update ruby gem dependencies.
|
117
|
+
test_files: []
|