sugarjar 1.1.2 → 1.1.3

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: 4263a42ebb922645e2e0735c3ca33ad94df880fb01f881b2cacb602d733c533e
4
- data.tar.gz: 616fb99c535c491324c1dcc4906b37c8cb424566b62dc64377c61b9a5ef5fd49
3
+ metadata.gz: c689945af0d2bfb7b38477d19da9f58503a15b7be931ab021c4a121a07e6198c
4
+ data.tar.gz: e5fb66f22db68dce1ef31199ea688ff768d753b5df65bc8479744c010d4072c3
5
5
  SHA512:
6
- metadata.gz: 1d918daf7096d1889bf72ee0eca74ef473234ed1ed46e4275418028e9a32c9284b4412ff202a932a3cc43c777bbf55d1455ce8fd8805c965184e4d2bc740e527
7
- data.tar.gz: 0657a6629d97623d40f68d0ffe7a3e0522c951d9b22dc0c7b4b918d78eb27b026ab68d347b1c2fa68661536eceef9cbf3de3ee82b4ea4381da2675f1d34b3f2d
6
+ metadata.gz: 9979e5aa13fd2a176cc5a391b9aef8353c1ddb7e63392ab6291f1781c3a99c39f9e4415a3c8cf02720ed2e0c6683a470978ba4ded3be9f2bb993120980a34863
7
+ data.tar.gz: 81ba9f2079a9cc6a88e9052092795c722f9a48bd6f9d763ddc33dddd48fbde65049a16dca2ca66ad39d2a33f179d175a712d22517e6e8103a5089a8d26d9592d
data/README.md CHANGED
@@ -123,34 +123,142 @@ to `git clone` under the hood.
123
123
  ## Work with stacked branches more easily
124
124
 
125
125
  It's important to break changes into reviewable chunks, but working with
126
- stacked branches can be confusing. Enter `binfo` - it gives you a view of your
127
- current branch all the way up to master. In this example imagine we have a
128
- branch structure like:
126
+ stacked branches can be confusing. SugarJar provides several tools to make this
127
+ easier.
129
128
 
130
- ```text
131
- +- test2.1
132
- /
133
- master --- test --- test2 --- test3
129
+ First, and foremost, is `feature` and `subfeature`. Regardless of stacking, the
130
+ way to create a new feature bracnh with sugarjar is with `sj feature` (or `sj
131
+ f` for short):
132
+
133
+ ```shell
134
+ $ sj feature mynewthing
135
+ Created feature branch mynewthing based on origin/main
134
136
  ```
135
137
 
136
- This is what `binfo` on test3 looks like:
138
+ A "feature" in SugarJar parliance just means that the branch is always created
139
+ from "most_main" - this is usually "upstream/main", but SJ will figure out
140
+ which remote is the "upstream", even if it's "origin", and then will determine
141
+ the primary branch ("main" or for older repos "master"). It's also smart enough
142
+ to fetch that remote first to make sure you're working on the latest HEAD.
143
+
144
+ When you want to create a stacked PR, you can create "subfeature", which, at
145
+ its core is just a branch created from the current branch:
137
146
 
138
147
  ```shell
