logfmt 0.0.10 → 0.1.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile +2 -1
- data/README.md +145 -1
- data/Rakefile +30 -1
- data/lib/logfmt/logger.rb +74 -0
- data/lib/logfmt/version.rb +1 -1
- data/lib/logfmt.rb +1 -0
- data/logfmt.gemspec +40 -0
- metadata +9 -11
- data/bin/bundle +0 -114
- data/bin/console +0 -8
- data/bin/rake +0 -29
- data/bin/rspec +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8f2e9e3f3d271e1cad7120cb1fedc6a839050004a51ccd72a9e0ef019b242e6
|
4
|
+
data.tar.gz: 01035abc746fce52ac36c672bec2640a3c4d436f300b244d13b4e936b655030b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb92737ee195acf40cfae4ae48b73895165568690984448e75d9bd4c3a3131f570721ebf0182778c959dc312182f6ebc9bcc0a6a26a877f09e24faa16f2377ff
|
7
|
+
data.tar.gz: 3df2ec4510aad12b18cbe6d1f2da2ffc7b8e3114bb3c66a4b74ae9d04965a5ba766a90db1b7510104295e0c133d36b2bff7190ac80bbbdfac85d770a4b1bb98d
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
|
|
5
5
|
|
6
6
|
## \[Unreleased\]
|
7
7
|
|
8
|
+
## [0.1.0.beta.1] 2022-10-21
|
9
|
+
### Added
|
10
|
+
- Add `Logfmt::Logger` and `Logfmt::TaggedLogger`.
|
11
|
+
The later is distributed as its own gem, `logfmt-tagged_logger`, but lives in this repo.
|
12
|
+
|
8
13
|
## [0.0.10] 2022-04-30
|
9
14
|
### Changed
|
10
15
|
- Autoload the `Logfmt::Parser` when it's used, in preparation for the coming `Logfmt::Logger` and friends.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,58 @@
|
|
1
1
|
# Logfmt
|
2
2
|
|
3
|
-
|
3
|
+
Write and parse structured log lines in the [logfmt style][logfmt-blog].
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem "logfmt"
|
11
|
+
```
|
12
|
+
|
13
|
+
And then install:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
$ gem install logfmt
|
23
|
+
```
|
24
|
+
|
25
|
+
### Versioning
|
26
|
+
|
27
|
+
This project adheres to [Semantic Versioning][semver].
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
`Logfmt` is composed to two parts: writing structured log lines in the `logfmt` style, and parsing `logfmt`-style log lines.
|
32
|
+
|
33
|
+
While writing and parsing `logfmt` are related, we've found that it's common to only need to do one or there other in a single application.
|
34
|
+
To support that usage, `Logfmt` leverages Ruby's `autoload` to lazily load the `Logfmt::Parser` or `Logfmt::Logger` (and associated code) into memory.
|
35
|
+
In the general case that looks something like:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
require "logfmt"
|
39
|
+
|
40
|
+
Logfmt # This constant was already loaded, but neither Logfmt::Parser
|
41
|
+
# nor Logfmt::Logger constants are loaded. Yet.
|
42
|
+
|
43
|
+
Logfmt.parse("…")
|
44
|
+
# OR
|
45
|
+
Logfmt::Parser.parse("…")
|
46
|
+
|
47
|
+
# Either of the above will load the Logfmt::Parser constant.
|
48
|
+
# Similarly you can autoload the Logfmt::Logger via
|
49
|
+
|
50
|
+
Logfmt::Logger.new
|
51
|
+
```
|
52
|
+
|
53
|
+
If you want to eagerly load the logger or parser, you can do that by requiring them directly
|
54
|
+
|
55
|
+
### Parsing log lines
|
4
56
|
|
5
57
|
```ruby
|
6
58
|
require "logfmt/parser"
|
@@ -8,3 +60,95 @@ require "logfmt/parser"
|
|
8
60
|
Logfmt::Parser.parse('foo=bar a=14 baz="hello kitty" cool%story=bro f %^asdf')
|
9
61
|
#=> {"foo"=>"bar", "a"=>14, "baz"=>"hello kitty", "cool%story"=>"bro", "f"=>true, "%^asdf"=>true}
|
10
62
|
```
|
63
|
+
|
64
|
+
### Writing log lines
|
65
|
+
|
66
|
+
The `Logfmt::Logger` is built on the stdlib `::Logger` and adheres to its API.
|
67
|
+
The primary difference is that `Logfmt::Logger` defaults to a `logfmt`-style formatter.
|
68
|
+
Specifically, a `Logfmt::Logger::KeyValueFormatter`, which results in log lines something like this:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
require "logfmt/logger"
|
72
|
+
|
73
|
+
logger = Logfmt::Logger.new($stdout)
|
74
|
+
|
75
|
+
logger.info(foo: "bar", a: 14, "baz" => "hello kitty", "cool%story" => "bro", f: true, "%^asdf" => true)
|
76
|
+
#=> time=2022-04-20T23:30:54.647403Z severity=INFO foo=bar a=14 baz="hello kitty" cool%story=bro f %^asdf
|
77
|
+
|
78
|
+
logger.debug("MADE IT HERE!")
|
79
|
+
#=> time=2022-04-20T23:33:44.912595Z severity=DEBUG msg="MADE IT HERE!"
|
80
|
+
```
|
81
|
+
|
82
|
+
#### Tagged log lines
|
83
|
+
|
84
|
+
The `logfmt-tagged_logger` gem adds support for Rails-style [tagged logging][tagged-logger].
|
85
|
+
This gem adds a `Logfmt::TaggedLogger` which is built on `ActiveSupport::TaggedLogger`, but emits the tags in logfmt-style, as key/value pairs.
|
86
|
+
For example
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
logger = Logfmt::TaggedLogger.new($stdout)
|
90
|
+
|
91
|
+
logger.tagged(source: "api") do
|
92
|
+
logger.info(foo: "bar")
|
93
|
+
end
|
94
|
+
|
95
|
+
#=> time=2022-04-20T23:33:44.912595Z severity=info source=api foo=bar"
|
96
|
+
```
|
97
|
+
|
98
|
+
You can also pass "bare" tags and they'll be collected and emitted under the `tags` key.
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
logger = Logfmt::TaggedLogger.new($stdout)
|
102
|
+
|
103
|
+
logger.tagged("API", "1.2.3.4") do
|
104
|
+
logger.info(foo: "bar")
|
105
|
+
end
|
106
|
+
|
107
|
+
#=> time=2022-04-20T23:33:44.912595Z severity=info tags="[API] [1.2.3.4]" foo=bar"
|
108
|
+
```
|
109
|
+
|
110
|
+
It's likely more helpful and useful to use meaningful key/values for your tags, rather than bare tags.
|
111
|
+
|
112
|
+
#### Expected key/value transformations
|
113
|
+
|
114
|
+
When writing a log line with the `Logfmt::Logger::KeyValueFormatter` the keys and/or values will be transformed thusly:
|
115
|
+
|
116
|
+
* "Bare messages" (those with no key given when invoking the logger) will be wrapped in the `msg` key.
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
logger.info("here")
|
120
|
+
#=> time=2022-04-20T23:33:49.912997Z severity=INFO msg=here
|
121
|
+
```
|
122
|
+
|
123
|
+
* Values, including bare messages, containing white space or control characters (spaces, tabs, newlines, emoji, etc…) will be wrapped in double quotes (`""`) and fully escaped.
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
logger.info("👻 Boo!")
|
127
|
+
#=> time=2022-04-20T23:33:35.912595Z severity=INFO msg="\u{1F47B} Boo!"
|
128
|
+
|
129
|
+
logger.info(number: 42, with_quotes: %{These "are" 'quotes', OK?})
|
130
|
+
#=> time=2022-04-20T23:33:36.412183Z severity=INFO number=42 with_quotes="These \"are\" 'quotes', OK?"
|
131
|
+
```
|
132
|
+
|
133
|
+
* Floating point values are truncated to three digits.
|
134
|
+
|
135
|
+
* Time values are formatted as ISO8601 strings, with six digits sub-second precision.
|
136
|
+
|
137
|
+
* A value that is an Array is wrapped in square brackets, and then the above rules applied to each Array value.
|
138
|
+
This works well for arrays of simple values - like numbers, symbols, or simple strings.
|
139
|
+
But complex data structures will result in human mind-breaking escape sequences.
|
140
|
+
So don't do that.
|
141
|
+
Keep values simple.
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
logger.info(an_array: [1, "two", :three])
|
145
|
+
#=> time=2022-04-20T23:33:36.412183Z severity=INFO an_array="[1, two, three]"
|
146
|
+
```
|
147
|
+
|
148
|
+
**NOTE**: it is **not** expected that log lines generated by `Logfmt` can be round-tripped by parsing the log line with `Logfmt`.
|
149
|
+
Specifically, this applies to Unicode and some control characters, as well as bare messages which will be wrapped in the `msg` key when writing.
|
150
|
+
Additionally, symbol keys will be parsed back into string keys.
|
151
|
+
|
152
|
+
[logfmt-blog]: https://brandur.org/logfmt "Structured log lines with key/value pairs"
|
153
|
+
[semver]: https://semver.org/spec/v2.0.0.html "Semantic Versioning 2.0.0"
|
154
|
+
[tagged-logger]: https://guides.rubyonrails.org/debugging_rails_applications.html#tagged-logging "Tagged Logging"
|
data/Rakefile
CHANGED
@@ -1,8 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "bundler/
|
3
|
+
require "bundler/gem_helper"
|
4
4
|
require "rspec/core/rake_task"
|
5
5
|
|
6
|
+
desc "Run all specs"
|
6
7
|
RSpec::Core::RakeTask.new(:spec)
|
7
8
|
|
9
|
+
namespace "logfmt" do
|
10
|
+
Bundler::GemHelper.install_tasks name: "logfmt"
|
11
|
+
end
|
12
|
+
|
13
|
+
# Inspired by how dotenv/dotenv-rails handles mulitple Gems in a single repo
|
14
|
+
class LogFmtTaggedLoggerGemHelper < Bundler::GemHelper
|
15
|
+
def guard_already_tagged
|
16
|
+
# noop
|
17
|
+
end
|
18
|
+
|
19
|
+
def tag_version
|
20
|
+
# noop
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
namespace "logfmt-tagged_logger" do
|
25
|
+
LogFmtTaggedLoggerGemHelper.install_tasks name: "logfmt-tagged_logger"
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Build logfmt and logfmt-tagged_logger into the pkg directory"
|
29
|
+
task build: ["logfmt:build", "logfmt-tagged_logger:build"]
|
30
|
+
|
31
|
+
desc "Build and install logfmt and logfmt-tagged_logger into system gems"
|
32
|
+
task install: ["logfmt:install", "logfmt-tagged_logger:install"]
|
33
|
+
|
34
|
+
desc "Create tag, build, and push logfmt and logfmt-tagged_logger to rubygems.org"
|
35
|
+
task release: ["logfmt:release", "logfmt-tagged_logger:release"]
|
36
|
+
|
8
37
|
task default: :spec
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../logfmt"
|
4
|
+
require "logger"
|
5
|
+
require "time"
|
6
|
+
|
7
|
+
module Logfmt
|
8
|
+
class Logger < ::Logger
|
9
|
+
def initialize(*args, **kwargs)
|
10
|
+
super
|
11
|
+
@formatter ||= KeyValueFormatter.new
|
12
|
+
end
|
13
|
+
|
14
|
+
class KeyValueFormatter < ::Logger::Formatter
|
15
|
+
def call(severity, timestamp, progname, msg)
|
16
|
+
%(time=#{format_datetime(timestamp)} severity=#{severity.ljust(5)}#{format_progname(progname)} #{format_message(msg)}\n)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def format_datetime(time)
|
22
|
+
time.utc.iso8601(6)
|
23
|
+
end
|
24
|
+
|
25
|
+
def format_message(msg)
|
26
|
+
return unless msg
|
27
|
+
|
28
|
+
if msg.respond_to?(:to_hash)
|
29
|
+
pairs = msg.to_hash.map { |k, v| format_pair(k, v) }
|
30
|
+
pairs.compact.join(" ")
|
31
|
+
else
|
32
|
+
format_pair("msg", msg)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_pair(key, value)
|
37
|
+
return nil if value.nil?
|
38
|
+
|
39
|
+
# Return a bare key when the value is a `TrueClass`
|
40
|
+
return key if value == true
|
41
|
+
|
42
|
+
"#{key}=#{format_value(value)}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def format_progname(progname)
|
46
|
+
return nil unless progname
|
47
|
+
|
48
|
+
# Format this pair like any other to ensure quoting, escaping, etc…,
|
49
|
+
# But we also need a leading space so we can interpolate the resulting
|
50
|
+
# key/value pair into our log line.
|
51
|
+
" #{format_pair(" progname", progname)}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def format_value(value)
|
55
|
+
if value.is_a?(Float)
|
56
|
+
format("%.3f", value)
|
57
|
+
elsif value.is_a?(Time)
|
58
|
+
format_datetime(value)
|
59
|
+
elsif value.respond_to?(:to_ary)
|
60
|
+
format_value(
|
61
|
+
"[#{Array(value).map { |v| format_value(v) }.join(", ")}]"
|
62
|
+
)
|
63
|
+
else
|
64
|
+
# Interpolating due to a weird/subtle behaviour possible in #to_s.
|
65
|
+
# Namely, it's possible it doesn't actually return a String:
|
66
|
+
# https://github.com/ruby/spec/blob/3affe1e54fcd11918a242ad5d4a7ba895ee30c4c/language/string_spec.rb#L130-L141
|
67
|
+
value = "#{value}" # rubocop:disable Style/RedundantInterpolation
|
68
|
+
value = value.dump if value.match?(/[[:space:]]|[[:cntrl:]]/) # wrap in quotes and escape control characters
|
69
|
+
value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/logfmt/version.rb
CHANGED
data/lib/logfmt.rb
CHANGED
data/logfmt.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/logfmt/version"
|
4
|
+
require "English"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "logfmt"
|
8
|
+
spec.version = Logfmt::VERSION
|
9
|
+
spec.authors = ["Timothée Peignier"]
|
10
|
+
spec.email = ["timothee.peignier@tryphon.org"]
|
11
|
+
|
12
|
+
spec.summary = "Write and parse logfmt messages."
|
13
|
+
spec.description = "Write and parse log lines in the logfmt style."
|
14
|
+
spec.homepage = "https://github.com/cyberdelia/logfmt-ruby"
|
15
|
+
spec.license = "MIT"
|
16
|
+
spec.required_ruby_version = ">= 2.5.0"
|
17
|
+
|
18
|
+
spec.metadata = {
|
19
|
+
"bug_tracker_uri" => "#{spec.homepage}/issues",
|
20
|
+
"changelog_uri" => "#{spec.homepage}/blog/master/CHANGELOG.md",
|
21
|
+
"documentation_uri" => spec.homepage,
|
22
|
+
"source_code_uri" => spec.homepage
|
23
|
+
}
|
24
|
+
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
+
`git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
27
|
+
.reject { |f|
|
28
|
+
(f == __FILE__) ||
|
29
|
+
f.match?(%r{\A(?:(?:bin|spec|features)/|\.(?:git|github))}) ||
|
30
|
+
f.match?(/tagged_logger/)
|
31
|
+
}
|
32
|
+
end
|
33
|
+
spec.bindir = "bin"
|
34
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
35
|
+
spec.require_paths = ["lib"]
|
36
|
+
|
37
|
+
spec.add_development_dependency "pry-byebug", "~> 3.9"
|
38
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
39
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
40
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logfmt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.1.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Timothée Peignier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry-byebug
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
|
-
description:
|
55
|
+
description: Write and parse log lines in the logfmt style.
|
56
56
|
email:
|
57
57
|
- timothee.peignier@tryphon.org
|
58
58
|
executables: []
|
@@ -65,13 +65,11 @@ files:
|
|
65
65
|
- README.md
|
66
66
|
- Rakefile
|
67
67
|
- bench.rb
|
68
|
-
- bin/bundle
|
69
|
-
- bin/console
|
70
|
-
- bin/rake
|
71
|
-
- bin/rspec
|
72
68
|
- lib/logfmt.rb
|
69
|
+
- lib/logfmt/logger.rb
|
73
70
|
- lib/logfmt/parser.rb
|
74
71
|
- lib/logfmt/version.rb
|
72
|
+
- logfmt.gemspec
|
75
73
|
homepage: https://github.com/cyberdelia/logfmt-ruby
|
76
74
|
licenses:
|
77
75
|
- MIT
|
@@ -88,15 +86,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
88
86
|
requirements:
|
89
87
|
- - ">="
|
90
88
|
- !ruby/object:Gem::Version
|
91
|
-
version: 2.
|
89
|
+
version: 2.5.0
|
92
90
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
91
|
requirements:
|
94
|
-
- - "
|
92
|
+
- - ">"
|
95
93
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
94
|
+
version: 1.3.1
|
97
95
|
requirements: []
|
98
96
|
rubygems_version: 3.3.7
|
99
97
|
signing_key:
|
100
98
|
specification_version: 4
|
101
|
-
summary:
|
99
|
+
summary: Write and parse logfmt messages.
|
102
100
|
test_files: []
|
data/bin/bundle
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'bundle' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
require "rubygems"
|
12
|
-
|
13
|
-
m = Module.new do
|
14
|
-
module_function
|
15
|
-
|
16
|
-
def invoked_as_script?
|
17
|
-
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
-
end
|
19
|
-
|
20
|
-
def env_var_version
|
21
|
-
ENV["BUNDLER_VERSION"]
|
22
|
-
end
|
23
|
-
|
24
|
-
def cli_arg_version
|
25
|
-
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
-
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
-
bundler_version = nil
|
28
|
-
update_index = nil
|
29
|
-
ARGV.each_with_index do |a, i|
|
30
|
-
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
-
bundler_version = a
|
32
|
-
end
|
33
|
-
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
-
bundler_version = $1
|
35
|
-
update_index = i
|
36
|
-
end
|
37
|
-
bundler_version
|
38
|
-
end
|
39
|
-
|
40
|
-
def gemfile
|
41
|
-
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
-
return gemfile if gemfile && !gemfile.empty?
|
43
|
-
|
44
|
-
File.expand_path("../../Gemfile", __FILE__)
|
45
|
-
end
|
46
|
-
|
47
|
-
def lockfile
|
48
|
-
lockfile =
|
49
|
-
case File.basename(gemfile)
|
50
|
-
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
51
|
-
else "#{gemfile}.lock"
|
52
|
-
end
|
53
|
-
File.expand_path(lockfile)
|
54
|
-
end
|
55
|
-
|
56
|
-
def lockfile_version
|
57
|
-
return unless File.file?(lockfile)
|
58
|
-
lockfile_contents = File.read(lockfile)
|
59
|
-
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
-
Regexp.last_match(1)
|
61
|
-
end
|
62
|
-
|
63
|
-
def bundler_requirement
|
64
|
-
@bundler_requirement ||=
|
65
|
-
env_var_version || cli_arg_version ||
|
66
|
-
bundler_requirement_for(lockfile_version)
|
67
|
-
end
|
68
|
-
|
69
|
-
def bundler_requirement_for(version)
|
70
|
-
return "#{Gem::Requirement.default}.a" unless version
|
71
|
-
|
72
|
-
bundler_gem_version = Gem::Version.new(version)
|
73
|
-
|
74
|
-
requirement = bundler_gem_version.approximate_recommendation
|
75
|
-
|
76
|
-
return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0")
|
77
|
-
|
78
|
-
requirement += ".a" if bundler_gem_version.prerelease?
|
79
|
-
|
80
|
-
requirement
|
81
|
-
end
|
82
|
-
|
83
|
-
def load_bundler!
|
84
|
-
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
85
|
-
|
86
|
-
activate_bundler
|
87
|
-
end
|
88
|
-
|
89
|
-
def activate_bundler
|
90
|
-
gem_error = activation_error_handling do
|
91
|
-
gem "bundler", bundler_requirement
|
92
|
-
end
|
93
|
-
return if gem_error.nil?
|
94
|
-
require_error = activation_error_handling do
|
95
|
-
require "bundler/version"
|
96
|
-
end
|
97
|
-
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
98
|
-
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
99
|
-
exit 42
|
100
|
-
end
|
101
|
-
|
102
|
-
def activation_error_handling
|
103
|
-
yield
|
104
|
-
nil
|
105
|
-
rescue StandardError, LoadError => e
|
106
|
-
e
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
m.load_bundler!
|
111
|
-
|
112
|
-
if m.invoked_as_script?
|
113
|
-
load Gem.bin_path("bundler", "bundle")
|
114
|
-
end
|
data/bin/console
DELETED
data/bin/rake
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'rake' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
-
Pathname.new(__FILE__).realpath)
|
14
|
-
|
15
|
-
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
-
|
17
|
-
if File.file?(bundle_binstub)
|
18
|
-
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
-
load(bundle_binstub)
|
20
|
-
else
|
21
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
require "rubygems"
|
27
|
-
require "bundler/setup"
|
28
|
-
|
29
|
-
load Gem.bin_path("rake", "rake")
|
data/bin/rspec
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'rspec' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
-
Pathname.new(__FILE__).realpath)
|
14
|
-
|
15
|
-
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
-
|
17
|
-
if File.file?(bundle_binstub)
|
18
|
-
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
-
load(bundle_binstub)
|
20
|
-
else
|
21
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
require "rubygems"
|
27
|
-
require "bundler/setup"
|
28
|
-
|
29
|
-
load Gem.bin_path("rspec-core", "rspec")
|