sugarjar 0.0.10 → 1.0.0
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 +4 -4
- data/README.md +85 -30
- data/bin/sj +48 -10
- data/lib/sugarjar/commands.rb +293 -60
- data/lib/sugarjar/config.rb +3 -2
- data/lib/sugarjar/util.rb +47 -3
- data/lib/sugarjar/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95e4979017c0ed58f99c446d9215a6b64aec7d5ebc22694a95903710d5af9d7e
|
4
|
+
data.tar.gz: b4b7a648bc7e8002e46dfbaa73cc52749cd38258b5782a2b33a6d66db98facfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e34735382f6646bf5fe1577eb6637ad7aaceaa9ccf2d2dad024d4a95f3e2a0e8ec080fe086fd5dae7354b3f15f83d26e6ae8b067a1fae9fb5b3da777f9e1f86
|
7
|
+
data.tar.gz: 155d1aa1c7148f2d7181678f64ef64b17fb5efc90386ce3bd27c2bcc7b256113680b4e69a16558790ab3c77080325fc36a56c9f3cc76cf4962f8f575cd00d5d7
|
data/README.md
CHANGED
@@ -3,10 +3,17 @@
|
|
3
3
|
[](https://github.com/jaymzh/sugarjar/actions?query=workflow%3ALint)
|
4
4
|
[](https://github.com/jaymzh/sugarjar/actions?query=workflow%3AUnittests)
|
5
5
|
[](https://github.com/jaymzh/sugarjar/actions?query=workflow%3A%22DCO+Check%22)
|
6
|
-
[](https://badge.fury.io/rb/sugarjar)
|
7
6
|
|
8
|
-
|
9
|
-
[
|
7
|
+
> [!IMPORTANT]
|
8
|
+
> You probably want to use [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, this is
|
12
|
+
> likely to be deprecated at some point. Sapling is far more feature rich,
|
13
|
+
> faster, and have more development resources behind them.
|
14
|
+
|
15
|
+
Welcome to SugarJar - a git/github helper. It needs one of the GitHub CLI's:
|
16
|
+
either [gh](https://cli.github.com/) or the older [hub](https://hub.github.com/).
|
10
17
|
|
11
18
|
SugarJar is inspired by [arcanist](https://github.com/phacility/arcanist), and
|
12
19
|
its replacement at Facebook, JellyFish. Many of the features they provide for
|
@@ -19,6 +26,30 @@ If you miss Mondrian or Phabricator - this is the tool for you!
|
|
19
26
|
|
20
27
|
If you don't, there's a ton of useful stuff for everyone!
|
21
28
|
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
Sugarjar is packaged in a variety of Linux distributions - see if it's on the
|
32
|
+
list here, and if so, use your package manager (or `gem`) to install it:
|
33
|
+
|
34
|
+
[](https://repology.org/project/sugarjar/versions)
|
35
|
+
|
36
|
+
For Ubuntu users, Sugarjar will likely be available starting in the upcoming
|
37
|
+
23.04 release. Until then, for supported LTS releases starting 20.04 (focal)
|
38
|
+
and the latest non-LTS release, you can use [this PPA](
|
39
|
+
https://launchpad.net/~michel-slm/+archive/ubuntu/sugarjar) maintained by the
|
40
|
+
Debian package maintainer.
|
41
|
+
|
42
|
+
Another option is to use our [omnibus
|
43
|
+
packages](https://github.com/jaymzh/sugarjar/releases). We keep Omnibus
|
44
|
+
packages for most distros that do not package Sugarjar. Omnibus packages are
|
45
|
+
distro packages (deb, rpm, etc.) that have all dependencies bundled up together
|
46
|
+
(including Ruby), and install in `/opt/sugarjar` allowing you to manage the
|
47
|
+
installation with your package manager, but with as a hermetically sealed app
|
48
|
+
that doesn't depend on the rest of your distro.
|
49
|
+
|
50
|
+
Finally, if none of those work for you, you can clone this repo and run it
|
51
|
+
directly from there.
|
52
|
+
|
22
53
|
## Auto cleanup squash-merged branches
|
23
54
|
|
24
55
|
It is common for a PR to go back and forth with a variety of nits, lint fixes,
|
@@ -73,7 +104,7 @@ This will:
|
|
73
104
|
* Clone your fork
|
74
105
|
* Add the original as an 'upstream' remote
|
75
106
|
|
76
|
-
Note that it takes
|
107
|
+
Note that it takes short names for repos. No need to specify a full URL,
|
77
108
|
just a $org/$repo.
|
78
109
|
|
79
110
|
Like `git clone`, `sj sclone` will accept an additional argument as the
|
@@ -198,6 +229,15 @@ smartlog` or `sj sl` for short.
|
|
198
229
|
|
199
230
|

|
200
231
|
|
232
|
+
## Pulling in suggestions from the web
|
233
|
+
|
234
|
+
When someone 'suggests' a change in the GitHub WebUI, once you choose to commit
|
235
|
+
them, your origin and local branches are no longer in-sync. The
|
236
|
+
`pullsuggestions` command will attempt to merge in any remote commits to your
|
237
|
+
local branch. This command will show a diff and ask for confirmation before
|
238
|
+
attempting the merge and - if allowed to continue - will use a fast-forward
|
239
|
+
merge.
|
240
|
+
|
201
241
|
## And more!
|
202
242
|
|
203
243
|
See `sj help` for more commands!
|
@@ -205,8 +245,11 @@ See `sj help` for more commands!
|
|
205
245
|
## Using SugarJar as a git wrapper
|
206
246
|
|
207
247
|
SugarJar, by default, will pass any command it doesn't know straight to `hub`
|
208
|
-
(which passes commands **it** doesn't know to `git`).
|
209
|
-
to `
|
248
|
+
(which passes commands **it** doesn't know to `git`). If you have configured
|
249
|
+
SugarJar to use `gh` instead of `hub`, then it will pass commands straight to
|
250
|
+
`git` since `gh` doesn't act as a `git` wrapper.
|
251
|
+
|
252
|
+
As such you can alias it to `git` and just have a super-git.
|
210
253
|
|
211
254
|
```shell
|
212
255
|
$ alias git=sj
|
@@ -248,8 +291,8 @@ log_level: debug
|
|
248
291
|
github_user: jaymzh
|
249
292
|
```
|
250
293
|
|
251
|
-
In addition, the environment variable `
|
252
|
-
|
294
|
+
In addition, the environment variable `SUGARJAR_LOGLEVEL` can be defined to set
|
295
|
+
a log level. This is primarily used as a way to turn debug on earlier in order to
|
253
296
|
troubleshoot configuration parsing.
|
254
297
|
|
255
298
|
## Repository Configuration
|
@@ -258,9 +301,15 @@ Sugarjar looks for a `.sugarjar.yaml` in the root of the repository to tell it
|
|
258
301
|
how to handle repo-specific things. Currently there options are:
|
259
302
|
|
260
303
|
* `lint` - A list of scripts to run on `sj lint`. These should be linters like
|
261
|
-
rubocop or pyflake.
|
304
|
+
rubocop or pyflake. Linters will be run from the root of the repo.
|
305
|
+
* `lint_list_cmd` - A command to run which will print out linters to run, one
|
306
|
+
per line. Takes precedence over `lint`. The command (and the resulting
|
307
|
+
linters) will be run from the root of the repo.
|
262
308
|
* `unit` - A list of scripts to run on `sj unit`. These should be unittest
|
263
|
-
runners like rspec or pyunit.
|
309
|
+
runners like rspec or pyunit. Test will be run from the root of the repo.
|
310
|
+
* `unit_list_cmd` - A command to run which will print out the unit tests to
|
311
|
+
run, one more line. Takes precedence over `unit`. The command (and the
|
312
|
+
resulting unit tests) will be run from the root of the repo.
|
264
313
|
* `on_push` - A list of types (`lint`, `unit`) of checks to run before pushing.
|
265
314
|
It is highly recommended this is only `lint`. The goal here is to allow for
|
266
315
|
the user to get quick stylistic feedback before pushing their branch to avoid
|
@@ -312,34 +361,40 @@ sj clone jaymzh/sugarjar --github-host githuh.com
|
|
312
361
|
We will add the `hub.host` to the `sugarjar` clone so that future `hub` or `sj`
|
313
362
|
commands work without needing to specify..
|
314
363
|
|
315
|
-
##
|
316
|
-
|
317
|
-
There are many ways to install SugarJar. The easiest is to use one of the
|
318
|
-
packages we provide in the
|
319
|
-
[releases](https://github.com/jaymzh/sugarjar/releases) section. Currently we
|
320
|
-
provide packages for Fedora, CentOS, Debian, and Ubuntu, but if you want
|
321
|
-
others, file an Issue. Since these packages are
|
322
|
-
[omnibus](https://github.com/chef/omnibus) packages which means they are bundled
|
323
|
-
with all of their dependencies. This means these packages will likely work as-is
|
324
|
-
on later releases of these distros or any similar distros.
|
364
|
+
## Choosing a GitHub CLI
|
325
365
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
366
|
+
SugarJar will use `gh` if it is available or otherwise fall back to `hub`. You
|
367
|
+
can override this by specifying `--github-cli` on the command line or setting
|
368
|
+
`github_cli` to either `gh` or `hub` (it defaults to `auto`) in your
|
369
|
+
configuration.
|
330
370
|
|
331
371
|
## FAQ
|
332
372
|
|
333
|
-
Why the name SugarJar
|
373
|
+
**Why the name SugarJar?**
|
334
374
|
|
335
|
-
It's mostly a
|
375
|
+
It's mostly a backronym. Like jellyfish, I wanted two letters that were on home
|
336
376
|
row on different sides of the keyboard to make it easy to type. I looked at the
|
337
377
|
possible options that where there and not taken and tried to find one I could
|
338
378
|
make an appropriate name out of. Since this utility adds lots of sugar to git
|
339
379
|
and github, it seemed appropriate.
|
340
380
|
|
341
|
-
Why did you use `hub` instead of the newer `gh` CLI
|
381
|
+
**Why did you originally use `hub` instead of the newer `gh` CLI?**
|
382
|
+
|
383
|
+
When I originally wrote SugarJar, `gh` was in early development, and `hub` had
|
384
|
+
many more features. In addition, I wrote SugarJar to be a wrapper for git/hub,
|
385
|
+
and `hub` allows this but `gh` does not.
|
386
|
+
|
387
|
+
When `gh` matured, we added experimental `gh` support in 0.0.11, and switched the
|
388
|
+
default to prefer `gh` in 1.0.0.
|
389
|
+
|
390
|
+
**I'd like to package SugarJar for my favorite distro/OS, is that OK?**
|
391
|
+
|
392
|
+
Of course! But I'd appreciate you emailing me to give me a heads up. Doing so
|
393
|
+
will allow me to make sure it shows up in the Repology badge above as well as
|
394
|
+
stop building Omnibus packages for whatever distro.
|
395
|
+
|
396
|
+
**What platforms does it work on?**
|
342
397
|
|
343
|
-
|
344
|
-
|
345
|
-
|
398
|
+
Since it's Ruby, it should work across all platforms, however, it's developed
|
399
|
+
and primarily tested on Linux as well as regularly used on Mac. I've not tested
|
400
|
+
it on Windows, but I'll happily accept patches for Windows compatibility.
|
data/bin/sj
CHANGED
@@ -29,12 +29,22 @@ parser = OptionParser.new do |opts|
|
|
29
29
|
opts.separator ''
|
30
30
|
opts.separator 'OPTIONS:'
|
31
31
|
|
32
|
-
opts.on('--[no-]fallthru', 'Fall-thru to git') do |fallthru|
|
32
|
+
opts.on('--[no-]fallthru', 'Fall-thru to git. [default: true]') do |fallthru|
|
33
33
|
options['fallthru'] = fallthru
|
34
34
|
end
|
35
35
|
|
36
|
-
opts.on('--
|
37
|
-
options['
|
36
|
+
opts.on('--feature-prefix', 'Prefix to use for feature branches') do |prefix|
|
37
|
+
options['feature_prefix'] = prefix
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on(
|
41
|
+
'--github-cli CLI',
|
42
|
+
%w{gh cli},
|
43
|
+
'Github CLI to use ("gh" or "hub" or "auto"). Auto (the default) will ' +
|
44
|
+
'prefer "gh" if it is available but will fall back to "hub." ' +
|
45
|
+
'[default: "auto"]',
|
46
|
+
) do |cli|
|
47
|
+
options['github_cli'] = cli
|
38
48
|
end
|
39
49
|
|
40
50
|
opts.on(
|
@@ -48,6 +58,10 @@ parser = OptionParser.new do |opts|
|
|
48
58
|
options['github_host'] = host
|
49
59
|
end
|
50
60
|
|
61
|
+
opts.on('--github-user USER', 'Github username') do |user|
|
62
|
+
options['github_user'] = user
|
63
|
+
end
|
64
|
+
|
51
65
|
opts.on('-h', '--help', 'Print this help message') do
|
52
66
|
puts opts
|
53
67
|
exit
|
@@ -55,22 +69,24 @@ parser = OptionParser.new do |opts|
|
|
55
69
|
|
56
70
|
opts.on(
|
57
71
|
'--ignore-dirty',
|
58
|
-
'Tell command that check for a dirty repo to carry on anyway.'
|
72
|
+
'Tell command that check for a dirty repo to carry on anyway. ' +
|
73
|
+
'[default: false]',
|
59
74
|
) do
|
60
75
|
options['ignore_dirty'] = true
|
61
76
|
end
|
62
77
|
|
63
78
|
opts.on(
|
64
79
|
'--ignore-prerun-failure',
|
65
|
-
'Ignore preprun failure on *push commands.',
|
80
|
+
'Ignore preprun failure on *push commands. [default: false]',
|
66
81
|
) do
|
67
82
|
options['ignore_prerun_failure'] = true
|
68
83
|
end
|
69
84
|
|
70
85
|
opts.on(
|
71
86
|
'--log-level LEVEL',
|
72
|
-
'Set logging level (fatal, error, warning, info, debug, trace).
|
73
|
-
'
|
87
|
+
'Set logging level (fatal, error, warning, info, debug, trace). This can ' +
|
88
|
+
'also be set via the SUGARJAR_LOGLEVEL environment variable. [default: ' +
|
89
|
+
'info]',
|
74
90
|
) do |level|
|
75
91
|
options['log_level'] = level
|
76
92
|
end
|
@@ -118,6 +134,12 @@ COMMANDS:
|
|
118
134
|
of preference it will be upstream/master, origin/master, master,
|
119
135
|
depending upon what remotes are available.
|
120
136
|
|
137
|
+
Note that you can specify "--feature-prefix" (or add
|
138
|
+
"feature_prefix" to your config) to have all features created
|
139
|
+
with a prefix. This is useful for branch-based workflows where
|
140
|
+
developers are expected to create branches names that, for
|
141
|
+
example, start with their username.
|
142
|
+
|
121
143
|
forcepush, fpush
|
122
144
|
The same as "smartpush", but uses "--force-with-lease". This is
|
123
145
|
a "safer" way of doing force-pushes and is the recommended way
|
@@ -128,6 +150,11 @@ COMMANDS:
|
|
128
150
|
lint
|
129
151
|
Run any linters configured in .sugarjar.yaml.
|
130
152
|
|
153
|
+
pullsuggestions, ps
|
154
|
+
Pull any suggestions *that have been committed* in the GitHub UI.
|
155
|
+
This will show the diff and prompt for confirmation before
|
156
|
+
merging. Note that a fast-forward merge will be used.
|
157
|
+
|
131
158
|
smartclone, sclone
|
132
159
|
A smart wrapper to "git clone" that handles forking and managing
|
133
160
|
remotes for you.
|
@@ -162,6 +189,10 @@ COMMANDS:
|
|
162
189
|
version
|
163
190
|
Print the version of sugarjar, and then run 'hub version'
|
164
191
|
to show the hub and git versions.
|
192
|
+
|
193
|
+
Be sure to checkout Sapling (https://sapling-scm.com/)! This was written as
|
194
|
+
a stop-gap to get Sapling features before it was open-sourced, and as such
|
195
|
+
I may deprecate this in the future.
|
165
196
|
COMMANDS
|
166
197
|
|
167
198
|
# rubocop:enable Layout/HeredocIndentation
|
@@ -232,7 +263,9 @@ else
|
|
232
263
|
end
|
233
264
|
end
|
234
265
|
|
235
|
-
|
266
|
+
subcommand = argv_copy.reject { |x| x.start_with?('-') }.first
|
267
|
+
|
268
|
+
if ARGV.empty? || !subcommand
|
236
269
|
puts parser
|
237
270
|
exit
|
238
271
|
end
|
@@ -243,7 +276,6 @@ options = config.merge(options)
|
|
243
276
|
SugarJar::Log.level = options['log_level'].to_sym if options['log_level']
|
244
277
|
sj = SugarJar::Commands.new(options)
|
245
278
|
|
246
|
-
subcommand = argv_copy.reject { |x| x.start_with?('-') }.first
|
247
279
|
is_valid_command = valid_commands.include?(subcommand.to_sym)
|
248
280
|
argv_copy.delete(subcommand)
|
249
281
|
SugarJar::Log.debug("subcommand is #{subcommand}")
|
@@ -265,7 +297,13 @@ if is_valid_command
|
|
265
297
|
sj.send(subcommand.to_sym, *extra_opts)
|
266
298
|
elsif options['fallthru']
|
267
299
|
SugarJar::Log.debug("Falling thru to: hub #{ARGV.join(' ')}")
|
268
|
-
|
300
|
+
if options['github_cli'] == 'hub'
|
301
|
+
exec('hub', *ARGV)
|
302
|
+
else
|
303
|
+
# If we're using 'gh', it doesn't have 'git fall thru' support, so
|
304
|
+
# we pass thru directly to 'git'
|
305
|
+
exec('git', *ARGV)
|
306
|
+
end
|
269
307
|
else
|
270
308
|
SugarJar::Log.error("No such subcommand: #{subcommand}")
|
271
309
|
end
|
data/lib/sugarjar/commands.rb
CHANGED
@@ -22,20 +22,29 @@ class SugarJar
|
|
22
22
|
@ignore_prerun_failure = options['ignore_prerun_failure']
|
23
23
|
@repo_config = SugarJar::RepoConfig.config
|
24
24
|
@color = options['color']
|
25
|
+
@feature_prefix = options['feature_prefix']
|
26
|
+
@checks = {}
|
27
|
+
@main_branch = nil
|
28
|
+
@main_remote_branches = {}
|
25
29
|
return if options['no_change']
|
26
30
|
|
27
|
-
|
31
|
+
# technically this doesn't "change" things, but we won't have this
|
32
|
+
# option on the no_change call
|
33
|
+
@cli = determine_cli(options['github_cli'])
|
34
|
+
|
35
|
+
set_hub_host
|
28
36
|
set_commit_template if @repo_config['commit_template']
|
29
37
|
end
|
30
38
|
|
31
39
|
def feature(name, base = nil)
|
32
40
|
assert_in_repo
|
33
41
|
SugarJar::Log.debug("Feature: #{name}, #{base}")
|
34
|
-
|
42
|
+
name = fprefix(name)
|
43
|
+
die("#{name} already exists!") if all_local_branches.include?(name)
|
35
44
|
base ||= most_main
|
36
45
|
base_pieces = base.split('/')
|
37
|
-
|
38
|
-
|
46
|
+
git('fetch', base_pieces[0]) if base_pieces.length > 1
|
47
|
+
git('checkout', '-b', name, base)
|
39
48
|
SugarJar::Log.info(
|
40
49
|
"Created feature branch #{color(name, :green)} based on " +
|
41
50
|
color(base, :green),
|
@@ -45,6 +54,7 @@ class SugarJar
|
|
45
54
|
def bclean(name = nil)
|
46
55
|
assert_in_repo
|
47
56
|
name ||= current_branch
|
57
|
+
name = fprefix(name) unless all_local_branches.include?(name)
|
48
58
|
if clean_branch(name)
|
49
59
|
SugarJar::Log.info("#{name}: #{color('reaped', :green)}")
|
50
60
|
else
|
@@ -58,7 +68,7 @@ class SugarJar
|
|
58
68
|
def bcleanall
|
59
69
|
assert_in_repo
|
60
70
|
curr = current_branch
|
61
|
-
|
71
|
+
all_local_branches.each do |branch|
|
62
72
|
if MAIN_BRANCHES.include?(branch)
|
63
73
|
SugarJar::Log.debug("Skipping #{branch}")
|
64
74
|
next
|
@@ -76,8 +86,8 @@ class SugarJar
|
|
76
86
|
end
|
77
87
|
|
78
88
|
# Return to the branch we were on, or main
|
79
|
-
if
|
80
|
-
|
89
|
+
if all_local_branches.include?(curr)
|
90
|
+
git('checkout', curr)
|
81
91
|
else
|
82
92
|
checkout_main_branch
|
83
93
|
end
|
@@ -85,18 +95,18 @@ class SugarJar
|
|
85
95
|
|
86
96
|
def co(*args)
|
87
97
|
assert_in_repo
|
88
|
-
s =
|
98
|
+
s = git('checkout', *args)
|
89
99
|
SugarJar::Log.info(s.stderr + s.stdout.chomp)
|
90
100
|
end
|
91
101
|
|
92
102
|
def br
|
93
103
|
assert_in_repo
|
94
|
-
SugarJar::Log.info(
|
104
|
+
SugarJar::Log.info(git('branch', '-v').stdout.chomp)
|
95
105
|
end
|
96
106
|
|
97
107
|
def binfo
|
98
108
|
assert_in_repo
|
99
|
-
SugarJar::Log.info(
|
109
|
+
SugarJar::Log.info(git(
|
100
110
|
'log', '--graph', '--oneline', '--decorate', '--boundary',
|
101
111
|
"#{tracked_branch}.."
|
102
112
|
).stdout.chomp)
|
@@ -105,7 +115,7 @@ class SugarJar
|
|
105
115
|
# binfo for all branches
|
106
116
|
def smartlog
|
107
117
|
assert_in_repo
|
108
|
-
SugarJar::Log.info(
|
118
|
+
SugarJar::Log.info(git(
|
109
119
|
'log', '--graph', '--oneline', '--decorate', '--boundary',
|
110
120
|
'--branches', "#{most_main}.."
|
111
121
|
).stdout.chomp)
|
@@ -142,24 +152,24 @@ class SugarJar
|
|
142
152
|
|
143
153
|
def qamend(*args)
|
144
154
|
assert_in_repo
|
145
|
-
SugarJar::Log.info(
|
155
|
+
SugarJar::Log.info(git('commit', '--amend', '--no-edit', *args).stdout)
|
146
156
|
end
|
147
157
|
|
148
158
|
alias amendq qamend
|
149
159
|
|
150
160
|
def upall
|
151
161
|
assert_in_repo
|
152
|
-
|
162
|
+
all_local_branches.each do |branch|
|
153
163
|
next if MAIN_BRANCHES.include?(branch)
|
154
164
|
|
155
|
-
|
165
|
+
git('checkout', branch)
|
156
166
|
result = gitup
|
157
167
|
if result['so'].error?
|
158
168
|
SugarJar::Log.error(
|
159
169
|
"#{color(branch, :red)} failed rebase. Reverting attempt and " +
|
160
170
|
'moving to next branch. Try `sj up` manually on that branch.',
|
161
171
|
)
|
162
|
-
|
172
|
+
git('rebase', '--abort')
|
163
173
|
else
|
164
174
|
SugarJar::Log.info(
|
165
175
|
"#{color(branch, :green)} rebased on " +
|
@@ -176,21 +186,42 @@ class SugarJar
|
|
176
186
|
|
177
187
|
reponame = File.basename(repo, '.git')
|
178
188
|
dir ||= reponame
|
189
|
+
org = extract_org(repo)
|
190
|
+
|
179
191
|
SugarJar::Log.info("Cloning #{reponame}...")
|
180
|
-
hub('clone', canonicalize_repo(repo), dir, *args)
|
181
192
|
|
193
|
+
# GH's 'fork' command (with the --clone arg) will fork, if necessary,
|
194
|
+
# then clone, and then setup the remotes with the appropriate names. So
|
195
|
+
# we just let it do all the work for us and return.
|
196
|
+
#
|
197
|
+
# Unless the repo is in our own org and cannot be forked, then it
|
198
|
+
# will fail.
|
199
|
+
if gh? && org != @ghuser
|
200
|
+
ghcli('repo', 'fork', '--clone', canonicalize_repo(repo), dir, *args)
|
201
|
+
SugarJar::Log.info('Remotes "origin" and "upstream" configured.')
|
202
|
+
return
|
203
|
+
end
|
204
|
+
|
205
|
+
# For 'hub' first we clone, using git, as 'hub' always needs a repo to
|
206
|
+
# operate on.
|
207
|
+
#
|
208
|
+
# Or for 'gh' when we can't fork...
|
209
|
+
git('clone', canonicalize_repo(repo), dir, *args)
|
210
|
+
|
211
|
+
# Then we go into it and attempt to use the 'fork' capability
|
212
|
+
# or if not
|
182
213
|
Dir.chdir dir do
|
183
214
|
# Now that we have a repo, if we have a hub host set it.
|
184
|
-
set_hub_host
|
215
|
+
set_hub_host
|
185
216
|
|
186
|
-
org = extract_org(repo)
|
187
217
|
SugarJar::Log.debug("Comparing org #{org} to ghuser #{@ghuser}")
|
188
218
|
if org == @ghuser
|
189
219
|
puts 'Cloned forked or self-owned repo. Not creating "upstream".'
|
220
|
+
SugarJar::Log.info('Remotes "origin" and "upstream" configured.')
|
190
221
|
return
|
191
222
|
end
|
192
223
|
|
193
|
-
s =
|
224
|
+
s = ghcli_nofail('repo', 'fork', '--remote-name=origin')
|
194
225
|
if s.error?
|
195
226
|
if s.stdout.include?('SAML enforcement')
|
196
227
|
SugarJar::Log.info(
|
@@ -199,18 +230,18 @@ class SugarJar
|
|
199
230
|
)
|
200
231
|
exit(1)
|
201
232
|
else
|
202
|
-
#
|
203
|
-
# already existed. If we got an error, but didn't recognize
|
204
|
-
# that, we'll assume that's what happened and try to add the
|
205
|
-
#
|
233
|
+
# gh as well as old versions of hub, it would fail if the upstream
|
234
|
+
# fork already existed. If we got an error, but didn't recognize
|
235
|
+
# that, we'll assume that's what happened and try to add the remote
|
236
|
+
# ourselves.
|
206
237
|
SugarJar::Log.info("Fork (#{@ghuser}/#{reponame}) detected.")
|
207
238
|
SugarJar::Log.debug(
|
208
239
|
'The above is a bit of a lie. "hub" failed to fork and it was ' +
|
209
240
|
'not a SAML error, so our best guess is that a fork exists ' +
|
210
241
|
'and so we will try to configure it.',
|
211
242
|
)
|
212
|
-
|
213
|
-
|
243
|
+
git('remote', 'rename', 'origin', 'upstream')
|
244
|
+
git('remote', 'add', 'origin', forked_repo(repo, @ghuser))
|
214
245
|
end
|
215
246
|
else
|
216
247
|
SugarJar::Log.info("Forked #{reponame} to #{@ghuser}")
|
@@ -247,11 +278,15 @@ class SugarJar
|
|
247
278
|
|
248
279
|
def version
|
249
280
|
puts "sugarjar version #{SugarJar::VERSION}"
|
250
|
-
puts
|
281
|
+
puts ghcli('version').stdout
|
282
|
+
# 'hub' prints the 'git' version, but gh doesn't, so if we're on 'gh'
|
283
|
+
# print out the git version directly
|
284
|
+
puts git('version').stdout if gh?
|
251
285
|
end
|
252
286
|
|
253
|
-
def smartpullrequest
|
287
|
+
def smartpullrequest(*args)
|
254
288
|
assert_in_repo
|
289
|
+
assert_common_main_branch
|
255
290
|
if dirty?
|
256
291
|
SugarJar::Log.warn(
|
257
292
|
'Your repo is dirty, so I am not going to create a pull request. ' +
|
@@ -259,14 +294,73 @@ class SugarJar
|
|
259
294
|
)
|
260
295
|
exit(1)
|
261
296
|
end
|
262
|
-
|
297
|
+
if gh?
|
298
|
+
SugarJar::Log.trace("Running: gh pr create #{args.join(' ')}")
|
299
|
+
system(which('gh'), 'pr', 'create', *args)
|
300
|
+
else
|
301
|
+
SugarJar::Log.trace("Running: hub pull-request #{args.join(' ')}")
|
302
|
+
system(which('hub'), 'pull-request', *args)
|
303
|
+
end
|
263
304
|
end
|
264
305
|
|
265
306
|
alias spr smartpullrequest
|
266
307
|
alias smartpr smartpullrequest
|
267
308
|
|
309
|
+
def pullsuggestions
|
310
|
+
assert_in_repo
|
311
|
+
|
312
|
+
if dirty?
|
313
|
+
if @ignore_dirty
|
314
|
+
SugarJar::Log.warn(
|
315
|
+
'Your repo is dirty, but --ignore-dirty was specified, so ' +
|
316
|
+
'carrying on anyway.',
|
317
|
+
)
|
318
|
+
else
|
319
|
+
SugarJar::Log.error(
|
320
|
+
'Your repo is dirty, so I am not going to push. Please commit ' +
|
321
|
+
'or amend first.',
|
322
|
+
)
|
323
|
+
exit(1)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
src = "origin/#{current_branch}"
|
328
|
+
fetch('origin')
|
329
|
+
diff = git('diff', src).stdout
|
330
|
+
return unless diff && !diff.empty?
|
331
|
+
|
332
|
+
puts "Will merge the following suggestions:\n\n#{diff}"
|
333
|
+
|
334
|
+
loop do
|
335
|
+
$stdout.print("\nAre you sure? [y/n] ")
|
336
|
+
ans = $stdin.gets.strip
|
337
|
+
case ans
|
338
|
+
when /^[Yy]$/
|
339
|
+
system(which('git'), 'merge', '--ff', "origin/#{current_branch}")
|
340
|
+
break
|
341
|
+
when /^[Nn]$/, /^[Qq](uit)?/
|
342
|
+
puts 'Not merging at user request...'
|
343
|
+
break
|
344
|
+
else
|
345
|
+
puts "Didn't understand '#{ans}'."
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
alias ps pullsuggestions
|
351
|
+
|
268
352
|
private
|
269
353
|
|
354
|
+
def fprefix(name)
|
355
|
+
return name unless @feature_prefix
|
356
|
+
|
357
|
+
newname = "#{@feature_prefix}#{name}"
|
358
|
+
SugarJar::Log.debug(
|
359
|
+
"Munging feature name: #{name} -> #{newname} due to feature prefix",
|
360
|
+
)
|
361
|
+
newname
|
362
|
+
end
|
363
|
+
|
270
364
|
def _smartpush(remote, branch, force)
|
271
365
|
unless remote && branch
|
272
366
|
remote ||= 'origin'
|
@@ -302,11 +396,11 @@ class SugarJar
|
|
302
396
|
|
303
397
|
args = ['push', remote, branch]
|
304
398
|
args << '--force-with-lease' if force
|
305
|
-
puts
|
399
|
+
puts git(*args).stderr
|
306
400
|
end
|
307
401
|
|
308
402
|
def dirty?
|
309
|
-
s =
|
403
|
+
s = git_nofail('diff', '--quiet')
|
310
404
|
s.error?
|
311
405
|
end
|
312
406
|
|
@@ -343,9 +437,9 @@ class SugarJar
|
|
343
437
|
end
|
344
438
|
|
345
439
|
def set_hub_host
|
346
|
-
return unless in_repo
|
440
|
+
return unless hub? && in_repo && @ghhost
|
347
441
|
|
348
|
-
s =
|
442
|
+
s = git_nofail('config', '--local', '--get', 'hub.host')
|
349
443
|
if s.error?
|
350
444
|
SugarJar::Log.info("Setting repo hub.host = #{@ghhost}")
|
351
445
|
else
|
@@ -363,7 +457,7 @@ class SugarJar
|
|
363
457
|
end
|
364
458
|
return
|
365
459
|
end
|
366
|
-
|
460
|
+
git('config', '--local', '--add', 'hub.host', @ghhost)
|
367
461
|
end
|
368
462
|
|
369
463
|
def set_commit_template
|
@@ -384,7 +478,7 @@ class SugarJar
|
|
384
478
|
)
|
385
479
|
end
|
386
480
|
|
387
|
-
s =
|
481
|
+
s = git_nofail('config', '--local', 'commit.template')
|
388
482
|
unless s.error?
|
389
483
|
current = s.stdout.strip
|
390
484
|
if current == @repo_config['commit_template']
|
@@ -402,18 +496,60 @@ class SugarJar
|
|
402
496
|
'Setting repo-specific commit template to ' +
|
403
497
|
"#{@repo_config['commit_template']} per sugarjar repo config.",
|
404
498
|
)
|
405
|
-
|
499
|
+
git(
|
406
500
|
'config', '--local', 'commit.template', @repo_config['commit_template']
|
407
501
|
)
|
408
502
|
end
|
409
503
|
|
410
|
-
def
|
411
|
-
unless @repo_config[type]
|
412
|
-
|
413
|
-
|
504
|
+
def get_checks_from_command(type)
|
505
|
+
return nil unless @repo_config["#{type}_list_cmd"]
|
506
|
+
|
507
|
+
cmd = @repo_config["#{type}_list_cmd"]
|
508
|
+
short = cmd.split.first
|
509
|
+
unless File.exist?(short)
|
510
|
+
SugarJar::Log.error(
|
511
|
+
"Configured #{type}_list_cmd #{short} does not exist!",
|
512
|
+
)
|
513
|
+
return false
|
514
|
+
end
|
515
|
+
s = Mixlib::ShellOut.new(cmd).run_command
|
516
|
+
if s.error?
|
517
|
+
SugarJar::Log.error(
|
518
|
+
"#{type}_list_cmd (#{cmd}) failed: #{s.format_for_exception}",
|
519
|
+
)
|
520
|
+
return false
|
521
|
+
end
|
522
|
+
s.stdout.split("\n")
|
523
|
+
end
|
524
|
+
|
525
|
+
# determine if we're using the _list_cmd and if so run it to get the
|
526
|
+
# checks, or just use the directly-defined check, and cache it
|
527
|
+
def get_checks(type)
|
528
|
+
return @checks[type] if @checks[type]
|
529
|
+
|
530
|
+
ret = get_checks_from_command(type)
|
531
|
+
if ret
|
532
|
+
SugarJar::Log.debug("Found #{type}s: #{ret}")
|
533
|
+
@checks[type] = ret
|
534
|
+
# if it's explicitly false, we failed to run the command
|
535
|
+
elsif ret == false
|
536
|
+
@checks[type] = false
|
537
|
+
# otherwise, we move on (basically: it's nil, there was no _list_cmd)
|
538
|
+
else
|
539
|
+
SugarJar::Log.debug("[#{type}]: using listed linters: #{ret}")
|
540
|
+
@checks[type] = @repo_config[type] || []
|
414
541
|
end
|
542
|
+
@checks[type]
|
543
|
+
end
|
544
|
+
|
545
|
+
def run_check(type)
|
415
546
|
Dir.chdir repo_root do
|
416
|
-
|
547
|
+
checks = get_checks(type)
|
548
|
+
# if we failed to determine the checks, the the checks have effectively
|
549
|
+
# failed
|
550
|
+
return false unless checks
|
551
|
+
|
552
|
+
checks.each do |check|
|
417
553
|
SugarJar::Log.debug("Running #{type} #{check}")
|
418
554
|
|
419
555
|
short = check.split.first
|
@@ -431,7 +567,7 @@ class SugarJar
|
|
431
567
|
SugarJar::Log.warn(
|
432
568
|
"The linter modified the repo. Here's the diff:\n",
|
433
569
|
)
|
434
|
-
puts
|
570
|
+
puts git('diff').stdout
|
435
571
|
loop do
|
436
572
|
$stdout.print(
|
437
573
|
"\nWould you like to\n\t[q]uit and inspect\n\t[a]mend the " +
|
@@ -483,16 +619,53 @@ class SugarJar
|
|
483
619
|
exit(1)
|
484
620
|
end
|
485
621
|
|
622
|
+
def assert_common_main_branch
|
623
|
+
upstream_branch = main_remote_branch(upstream)
|
624
|
+
unless main_branch == upstream_branch
|
625
|
+
die(
|
626
|
+
"The local main branch is '#{main_branch}', but the main branch " +
|
627
|
+
"of the #{upstream} remote is '#{upstream_branch}'. You probably " +
|
628
|
+
"want to rename your local branch by doing:\n\t" +
|
629
|
+
"git branch -m #{main_branch} #{upstream_branch}\n\t" +
|
630
|
+
"git fetch #{upstream}\n\t" +
|
631
|
+
"git branch -u #{upstream}/#{upstream_branch} #{upstream_branch}\n" +
|
632
|
+
"\tgit remote set-head #{upstream} -a",
|
633
|
+
)
|
634
|
+
end
|
635
|
+
return if upstream_branch == 'origin'
|
636
|
+
|
637
|
+
origin_branch = main_remote_branch('origin')
|
638
|
+
return if origin_branch == upstream_branch
|
639
|
+
|
640
|
+
die(
|
641
|
+
"The main branch of your upstream (#{upstream_branch}) and your " +
|
642
|
+
"fork/origin (#{origin_branch}) are not the same. You should go " +
|
643
|
+
"to https://#{@ghhost || 'github.com'}/#{@ghuser}/#{repo_name}/" +
|
644
|
+
'branches/ and rename the \'default\' branch to ' +
|
645
|
+
"'#{upstream_branch}'. It will then give you some commands to " +
|
646
|
+
'run to update this clone.',
|
647
|
+
)
|
648
|
+
end
|
649
|
+
|
486
650
|
def assert_in_repo
|
487
651
|
die('sugarjar must be run from inside a git repo') unless in_repo
|
488
652
|
end
|
489
653
|
|
654
|
+
def determine_main_branch(branches)
|
655
|
+
branches.include?('main') ? 'main' : 'master'
|
656
|
+
end
|
657
|
+
|
490
658
|
def main_branch
|
491
|
-
@main_branch =
|
659
|
+
@main_branch = determine_main_branch(all_local_branches)
|
660
|
+
end
|
661
|
+
|
662
|
+
def main_remote_branch(remote)
|
663
|
+
@main_remote_branches[remote] ||=
|
664
|
+
determine_main_branch(all_remote_branches(remote))
|
492
665
|
end
|
493
666
|
|
494
667
|
def checkout_main_branch
|
495
|
-
|
668
|
+
git('checkout', main_branch)
|
496
669
|
end
|
497
670
|
|
498
671
|
def clean_branch(name)
|
@@ -503,15 +676,25 @@ class SugarJar
|
|
503
676
|
|
504
677
|
SugarJar::Log.debug('branch deemed safe to delete...')
|
505
678
|
checkout_main_branch
|
506
|
-
|
679
|
+
git('branch', '-D', name)
|
507
680
|
gitup
|
508
681
|
true
|
509
682
|
end
|
510
683
|
|
511
|
-
def
|
684
|
+
def all_remote_branches(remote = 'origin')
|
685
|
+
branches = []
|
686
|
+
git('branch', '-r', '--format', '%(refname)').stdout.lines.each do |line|
|
687
|
+
next unless line.start_with?("refs/remotes/#{remote}/")
|
688
|
+
|
689
|
+
branches << branch_from_ref(line.strip, :remote)
|
690
|
+
end
|
691
|
+
branches
|
692
|
+
end
|
693
|
+
|
694
|
+
def all_local_branches
|
512
695
|
branches = []
|
513
|
-
|
514
|
-
branches << line.strip
|
696
|
+
git('branch', '--format', '%(refname)').stdout.lines.each do |line|
|
697
|
+
branches << branch_from_ref(line.strip)
|
515
698
|
end
|
516
699
|
branches
|
517
700
|
end
|
@@ -520,12 +703,12 @@ class SugarJar
|
|
520
703
|
# cherry -v will output 1 line per commit on the target branch
|
521
704
|
# prefixed by a - or + - anything with a - can be dropped, anything
|
522
705
|
# else cannot.
|
523
|
-
out =
|
706
|
+
out = git(
|
524
707
|
'cherry', '-v', tracked_branch, branch
|
525
708
|
).stdout.lines.reject do |line|
|
526
709
|
line.start_with?('-')
|
527
710
|
end
|
528
|
-
if out.
|
711
|
+
if out.empty?
|
529
712
|
SugarJar::Log.debug(
|
530
713
|
"cherry-pick shows branch #{branch} obviously safe to delete",
|
531
714
|
)
|
@@ -539,8 +722,8 @@ class SugarJar
|
|
539
722
|
# First we need a temp branch to work on
|
540
723
|
tmpbranch = "_sugar_jar.#{Process.pid}"
|
541
724
|
|
542
|
-
|
543
|
-
s =
|
725
|
+
git('checkout', '-b', tmpbranch, tracked_branch)
|
726
|
+
s = git_nofail('merge', '--squash', branch)
|
544
727
|
if s.error?
|
545
728
|
cleanup_tmp_branch(tmpbranch, branch)
|
546
729
|
SugarJar::Log.debug(
|
@@ -551,7 +734,7 @@ class SugarJar
|
|
551
734
|
return false
|
552
735
|
end
|
553
736
|
|
554
|
-
s =
|
737
|
+
s = git('diff', '--staged')
|
555
738
|
out = s.stdout
|
556
739
|
SugarJar::Log.debug("Squash-merged diff: #{out}")
|
557
740
|
cleanup_tmp_branch(tmpbranch, branch)
|
@@ -569,18 +752,22 @@ class SugarJar
|
|
569
752
|
end
|
570
753
|
|
571
754
|
def cleanup_tmp_branch(tmp, backto)
|
572
|
-
|
573
|
-
|
574
|
-
|
755
|
+
git('reset', '--hard', tracked_branch)
|
756
|
+
git('checkout', backto)
|
757
|
+
git('branch', '-D', tmp)
|
575
758
|
end
|
576
759
|
|
577
760
|
def current_branch
|
578
|
-
|
761
|
+
branch_from_ref(git('symbolic-ref', 'HEAD').stdout.strip)
|
579
762
|
end
|
580
763
|
|
581
764
|
def fetch_upstream
|
582
765
|
us = upstream
|
583
|
-
|
766
|
+
fetch(us) if us
|
767
|
+
end
|
768
|
+
|
769
|
+
def fetch(remote)
|
770
|
+
git('fetch', remote)
|
584
771
|
end
|
585
772
|
|
586
773
|
def gitup
|
@@ -598,7 +785,7 @@ class SugarJar
|
|
598
785
|
)
|
599
786
|
end
|
600
787
|
SugarJar::Log.debug('Rebasing')
|
601
|
-
s =
|
788
|
+
s = git_nofail('rebase', base)
|
602
789
|
{
|
603
790
|
'so' => s,
|
604
791
|
'base' => base,
|
@@ -606,7 +793,7 @@ class SugarJar
|
|
606
793
|
end
|
607
794
|
|
608
795
|
def tracked_branch
|
609
|
-
s =
|
796
|
+
s = git_nofail(
|
610
797
|
'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'
|
611
798
|
)
|
612
799
|
if s.error?
|
@@ -628,7 +815,7 @@ class SugarJar
|
|
628
815
|
def upstream
|
629
816
|
return @remote if @remote
|
630
817
|
|
631
|
-
s =
|
818
|
+
s = git('remote')
|
632
819
|
|
633
820
|
remotes = s.stdout.lines.map(&:strip)
|
634
821
|
SugarJar::Log.debug("remotes is #{remotes}")
|
@@ -646,6 +833,13 @@ class SugarJar
|
|
646
833
|
@remote
|
647
834
|
end
|
648
835
|
|
836
|
+
def branch_from_ref(ref, type = :local)
|
837
|
+
# local branches are refs/head/XXXX
|
838
|
+
# remote branches are refs/remotes/<remote>/XXXX
|
839
|
+
base = type == :local ? 2 : 3
|
840
|
+
ref.split('/')[base..].join('/')
|
841
|
+
end
|
842
|
+
|
649
843
|
def color(string, *colors)
|
650
844
|
if @color
|
651
845
|
pastel.decorate(string, *colors)
|
@@ -660,5 +854,44 @@ class SugarJar
|
|
660
854
|
Pastel.new
|
661
855
|
end
|
662
856
|
end
|
857
|
+
|
858
|
+
def determine_cli(cli)
|
859
|
+
return cli if %w{gh hub}.include?(cli)
|
860
|
+
|
861
|
+
die("'github_cli' has unknown setting: #{cli}") unless cli == 'auto'
|
862
|
+
|
863
|
+
SugarJar::Log.debug('github_cli set to auto')
|
864
|
+
|
865
|
+
if which_nofail('gh')
|
866
|
+
SugarJar::Log.debug('Found "gh"')
|
867
|
+
return 'gh'
|
868
|
+
end
|
869
|
+
if which_nofail('hub')
|
870
|
+
SugarJar::Log.debug('Did not find "gh" but did find "hub"')
|
871
|
+
return 'hub'
|
872
|
+
end
|
873
|
+
|
874
|
+
die(
|
875
|
+
'Neither "gh" nor "hub" found in PATH, please ensure at least one ' +
|
876
|
+
'of these utilities is in the PATH. If both are available you can ' +
|
877
|
+
'specify which to use with --github-cli',
|
878
|
+
)
|
879
|
+
end
|
880
|
+
|
881
|
+
def hub?
|
882
|
+
@cli == 'hub'
|
883
|
+
end
|
884
|
+
|
885
|
+
def gh?
|
886
|
+
@cli == 'gh'
|
887
|
+
end
|
888
|
+
|
889
|
+
def ghcli_nofail(*args)
|
890
|
+
gh? ? gh_nofail(*args) : hub_nofail(*args)
|
891
|
+
end
|
892
|
+
|
893
|
+
def ghcli(*args)
|
894
|
+
gh? ? gh(*args) : hub(*args)
|
895
|
+
end
|
663
896
|
end
|
664
897
|
end
|
data/lib/sugarjar/config.rb
CHANGED
@@ -6,14 +6,15 @@ class SugarJar
|
|
6
6
|
# This is stuff like log level, github-user, etc.
|
7
7
|
class Config
|
8
8
|
DEFAULTS = {
|
9
|
-
'
|
9
|
+
'github_cli' => 'auto',
|
10
|
+
'github_user' => ENV.fetch('USER'),
|
10
11
|
'fallthru' => true,
|
11
12
|
}.freeze
|
12
13
|
|
13
14
|
def self._find_ordered_files
|
14
15
|
[
|
15
16
|
'/etc/sugarjar/config.yaml',
|
16
|
-
"#{
|
17
|
+
"#{Dir.home}/.config/sugarjar/config.yaml",
|
17
18
|
].select { |f| File.exist?(f) }
|
18
19
|
end
|
19
20
|
|
data/lib/sugarjar/util.rb
CHANGED
@@ -26,11 +26,25 @@ class SugarJar
|
|
26
26
|
exit(1)
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def git_nofail(*args)
|
30
30
|
if %w{diff log grep branch}.include?(args[0]) &&
|
31
31
|
args.none? { |x| x.include?('color') }
|
32
32
|
args << (@color ? '--color' : '--no-color')
|
33
33
|
end
|
34
|
+
SugarJar::Log.trace("Running: git #{args.join(' ')}")
|
35
|
+
Mixlib::ShellOut.new([which('git')] + args).run_command
|
36
|
+
end
|
37
|
+
|
38
|
+
def git(*args)
|
39
|
+
s = git_nofail(*args)
|
40
|
+
s.error!
|
41
|
+
s
|
42
|
+
end
|
43
|
+
|
44
|
+
def hub_nofail(*args)
|
45
|
+
# this allows us to use 'hub' stuff that's top-level, but is under
|
46
|
+
# repo for this.
|
47
|
+
args.delete_at(0) if args[0] == 'repo'
|
34
48
|
SugarJar::Log.trace("Running: hub #{args.join(' ')}")
|
35
49
|
s = Mixlib::ShellOut.new([which('hub')] + args).run_command
|
36
50
|
if s.error?
|
@@ -84,13 +98,43 @@ class SugarJar
|
|
84
98
|
s
|
85
99
|
end
|
86
100
|
|
101
|
+
def gh_nofail(*args)
|
102
|
+
SugarJar::Log.trace("Running: gh #{args.join(' ')}")
|
103
|
+
s = Mixlib::ShellOut.new([which('gh')] + args).run_command
|
104
|
+
if s.error? && s.stderr.include?('gh auth')
|
105
|
+
SugarJar::Log.info(
|
106
|
+
'gh was run but no github token exists. Will run "gh auth login" ' +
|
107
|
+
"to force\ngh to authenticate...",
|
108
|
+
)
|
109
|
+
unless system(which('gh'), 'auth', 'login', '-p', 'ssh')
|
110
|
+
SugarJar::Log.fatal(
|
111
|
+
'That failed, I will bail out. Hub needs to get a github ' +
|
112
|
+
'token. Try running "gh auth login" (will list info about ' +
|
113
|
+
'your account) and try this again when that works.',
|
114
|
+
)
|
115
|
+
exit(1)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
s
|
119
|
+
end
|
120
|
+
|
121
|
+
def gh(*args)
|
122
|
+
s = gh_nofail(*args)
|
123
|
+
s.error!
|
124
|
+
s
|
125
|
+
end
|
126
|
+
|
87
127
|
def in_repo
|
88
|
-
s =
|
128
|
+
s = git_nofail('rev-parse', '--is-inside-work-tree')
|
89
129
|
!s.error? && s.stdout.strip == 'true'
|
90
130
|
end
|
91
131
|
|
92
132
|
def repo_root
|
93
|
-
|
133
|
+
git('rev-parse', '--show-toplevel').stdout.strip
|
134
|
+
end
|
135
|
+
|
136
|
+
def repo_name
|
137
|
+
repo_root.split('/').last
|
94
138
|
end
|
95
139
|
end
|
96
140
|
end
|
data/lib/sugarjar/version.rb
CHANGED
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: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Phil Dibowitz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mixlib-log
|
@@ -95,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
requirements: []
|
98
|
-
rubygems_version: 3.3.
|
98
|
+
rubygems_version: 3.3.7
|
99
99
|
signing_key:
|
100
100
|
specification_version: 4
|
101
101
|
summary: A git/github helper script
|