sugarjar 1.1.1 → 1.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc16295007c8698083a182a521c68481b3cb421644def0115aa04286867dd1eb
4
- data.tar.gz: c901d92e5d7d5287472f52cf56a83d29a5b1b4b0248232278b36e1706bc7117d
3
+ metadata.gz: 4263a42ebb922645e2e0735c3ca33ad94df880fb01f881b2cacb602d733c533e
4
+ data.tar.gz: 616fb99c535c491324c1dcc4906b37c8cb424566b62dc64377c61b9a5ef5fd49
5
5
  SHA512:
6
- metadata.gz: 6d64d758a56feac59e5617544cdde17341c804a8831524c49222f6397e47e886ed16f42280d60584a5231d279410839bdacebda66827ae77bb115addb24f3b6d
7
- data.tar.gz: e65b75d83d852906c713f00d6424a76897177f39eb1f2eaa0b5d17896b6d2fb288de3d1cf0946f5587f5674819a074782279ecdb26094c8038d221fcd7ceab0f
6
+ metadata.gz: 1d918daf7096d1889bf72ee0eca74ef473234ed1ed46e4275418028e9a32c9284b4412ff202a932a3cc43c777bbf55d1455ce8fd8805c965184e4d2bc740e527
7
+ data.tar.gz: 0657a6629d97623d40f68d0ffe7a3e0522c951d9b22dc0c7b4b918d78eb27b026ab68d347b1c2fa68661536eceef9cbf3de3ee82b4ea4381da2675f1d34b3f2d
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.
@@ -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,11 +147,14 @@ 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?
143
160
  backout = ''
@@ -156,6 +173,8 @@ class SugarJar
156
173
  SugarJar::Log.info(
157
174
  "#{color(current_branch, :green)} rebased on #{result['base']}",
158
175
  )
176
+ # go back to where we were if we rebased a different branch
177
+ git('checkout', curr) if branch != curr
159
178
  end
160
179
  end
161
180
 
@@ -302,6 +321,7 @@ class SugarJar
302
321
  def smartpullrequest(*args)
303
322
  assert_in_repo
304
323
  assert_common_main_branch
324
+
305
325
  if dirty?
306
326
  SugarJar::Log.warn(
307
327
  'Your repo is dirty, so I am not going to create a pull request. ' +
@@ -309,9 +329,38 @@ class SugarJar
309
329
  )
310
330
  exit(1)
311
331
  end
332
+
312
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
313
362
  SugarJar::Log.trace("Running: gh pr create #{args.join(' ')}")
314
- system(which('gh'), 'pr', 'create', '--fill', *args)
363
+ system(which('gh'), 'pr', 'create', *args)
315
364
  else
316
365
  SugarJar::Log.trace("Running: hub pull-request #{args.join(' ')}")
317
366
  system(which('hub'), 'pull-request', *args)
@@ -341,7 +390,7 @@ class SugarJar
341
390
 
342
391
  src = "origin/#{current_branch}"
343
392
  fetch('origin')
344
- diff = git('diff', src).stdout
393
+ diff = git('diff', "..#{src}").stdout
345
394
  return unless diff && !diff.empty?
346
395
 
347
396
  puts "Will merge the following suggestions:\n\n#{diff}"
@@ -369,6 +418,9 @@ class SugarJar
369
418
  def fprefix(name)
370
419
  return name unless @feature_prefix
371
420
 
421
+ return name if name.start_with?(@feature_prefix)
422
+ return name if all_local_branches.include?(name)
423
+
372
424
  newname = "#{@feature_prefix}#{name}"
373
425
  SugarJar::Log.debug(
374
426
  "Munging feature name: #{name} -> #{newname} due to feature prefix",
@@ -712,11 +764,15 @@ class SugarJar
712
764
  end
713
765
 
714
766
  def all_local_branches
715
- branches = []
716
- git('branch', '--format', '%(refname)').stdout.lines.each do |line|
717
- branches << branch_from_ref(line.strip)
767
+ git(
768
+ 'branch', '--format', '%(refname)'
769
+ ).stdout.lines.map do |line|
770
+ branch_from_ref(line.strip)
718
771
  end
719
- branches
772
+ end
773
+
774
+ def all_remotes
775
+ git('remote').stdout.lines.map(&:strip)
720
776
  end
721
777
 
722
778
  def safe_to_clean(branch)
@@ -794,14 +850,28 @@ class SugarJar
794
850
  SugarJar::Log.debug('Fetching upstream')
795
851
  fetch_upstream
796
852
  curr = current_branch
797
- 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
798
868
  if !MAIN_BRANCHES.include?(curr) && base == "origin/#{curr}"
799
869
  SugarJar::Log.warn(
800
870
  "This branch is tracking origin/#{curr}, which is probably your " +
801
871
  'downstream (where you push _to_) as opposed to your upstream ' +
802
872
  '(where you pull _from_). This means that "sj up" is probably ' +
803
873
  'rebasing on the wrong thing and doing nothing. You probably want ' +
804
- 'to do a "git branch -u upstream".',
874
+ "to do a 'git branch -u #{most_main}'.",
805
875
  )
806
876
  end
807
877
  SugarJar::Log.debug('Rebasing')
@@ -812,6 +882,12 @@ class SugarJar
812
882
  }
813
883
  end
814
884
 
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
+
815
891
  def rebase_in_progress?
816
892
  # for rebase without -i
817
893
  rebase_file = git('rev-parse', '--git-path', 'rebase-apply').stdout.strip
@@ -821,12 +897,13 @@ class SugarJar
821
897
  File.exist?(rebase_file) || File.exist?(rebase_merge_file)
822
898
  end
823
899
 
824
- def tracked_branch
900
+ def tracked_branch(fallback: true)
825
901
  s = git_nofail(
826
902
  'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'
827
903
  )
828
904
  if s.error?
829
- most_main
905
+ fallback ? most_main : nil
906
+
830
907
  else
831
908
  s.stdout.strip
832
909
  end
@@ -844,9 +921,7 @@ class SugarJar
844
921
  def upstream
845
922
  return @remote if @remote
846
923
 
847
- s = git('remote')
848
-
849
- remotes = s.stdout.lines.map(&:strip)
924
+ remotes = all_remotes
850
925
  SugarJar::Log.debug("remotes is #{remotes}")
851
926
  if remotes.empty?
852
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
@@ -1,3 +1,3 @@
1
1
  class SugarJar
2
- VERSION = '1.1.1'.freeze
2
+ VERSION = '1.1.2'.freeze
3
3
  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: 1.1.1
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: 2024-02-13 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