sugarjar 2.0.0.beta.1 → 2.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.
data/lib/sugarjar/util.rb CHANGED
@@ -1,289 +1,21 @@
1
- require_relative 'log'
2
-
3
1
  require 'mixlib/shellout'
4
2
 
3
+ require_relative 'log'
4
+
5
5
  class SugarJar
6
- # Some common methods needed by other classes
7
6
  module Util
8
- def extract_org(repo)
9
- if repo.start_with?('http')
10
- File.basename(File.dirname(repo))
11
- elsif repo.start_with?('git@')
12
- repo.split(':')[1].split('/')[0]
13
- else
14
- # assume they passed in a ghcli-friendly name
15
- repo.split('/').first
16
- end
17
- end
18
-
19
- def extract_repo(repo)
20
- File.basename(repo, '.git')
21
- end
22
-
23
- def forked_repo(repo, username)
24
- repo = if repo.start_with?('http', 'git@')
25
- File.basename(repo)
26
- else
27
- "#{File.basename(repo)}.git"
28
- end
29
- "git@#{@ghhost || 'github.com'}:#{username}/#{repo}"
30
- end
31
-
32
- # gh utils will default to https, but we should always default to SSH
33
- # unless otherwise specified since https will cause prompting.
34
- def canonicalize_repo(repo)
35
- # if they fully-qualified it, we're good
36
- return repo if repo.start_with?('http', 'git@')
37
-
38
- # otherwise, ti's a shortname
39
- cr = "git@#{@ghhost || 'github.com'}:#{repo}.git"
40
- SugarJar::Log.debug("canonicalized #{repo} to #{cr}")
41
- cr
42
- end
43
-
44
- def set_commit_template
45
- unless in_repo
46
- SugarJar::Log.debug('Skipping set_commit_template: not in repo')
47
- return
48
- end
49
-
50
- realpath = if @repo_config['commit_template'].start_with?('/')
51
- @repo_config['commit_template']
52
- else
53
- "#{repo_root}/#{@repo_config['commit_template']}"
54
- end
55
- unless File.exist?(realpath)
56
- die(
57
- "Repo config specifies #{@repo_config['commit_template']} as the " +
58
- 'commit template, but that file does not exist.',
59
- )
60
- end
61
-
62
- s = git_nofail('config', '--local', 'commit.template')
63
- unless s.error?
64
- current = s.stdout.strip
65
- if current == @repo_config['commit_template']
66
- SugarJar::Log.debug('Commit template already set correctly')
67
- return
68
- else
69
- SugarJar::Log.warn(
70
- "Updating repo-specific commit template from #{current} " +
71
- "to #{@repo_config['commit_template']}",
72
- )
73
- end
74
- end
75
-
76
- SugarJar::Log.debug(
77
- 'Setting repo-specific commit template to ' +
78
- "#{@repo_config['commit_template']} per sugarjar repo config.",
79
- )
80
- git(
81
- 'config', '--local', 'commit.template', @repo_config['commit_template']
82
- )
83
- end
84
-
85
- def run_prepush
86
- @repo_config['on_push']&.each do |item|
87
- SugarJar::Log.debug("Running on_push check type #{item}")
88
- unless send(:run_check, item)
89
- SugarJar::Log.info("[prepush]: #{item} #{color('failed', :red)}.")
90
- return false
91
- end
92
- end
93
- true
94
- end
7
+ # a mixin to hold stuff that Commands and RepoConfig both use
8
+ def self.which(cmd)
9
+ path = which_nofail(cmd)
10
+ return path if path
95
11
 
96
- def die(msg)
97
- SugarJar::Log.fatal(msg)
12
+ SugarJar::Log.fatal("Could not find #{cmd} in your path")
98
13
  exit(1)
99
14
  end
100
15
 