139
- $ sj binfo
140
- * e451865 (HEAD -> test3) test3
141
- * e545b41 (test2) test2
142
- * c808eae (test1) test1
143
- o 44cf9e2 (origin/master, origin/HEAD, master) Lint/gemspec cleanups
148
+ $ sj subfeature dependentnewthing
149
+ Created feature branch dependentnewthing based on mynewthing
144
150
  ```
145
151
 
146
- while `binfo` on test2.1 looks like:
152
+ If you create branches like this then sugarjar can now make several things
153
+ much easier:
147
154
 
148
- ```shell
149
- $ sj binfo
150
- * 36d0136 (HEAD -> test2.1) test2.1
151
- * e545b41 (test2) test2
152
- * c808eae (test1) test1
153
- o 44cf9e2 (origin/master, origin/HEAD, master) Lint/gemspec cleanups
155
+ * `sj up` will rebase intelligently
156
+ * After an `sj bclean` of a branch earlier in the tree, `sj up` will update
157
+ the tracked branch to "most_main"
158
+
159
+ There are two commands that will show you the state of your stacked branches:
160
+
161
+ * `sj binfo` - shows the current branch and its ancestors up to your primary branch
162
+ * `sj smartlist` (aka `sj sl`) - shows you the whole tree.
163
+
164
+ To continue with the example above, my `smartlist` might look like:
165
+
166
+ ```text
167
+ $ sj sl
168
+ * 59c0522 (HEAD -> dependentnewthing) anothertest
169
+ * 6ebaa28 (mynewthing) test
170
+ o 7a0ffd0 (tag: v1.1.2, origin/main, origin/HEAD, main) Version bump (#160)
171
+ ```
172
+
173
+ This is simple. Now lets make a different feature stack:
174
+
175
+ ```text
176
+ $ sj feature anotherfeature
177
+ Created feature branch anotherfeature based on origin/main
178
+ # do stuff
179
+ $ sj subfeature dependent2
180
+ Created feature branch dependent2 based on anotherfeature
181
+ # do stuff
182
+ ```
183
+
184
+ The `smartlist` will now show us this tree, and it's a bit more interesting:
185
+
186
+ ```text
187
+ $ sj sl
188
+ * af6f143 (HEAD -> dependent2) morestuff
189
+ * 028c7f4 (anotherfeature) stuff
190
+ | * 59c0522 (dependentnewthing) anothertest
191
+ | * 6ebaa28 (mynewthing) test
192
+ |/
193
+ o 7a0ffd0 (tag: v1.1.2, origin/main, origin/HEAD, main) Version bump (#160)
194
+ ```
195
+
196
+ Now, what happens if I make a change to `mynewthing`?
197
+
198
+ ```text
199
+ $ sj co mynewthing
200
+ Switched to branch 'mynewthing'
201
+ Your branch is ahead of 'origin/main' by 1 commit.
202
+ (use "git push" to publish your local commits)
203
+ $ echo 'randomchange' >> README.md
204
+ $ git commit -a -m change
205
+ [mynewthing d33e082] change
206
+ 1 file changed, 1 insertion(+)
207
+ $ sj sl
208
+ * d33e082 (HEAD -> mynewthing) change
209
+ | * af6f143 (dependent2) morestuff
210
+ | * 028c7f4 (anotherfeature) stuff
211
+ | | * 59c0522 (dependentnewthing) anothertest
212
+ | |/
213
+ |/|
214
+ * | 6ebaa28 test
215
+ |/
216
+ o 7a0ffd0 (tag: v1.1.2, origin/main, origin/HEAD, main) Version bump (#160)
217
+ ```
218
+
219
+ We can see here now that `dependentnewthing`, is based off a commit that _used_
220
+ to be `mynewthing`, but `mynewthing` has moved. But SugarJar will handle this
221
+ all correctly when we ask it to update the branch:
222
+
223
+ ```text
224
+ $ sj co dependentnewthing
225
+ Switched to branch 'dependentnewthing'
226
+ Your branch and 'mynewthing' have diverged,
227
+ and have 1 and 1 different commits each, respectively.
228
+ (use "git pull" if you want to integrate the remote branch with yours)
229
+ $ sj up
230
+ dependentnewthing rebased on mynewthing
231
+ $ sj sl
232
+ * 93ed585 (HEAD -> dependentnewthing) anothertest
233
+ * d33e082 (mynewthing) change
234
+ * 6ebaa28 test
235
+ | * af6f143 (dependent2) morestuff
236
+ | * 028c7f4 (anotherfeature) stuff
237
+ |/
238
+ o 7a0ffd0 (tag: v1.1.2, origin/main, origin/HEAD, main) Version bump (#160)
239
+ ```
240
+
241
+ Now, lets say that `mynewthing` gets merged and we use `bclean` to clean it all
242
+ up, what happens then?
243
+
244
+ ```text
245
+ $ sj up
246
+ The brach we were tracking is gone, resetting tracking to origin/main
247
+ dependentnewthing rebased on origin/main
248
+ ```
249
+
250
+ ### Creating Stacked PRs with subfeatures
251
+
252
+ When dependent branches are created with `subfeature`, when you create a PR,
253
+ SugarJar will automatically set the 'base' of the PR to the parent branch. By
254
+ default it'll prompt you about this, but you can set `pr_autostack` to `true`
255
+ in your config to tell it to always do this (or `false` to never do this):
256
+
257
+ ```text
258
+ $ sj spr
259
+ Autofilling in PR from commit message
260
+ It looks like this is a subfeature, would you like to base this PR on mynewthing? [y/n] y
261
+ ...
154
262
  ```
155
263
 
156
264
  ## Have a better lint/unittest experience!
data/bin/sj CHANGED
@@ -93,8 +93,8 @@ parser = OptionParser.new do |opts|
93
93
 
94
94
  opts.on(
95
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]',
96
+ 'When creating a PR, auto fill the title & description from the top ' +
97
+ 'commit if we are using "gh". [default: true]',
98
98
  ) do |autofill|
99
99
  options['pr_autofill'] = autofill
100
100
  end
