sugarjar 1.1.0 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 017705b23c86a5a5c6f1695c5e7dabca591409d2f99039c592d9db14822d7cd2
4
- data.tar.gz: e41d40f68013573e5074772d061aa8c55fc69f860d6f63688219a995ab409abc
3
+ metadata.gz: 4263a42ebb922645e2e0735c3ca33ad94df880fb01f881b2cacb602d733c533e
4
+ data.tar.gz: 616fb99c535c491324c1dcc4906b37c8cb424566b62dc64377c61b9a5ef5fd49
5
5
  SHA512:
6
- metadata.gz: 54d411046b2f5cab10e97d740e0c4c335a17ec9c4cefcd363720f06660ba4a3310d8ab2a48e057f9047b16d116e30e0e1b082d78953fe9570cee3bee2d14f6f0
7
- data.tar.gz: fefe49ca8cd8a8b8c80139a10cc874d24a08808349cae3a71237f47b263502c2fafc92a12d947bcf9b1c17a977bd4ffff8c3956f17bd0f1a18f68dfb566d8b2f
6
+ metadata.gz: 1d918daf7096d1889bf72ee0eca74ef473234ed1ed46e4275418028e9a32c9284b4412ff202a932a3cc43c777bbf55d1455ce8fd8805c965184e4d2bc740e527
7
+ data.tar.gz: 0657a6629d97623d40f68d0ffe7a3e0522c951d9b22dc0c7b4b918d78eb27b026ab68d347b1c2fa68661536eceef9cbf3de3ee82b4ea4381da2675f1d34b3f2d
data/README.md CHANGED
@@ -5,14 +5,13 @@
5
5
  [![DCO](https://github.com/jaymzh/sugarjar/workflows/DCO%20Check/badge.svg)](https://github.com/jaymzh/sugarjar/actions?query=workflow%3A%22DCO+Check%22)
6
6
 
7
7
  > [!IMPORTANT]
8
- > If you are a _new_ user, I suggest looking at [Sapling](https://sapling-scm.com/)
9
- > instead of this. This was written as a stop-gap to approximate some features
10
- > of the Facebook/Meta internal development tools before they were released.
11
- > Now that those tools have been open-sourced and work with GitHub, new users
12
- > will likely want to start there. Sapling is far more feature rich, faster,
13
- > and have more development resources behind them. SugarJar is a smaller
14
- > transition, and for the time being I'm maintaining it for all existing users,
15
- > and for those who may not yet be ready for the transition to Sapling.
8
+ > As this was meant to replace arc/jf, which has now been open-sourced as
9
+ > [Sapling](https://sapling-scm.com/), I highly recommend taking a look at that!
10
+ >
11
+ > Sapling is a great tool and solves a variety of problems SugarJar will never
12
+ > be able to. However, it is a bigger workflow change, so existing SJ users
13
+ > may choose to stick with this. Similarly some workflows may not be suitable
14
+ > for Sapling. I still plan to maintain and develop SugarJar for the time being.
16
15
 
17
16
  Welcome to SugarJar - a git/github helper. It needs one of the GitHub CLI's:
18
17
  either [gh](https://cli.github.com/) or the older [hub](https://hub.github.com/).
@@ -33,18 +32,29 @@ If you don't, there's a ton of useful stuff for everyone!
33
32
  Sugarjar is packaged in a variety of Linux distributions - see if it's on the
34
33
  list here, and if so, use your package manager (or `gem`) to install it:
35
34
 
36
- [![Packaging status](https://repology.org/badge/vertical-allrepos/sugarjar.svg)](https://repology.org/project/sugarjar/versions)
35
+ [![Packaging status](https://repology.org/badge/vertical-allrepos/sugarjar.svg?exclude_unsupported=1)](https://repology.org/project/sugarjar/versions)
37
36
 
38
- For MacOS users, you can use our Homebrew Tap:
37
+ If you are using a Linux distribution version that is end-of-life'd, click the
38
+ above image, it'll take you to a page that lists unsupported distro versions
39
+ as well (they'll have older SugarJar, but they'll probably still have some
40
+ version).
41
+
42
+ Ubuntu users, Ubuntu versions prior to 24.x cannot be updated, so if you're on
43
+ an older Ubuntu please use [this
44
+ PPA](https://launchpad.net/~michel-slm/+archive/ubuntu/sugarjar) from our
45
+ Ubuntu package maintainer.
46
+
47
+ For MacOS users, we recommend using Homebrew - SugarJar is now in Homebrew Core.
48
+
49
+ NOTE: If you previously used our custom Homebrew tap, you should remove and
50
+ untap it:
39
51
 
40
52
  ```shell
41
- homebrew tap jaymzh/sugarjar
42
- homebrew install sugarjar
53
+ homebrew uninstall sugarjar
54
+ homebrew untap jaymzh/sugarjar
43
55
  ```
44
56
 
45
- You can also weigh in on [this
46
- PR](https://github.com/Homebrew/homebrew-core/pull/157910) and tell the
47
- Homebrew folks you'd like to see it in core.
57
+ Then you can install the core version (`brew install sugarjar`).
48
58
 
49
59
  Finally, if none of those work for you, you can clone this repo and run it
50
60
  directly from there.
@@ -410,3 +420,9 @@ will allow me to make sure it shows up in the Repology badge above.
410
420
  Since it's Ruby, it should work across all platforms, however, it's developed
411
421
  and primarily tested on Linux as well as regularly used on Mac. I've not tested
412
422
  it on Windows, but I'll happily accept patches for Windows compatibility.
423
+
424
+ **How do I get tab-completion?**
425
+
426
+ If the package for your OS/distro didn't set it up manually, you should find
427
+ that `sugarjar_completion.bash` is included in the package, and you can simply
428
+ source that in your dotfiles, assuming you are using bash.
data/bin/sj CHANGED
@@ -91,6 +91,24 @@ parser = OptionParser.new do |opts|
91
91
  options['log_level'] = level
92
92
  end
93
93
 
94
+ opts.on(
95
+ '--[no-]pr-autofill',
96
+ 'When creating a PR, auto fill the title & description from the commit ' +
97
+ 'if there is a single commit and if we are using "gh". [default: true]',
98
+ ) do |autofill|
99
+ options['pr_autofill'] = autofill
100
+ end
101
+
102
+ opts.on(
103
+ '--[no-]pr-autostack',
104
+ 'When creating a PR, if this is a subfeature, should we make it a ' +
105
+ 'PR on the PR for the parent feature. If not specified, we prompt ' +
106
+ 'when this happens, when true always do this, when false never do ' +
107
+ 'this. Only applicable when usiing "gh".',
108
+ ) do |autostack|
109
+ options['pr_autostack'] = autostack
110
+ end
111
+
94
112
  opts.on('--[no-]use-color', 'Enable color. [default: true]') do |color|
95
113
  options['color'] = color
96
114
  end
@@ -112,10 +130,10 @@ COMMANDS:
112
130
  Same as "amend" but without changing the message. Alias for
113
131
  "git commit --amend --no-edit".
114
132
 
115
- bclean
116
- If safe, delete the current branch. Unlike "git branch -d",
117
- bclean can handle squash-merged branches. Think of it as
118
- a smarter "git branch -d".
133
+ bclean [<branch>]
134
+ If safe, delete the current branch (or the specified branch).
135
+ Unlike "git branch -d", bclean can handle squash-merged branches.
136
+ Think of it as a smarter "git branch -d".
119
137
 
120
138
  bcleanall
121
139
  Walk all branches, and try to delete them if it's safe. See
@@ -127,7 +145,7 @@ COMMANDS:
127
145
  br
128
146
  Verbose branch list. An alias for "git branch -v".
129
147
 
130
- feature
148
+ feature, f <branch_name>
131
149
  Create a "feature" branch. It's morally equivalent to
132
150
  "git checkout -b" except it defaults to creating it based on
133
151
  some form of 'master' instead of your current branch. In order
@@ -177,11 +195,17 @@ COMMANDS:
177
195
  A smart wrapper to "git push" that runs whatever is defined in
178
196
  "on_push" in .sugarjar.yml, and only pushes if they succeed.
179
197
 
198
+ subfeature, sf <feature>
199
+ An alias for 'sj feature <feature> <current_branch>'
200
+
180
201
  unit
181
202
  Run any unitests configured in .sugarjar.yaml.
182
203
 
183
- up
184
- Rebase the current branch on upstream/master or origin/master.
204
+ up [<branch>]
205
+ Rebase the current branch (or specified branch) intelligently.
206
+ In most causes this will check for a main (or master) branch on
207
+ upstream, then origin. If a branch explicitly tracks something
208
+ else, then that will be used, instead.
185
209
 
186
210
  upall
187
211
  Same as "up", but for all branches.
@@ -190,9 +214,9 @@ COMMANDS:
190
214
  Print the version of sugarjar, and then run 'hub version'
191
215
  to show the hub and git versions.
192
216
 
193
- Be sure to checkout Sapling (https://sapling-scm.com/)! This was written as
217
+ Be sure to checkout Sapling (https://sapling-scm.com/)! SugarJar was written as
194
218
  a stop-gap to get Sapling features before it was open-sourced, and as such
195
- I may deprecate this in the future.
219
+ Sapling may serve your needs even better.
196
220
  COMMANDS
197
221
 
198
222
  # rubocop:enable Layout/HeredocIndentation
@@ -0,0 +1,42 @@
1
+ # bash completion for sugarjar
2
+
3
+ SJCONFIG="$HOME/.config/sugarjar/config.yaml"
4
+
5
+ _sugarjar_completions()
6
+ {
7
+ if [ "${#COMP_WORDS[@]}" -eq 2 ]; then
8
+ return
9
+ fi
10
+
11
+ local -a suggestions
12
+
13
+ # grap the feature_prefix if we have one so that we
14
+ # can let the user ignore that part. If we have `yq`
15
+ # we'll use it as that's going to be always 100%
16
+ # reliable, but if we don't, do our best with shell
17
+ # utils
18
+ local prefix=''
19
+ if [ -e "$SJCONFIG" ]; then
20
+ if type yq &>/dev/null; then
21
+ prefix=$(yq .feature_prefix $SJCONFIG)
22
+ else
23
+ # the xargs removes extra spaces
24
+ prefix=$(grep feature_prefix $SJCONFIG | cut -f2 -d: | xargs)
25
+ fi
26
+ fi
27
+
28
+ case "${COMP_WORDS[1]}" in
29
+ co|checkout|bclean)
30
+ local branches=$(git branch | sed -e 's/* //g' | xargs)
31
+ if [ -n "$prefix" ]; then
32
+ local branches=$(echo $branches | sed -e "s!$prefix!!g")
33
+ fi
34
+ suggestions=($(compgen -W "$branches" -- "${COMP_WORDS[2]}"))
35
+ COMPREPLY=("${suggestions[@]}")
36
+ ;;
37
+ *)
38
+ return
39
+ esac
40
+ }
41
+
42
+ complete -F _sugarjar_completions sj
@@ -23,6 +23,8 @@ class SugarJar
23
23
  @repo_config = SugarJar::RepoConfig.config
24
24
  SugarJar::Log.debug("Repoconfig: #{@repo_config}")
25
25
  @color = options['color']
26
+ @pr_autofill = options['pr_autofill']
27
+ @pr_autostack = options['pr_autostack']
26
28
  @feature_prefix = options['feature_prefix']
27
29
  @checks = {}
28
30
  @main_branch = nil
@@ -43,19 +45,31 @@ class SugarJar
43
45
  name = fprefix(name)
44
46
  die("#{name} already exists!") if all_local_branches.include?(name)
45
47
  base ||= most_main
46
- base_pieces = base.split('/')
47
- git('fetch', base_pieces[0]) if base_pieces.length > 1
48
+ # If our base is a local branch, don't try to parse it for a remote name
49
+ unless all_local_branches.include?(base)
50
+ base_pieces = base.split('/')
51
+ git('fetch', base_pieces[0]) if base_pieces.length > 1
52
+ end
48
53
  git('checkout', '-b', name, base)
54
+ git('branch', '-u', base)
49
55
  SugarJar::Log.info(
50
56
  "Created feature branch #{color(name, :green)} based on " +
51
57
  color(base, :green),
52
58
  )
53
59
  end
60
+ alias f feature
61
+
62
+ def subfeature(name)
63
+ assert_in_repo
64
+ SugarJar::Log.debug("Subfature: #{name}")
65
+ feature(name, current_branch)
66
+ end
67
+ alias sf subfeature
54
68
 
55
69
  def bclean(name = nil)
56
70
  assert_in_repo
57
71
  name ||= current_branch
58
- name = fprefix(name) unless all_local_branches.include?(name)
72
+ name = fprefix(name)
59
73
  if clean_branch(name)
60
74
  SugarJar::Log.info("#{name}: #{color('reaped', :green)}")
61
75
  else
@@ -100,7 +114,7 @@ class SugarJar
100
114
  # and then add any featureprefix, and if _that_ is a branch
101
115
  # name, replace the last arguement with that
102
116
  name = args.last
103
- bname = fprefix(name) unless all_local_branches.include?(name)
117
+ bname = fprefix(name)
104
118
  if all_local_branches.include?(bname)
105
119
  SugarJar::Log.debug("Featurepefixing #{name} -> #{bname}")
106
120
  args[-1] = bname
@@ -133,17 +147,25 @@ class SugarJar
133
147
 
134
148
  alias sl smartlog
135
149
 
136
- def up
150
+ def up(branch = nil)
137
151
  assert_in_repo
152
+ branch ||= current_branch
153
+ branch = fprefix(branch)
138
154
  # get a copy of our current branch, if rebase fails, we won't
139
155
  # be able to determine it without backing out
140
156
  curr = current_branch
157
+ git('checkout', branch)
141
158
  result = gitup
142
159
  if result['so'].error?
160
+ backout = ''
161
+ if rebase_in_progress?
162
+ backout = ' You can get out of this with a `git rebase --abort`.'
163
+ end
164
+
143
165
  die(
144
166
  "#{color(curr, :red)}: Failed to rebase on " +
145
- "#{result['base']}. Leaving the repo as-is. You can get out of " +
146
- 'this with a `git rebase --abort`. Output from failed rebase is: ' +
167
+ "#{result['base']}. Leaving the repo as-is.#{backout} " +
168
+ 'Output from failed rebase is: ' +
147
169
  "\nSTDOUT:\n#{result['so'].stdout.lines.map { |x| "\t#{x}" }.join}" +
148
170
  "\nSTDERR:\n#{result['so'].stderr.lines.map { |x| "\t#{x}" }.join}",
149
171
  )
@@ -151,6 +173,8 @@ class SugarJar
151
173
  SugarJar::Log.info(
152
174
  "#{color(current_branch, :green)} rebased on #{result['base']}",
153
175
  )
176
+ # go back to where we were if we rebased a different branch
177
+ git('checkout', curr) if branch != curr
154
178
  end
155
179
  end
156
180
 
@@ -179,7 +203,7 @@ class SugarJar
179
203
  "#{color(branch, :red)} failed rebase. Reverting attempt and " +
180
204
  'moving to next branch. Try `sj up` manually on that branch.',
181
205
  )
182
- git('rebase', '--abort')
206
+ git('rebase', '--abort') if rebase_in_progress?
183
207
  else
184
208
  SugarJar::Log.info(
185
209
  "#{color(branch, :green)} rebased on " +
@@ -297,6 +321,7 @@ class SugarJar
297
321
  def smartpullrequest(*args)
298
322
  assert_in_repo
299
323
  assert_common_main_branch
324
+
300
325
  if dirty?
301
326
  SugarJar::Log.warn(
302
327
  'Your repo is dirty, so I am not going to create a pull request. ' +
@@ -304,9 +329,38 @@ class SugarJar
304
329
  )
305
330
  exit(1)
306
331
  end
332
+
307
333
  if gh?
334
+ curr = current_branch
335
+ base = tracked_branch
336
+ if @pr_autofill
337
+ num_commits = git(
338
+ 'rev-list', '--count', curr, "^#{base}"
339
+ ).stdout.strip.to_i
340
+ if num_commits > 1
341
+ SugarJar::Log.debug(
342
+ "Not using --fill because there are #{num_commits} commits",
343
+ )
344
+ else
345
+ SugarJar::Log.info('Autofilling in PR from commit message')
346
+ args.unshift('--fill')
347
+ end
348
+ end
349
+ if subfeature?(base)
350
+ # nil is prompt, true is always, false is never
351
+ if @pr_autostack.nil?
352
+ $stdout.print(
353
+ 'It looks like this is a subfeature, would you like to base ' +
354
+ "this PR on #{base}? [y/n] ",
355
+ )
356
+ ans = $stdin.gets.strip
357
+ args += ['--base', base] if %w{Y y}.include?(ans)
358
+ elsif @pr_autostack
359
+ args += ['--base', base]
360
+ end
361
+ end
308
362
  SugarJar::Log.trace("Running: gh pr create #{args.join(' ')}")
309
- system(which('gh'), 'pr', 'create', '--fill', *args)
363
+ system(which('gh'), 'pr', 'create', *args)
310
364
  else
311
365
  SugarJar::Log.trace("Running: hub pull-request #{args.join(' ')}")
312
366
  system(which('hub'), 'pull-request', *args)
@@ -336,7 +390,7 @@ class SugarJar
336
390
 
337
391
  src = "origin/#{current_branch}"
338
392
  fetch('origin')
339
- diff = git('diff', src).stdout
393
+ diff = git('diff', "..#{src}").stdout
340
394
  return unless diff && !diff.empty?
341
395
 
342
396
  puts "Will merge the following suggestions:\n\n#{diff}"
@@ -364,6 +418,9 @@ class SugarJar
364
418
  def fprefix(name)
365
419
  return name unless @feature_prefix
366
420
 
421
+ return name if name.start_with?(@feature_prefix)
422
+ return name if all_local_branches.include?(name)
423
+
367
424
  newname = "#{@feature_prefix}#{name}"
368
425
  SugarJar::Log.debug(
369
426
  "Munging feature name: #{name} -> #{newname} due to feature prefix",
@@ -707,11 +764,15 @@ class SugarJar
707
764
  end
708
765
 
709
766
  def all_local_branches
710
- branches = []
711
- git('branch', '--format', '%(refname)').stdout.lines.each do |line|
712
- branches << branch_from_ref(line.strip)
767
+ git(
768
+ 'branch', '--format', '%(refname)'
769
+ ).stdout.lines.map do |line|
770
+ branch_from_ref(line.strip)
713
771
  end
714
- branches
772
+ end
773
+
774
+ def all_remotes
775
+ git('remote').stdout.lines.map(&:strip)
715
776
  end
716
777
 
717
778
  def safe_to_clean(branch)
@@ -789,14 +850,28 @@ class SugarJar
789
850
  SugarJar::Log.debug('Fetching upstream')
790
851
  fetch_upstream
791
852
  curr = current_branch
792
- base = tracked_branch
853
+ # this isn't a hash, it's a named param, silly rubocop
854
+ # rubocop:disable Style/HashSyntax
855
+ base = tracked_branch(fallback: false)
856
+ # rubocop:enable Style/HashSyntax
857
+ unless base
858
+ SugarJar::Log.info(
859
+ 'The brach we were tracking is gone, resetting tracking to ' +
860
+ most_main,
861
+ )
862
+ git('branch', '-u', most_main)
863
+ base = most_main
864
+ end
865
+ # If this is a subfeature based on a local branch which has since
866
+ # been deleted, 'tracked branch' will automatically return <most_main>
867
+ # so we don't need any special handling for that
793
868
  if !MAIN_BRANCHES.include?(curr) && base == "origin/#{curr}"
794
869
  SugarJar::Log.warn(
795
870
  "This branch is tracking origin/#{curr}, which is probably your " +
796
871
  'downstream (where you push _to_) as opposed to your upstream ' +
797
872
  '(where you pull _from_). This means that "sj up" is probably ' +
798
873
  'rebasing on the wrong thing and doing nothing. You probably want ' +
799
- 'to do a "git branch -u upstream".',
874
+ "to do a 'git branch -u #{most_main}'.",
800
875
  )
801
876
  end
802
877
  SugarJar::Log.debug('Rebasing')
@@ -807,12 +882,28 @@ class SugarJar
807
882
  }
808
883
  end
809
884
 
810
- def tracked_branch
885
+ # determine if this branch is based on another local branch (i.e. is a
886
+ # subfeature). Used to figure out of we should stack the PR
887
+ def subfeature?(base)
888
+ all_local_branches.reject { |x| x == most_main }.include?(base)
889
+ end
890
+
891
+ def rebase_in_progress?
892
+ # for rebase without -i
893
+ rebase_file = git('rev-parse', '--git-path', 'rebase-apply').stdout.strip
894
+ # for rebase -i
895
+ rebase_merge_file = git('rev-parse', '--git-path', 'rebase-merge').
896
+ stdout.strip
897
+ File.exist?(rebase_file) || File.exist?(rebase_merge_file)
898
+ end
899
+
900
+ def tracked_branch(fallback: true)
811
901
  s = git_nofail(
812
902
  'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'
813
903
  )
814
904
  if s.error?
815
- most_main
905
+ fallback ? most_main : nil
906
+
816
907
  else
817
908
  s.stdout.strip
818
909
  end
@@ -830,9 +921,7 @@ class SugarJar
830
921
  def upstream
831
922
  return @remote if @remote
832
923
 
833
- s = git('remote')
834
-
835
- remotes = s.stdout.lines.map(&:strip)
924
+ remotes = all_remotes
836
925
  SugarJar::Log.debug("remotes is #{remotes}")
837
926
  if remotes.empty?
838
927
  @remote = nil
@@ -9,6 +9,8 @@ class SugarJar
9
9
  'github_cli' => 'auto',
10
10
  'github_user' => ENV.fetch('USER'),
11
11
  'fallthru' => true,
12
+ 'pr_autofill' => true,
13
+ 'pr_autostack' => nil,
12
14
  }.freeze
13
15
 
14
16
  def self._find_ordered_files
data/lib/sugarjar/util.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require_relative 'log'
2
2
 
3
+ require 'mixlib/shellout'
4
+
3
5
  class SugarJar
4
6
  # Some common methods needed by other classes
5
7
  module Util
@@ -1,3 +1,3 @@
1
1
  class SugarJar
2
- VERSION = '1.1.0'.freeze
2
+ VERSION = '1.1.2'.freeze
3
3
  end
data/sugarjar.gemspec CHANGED
@@ -8,14 +8,16 @@ Gem::Specification.new do |spec|
8
8
  spec.email = ['phil@ipom.com']
9
9
  spec.license = 'Apache-2.0'
10
10
  spec.homepage = 'https://github.com/jaymzh/sugarjar'
11
- spec.required_ruby_version = '>= 3.1'
11
+ # We'll support 3.0 until 2024-03-31 when it goes EOL
12
+ # https://www.ruby-lang.org/en/downloads/branches/
13
+ spec.required_ruby_version = '>= 3.0'
12
14
  docs = %w{README.md LICENSE Gemfile sugarjar.gemspec}
13
15
  spec.extra_rdoc_files = docs
14
16
  spec.executables << 'sj'
15
17
  spec.files =
16
18
  Dir.glob('lib/sugarjar/*.rb') +
17
19
  Dir.glob('bin/*') +
18
- docs
20
+ Dir.glob('extras/*')
19
21
 
20
22
  spec.add_dependency 'deep_merge'
21
23
  spec.add_dependency 'mixlib-log'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sugarjar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Dibowitz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-31 00:00:00.000000000 Z
11
+ date: 2024-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge
@@ -82,6 +82,7 @@ files:
82
82
  - LICENSE
83
83
  - README.md
84
84
  - bin/sj
85
+ - extras/sugarjar_completion.bash
85
86
  - lib/sugarjar/commands.rb
86
87
  - lib/sugarjar/config.rb
87
88
  - lib/sugarjar/log.rb
@@ -106,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
107
  requirements:
107
108
  - - ">="
108
109
  - !ruby/object:Gem::Version
109
- version: '3.1'
110
+ version: '3.0'
110
111
  required_rubygems_version: !ruby/object:Gem::Requirement
111
112
  requirements:
112
113
  - - ">="