101
- def assert_common_main_branch
102
- upstream_branch = main_remote_branch(upstream)
103
- unless main_branch == upstream_branch
104
- die(
105
- "The local main branch is '#{main_branch}', but the main branch " +
106
- "of the #{upstream} remote is '#{upstream_branch}'. You probably " +
107
- "want to rename your local branch by doing:\n\t" +
108
- "git branch -m #{main_branch} #{upstream_branch}\n\t" +
109
- "git fetch #{upstream}\n\t" +
110
- "git branch -u #{upstream}/#{upstream_branch} #{upstream_branch}\n" +
111
- "\tgit remote set-head #{upstream} -a",
112
- )
113
- end
114
- return if upstream_branch == 'origin'
115
-
116
- origin_branch = main_remote_branch('origin')
117
- return if origin_branch == upstream_branch
118
-
119
- die(
120
- "The main branch of your upstream (#{upstream_branch}) and your " +
121
- "fork/origin (#{origin_branch}) are not the same. You should go " +
122
- "to https://#{@ghhost || 'github.com'}/#{@ghuser}/#{repo_name}/" +
123
- 'branches/ and rename the \'default\' branch to ' +
124
- "'#{upstream_branch}'. It will then give you some commands to " +
125
- 'run to update this clone.',
126
- )
127
- end
128
-
129
- def assert_in_repo
130
- die('sugarjar must be run from inside a git repo') unless in_repo
131
- end
132
-
133
- def determine_main_branch(branches)
134
- branches.include?('main') ? 'main' : 'master'
135
- end
136
-
137
- def main_branch
138
- @main_branch = determine_main_branch(all_local_branches)
139
- end
140
-
141
- def main_remote_branch(remote)
142
- @main_remote_branches[remote] ||=
143
- determine_main_branch(all_remote_branches(remote))
144
- end
145
-
146
- def checkout_main_branch
147
- git('checkout', main_branch)
148
- end
149
-
150
- def all_remote_branches(remote = 'origin')
151
- branches = []
152
- git('branch', '-r', '--format', '%(refname)').stdout.lines.each do |line|
153
- next unless line.start_with?("refs/remotes/#{remote}/")
154
-
155
- branches << branch_from_ref(line.strip, :remote)
156
- end
157
- branches
158
- end
159
-
160
- def all_local_branches
161
- git(
162
- 'branch', '--format', '%(refname)'
163
- ).stdout.lines.map do |line|
164
- next if line.start_with?('(HEAD detached')
165
-
166
- branch_from_ref(line.strip)
167
- end
168
- end
169
-
170
- def all_remotes
171
- git('remote').stdout.lines.map(&:strip)
172
- end
173
-
174
- def current_branch
175
- branch_from_ref(git('symbolic-ref', 'HEAD').stdout.strip)
176
- end
177
-
178
- def fetch_upstream
179
- us = upstream
180
- fetch(us) if us
181
- end
182
-
183
- def fetch(remote)
184
- git('fetch', remote)
185
- end
186
-
187
- # determine if this branch is based on another local branch (i.e. is a
188
- # subfeature). Used to figure out of we should stack the PR
189
- def subfeature?(base)
190
- all_local_branches.reject { |x| x == most_main }.include?(base)
191
- end
192
-
193
- def tracked_branch(fallback: true)
194
- branch = nil
195
- s = git_nofail(
196
- 'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'
197
- )
198
- if s.error?
199
- branch = fallback ? most_main : nil
200
- SugarJar::Log.debug("No specific tracked branch, using #{branch}")
201
- else
202
- branch = s.stdout.strip
203
- SugarJar::Log.debug(
204
- "Using explicit tracked branch: #{branch}, use " +
205
- '`git branch -u` to change',
206
- )
207
- end
208
- branch
209
- end
210
-
211
- def most_main
212
- us = upstream
213
- if us
214
- "#{us}/#{main_branch}"
215
- else
216
- main_branch
217
- end
218
- end
219
-
220
- def upstream
221
- return @remote if @remote
222
-
223
- remotes = all_remotes
224
- SugarJar::Log.debug("remotes is #{remotes}")
225
- if remotes.empty?
226
- @remote = nil
227
- elsif remotes.length == 1
228
- @remote = remotes[0]
229
- elsif remotes.include?('upstream')
230
- @remote = 'upstream'
231
- elsif remotes.include?('origin')
232
- @remote = 'origin'
233
- else
234
- raise 'Could not determine "upstream" remote to use...'
235
- end
236
- @remote
237
- end
238
-
239
- # Whatever org we push to, regardless of if this is a fork or not
240
- def push_org
241
- url = git('remote', 'get-url', 'origin').stdout.strip
242
- extract_org(url)
243
- end
244
-
245
- def branch_from_ref(ref, type = :local)
246
- # local branches are refs/head/XXXX
247
- # remote branches are refs/remotes/<remote>/XXXX
248
- base = type == :local ? 2 : 3
249
- ref.split('/')[base..].join('/')
250
- end
251
-
252
- def color(string, *colors)
253
- if @color
254
- pastel.decorate(string, *colors)
255
- else
256
- string
257
- end
258
- end
259
-
260
- def pastel
261
- @pastel ||= begin
262
- require 'pastel'
263
- Pastel.new
264
- end
265
- end
266
-
267
- def gh_avail?
268
- !!which_nofail('gh')
269
- end
270
-
271
- def fprefix(name)
272
- return name unless @feature_prefix
273
-
274
- return name if name.start_with?(@feature_prefix)
275
- return name if all_local_branches.include?(name)
276
-
277
- newname = "#{@feature_prefix}#{name}"
278
- SugarJar::Log.debug(
279
- "Munging feature name: #{name} -> #{newname} due to feature prefix",
280
- )
281
- newname
282
- end
283
-
284
16
  # Finds the first entry in the path for a binary and checks
285
17
  # to make sure it's not us. Warn if it is us as that won't work in 2.x
286
- def which_nofail(cmd)
18
+ def self.which_nofail(cmd)
287
19
  ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
288
20
  p = File.join(dir, cmd)
289
21
  next unless File.exist?(p) && File.executable?(p)
@@ -299,43 +31,31 @@ class SugarJar
299
31
  false
300
32
  end
301
33
 
302
- def which(cmd)
303
- path = which_nofail(cmd)
304
- return path if path
305
-
306
- SugarJar::Log.fatal("Could not find #{cmd} in your path")
307
- exit(1)
308
- end
309
-
310
- def git_nofail(*args)
34
+ def self.git_nofail(*args, color: true)
311
35
  if %w{diff log grep branch}.include?(args[0]) &&
312
36
  args.none? { |x| x.include?('color') }
313
- args << (@color ? '--color' : '--no-color')
37
+ args << (color ? '--color' : '--no-color')
314
38
  end
315
39
  SugarJar::Log.trace("Running: git #{args.join(' ')}")
316
40
  Mixlib::ShellOut.new([which('git')] + args).run_command
317
41
  end
318
42
 
319
- def git(*args)
320
- s = git_nofail(*args)
43
+ def self.git(*, color: true)
44
+ s = git_nofail(*, :color => color)
321
45
  s.error!
322
46
  s
323
47
  end
324
48
 
325
- def ghcli_nofail(*args)
49
+ def self.ghcli_nofail(*args)
326
50
  SugarJar::Log.trace("Running: gh #{args.join(' ')}")
327
- s = Mixlib::ShellOut.new([which('gh')] + args).run_command
51
+ gh = which('gh')
52
+ s = Mixlib::ShellOut.new([gh] + args).run_command
328
53
  if s.error? && s.stderr.include?('gh auth')
329
54
  SugarJar::Log.info(
330
55
  'gh was run but no github token exists. Will run "gh auth login" ' +
331
56
  "to force\ngh to authenticate...",
332
57
  )
333
- ENV['GITHUB_HOST'] = @ghhost if @ghhost
334
- args = [
335
- which('gh'), 'auth', 'login', '-p', 'ssh'
336
- ]
337
- args + ['--hostname', @ghhost] if @ghhost
338
- unless system(which('gh'), 'auth', 'login', '-p', 'ssh')
58
+ unless system(gh, 'auth', 'login', '-p', 'ssh')
339
59
  SugarJar::Log.fatal(
340
60
  'That failed, I will bail out. Hub needs to get a github ' +
341
61
  'token. Try running "gh auth login" (will list info about ' +
@@ -347,28 +67,19 @@ class SugarJar
347
67
  s
348
68
  end
349
69
 
350
- def ghcli(*args)
351
- s = ghcli_nofail(*args)
70
+ def self.ghcli(*)
71
+ s = ghcli_nofail(*)
352
72
  s.error!
353
73
  s
354
74
  end
355
75
 
356
- def in_repo
76
+ def self.in_repo?
357
77
  s = git_nofail('rev-parse', '--is-inside-work-tree')
358
78
  !s.error? && s.stdout.strip == 'true'
359
79
  end
360
80
 
361
- def dirty?
362
- s = git_nofail('diff', '--quiet')
363
- s.error?
364
- end
365
-
366
- def repo_root
81
+ def self.repo_root
367
82
  git('rev-parse', '--show-toplevel').stdout.strip
368
83
  end
369
-
370
- def repo_name
371
- repo_root.split('/').last
372
- end
373
84
  end
374
85
  end
@@ -1,3 +1,3 @@
1
1
  class SugarJar
2
- VERSION = '2.0.0.beta.1'.freeze
2
+ VERSION = '2.0.1'.freeze
3
3
  end
data/sugarjar.gemspec CHANGED
@@ -8,14 +8,20 @@ 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
- # 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'
14
- docs = %w{README.md LICENSE Gemfile sugarjar.gemspec}
11
+ spec.required_ruby_version = '>= 3.2'
12
+ docs = %w{
13
+ README.md
14
+ LICENSE
15
+ Gemfile
16
+ sugarjar.gemspec
17
+ CONTRIBUTING.md
18
+ CHANGELOG.md
19
+ } + Dir.glob('examples/*')
15
20
  spec.extra_rdoc_files = docs
16
21
  spec.executables << 'sj'
17
22
  spec.files =
18
23
  Dir.glob('lib/sugarjar/*.rb') +
24
+ Dir.glob('lib/sugarjar/commands/*.rb') +
19
25
  Dir.glob('bin/*') +
20
26
  Dir.glob('extras/*')
21
27
 
@@ -28,7 +34,7 @@ Gem::Specification.new do |spec|
28
34
  'bug_tracker_uri' => 'https://github.com/jaymzh/sugarjar/issues',
29
35
  'changelog_uri' =>
30
36
  'https://github.com/jaymzh/sugarjar/blob/main/CHANGELOG.md',
31
- 'homepage_uri' => 'https://github.com/jaymzh/sugajar',
37
+ 'homepage_uri' => 'https://github.com/jaymzh/sugarjar',
32
38
  'source_code_uri' => 'https://github.com/jaymzh/sugarjar',
33
39
  }