@@ -104,7 +104,7 @@ parser = OptionParser.new do |opts|
104
104
  'When creating a PR, if this is a subfeature, should we make it a ' +
105
105
  'PR on the PR for the parent feature. If not specified, we prompt ' +
106
106
  'when this happens, when true always do this, when false never do ' +
107
- 'this. Only applicable when usiing "gh".',
107
+ 'this. Only applicable when usiing "gh" and on branch-based PRs.',
108
108
  ) do |autostack|
109
109
  options['pr_autostack'] = autostack
110
110
  end
@@ -334,31 +334,40 @@ class SugarJar
334
334
  curr = current_branch
335
335
  base = tracked_branch
336
336
  if @pr_autofill
337
+ SugarJar::Log.info('Autofilling in PR from commit message')
337
338
  num_commits = git(
338
339
  'rev-list', '--count', curr, "^#{base}"
339
340
  ).stdout.strip.to_i
340
341
  if num_commits > 1
341
- SugarJar::Log.debug(
342
- "Not using --fill because there are #{num_commits} commits",
343
- )
342
+ args.unshift('--fill-first')
344
343
  else
345
- SugarJar::Log.info('Autofilling in PR from commit message')
346
344
  args.unshift('--fill')
347
345
  end
348
346
  end
349
347
  if subfeature?(base)
348
+ if upstream != push_org
349
+ SugarJar::Log.warn(
350
+ 'Unfortunately you cannot based one PR on another PR when' +
351
+ " using fork-based PRs. We will base this on #{most_main}." +
352
+ ' This just means the PR "Changes" tab will show changes for' +
353
+ ' the full stack until those other PRs are merged and this PR' +
354
+ ' PR is rebased.',
355
+ )
350
356
  # nil is prompt, true is always, false is never
351
- if @pr_autostack.nil?
357
+ elsif @pr_autostack.nil?
352
358
  $stdout.print(
353
359
  'It looks like this is a subfeature, would you like to base ' +
354
360
  "this PR on #{base}? [y/n] ",
355
361
  )
356
362
  ans = $stdin.gets.strip
357
- args += ['--base', base] if %w{Y y}.include?(ans)
363
+ args.unshift('--base', base) if %w{Y y}.include?(ans)
358
364
  elsif @pr_autostack
359
- args += ['--base', base]
365
+ args.unshift('--base', base)
360
366
  end
361
367
  end
368
+ # <org>:<branch> is the GH API syntax for:
369
+ # look for a branch of name <branch>, from a fork in owner <org>
370
+ args.unshift('--head', "#{push_org}:#{curr}")
362
371
  SugarJar::Log.trace("Running: gh pr create #{args.join(' ')}")
363
372
  system(which('gh'), 'pr', 'create', *args)
364
373
  else
@@ -482,6 +491,10 @@ class SugarJar
482
491
  end
483
492
  end
484
493
 
494
+ def extract_repo(repo)
495
+ File.basename(repo, '.git')
496
+ end
497
+
485
498
  def forked_repo(repo, username)
486
499
  repo = if repo.start_with?('http', 'git@')
487
500
  File.basename(repo)
@@ -898,15 +911,21 @@ class SugarJar
898
911
  end
899
912
 
900
913
  def tracked_branch(fallback: true)
914
+ branch = nil
901
915
  s = git_nofail(
902
916
  'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'
903
917
  )
904
918
  if s.error?
905
- fallback ? most_main : nil
906
-
919
+ branch = fallback ? most_main : nil
920
+ SugarJar::Log.debug("No specific tracked branch, using #{branch}")
907
921
  else
908
- s.stdout.strip
922
+ branch = s.stdout.strip
923
+ SugarJar::Log.debug(
924
+ "Using explicit tracked branch: #{branch}, use " +
925
+ '`git branch -u` to change',
926
+ )
909
927
  end
928
+ branch
910
929
  end
911
930
 
912
931
  def most_main
@@ -937,6 +956,12 @@ class SugarJar
937
956
  @remote
938
957
  end
939
958
 
959
+ # Whatever org we push to, regardless of if this is a fork or not
960
+ def push_org
961
+ url = git('remote', 'get-url', 'origin').stdout.strip
962
+ extract_org(url)
963
+ end
964
+
940
965
  def branch_from_ref(ref, type = :local)
941
966
  # local branches are refs/head/XXXX
942
967
  # remote branches are refs/remotes/<remote>/XXXX
@@ -1,3 +1,3 @@
1
1
  class SugarJar
2
- VERSION = '1.1.2'.freeze
2
+ VERSION = '1.1.3'.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.2
4
+ version: 1.1.3
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-04-26 00:00:00.000000000 Z
11
+ date: 2025-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge