sugarjar 0.0.9 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +73 -13
- data/bin/sj +31 -6
- data/lib/sugarjar/commands.rb +309 -86
- data/lib/sugarjar/config.rb +3 -2
- data/lib/sugarjar/util.rb +47 -3
- data/lib/sugarjar/version.rb +1 -1
- data/sugarjar.gemspec +3 -0
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f4c70f80f34b048ba0d6b526e5eb20fcc51164b8ef78412a38ad5c953296898
|
4
|
+
data.tar.gz: 53958fab72a6c93d35617b63ffdb178cddcf1f97837a321533836896b0336c8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b3c546fe02babc8b186cf4f5de2d6a2716e371228af676dd5550d56b1f17db9d310d135f47a1905e77a98ed32ebd6716292bc19059a1e6e9e4733f725422900
|
7
|
+
data.tar.gz: 37df61e3b4161c2737dcf6392b5db3dcb8feef5d402868b48d6f28db9cb2254ddaf9b39d2719ea88071c4f37feb32efd9d327c105c3dcde428f495957e85913e
|
data/LICENSE
CHANGED
@@ -186,7 +186,7 @@
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
187
187
|
identification within third-party archives.
|
188
188
|
|
189
|
-
Copyright
|
189
|
+
Copyright 2020-present Phil Dibowitz
|
190
190
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
192
192
|
you may not use this file except in compliance with the License.
|
data/README.md
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
[![Lint](https://github.com/jaymzh/sugarjar/workflows/Lint/badge.svg)](https://github.com/jaymzh/sugarjar/actions?query=workflow%3ALint)
|
4
4
|
[![Unittest](https://github.com/jaymzh/sugarjar/workflows/Unittests/badge.svg)](https://github.com/jaymzh/sugarjar/actions?query=workflow%3AUnittests)
|
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
|
-
[![Gem Version](https://badge.fury.io/rb/sugarjar.svg)](https://badge.fury.io/rb/sugarjar)
|
7
6
|
|
8
|
-
Welcome to SugarJar - a git/github helper. It
|
9
|
-
[hub](https://hub.github.com/),
|
7
|
+
Welcome to SugarJar - a git/github helper. It needs one of the GitHub CLI's:
|
8
|
+
the current default is [hub](https://hub.github.com/), but there is
|
9
|
+
experimental support for [gh](https://cli.github.com/). So you will need one of
|
10
|
+
those two installed.
|
10
11
|
|
11
12
|
SugarJar is inspired by [arcanist](https://github.com/phacility/arcanist), and
|
12
13
|
its replacement at Facebook, JellyFish. Many of the features they provide for
|
@@ -19,6 +20,24 @@ If you miss Mondrian or Phabricator - this is the tool for you!
|
|
19
20
|
|
20
21
|
If you don't, there's a ton of useful stuff for everyone!
|
21
22
|
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
Sugarjar is packaged in a variety of Linux distributions - see if it's on the
|
26
|
+
list here, and if so, use your package manager (or `gem`) to install it:
|
27
|
+
|
28
|
+
[![Packaging status](https://repology.org/badge/vertical-allrepos/sugarjar.svg)](https://repology.org/project/sugarjar/versions)
|
29
|
+
|
30
|
+
Another option is to use our [omnibus
|
31
|
+
packages](https://github.com/jaymzh/sugarjar/releases). We keep Omnibus
|
32
|
+
packages for most distros that do not package Sugarjar. Omnibus packages are
|
33
|
+
distro packages (deb, rpm, etc.) that have all dependencies bundled up together
|
34
|
+
(including Ruby), and install in `/opt/sugarjar` allowing you to manage the
|
35
|
+
installation with your package manager, but with as a hermetically sealed app
|
36
|
+
that doesn't depend on the rest of your distro.
|
37
|
+
|
38
|
+
Finally, if none of those work for you, you can clone this repo and run it
|
39
|
+
directly from there.
|
40
|
+
|
22
41
|
## Auto cleanup squash-merged branches
|
23
42
|
|
24
43
|
It is common for a PR to go back and forth with a variety of nits, lint fixes,
|
@@ -73,7 +92,7 @@ This will:
|
|
73
92
|
* Clone your fork
|
74
93
|
* Add the original as an 'upstream' remote
|
75
94
|
|
76
|
-
Note that it takes
|
95
|
+
Note that it takes short names for repos. No need to specify a full URL,
|
77
96
|
just a $org/$repo.
|
78
97
|
|
79
98
|
Like `git clone`, `sj sclone` will accept an additional argument as the
|
@@ -198,6 +217,15 @@ smartlog` or `sj sl` for short.
|
|
198
217
|
|
199
218
|
![smartlog screenshot](https://github.com/jaymzh/sugarjar/blob/master/smartlog.png)
|
200
219
|
|
220
|
+
## Pulling in suggestions from the web
|
221
|
+
|
222
|
+
When someone 'suggests' a change in the GitHub WebUI, once you choose to commit
|
223
|
+
them, your origin and local branches are no longer in-sync. The
|
224
|
+
`pullsuggestions` command will attempt to merge in any remote commits to your
|
225
|
+
local branch. This command will show a diff and ask for confirmation before
|
226
|
+
attempting the merge and - if allowed to continue - will use a fast-forward
|
227
|
+
merge.
|
228
|
+
|
201
229
|
## And more!
|
202
230
|
|
203
231
|
See `sj help` for more commands!
|
@@ -205,8 +233,11 @@ See `sj help` for more commands!
|
|
205
233
|
## Using SugarJar as a git wrapper
|
206
234
|
|
207
235
|
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 `
|
236
|
+
(which passes commands **it** doesn't know to `git`). If you have configured
|
237
|
+
SugarJar to use `gh` instead of `hub`, then it will pass commands straight to
|
238
|
+
`git` since `gh` doesn't act as a `git` wrapper.
|
239
|
+
|
240
|
+
As such you can alias it to `git` and just have a super-git.
|
210
241
|
|
211
242
|
```shell
|
212
243
|
$ alias git=sj
|
@@ -244,8 +275,8 @@ yaml file is a straight key-value pair of options without their '--'. For
|
|
244
275
|
example:
|
245
276
|
|
246
277
|
```yaml
|
247
|
-
|
248
|
-
|
278
|
+
log_level: debug
|
279
|
+
github_user: jaymzh
|
249
280
|
```
|
250
281
|
|
251
282
|
In addition, the environment variable `SUGARJAR_DEBUG` can be defined to set
|
@@ -258,9 +289,15 @@ Sugarjar looks for a `.sugarjar.yaml` in the root of the repository to tell it
|
|
258
289
|
how to handle repo-specific things. Currently there options are:
|
259
290
|
|
260
291
|
* `lint` - A list of scripts to run on `sj lint`. These should be linters like
|
261
|
-
rubocop or pyflake.
|
292
|
+
rubocop or pyflake. Linters will be run from the root of the repo.
|
293
|
+
* `lint_list_cmd` - A command to run which will print out linters to run, one
|
294
|
+
per line. Takes precedence over `lint`. The command (and the resulting
|
295
|
+
linters) will be run from the root of the repo.
|
262
296
|
* `unit` - A list of scripts to run on `sj unit`. These should be unittest
|
263
|
-
runners like rspec or pyunit.
|
297
|
+
runners like rspec or pyunit. Test will be run fro mthe root of the repo.
|
298
|
+
* `unit_list_cmd` - A command to run which will print out the unit tests to
|
299
|
+
run, one more line. Takes precedence over `unit`. The command (and the
|
300
|
+
resulting unit tests) will be run from the root of the repo.
|
264
301
|
* `on_push` - A list of types (`lint`, `unit`) of checks to run before pushing.
|
265
302
|
It is highly recommended this is only `lint`. The goal here is to allow for
|
266
303
|
the user to get quick stylistic feedback before pushing their branch to avoid
|
@@ -312,6 +349,16 @@ sj clone jaymzh/sugarjar --github-host githuh.com
|
|
312
349
|
We will add the `hub.host` to the `sugarjar` clone so that future `hub` or `sj`
|
313
350
|
commands work without needing to specify..
|
314
351
|
|
352
|
+
## Support for `gh`
|
353
|
+
|
354
|
+
As of version 0.11 there is experimental support for the `gh` CLI (instead of
|
355
|
+
`hub`). If you would like to use `gh`, install it and then add the following
|
356
|
+
to your configuration:
|
357
|
+
|
358
|
+
```yaml
|
359
|
+
github_cli: gh
|
360
|
+
```
|
361
|
+
|
315
362
|
## FAQ
|
316
363
|
|
317
364
|
Why the name SugarJar?
|
@@ -324,6 +371,19 @@ and github, it seemed appropriate.
|
|
324
371
|
|
325
372
|
Why did you use `hub` instead of the newer `gh` CLI?
|
326
373
|
|
327
|
-
|
328
|
-
|
329
|
-
|
374
|
+
When I originally wrote SugarJar, `gh` was in early development, and `hub` had
|
375
|
+
many more features. Now that `gh` has matured, we have experimental support for
|
376
|
+
`gh` and will switch it to the default at some point.
|
377
|
+
|
378
|
+
In addition, I wanted SugarJar to be able to be a git wrapper, and so wrapping
|
379
|
+
`hub` allows us to do that but wrapping `gh` does not.
|
380
|
+
|
381
|
+
I'd like to package SugarJar for my favorite distro/OS, is that OK?
|
382
|
+
|
383
|
+
Of course! But I'd appreciate you emailing me to give me a heads up. Doing so
|
384
|
+
will allow me to make sure it shows up in the Repology badge above as well as
|
385
|
+
stop building Omnibus packages for whatever distro.
|
386
|
+
|
387
|
+
Does it work on Windows/Mac?
|
388
|
+
|
389
|
+
It should! Though I will admit I don't regularly test on non-Linux OSes.
|
data/bin/sj
CHANGED
@@ -33,8 +33,13 @@ parser = OptionParser.new do |opts|
|
|
33
33
|
options['fallthru'] = fallthru
|
34
34
|
end
|
35
35
|
|
36
|
-
opts.on(
|
37
|
-
|
36
|
+
opts.on(
|
37
|
+
'--github-cli CLI',
|
38
|
+
%w{gh cli},
|
39
|
+
'Github CLI to use ("gh" or "hub"). Note that support for "gh" is ' +
|
40
|
+
'currently experimental. default: "hub"',
|
41
|
+
) do |cli|
|
42
|
+
options['github_cli'] = cli
|
38
43
|
end
|
39
44
|
|
40
45
|
opts.on(
|
@@ -48,6 +53,10 @@ parser = OptionParser.new do |opts|
|
|
48
53
|
options['github_host'] = host
|
49
54
|
end
|
50
55
|
|
56
|
+
opts.on('--github-user USER', 'Github username') do |user|
|
57
|
+
options['github_user'] = user
|
58
|
+
end
|
59
|
+
|
51
60
|
opts.on('-h', '--help', 'Print this help message') do
|
52
61
|
puts opts
|
53
62
|
exit
|
@@ -128,6 +137,11 @@ COMMANDS:
|
|
128
137
|
lint
|
129
138
|
Run any linters configured in .sugarjar.yaml.
|
130
139
|
|
140
|
+
pullsuggestions, ps
|
141
|
+
Pull any suggestions *that have been committed* in the GitHub UI.
|
142
|
+
This will show the diff and prompt for confirmation before
|
143
|
+
merging. Note that a fast-forward merge will be used.
|
144
|
+
|
131
145
|
smartclone, sclone
|
132
146
|
A smart wrapper to "git clone" that handles forking and managing
|
133
147
|
remotes for you.
|
@@ -182,19 +196,23 @@ extra_opts = []
|
|
182
196
|
config = SugarJar::Config.config
|
183
197
|
|
184
198
|
valid_commands = sj.public_methods - Object.public_methods
|
185
|
-
|
186
|
-
|
199
|
+
possible_valid_command = ARGV.any? do |arg|
|
200
|
+
valid_commands.include?(arg.to_s.to_sym)
|
201
|
+
end
|
187
202
|
|
188
203
|
# if we're configured to fall thru and the subcommand isn't one
|
189
204
|
# we recognize, don't parse the options as they may be different
|
190
205
|
# than git's. For example `git config -l` - we error because we
|
191
206
|
# require an arguement to `-l`.
|
192
|
-
if config['fallthru'] && !
|
207
|
+
if config['fallthru'] && !possible_valid_command
|
193
208
|
SugarJar::Log.debug(
|
194
209
|
'Skipping option parsing: fall-thru is set and we do not recognize ' +
|
195
210
|
'any subcommands',
|
196
211
|
)
|
197
212
|
else
|
213
|
+
SugarJar::Log.debug(
|
214
|
+
'We MIGHT have a valid command... parse-command line options',
|
215
|
+
)
|
198
216
|
# We want to allow people to pass in extra args to be passed to
|
199
217
|
# git commands, but OptionParser doesn't easily allow this. So we
|
200
218
|
# loop over it, catching exceptions.
|
@@ -240,6 +258,7 @@ SugarJar::Log.level = options['log_level'].to_sym if options['log_level']
|
|
240
258
|
sj = SugarJar::Commands.new(options)
|
241
259
|
|
242
260
|
subcommand = argv_copy.reject { |x| x.start_with?('-') }.first
|
261
|
+
is_valid_command = valid_commands.include?(subcommand.to_sym)
|
243
262
|
argv_copy.delete(subcommand)
|
244
263
|
SugarJar::Log.debug("subcommand is #{subcommand}")
|
245
264
|
|
@@ -260,7 +279,13 @@ if is_valid_command
|
|
260
279
|
sj.send(subcommand.to_sym, *extra_opts)
|
261
280
|
elsif options['fallthru']
|
262
281
|
SugarJar::Log.debug("Falling thru to: hub #{ARGV.join(' ')}")
|
263
|
-
|
282
|
+
if options['github_cli'] == 'hub'
|
283
|
+
exec('hub', *ARGV)
|
284
|
+
else
|
285
|
+
# If we're using 'gh', it doesn't have 'git fall thru' support, so
|
286
|
+
# we pass thru directly to 'git'
|
287
|
+
exec('git', *ARGV)
|
288
|
+
end
|
264
289
|
else
|
265
290
|
SugarJar::Log.error("No such subcommand: #{subcommand}")
|
266
291
|
end
|
data/lib/sugarjar/commands.rb
CHANGED
@@ -12,28 +12,34 @@ class SugarJar
|
|
12
12
|
class Commands
|
13
13
|
include SugarJar::Util
|
14
14
|
|
15
|
+
MAIN_BRANCHES = %w{master main}.freeze
|
16
|
+
|
15
17
|
def initialize(options)
|
16
18
|
SugarJar::Log.debug("Commands.initialize options: #{options}")
|
17
19
|
@ghuser = options['github_user']
|
18
20
|
@ghhost = options['github_host']
|
21
|
+
@cli = options['github_cli']
|
19
22
|
@ignore_dirty = options['ignore_dirty']
|
20
23
|
@ignore_prerun_failure = options['ignore_prerun_failure']
|
21
24
|
@repo_config = SugarJar::RepoConfig.config
|
22
25
|
@color = options['color']
|
26
|
+
@checks = {}
|
27
|
+
@main_branch = nil
|
28
|
+
@main_remote_branches = {}
|
23
29
|
return if options['no_change']
|
24
30
|
|
25
|
-
set_hub_host
|
31
|
+
set_hub_host
|
26
32
|
set_commit_template if @repo_config['commit_template']
|
27
33
|
end
|
28
34
|
|
29
35
|
def feature(name, base = nil)
|
30
36
|
assert_in_repo
|
31
37
|
SugarJar::Log.debug("Feature: #{name}, #{base}")
|
32
|
-
die("#{name} already exists!") if
|
33
|
-
base ||=
|
38
|
+
die("#{name} already exists!") if all_local_branches.include?(name)
|
39
|
+
base ||= most_main
|
34
40
|
base_pieces = base.split('/')
|
35
|
-
|
36
|
-
|
41
|
+
git('fetch', base_pieces[0]) if base_pieces.length > 1
|
42
|
+
git('checkout', '-b', name, base)
|
37
43
|
SugarJar::Log.info(
|
38
44
|
"Created feature branch #{color(name, :green)} based on " +
|
39
45
|
color(base, :green),
|
@@ -56,9 +62,9 @@ class SugarJar
|
|
56
62
|
def bcleanall
|
57
63
|
assert_in_repo
|
58
64
|
curr = current_branch
|
59
|
-
|
60
|
-
if branch
|
61
|
-
SugarJar::Log.debug(
|
65
|
+
all_local_branches.each do |branch|
|
66
|
+
if MAIN_BRANCHES.include?(branch)
|
67
|
+
SugarJar::Log.debug("Skipping #{branch}")
|
62
68
|
next
|
63
69
|
end
|
64
70
|
|
@@ -73,28 +79,28 @@ class SugarJar
|
|
73
79
|
end
|
74
80
|
end
|
75
81
|
|
76
|
-
# Return to the branch we were on, or
|
77
|
-
if
|
78
|
-
|
82
|
+
# Return to the branch we were on, or main
|
83
|
+
if all_local_branches.include?(curr)
|
84
|
+
git('checkout', curr)
|
79
85
|
else
|
80
|
-
|
86
|
+
checkout_main_branch
|
81
87
|
end
|
82
88
|
end
|
83
89
|
|
84
90
|
def co(*args)
|
85
91
|
assert_in_repo
|
86
|
-
s =
|
92
|
+
s = git('checkout', *args)
|
87
93
|
SugarJar::Log.info(s.stderr + s.stdout.chomp)
|
88
94
|
end
|
89
95
|
|
90
96
|
def br
|
91
97
|
assert_in_repo
|
92
|
-
SugarJar::Log.info(
|
98
|
+
SugarJar::Log.info(git('branch', '-v').stdout.chomp)
|
93
99
|
end
|
94
100
|
|
95
101
|
def binfo
|
96
102
|
assert_in_repo
|
97
|
-
SugarJar::Log.info(
|
103
|
+
SugarJar::Log.info(git(
|
98
104
|
'log', '--graph', '--oneline', '--decorate', '--boundary',
|
99
105
|
"#{tracked_branch}.."
|
100
106
|
).stdout.chomp)
|
@@ -103,9 +109,9 @@ class SugarJar
|
|
103
109
|
# binfo for all branches
|
104
110
|
def smartlog
|
105
111
|
assert_in_repo
|
106
|
-
SugarJar::Log.info(
|
112
|
+
SugarJar::Log.info(git(
|
107
113
|
'log', '--graph', '--oneline', '--decorate', '--boundary',
|
108
|
-
'--branches', "#{
|
114
|
+
'--branches', "#{most_main}.."
|
109
115
|
).stdout.chomp)
|
110
116
|
end
|
111
117
|
|
@@ -113,13 +119,22 @@ class SugarJar
|
|
113
119
|
|
114
120
|
def up
|
115
121
|
assert_in_repo
|
122
|
+
# get a copy of our current branch, if rebase fails, we won't
|
123
|
+
# be able to determine it without backing out
|
124
|
+
curr = current_branch
|
116
125
|
result = gitup
|
117
|
-
if result
|
118
|
-
|
119
|
-
"#{color(
|
126
|
+
if result['so'].error?
|
127
|
+
die(
|
128
|
+
"#{color(curr, :red)}: Failed to rebase on " +
|
129
|
+
"#{result['base']}. Leaving the repo as-is. You can get out of " +
|
130
|
+
'this with a `git rebase --abort`. Output from failed rebase is: ' +
|
131
|
+
"\nSTDOUT:\n#{result['so'].stdout.lines.map { |x| "\t#{x}" }.join}" +
|
132
|
+
"\nSTDERR:\n#{result['so'].stderr.lines.map { |x| "\t#{x}" }.join}",
|
120
133
|
)
|
121
134
|
else
|
122
|
-
|
135
|
+
SugarJar::Log.info(
|
136
|
+
"#{color(current_branch, :green)} rebased on #{result['base']}",
|
137
|
+
)
|
123
138
|
end
|
124
139
|
end
|
125
140
|
|
@@ -131,28 +146,29 @@ class SugarJar
|
|
131
146
|
|
132
147
|
def qamend(*args)
|
133
148
|
assert_in_repo
|
134
|
-
SugarJar::Log.info(
|
149
|
+
SugarJar::Log.info(git('commit', '--amend', '--no-edit', *args).stdout)
|
135
150
|
end
|
136
151
|
|
137
152
|
alias amendq qamend
|
138
153
|
|
139
154
|
def upall
|
140
155
|
assert_in_repo
|
141
|
-
|
142
|
-
next if branch
|
156
|
+
all_local_branches.each do |branch|
|
157
|
+
next if MAIN_BRANCHES.include?(branch)
|
143
158
|
|
144
|
-
|
159
|
+
git('checkout', branch)
|
145
160
|
result = gitup
|
146
|
-
if result
|
147
|
-
SugarJar::Log.info(
|
148
|
-
"#{color(branch, :green)} rebased on #{color(result, :green)}",
|
149
|
-
)
|
150
|
-
else
|
161
|
+
if result['so'].error?
|
151
162
|
SugarJar::Log.error(
|
152
163
|
"#{color(branch, :red)} failed rebase. Reverting attempt and " +
|
153
|
-
'moving to next branch',
|
164
|
+
'moving to next branch. Try `sj up` manually on that branch.',
|
165
|
+
)
|
166
|
+
git('rebase', '--abort')
|
167
|
+
else
|
168
|
+
SugarJar::Log.info(
|
169
|
+
"#{color(branch, :green)} rebased on " +
|
170
|
+
color(result['base'], :green).to_s,
|
154
171
|
)
|
155
|
-
hub('rebase', '--abort')
|
156
172
|
end
|
157
173
|
end
|
158
174
|
end
|
@@ -164,28 +180,57 @@ class SugarJar
|
|
164
180
|
|
165
181
|
reponame = File.basename(repo, '.git')
|
166
182
|
dir ||= reponame
|
183
|
+
|
167
184
|
SugarJar::Log.info("Cloning #{reponame}...")
|
168
|
-
hub('clone', canonicalize_repo(repo), dir, *args)
|
169
185
|
|
186
|
+
# GH's 'fork' command (with the --clone arg) will fork, if necessary,
|
187
|
+
# then clone, and then setup the remotes with the appropriate names. So
|
188
|
+
# we just let it do all the work for us and return.
|
189
|
+
if gh?
|
190
|
+
ghcli('repo', 'fork', '--clone', canonicalize_repo(repo), dir, *args)
|
191
|
+
SugarJar::Log.info('Remotes "origin" and "upstream" configured.')
|
192
|
+
return
|
193
|
+
end
|
194
|
+
|
195
|
+
# For 'hub', first we clone, using git, as 'hub' always needs a repo
|
196
|
+
# to operate on.
|
197
|
+
git('clone', canonicalize_repo(repo), dir, *args)
|
198
|
+
|
199
|
+
# Then we go into it and attempt to use the 'fork' capability
|
170
200
|
Dir.chdir dir do
|
171
201
|
# Now that we have a repo, if we have a hub host set it.
|
172
|
-
set_hub_host
|
202
|
+
set_hub_host
|
173
203
|
|
174
204
|
org = extract_org(repo)
|
175
205
|
SugarJar::Log.debug("Comparing org #{org} to ghuser #{@ghuser}")
|
176
206
|
if org == @ghuser
|
177
207
|
puts 'Cloned forked or self-owned repo. Not creating "upstream".'
|
208
|
+
SugarJar::Log.info('Remotes "origin" and "upstream" configured.')
|
178
209
|
return
|
179
210
|
end
|
180
211
|
|
181
|
-
s =
|
212
|
+
s = ghcli_nofail('repo', 'fork', '--remote-name=origin')
|
182
213
|
if s.error?
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
214
|
+
if s.stdout.include?('SAML enforcement')
|
215
|
+
SugarJar::Log.info(
|
216
|
+
'Forking the repo failed because the repo requires SAML ' +
|
217
|
+
"authentication. Full output:\n\n\t#{s.stdout}",
|
218
|
+
)
|
219
|
+
exit(1)
|
220
|
+
else
|
221
|
+
# gh as well as old versions of hub, it would fail if the upstream
|
222
|
+
# fork already existed. If we got an error, but didn't recognize
|
223
|
+
# that, we'll assume that's what happened and try to add the remote
|
224
|
+
# ourselves.
|
225
|
+
SugarJar::Log.info("Fork (#{@ghuser}/#{reponame}) detected.")
|
226
|
+
SugarJar::Log.debug(
|
227
|
+
'The above is a bit of a lie. "hub" failed to fork and it was ' +
|
228
|
+
'not a SAML error, so our best guess is that a fork exists ' +
|
229
|
+
'and so we will try to configure it.',
|
230
|
+
)
|
231
|
+
git('remote', 'rename', 'origin', 'upstream')
|
232
|
+
git('remote', 'add', 'origin', forked_repo(repo, @ghuser))
|
233
|
+
end
|
189
234
|
else
|
190
235
|
SugarJar::Log.info("Forked #{reponame} to #{@ghuser}")
|
191
236
|
end
|
@@ -221,11 +266,15 @@ class SugarJar
|
|
221
266
|
|
222
267
|
def version
|
223
268
|
puts "sugarjar version #{SugarJar::VERSION}"
|
224
|
-
puts
|
269
|
+
puts ghcli('version').stdout
|
270
|
+
# 'hub' prints the 'git' version, but gh doesn't, so if we're on 'gh'
|
271
|
+
# print out the git version directly
|
272
|
+
puts git('version').stdout if gh?
|
225
273
|
end
|
226
274
|
|
227
|
-
def smartpullrequest
|
275
|
+
def smartpullrequest(*args)
|
228
276
|
assert_in_repo
|
277
|
+
assert_common_main_branch
|
229
278
|
if dirty?
|
230
279
|
SugarJar::Log.warn(
|
231
280
|
'Your repo is dirty, so I am not going to create a pull request. ' +
|
@@ -233,12 +282,61 @@ class SugarJar
|
|
233
282
|
)
|
234
283
|
exit(1)
|
235
284
|
end
|
236
|
-
|
285
|
+
if gh?
|
286
|
+
SugarJar::Log.trace("Running: gh pr create #{args.join(' ')}")
|
287
|
+
system(which('gh'), 'pr', 'create', *args)
|
288
|
+
else
|
289
|
+
SugarJar::Log.trace("Running: hub pull-request #{args.join(' ')}")
|
290
|
+
system(which('hub'), 'pull-request', *args)
|
291
|
+
end
|
237
292
|
end
|
238
293
|
|
239
294
|
alias spr smartpullrequest
|
240
295
|
alias smartpr smartpullrequest
|
241
296
|
|
297
|
+
def pullsuggestions
|
298
|
+
assert_in_repo
|
299
|
+
|
300
|
+
if dirty?
|
301
|
+
if @ignore_dirty
|
302
|
+
SugarJar::Log.warn(
|
303
|
+
'Your repo is dirty, but --ignore-dirty was specified, so ' +
|
304
|
+
'carrying on anyway.',
|
305
|
+
)
|
306
|
+
else
|
307
|
+
SugarJar::Log.error(
|
308
|
+
'Your repo is dirty, so I am not going to push. Please commit ' +
|
309
|
+
'or amend first.',
|
310
|
+
)
|
311
|
+
exit(1)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
src = "origin/#{current_branch}"
|
316
|
+
fetch('origin')
|
317
|
+
diff = git('diff', src).stdout
|
318
|
+
return unless diff && !diff.empty?
|
319
|
+
|
320
|
+
puts "Will merge the following suggestions:\n\n#{diff}"
|
321
|
+
|
322
|
+
loop do
|
323
|
+
$stdout.print("\nAre you sure? [y/n] ")
|
324
|
+
ans = $stdin.gets.strip
|
325
|
+
case ans
|
326
|
+
when /^[Yy]$/
|
327
|
+
system(which('git'), 'merge', '--ff', "origin/#{current_branch}")
|
328
|
+
break
|
329
|
+
when /^[Nn]$/, /^[Qq](uit)?/
|
330
|
+
puts 'Not merging at user request...'
|
331
|
+
break
|
332
|
+
else
|
333
|
+
puts "Didn't understand '#{ans}'."
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
alias ps pullsuggestions
|
339
|
+
|
242
340
|
private
|
243
341
|
|
244
342
|
def _smartpush(remote, branch, force)
|
@@ -276,11 +374,11 @@ class SugarJar
|
|
276
374
|
|
277
375
|
args = ['push', remote, branch]
|
278
376
|
args << '--force-with-lease' if force
|
279
|
-
puts
|
377
|
+
puts git(*args).stderr
|
280
378
|
end
|
281
379
|
|
282
380
|
def dirty?
|
283
|
-
s =
|
381
|
+
s = git_nofail('diff', '--quiet')
|
284
382
|
s.error?
|
285
383
|
end
|
286
384
|
|
@@ -317,9 +415,9 @@ class SugarJar
|
|
317
415
|
end
|
318
416
|
|
319
417
|
def set_hub_host
|
320
|
-
return unless in_repo
|
418
|
+
return unless hub? && in_repo && @ghhost
|
321
419
|
|
322
|
-
s =
|
420
|
+
s = git_nofail('config', '--local', '--get', 'hub.host')
|
323
421
|
if s.error?
|
324
422
|
SugarJar::Log.info("Setting repo hub.host = #{@ghhost}")
|
325
423
|
else
|
@@ -337,7 +435,7 @@ class SugarJar
|
|
337
435
|
end
|
338
436
|
return
|
339
437
|
end
|
340
|
-
|
438
|
+
git('config', '--local', '--add', 'hub.host', @ghhost)
|
341
439
|
end
|
342
440
|
|
343
441
|
def set_commit_template
|
@@ -358,7 +456,7 @@ class SugarJar
|
|
358
456
|
)
|
359
457
|
end
|
360
458
|
|
361
|
-
s =
|
459
|
+
s = git_nofail('config', '--local', 'commit.template')
|
362
460
|
unless s.error?
|
363
461
|
current = s.stdout.strip
|
364
462
|
if current == @repo_config['commit_template']
|
@@ -376,18 +474,60 @@ class SugarJar
|
|
376
474
|
'Setting repo-specific commit template to ' +
|
377
475
|
"#{@repo_config['commit_template']} per sugarjar repo config.",
|
378
476
|
)
|
379
|
-
|
477
|
+
git(
|
380
478
|
'config', '--local', 'commit.template', @repo_config['commit_template']
|
381
479
|
)
|
382
480
|
end
|
383
481
|
|
384
|
-
def
|
385
|
-
unless @repo_config[type]
|
386
|
-
|
387
|
-
|
482
|
+
def get_checks_from_command(type)
|
483
|
+
return nil unless @repo_config["#{type}_list_cmd"]
|
484
|
+
|
485
|
+
cmd = @repo_config["#{type}_list_cmd"]
|
486
|
+
short = cmd.split.first
|
487
|
+
unless File.exist?(short)
|
488
|
+
SugarJar::Log.error(
|
489
|
+
"Configured #{type}_list_cmd #{short} does not exist!",
|
490
|
+
)
|
491
|
+
return false
|
492
|
+
end
|
493
|
+
s = Mixlib::ShellOut.new(cmd).run_command
|
494
|
+
if s.error?
|
495
|
+
SugarJar::Log.error(
|
496
|
+
"#{type}_list_cmd (#{cmd}) failed: #{s.format_for_exception}",
|
497
|
+
)
|
498
|
+
return false
|
499
|
+
end
|
500
|
+
s.stdout.split("\n")
|
501
|
+
end
|
502
|
+
|
503
|
+
# determine if we're using the _list_cmd and if so run it to get the
|
504
|
+
# checks, or just use the directly-defined check, and cache it
|
505
|
+
def get_checks(type)
|
506
|
+
return @checks[type] if @checks[type]
|
507
|
+
|
508
|
+
ret = get_checks_from_command(type)
|
509
|
+
if ret
|
510
|
+
SugarJar::Log.debug("Found #{type}s: #{ret}")
|
511
|
+
@checks[type] = ret
|
512
|
+
# if it's explicitly false, we failed to run the command
|
513
|
+
elsif ret == false
|
514
|
+
@checks[type] = false
|
515
|
+
# otherwise, we move on (basically: it's nil, there was no _list_cmd)
|
516
|
+
else
|
517
|
+
SugarJar::Log.debug("[#{type}]: using listed linters: #{ret}")
|
518
|
+
@checks[type] = @repo_config[type] || []
|
388
519
|
end
|
520
|
+
@checks[type]
|
521
|
+
end
|
522
|
+
|
523
|
+
def run_check(type)
|
389
524
|
Dir.chdir repo_root do
|
390
|
-
|
525
|
+
checks = get_checks(type)
|
526
|
+
# if we failed to determine the checks, the the checks have effectively
|
527
|
+
# failed
|
528
|
+
return false unless checks
|
529
|
+
|
530
|
+
checks.each do |check|
|
391
531
|
SugarJar::Log.debug("Running #{type} #{check}")
|
392
532
|
|
393
533
|
short = check.split.first
|
@@ -405,7 +545,7 @@ class SugarJar
|
|
405
545
|
SugarJar::Log.warn(
|
406
546
|
"The linter modified the repo. Here's the diff:\n",
|
407
547
|
)
|
408
|
-
puts
|
548
|
+
puts git('diff').stdout
|
409
549
|
loop do
|
410
550
|
$stdout.print(
|
411
551
|
"\nWould you like to\n\t[q]uit and inspect\n\t[a]mend the " +
|
@@ -457,29 +597,82 @@ class SugarJar
|
|
457
597
|
exit(1)
|
458
598
|
end
|
459
599
|
|
600
|
+
def assert_common_main_branch
|
601
|
+
upstream_branch = main_remote_branch(upstream)
|
602
|
+
unless main_branch == upstream_branch
|
603
|
+
die(
|
604
|
+
"The local main branch is '#{main_branch}', but the main branch " +
|
605
|
+
"of the #{upstream} remote is '#{upstream_branch}'. You probably " +
|
606
|
+
"want to rename your local branch by doing:\n\t" +
|
607
|
+
"git branch -m #{main_branch} #{upstream_branch}\n\t" +
|
608
|
+
"git fetch #{upstream}\n\t" +
|
609
|
+
"git branch -u #{upstream}/#{upstream_branch} #{upstream_branch}\n" +
|
610
|
+
"\tgit remote set-head #{upstream} -a",
|
611
|
+
)
|
612
|
+
end
|
613
|
+
return if upstream_branch == 'origin'
|
614
|
+
|
615
|
+
origin_branch = main_remote_branch('origin')
|
616
|
+
return if origin_branch == upstream_branch
|
617
|
+
|
618
|
+
die(
|
619
|
+
"The main branch of your upstream (#{upstream_branch}) and your " +
|
620
|
+
"fork/origin (#{origin_branch}) are not the same. You should go " +
|
621
|
+
"to https://#{@ghhost || 'github.com'}/#{@ghuser}/#{repo_name}/" +
|
622
|
+
'branches/ and rename the \'default\' branch to ' +
|
623
|
+
"'#{upstream_branch}'. It will then give you some commands to " +
|
624
|
+
'run to update this clone.',
|
625
|
+
)
|
626
|
+
end
|
627
|
+
|
460
628
|
def assert_in_repo
|
461
629
|
die('sugarjar must be run from inside a git repo') unless in_repo
|
462
630
|
end
|
463
631
|
|
632
|
+
def determine_main_branch(branches)
|
633
|
+
branches.include?('main') ? 'main' : 'master'
|
634
|
+
end
|
635
|
+
|
636
|
+
def main_branch
|
637
|
+
@main_branch = determine_main_branch(all_local_branches)
|
638
|
+
end
|
639
|
+
|
640
|
+
def main_remote_branch(remote)
|
641
|
+
@main_remote_branches[remote] ||=
|
642
|
+
determine_main_branch(all_remote_branches(remote))
|
643
|
+
end
|
644
|
+
|
645
|
+
def checkout_main_branch
|
646
|
+
git('checkout', main_branch)
|
647
|
+
end
|
648
|
+
|
464
649
|
def clean_branch(name)
|
465
|
-
die(
|
650
|
+
die("Cannot remove #{name} branch") if MAIN_BRANCHES.include?(name)
|
466
651
|
SugarJar::Log.debug('Fetch relevant remote...')
|
467
652
|
fetch_upstream
|
468
653
|
return false unless safe_to_clean(name)
|
469
654
|
|
470
655
|
SugarJar::Log.debug('branch deemed safe to delete...')
|
471
|
-
|
472
|
-
|
656
|
+
checkout_main_branch
|
657
|
+
git('branch', '-D', name)
|
473
658
|
gitup
|
474
659
|
true
|
475
660
|
end
|
476
661
|
|
477
|
-
def
|
662
|
+
def all_remote_branches(remote = 'origin')
|
478
663
|
branches = []
|
479
|
-
|
480
|
-
next
|
664
|
+
git('branch', '-r', '--format', '%(refname)').stdout.lines.each do |line|
|
665
|
+
next unless line.start_with?("refs/remotes/#{remote}/")
|
666
|
+
|
667
|
+
branches << branch_from_ref(line.strip, :remote)
|
668
|
+
end
|
669
|
+
branches
|
670
|
+
end
|
481
671
|
|
482
|
-
|
672
|
+
def all_local_branches
|
673
|
+
branches = []
|
674
|
+
git('branch', '--format', '%(refname)').stdout.lines.each do |line|
|
675
|
+
branches << branch_from_ref(line.strip)
|
483
676
|
end
|
484
677
|
branches
|
485
678
|
end
|
@@ -488,7 +681,7 @@ class SugarJar
|
|
488
681
|
# cherry -v will output 1 line per commit on the target branch
|
489
682
|
# prefixed by a - or + - anything with a - can be dropped, anything
|
490
683
|
# else cannot.
|
491
|
-
out =
|
684
|
+
out = git(
|
492
685
|
'cherry', '-v', tracked_branch, branch
|
493
686
|
).stdout.lines.reject do |line|
|
494
687
|
line.start_with?('-')
|
@@ -502,24 +695,24 @@ class SugarJar
|
|
502
695
|
|
503
696
|
# if the "easy" check didn't work, it's probably because there
|
504
697
|
# was a squash-merge. To check for that we make our own squash
|
505
|
-
# merge to upstream/
|
698
|
+
# merge to upstream/main and see if that has any delta
|
506
699
|
|
507
700
|
# First we need a temp branch to work on
|
508
701
|
tmpbranch = "_sugar_jar.#{Process.pid}"
|
509
702
|
|
510
|
-
|
511
|
-
s =
|
703
|
+
git('checkout', '-b', tmpbranch, tracked_branch)
|
704
|
+
s = git_nofail('merge', '--squash', branch)
|
512
705
|
if s.error?
|
513
706
|
cleanup_tmp_branch(tmpbranch, branch)
|
514
707
|
SugarJar::Log.debug(
|
515
|
-
'Failed to merge changes into current
|
708
|
+
'Failed to merge changes into current main. This means we could ' +
|
516
709
|
'not figure out if this is merged or not. Check manually and use ' +
|
517
710
|
"'git branch -D #{branch}' if it is safe to do so.",
|
518
711
|
)
|
519
712
|
return false
|
520
713
|
end
|
521
714
|
|
522
|
-
s =
|
715
|
+
s = git('diff', '--staged')
|
523
716
|
out = s.stdout
|
524
717
|
SugarJar::Log.debug("Squash-merged diff: #{out}")
|
525
718
|
cleanup_tmp_branch(tmpbranch, branch)
|
@@ -530,34 +723,37 @@ class SugarJar
|
|
530
723
|
true
|
531
724
|
else
|
532
725
|
SugarJar::Log.debug(
|
533
|
-
'After squash-merging, this branch is NOT fully merged to
|
726
|
+
'After squash-merging, this branch is NOT fully merged to main',
|
534
727
|
)
|
535
728
|
false
|
536
729
|
end
|
537
730
|
end
|
538
731
|
|
539
732
|
def cleanup_tmp_branch(tmp, backto)
|
540
|
-
|
541
|
-
|
542
|
-
|
733
|
+
git('reset', '--hard', tracked_branch)
|
734
|
+
git('checkout', backto)
|
735
|
+
git('branch', '-D', tmp)
|
543
736
|
end
|
544
737
|
|
545
738
|
def current_branch
|
546
|
-
|
739
|
+
branch_from_ref(git('symbolic-ref', 'HEAD').stdout.strip)
|
547
740
|
end
|
548
741
|
|
549
742
|
def fetch_upstream
|
550
743
|
us = upstream
|
551
|
-
|
744
|
+
fetch(us) if us
|
745
|
+
end
|
746
|
+
|
747
|
+
def fetch(remote)
|
748
|
+
git('fetch', remote)
|
552
749
|
end
|
553
750
|
|
554
751
|
def gitup
|
555
752
|
SugarJar::Log.debug('Fetching upstream')
|
556
753
|
fetch_upstream
|
557
754
|
curr = current_branch
|
558
|
-
SugarJar::Log.debug('Rebasing')
|
559
755
|
base = tracked_branch
|
560
|
-
if curr
|
756
|
+
if !MAIN_BRANCHES.include?(curr) && base == "origin/#{curr}"
|
561
757
|
SugarJar::Log.warn(
|
562
758
|
"This branch is tracking origin/#{curr}, which is probably your " +
|
563
759
|
'downstream (where you push _to_) as opposed to your upstream ' +
|
@@ -566,34 +762,38 @@ class SugarJar
|
|
566
762
|
'to do a "git branch -u upstream".',
|
567
763
|
)
|
568
764
|
end
|
569
|
-
|
570
|
-
s
|
765
|
+
SugarJar::Log.debug('Rebasing')
|
766
|
+
s = git_nofail('rebase', base)
|
767
|
+
{
|
768
|
+
'so' => s,
|
769
|
+
'base' => base,
|
770
|
+
}
|
571
771
|
end
|
572
772
|
|
573
773
|
def tracked_branch
|
574
|
-
s =
|
774
|
+
s = git_nofail(
|
575
775
|
'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'
|
576
776
|
)
|
577
777
|
if s.error?
|
578
|
-
|
778
|
+
most_main
|
579
779
|
else
|
580
780
|
s.stdout.strip
|
581
781
|
end
|
582
782
|
end
|
583
783
|
|
584
|
-
def
|
784
|
+
def most_main
|
585
785
|
us = upstream
|
586
786
|
if us
|
587
|
-
"#{us}
|
787
|
+
"#{us}/#{main_branch}"
|
588
788
|
else
|
589
|
-
|
789
|
+
main_branch
|
590
790
|
end
|
591
791
|
end
|
592
792
|
|
593
793
|
def upstream
|
594
794
|
return @remote if @remote
|
595
795
|
|
596
|
-
s =
|
796
|
+
s = git('remote')
|
597
797
|
|
598
798
|
remotes = s.stdout.lines.map(&:strip)
|
599
799
|
SugarJar::Log.debug("remotes is #{remotes}")
|
@@ -611,6 +811,13 @@ class SugarJar
|
|
611
811
|
@remote
|
612
812
|
end
|
613
813
|
|
814
|
+
def branch_from_ref(ref, type = :local)
|
815
|
+
# local branches are refs/head/XXXX
|
816
|
+
# remote branches are refs/remotes/<remote>/XXXX
|
817
|
+
base = type == :local ? 2 : 3
|
818
|
+
ref.split('/')[base..].join('/')
|
819
|
+
end
|
820
|
+
|
614
821
|
def color(string, *colors)
|
615
822
|
if @color
|
616
823
|
pastel.decorate(string, *colors)
|
@@ -625,5 +832,21 @@ class SugarJar
|
|
625
832
|
Pastel.new
|
626
833
|
end
|
627
834
|
end
|
835
|
+
|
836
|
+
def hub?
|
837
|
+
@cli == 'hub'
|
838
|
+
end
|
839
|
+
|
840
|
+
def gh?
|
841
|
+
@cli == 'gh'
|
842
|
+
end
|
843
|
+
|
844
|
+
def ghcli_nofail(*args)
|
845
|
+
gh? ? gh_nofail(*args) : hub_nofail(*args)
|
846
|
+
end
|
847
|
+
|
848
|
+
def ghcli(*args)
|
849
|
+
gh? ? gh(*args) : hub(*args)
|
850
|
+
end
|
628
851
|
end
|
629
852
|
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' => 'hub',
|
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
data/sugarjar.gemspec
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: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Phil Dibowitz
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mixlib-log
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
description:
|
55
|
+
description:
|
56
56
|
email:
|
57
57
|
- phil@ipom.com
|
58
58
|
executables:
|
@@ -78,8 +78,9 @@ files:
|
|
78
78
|
homepage: https://github.com/jaymzh/sugarjar
|
79
79
|
licenses:
|
80
80
|
- Apache-2.0
|
81
|
-
metadata:
|
82
|
-
|
81
|
+
metadata:
|
82
|
+
rubygems_mfa_required: 'true'
|
83
|
+
post_install_message:
|
83
84
|
rdoc_options: []
|
84
85
|
require_paths:
|
85
86
|
- lib
|
@@ -94,8 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
95
|
- !ruby/object:Gem::Version
|
95
96
|
version: '0'
|
96
97
|
requirements: []
|
97
|
-
rubygems_version: 3.
|
98
|
-
signing_key:
|
98
|
+
rubygems_version: 3.3.7
|
99
|
+
signing_key:
|
99
100
|
specification_version: 4
|
100
101
|
summary: A git/github helper script
|
101
102
|
test_files: []
|