34
40
  end
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: 2.0.0.beta.1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Dibowitz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-13 00:00:00.000000000 Z
11
+ date: 2025-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge
@@ -77,13 +77,32 @@ extra_rdoc_files:
77
77
  - LICENSE
78
78
  - Gemfile
79
79
  - sugarjar.gemspec
80
+ - CONTRIBUTING.md
81
+ - CHANGELOG.md
82
+ - examples/sample_config.yaml
83
+ - examples/sample_repoconfig.yaml
80
84
  files:
85
+ - CHANGELOG.md
86
+ - CONTRIBUTING.md
81
87
  - Gemfile
82
88
  - LICENSE
83
89
  - README.md
84
90
  - bin/sj
91
+ - examples/sample_config.yaml
92
+ - examples/sample_repoconfig.yaml
85
93
  - extras/sugarjar_completion.bash
86
94
  - lib/sugarjar/commands.rb
95
+ - lib/sugarjar/commands/amend.rb
96
+ - lib/sugarjar/commands/bclean.rb
97
+ - lib/sugarjar/commands/branch.rb
98
+ - lib/sugarjar/commands/checks.rb
99
+ - lib/sugarjar/commands/debuginfo.rb
100
+ - lib/sugarjar/commands/feature.rb
101
+ - lib/sugarjar/commands/pullsuggestions.rb
102
+ - lib/sugarjar/commands/push.rb
103
+ - lib/sugarjar/commands/smartclone.rb
104
+ - lib/sugarjar/commands/smartpullrequest.rb
105
+ - lib/sugarjar/commands/up.rb
87
106
  - lib/sugarjar/config.rb
88
107
  - lib/sugarjar/log.rb
89
108
  - lib/sugarjar/repoconfig.rb
@@ -97,7 +116,7 @@ metadata:
97
116
  rubygems_mfa_required: 'true'
98
117
  bug_tracker_uri: https://github.com/jaymzh/sugarjar/issues
99
118
  changelog_uri: https://github.com/jaymzh/sugarjar/blob/main/CHANGELOG.md
100
- homepage_uri: https://github.com/jaymzh/sugajar
119
+ homepage_uri: https://github.com/jaymzh/sugarjar
101
120
  source_code_uri: https://github.com/jaymzh/sugarjar
102
121
  post_install_message:
103
122
  rdoc_options: []
@@ -107,14 +126,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
126
  requirements:
108
127
  - - ">="
109
128
  - !ruby/object:Gem::Version
110
- version: '3.0'
129
+ version: '3.2'
111
130
  required_rubygems_version: !ruby/object:Gem::Requirement
112
131
  requirements:
113
- - - ">"
132
+ - - ">="
114
133
  - !ruby/object:Gem::Version
115
- version: 1.3.1
134
+ version: '0'
116
135
  requirements: []
117
- rubygems_version: 3.3.7
136
+ rubygems_version: 3.5.22
118
137
  signing_key:
119
138
  specification_version: 4
120
139
  summary: A git/github helper script