sugarjar 2.0.2 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +123 -52
- data/bin/sj +80 -19
- data/examples/sample_config.yaml +6 -0
- data/examples/sample_repoconfig.yaml +19 -3
- data/lib/sugarjar/commands/bclean.rb +28 -13
- data/lib/sugarjar/commands/checks.rb +25 -8
- data/lib/sugarjar/commands/debuginfo.rb +1 -1
- data/lib/sugarjar/commands/feature.rb +25 -2
- data/lib/sugarjar/commands/push.rb +1 -1
- data/lib/sugarjar/commands/smartclone.rb +64 -7
- data/lib/sugarjar/commands/smartpullrequest.rb +29 -6
- data/lib/sugarjar/commands/up.rb +42 -10
- data/lib/sugarjar/commands.rb +93 -25
- data/lib/sugarjar/config.rb +33 -4
- data/lib/sugarjar/log.rb +2 -0
- data/lib/sugarjar/util.rb +28 -14
- data/lib/sugarjar/version.rb +1 -1
- metadata +2 -2
|
@@ -22,12 +22,12 @@ class SugarJar
|
|
|
22
22
|
exit(1)
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
|
-
exit(1) unless run_check('lint')
|
|
25
|
+
exit(1) unless run_check('lint', false)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def unit
|
|
29
29
|
assert_in_repo!
|
|
30
|
-
exit(1) unless run_check('unit')
|
|
30
|
+
exit(1) unless run_check('unit', false)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def get_checks_from_command(type)
|
|
@@ -71,7 +71,13 @@ class SugarJar
|
|
|
71
71
|
@checks[type]
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
# autorun is true when we're running from push, and false when someone
|
|
75
|
+
# ran 'lint' or 'unit' directly
|
|
76
|
+
#
|
|
77
|
+
# In the case of a autorun, if a linter changes the code, we require
|
|
78
|
+
# either the user amend, or bail out. If it's a manual run, then we
|
|
79
|
+
# allow them to just go on.
|
|
80
|
+
def run_check(type, autorun)
|
|
75
81
|
repo_root = SugarJar::Util.repo_root
|
|
76
82
|
Dir.chdir repo_root do
|
|
77
83
|
checks = get_checks(type)
|
|
@@ -81,6 +87,7 @@ class SugarJar
|
|
|
81
87
|
|
|
82
88
|
checks.each do |check|
|
|
83
89
|
SugarJar::Log.debug("Running #{type} #{check}")
|
|
90
|
+
skip_redo = false
|
|
84
91
|
|
|
85
92
|
short = check.split.first
|
|
86
93
|
if short.include?('/')
|
|
@@ -104,10 +111,15 @@ class SugarJar
|
|
|
104
111
|
)
|
|
105
112
|
puts git('diff').stdout
|
|
106
113
|
loop do
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
114
|
+
options = [
|
|
115
|
+
'[q]uit and inspect',
|
|
116
|
+
'[a]mend the changes to the current commit and re-run',
|
|
117
|
+
]
|
|
118
|
+
options << '[i]gnore the changes and keep going' unless autorun
|
|
119
|
+
|
|
120
|
+
msg = "\nWould you like to\n\t" + options.join("\n\t") + "\n > "
|
|
121
|
+
|
|
122
|
+
$stdout.print(msg)
|
|
111
123
|
ans = $stdin.gets.strip
|
|
112
124
|
case ans
|
|
113
125
|
when /^q/
|
|
@@ -118,9 +130,14 @@ class SugarJar
|
|
|
118
130
|
# break here, if we get out of this loop we 'redo', assuming
|
|
119
131
|
# the user chose this option
|
|
120
132
|
break
|
|
133
|
+
when /^i/
|
|
134
|
+
unless autorun
|
|
135
|
+
skip_redo = true
|
|
136
|
+
break
|
|
137
|
+
end
|
|
121
138
|
end
|
|
122
139
|
end
|
|
123
|
-
redo
|
|
140
|
+
redo unless skip_redo
|
|
124
141
|
end
|
|
125
142
|
|
|
126
143
|
if s.error?
|
|
@@ -5,10 +5,32 @@ class SugarJar
|
|
|
5
5
|
SugarJar::Log.debug("Feature: #{name}, #{base}")
|
|
6
6
|
name = fprefix(name)
|
|
7
7
|
die("#{name} already exists!") if all_local_branches.include?(name)
|
|
8
|
+
rel_branches = release_branches
|
|
8
9
|
if base
|
|
9
|
-
|
|
10
|
-
base
|
|
10
|
+
# If the user specified a base branch (sf mything base)
|
|
11
|
+
# we check if <base> is a release branch and if so, we make
|
|
12
|
+
# this track <upstream>/<base>
|
|
13
|
+
if rel_branches.include?(base)
|
|
14
|
+
newbase = "#{upstream}/#{base}"
|
|
15
|
+
SugarJar::Log.info(
|
|
16
|
+
"Base branch #{base} is a release branch, setting it to track " +
|
|
17
|
+
newbase,
|
|
18
|
+
)
|
|
19
|
+
base = newbase
|
|
20
|
+
else
|
|
21
|
+
fbase = fprefix(base)
|
|
22
|
+
base = fbase if all_local_branches.include?(fbase)
|
|
23
|
+
end
|
|
24
|
+
elsif rel_branches.include?(name)
|
|
25
|
+
# If the user did NOT specify a base *and* this new feature is
|
|
26
|
+
# a release branch, check it out tracking the upstream release
|
|
27
|
+
# branch instead of main
|
|
28
|
+
base = "#{upstream}/#{name}"
|
|
29
|
+
SugarJar::Log.info(
|
|
30
|
+
"Feature #{name} is a release branch, setting it to track #{base}",
|
|
31
|
+
)
|
|
11
32
|
else
|
|
33
|
+
# otherwise, fallback to most-main
|
|
12
34
|
base ||= most_main
|
|
13
35
|
end
|
|
14
36
|
# If our base is a local branch, don't try to parse it for a remote name
|
|
@@ -25,6 +47,7 @@ class SugarJar
|
|
|
25
47
|
end
|
|
26
48
|
alias f feature
|
|
27
49
|
|
|
50
|
+
# alias for "feature <current_branch>'
|
|
28
51
|
def subfeature(name)
|
|
29
52
|
assert_in_repo!
|
|
30
53
|
SugarJar::Log.debug("Subfature: #{name}")
|
|
@@ -43,7 +43,7 @@ class SugarJar
|
|
|
43
43
|
def run_prepush
|
|
44
44
|
@repo_config['on_push']&.each do |item|
|
|
45
45
|
SugarJar::Log.debug("Running on_push check type #{item}")
|
|
46
|
-
unless run_check(item)
|
|
46
|
+
unless run_check(item, true)
|
|
47
47
|
SugarJar::Log.info("[prepush]: #{item} #{color('failed', :red)}.")
|
|
48
48
|
return false
|
|
49
49
|
end
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
class SugarJar
|
|
2
2
|
class Commands
|
|
3
|
-
def smartclone(repo,
|
|
4
|
-
reponame = File.basename(repo, '.git')
|
|
5
|
-
dir ||= reponame
|
|
3
|
+
def smartclone(repo, *args)
|
|
6
4
|
org = extract_org(repo)
|
|
5
|
+
reponame = extract_repo(repo)
|
|
6
|
+
dir = if args.length.positive? && !args.first.start_with?('-')
|
|
7
|
+
args.shift
|
|
8
|
+
else
|
|
9
|
+
reponame
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
forkname = @fork_name || reponame
|
|
7
13
|
|
|
8
14
|
SugarJar::Log.info("Cloning #{reponame}...")
|
|
9
15
|
|
|
@@ -13,18 +19,69 @@ class SugarJar
|
|
|
13
19
|
#
|
|
14
20
|
# Unless the repo is in our own org and cannot be forked, then it
|
|
15
21
|
# will fail.
|
|
16
|
-
if
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
if @use_forks && @forge_user != org
|
|
23
|
+
if @repo_forge == 'gitlab'
|
|
24
|
+
_gitlab_clone(org, repo, dir, forkname, *args)
|
|
25
|
+
else
|
|
26
|
+
forge(
|
|
27
|
+
'repo', 'fork', '--clone', canonicalize_repo(repo), dir,
|
|
28
|
+
'--fork-name', forkname, *args
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
20
32
|
# make the main branch track upstream
|
|
21
33
|
Dir.chdir dir do
|
|
22
34
|
git('branch', '-u', "upstream/#{main_branch}")
|
|
23
35
|
end
|
|
36
|
+
else
|
|
37
|
+
git('clone', canonicalize_repo(repo), dir, *args)
|
|
24
38
|
end
|
|
25
39
|
|
|
26
40
|
SugarJar::Log.info('Remotes "origin" and "upstream" configured.')
|
|
27
41
|
end
|
|
28
42
|
alias sclone smartclone
|
|
43
|
+
|
|
44
|
+
def _gitlab_clone(_org, repo, dir, forkname, *)
|
|
45
|
+
# The gitlab CLI is much less forgiving about already-forked
|
|
46
|
+
# repos, and it has no option to clone to a differently-named
|
|
47
|
+
# directory. So we have to special case it.
|
|
48
|
+
|
|
49
|
+
extract_repo(repo)
|
|
50
|
+
|
|
51
|
+
# glab requires a short-name for the fork command...
|
|
52
|
+
shortname = repo_shortname(repo)
|
|
53
|
+
|
|
54
|
+
# We call fork without --clone since --clone can't clone
|
|
55
|
+
# to another directory. Also, we must specify =false, or it
|
|
56
|
+
# will prompt
|
|
57
|
+
s = forge_nofail(
|
|
58
|
+
'repo', 'fork', shortname, '--clone=false', '--name', forkname
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# It fails with:
|
|
62
|
+
# 409 {message: [Project namespace name has already been taken,
|
|
63
|
+
# Name has already been taken, Path has already been taken]}
|
|
64
|
+
#
|
|
65
|
+
# when there's already a fork... or if you happen to have a name
|
|
66
|
+
# collision. There's no way to tell, so we assume it means we've
|
|
67
|
+
# already forked.
|
|
68
|
+
if s.error?
|
|
69
|
+
if s.stderr.include?(' 409 ')
|
|
70
|
+
SugarJar::Log.debug('Forking failed, probably already forked')
|
|
71
|
+
else
|
|
72
|
+
s.error!
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Now we clone ourselves...
|
|
77
|
+
git('clone', canonicalize_repo(repo), dir, *)
|
|
78
|
+
Dir.chdir dir do
|
|
79
|
+
# and then configure remotes properly
|
|
80
|
+
git('remote', 'rename', 'origin', 'upstream')
|
|
81
|
+
|
|
82
|
+
fork_url = forked_repo(repo, @forge_user)
|
|
83
|
+
git('remote', 'add', 'origin', fork_url)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
29
86
|
end
|
|
30
87
|
end
|
|
@@ -60,10 +60,25 @@ class SugarJar
|
|
|
60
60
|
|
|
61
61
|
# <org>:<branch> is the GH API syntax for:
|
|
62
62
|
# look for a branch of name <branch>, from a fork in owner <org>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
if @repo_forge == 'github'
|
|
64
|
+
# On GitHub, the head is the org and the *BRANCH* name to use as
|
|
65
|
+
# the head branch...
|
|
66
|
+
args.unshift('--head', "#{push_org}:#{curr}")
|
|
67
|
+
else
|
|
68
|
+
# On GitLab, the head is the repo (org/repo) to use as the head
|
|
69
|
+
# _repo_, and then branch is configured seperately (with -s), but
|
|
70
|
+
# we don't need that since it defaults to the local branch name.
|
|
71
|
+
#
|
|
72
|
+
# Then we need --yes for it to not prompt us
|
|
73
|
+
args.unshift('--head', "#{push_org}/#{repo_name}", '--yes')
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
bin = SugarJar::Util.which(_forge_cmd)
|
|
77
|
+
subcmd = _pr_cmd
|
|
78
|
+
SugarJar::Log.trace(
|
|
79
|
+
"Running: #{bin} #{subcmd} create #{args.join(' ')}",
|
|
80
|
+
)
|
|
81
|
+
system(bin, subcmd, 'create', *args)
|
|
67
82
|
end
|
|
68
83
|
|
|
69
84
|
alias spr smartpullrequest
|
|
@@ -71,6 +86,10 @@ class SugarJar
|
|
|
71
86
|
|
|
72
87
|
private
|
|
73
88
|
|
|
89
|
+
def _pr_cmd
|
|
90
|
+
@repo_forge == 'gitlab' ? 'mr' : 'pr'
|
|
91
|
+
end
|
|
92
|
+
|
|
74
93
|
def assert_common_main_branch!
|
|
75
94
|
upstream_branch = main_remote_branch(upstream)
|
|
76
95
|
unless main_branch == upstream_branch
|
|
@@ -84,10 +103,14 @@ class SugarJar
|
|
|
84
103
|
"\tgit remote set-head #{upstream} -a",
|
|
85
104
|
)
|
|
86
105
|
end
|
|
87
|
-
|
|
106
|
+
|
|
107
|
+
# If we don't have an upstream and an origin, we're done
|
|
108
|
+
return if upstream == 'origin'
|
|
88
109
|
|
|
89
110
|
origin_branch = main_remote_branch('origin')
|
|
90
|
-
|
|
111
|
+
# NOTE: that on GL, forks don't fork any branches by default, even
|
|
112
|
+
# a main one, so if it's 'nil', then ignore.
|
|
113
|
+
return if origin_branch.nil? || origin_branch == upstream_branch
|
|
91
114
|
|
|
92
115
|
die(
|
|
93
116
|
"The main branch of your upstream (#{upstream_branch}) and your " +
|
data/lib/sugarjar/commands/up.rb
CHANGED
|
@@ -53,21 +53,53 @@ class SugarJar
|
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
def
|
|
56
|
+
def fsync
|
|
57
|
+
sync(:force => true)
|
|
58
|
+
end
|
|
59
|
+
alias forcesync fsync
|
|
60
|
+
|
|
61
|
+
def sync(force: false)
|
|
57
62
|
assert_in_repo!
|
|
58
63
|
dirty_check!
|
|
59
64
|
|
|
60
65
|
src = "origin/#{current_branch}"
|
|
61
66
|
fetch('origin')
|
|
62
|
-
|
|
63
|
-
if
|
|
64
|
-
SugarJar::Log.debug(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
want_reset = false
|
|
68
|
+
if force
|
|
69
|
+
SugarJar::Log.debug('Forcing reset instead of rebase at user request')
|
|
70
|
+
want_reset = true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
unless force
|
|
74
|
+
s = git_nofail('merge-base', '--is-ancestor', 'HEAD', src)
|
|
75
|
+
# if this IS an ancestor, we can just force reset.
|
|
76
|
+
#
|
|
77
|
+
# otherwise, we attempt a rebase to not lose anything (unless
|
|
78
|
+
# force is set)
|
|
79
|
+
if s.error?
|
|
80
|
+
SugarJar::Log.debug(
|
|
81
|
+
"Choosing rebase sync since this isn't a direct ancestor",
|
|
82
|
+
)
|
|
83
|
+
else
|
|
84
|
+
SugarJar::Log.debug('Choosing reset sync since this is an ancestor')
|
|
85
|
+
want_reset = true
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
if want_reset
|
|
70
90
|
git('reset', '--hard', src)
|
|
91
|
+
else
|
|
92
|
+
rebase(src)
|
|
93
|
+
s = git_nofail('rev-parse', '--verify', 'REBASE_HEAD')
|
|
94
|
+
unless s.error?
|
|
95
|
+
SugarJar::Log.info(
|
|
96
|
+
'Rebase required input. You may continue the rebase from' +
|
|
97
|
+
' here normally, or you may abort (`git rebase --abort`)' +
|
|
98
|
+
' and instead to `sj fsync` to skip a rebase and force' +
|
|
99
|
+
' reset to the remote branch.',
|
|
100
|
+
)
|
|
101
|
+
return
|
|
102
|
+
end
|
|
71
103
|
end
|
|
72
104
|
SugarJar::Log.info("Synced to #{src}.")
|
|
73
105
|
end
|
|
@@ -85,7 +117,7 @@ class SugarJar
|
|
|
85
117
|
# rubocop:enable Style/HashSyntax
|
|
86
118
|
unless base
|
|
87
119
|
SugarJar::Log.info(
|
|
88
|
-
'The
|
|
120
|
+
'The branch we were tracking is gone, resetting tracking to ' +
|
|
89
121
|
most_main,
|
|
90
122
|
)
|
|
91
123
|
git('branch', '-u', most_main)
|
data/lib/sugarjar/commands.rb
CHANGED
|
@@ -33,16 +33,32 @@ class SugarJar
|
|
|
33
33
|
@pr_autofill = options['pr_autofill']
|
|
34
34
|
@pr_autostack = options['pr_autostack']
|
|
35
35
|
@feature_prefix = options['feature_prefix']
|
|
36
|
+
@use_forks = options['use_forks']
|
|
37
|
+
@fork_name = options['fork_name']
|
|
36
38
|
@checks = {}
|
|
37
39
|
@main_branch = nil
|
|
38
40
|
@main_remote_branches = {}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
# This is CONFIGURED host, which may be null, as opposed
|
|
42
|
+
# to the method forge_host which will always return something
|
|
43
|
+
@_forge_host = @repo_config['forge_host'] || options['forge_host']
|
|
44
|
+
@repo_forge = @repo_config['forge_type'] || options['forge_type'] ||
|
|
45
|
+
_determine_forge_type
|
|
46
|
+
|
|
47
|
+
unless @repo_forge.nil?
|
|
48
|
+
cmd = _forge_cmd
|
|
49
|
+
unless SugarJar::Util.which_nofail(cmd)
|
|
50
|
+
die("No '#{cmd}' found, please install it'")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
41
53
|
|
|
42
|
-
|
|
54
|
+
user_option = "#{@repo_forge}_user"
|
|
55
|
+
@forge_user = @repo_config[user_option] || options[user_option]
|
|
43
56
|
|
|
44
|
-
# Tell the
|
|
45
|
-
|
|
57
|
+
# Tell the cli where to talk to, if not default
|
|
58
|
+
if @_forge_host
|
|
59
|
+
ENV['GH_HOST'] = @_forge_host
|
|
60
|
+
ENV['GL_HOST'] = @_forge_host
|
|
61
|
+
end
|
|
46
62
|
|
|
47
63
|
return if options['no_change']
|
|
48
64
|
|
|
@@ -52,12 +68,8 @@ class SugarJar
|
|
|
52
68
|
private
|
|
53
69
|
|
|
54
70
|
def forked_repo(repo, username)
|
|
55
|
-
repo =
|
|
56
|
-
|
|
57
|
-
else
|
|
58
|
-
"#{File.basename(repo)}.git"
|
|
59
|
-
end
|
|
60
|
-
"git@#{@ghhost || 'github.com'}:#{username}/#{repo}"
|
|
71
|
+
repo = extract_repo(repo)
|
|
72
|
+
"git@#{forge_host}:#{username}/#{repo}.git"
|
|
61
73
|
end
|
|
62
74
|
|
|
63
75
|
# gh utils will default to https, but we should always default to SSH
|
|
@@ -66,12 +78,34 @@ class SugarJar
|
|
|
66
78
|
# if they fully-qualified it, we're good
|
|
67
79
|
return repo if repo.start_with?('http', 'git@')
|
|
68
80
|
|
|
69
|
-
# otherwise,
|
|
70
|
-
cr = "git@#{
|
|
81
|
+
# otherwise, it's a shortname
|
|
82
|
+
cr = "git@#{forge_host}:#{repo}.git"
|
|
71
83
|
SugarJar::Log.debug("canonicalized #{repo} to #{cr}")
|
|
72
84
|
cr
|
|
73
85
|
end
|
|
74
86
|
|
|
87
|
+
def forge_host
|
|
88
|
+
# if one is specifically configured, use that
|
|
89
|
+
return @_forge_host if @_forge_host
|
|
90
|
+
|
|
91
|
+
# otherwise, if we're in a repo, use the hostname of the remote
|
|
92
|
+
if SugarJar::Util.in_repo?
|
|
93
|
+
url = remote_url_map.values.first
|
|
94
|
+
return extract_host(url)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
@repo_forge == 'gitlab' ? 'gitlab.com' : 'github.com'
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def repo_shortname(repo)
|
|
101
|
+
# if it's already a shortname, return
|
|
102
|
+
return repo unless repo.start_with?('http', 'git@')
|
|
103
|
+
|
|
104
|
+
repo_name = extract_repo(repo)
|
|
105
|
+
org_name = extract_org(repo)
|
|
106
|
+
[org_name, repo_name].join('/')
|
|
107
|
+
end
|
|
108
|
+
|
|
75
109
|
def set_commit_template
|
|
76
110
|
unless SugarJar::Util.in_repo?
|
|
77
111
|
SugarJar::Log.debug('Skipping set_commit_template: not in repo')
|
|
@@ -137,7 +171,7 @@ class SugarJar
|
|
|
137
171
|
end
|
|
138
172
|
|
|
139
173
|
def determine_main_branch(branches)
|
|
140
|
-
branches.include?('
|
|
174
|
+
branches.include?('master') ? 'master' : 'main'
|
|
141
175
|
end
|
|
142
176
|
|
|
143
177
|
def main_branch
|
|
@@ -263,7 +297,7 @@ class SugarJar
|
|
|
263
297
|
|
|
264
298
|
# Whatever org we push to, regardless of if this is a fork or not
|
|
265
299
|
def push_org
|
|
266
|
-
url =
|
|
300
|
+
url = remote_url_map['origin']
|
|
267
301
|
extract_org(url)
|
|
268
302
|
end
|
|
269
303
|
|
|
@@ -282,8 +316,8 @@ class SugarJar
|
|
|
282
316
|
end
|
|
283
317
|
end
|
|
284
318
|
|
|
285
|
-
def
|
|
286
|
-
!!SugarJar::Util.which_nofail(
|
|
319
|
+
def forge_cli_avail?
|
|
320
|
+
!!SugarJar::Util.which_nofail(_forge_cmd)
|
|
287
321
|
end
|
|
288
322
|
|
|
289
323
|
def fprefix(name)
|
|
@@ -310,12 +344,12 @@ class SugarJar
|
|
|
310
344
|
|
|
311
345
|
def extract_org(repo)
|
|
312
346
|
if repo.start_with?('http')
|
|
313
|
-
|
|
347
|
+
repo.split('://').last.split('/')[1..-2].join('/')
|
|
314
348
|
elsif repo.start_with?('git@')
|
|
315
|
-
repo.split(':')
|
|
349
|
+
repo.split(':').last.split('/')[0..-2].join('/')
|
|
316
350
|
else
|
|
317
|
-
# assume they passed in a
|
|
318
|
-
repo.split('/').
|
|
351
|
+
# assume they passed in a cli-friendly shortname
|
|
352
|
+
repo.split('/')[0..-2].join('/')
|
|
319
353
|
end
|
|
320
354
|
end
|
|
321
355
|
|
|
@@ -323,11 +357,23 @@ class SugarJar
|
|
|
323
357
|
File.basename(repo, '.git')
|
|
324
358
|
end
|
|
325
359
|
|
|
360
|
+
def extract_host(repo)
|
|
361
|
+
if repo.start_with?('git@')
|
|
362
|
+
repo.split(':').first.split('@').last
|
|
363
|
+
elsif repo.start_with?('http')
|
|
364
|
+
repo.split('/')[2]
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
326
368
|
def die(msg)
|
|
327
369
|
SugarJar::Log.fatal(msg)
|
|
328
370
|
exit(1)
|
|
329
371
|
end
|
|
330
372
|
|
|
373
|
+
def release_branches
|
|
374
|
+
@repo_config['release_branches'] || []
|
|
375
|
+
end
|
|
376
|
+
|
|
331
377
|
def worktree_branches
|
|
332
378
|
worktrees.values.map do |wt|
|
|
333
379
|
branch_from_ref(wt['branch'])
|
|
@@ -373,12 +419,34 @@ class SugarJar
|
|
|
373
419
|
SugarJar::Util.git_nofail(*, :color => @color)
|
|
374
420
|
end
|
|
375
421
|
|
|
376
|
-
def
|
|
377
|
-
SugarJar::Util.
|
|
422
|
+
def _determine_forge_type
|
|
423
|
+
if SugarJar::Util.in_repo?
|
|
424
|
+
gl = remote_url_map.values.any? { |x| x.include?('gitlab') }
|
|
425
|
+
return gl ? 'gitlab' : 'github'
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
# if all else fails, guess GH
|
|
429
|
+
'github'
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def _forge_cmd
|
|
433
|
+
@repo_forge == 'gitlab' ? 'glab' : 'gh'
|
|
378
434
|
end
|
|
379
435
|
|
|
380
|
-
def
|
|
381
|
-
|
|
436
|
+
def forge(*)
|
|
437
|
+
if @repo_forge == 'gitlab'
|
|
438
|
+
SugarJar::Util.glcli(*)
|
|
439
|
+
else
|
|
440
|
+
SugarJar::Util.ghcli(*)
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def forge_nofail(*)
|
|
445
|
+
if @repo_forge == 'gitlab'
|
|
446
|
+
SugarJar::Util.glcli_nofail(*)
|
|
447
|
+
else
|
|
448
|
+
SugarJar::Util.ghcli_nofail(*)
|
|
449
|
+
end
|
|
382
450
|
end
|
|
383
451
|
end
|
|
384
452
|
end
|
data/lib/sugarjar/config.rb
CHANGED
|
@@ -7,9 +7,11 @@ class SugarJar
|
|
|
7
7
|
class Config
|
|
8
8
|
DEFAULTS = {
|
|
9
9
|
'github_user' => ENV.fetch('USER'),
|
|
10
|
+
'gitlab_user' => ENV.fetch('USER'),
|
|
10
11
|
'pr_autofill' => true,
|
|
11
12
|
'pr_autostack' => nil,
|
|
12
13
|
'color' => true,
|
|
14
|
+
'use_forks' => true,
|
|
13
15
|
'ignore_deprecated_options' => [],
|
|
14
16
|
}.freeze
|
|
15
17
|
|
|
@@ -27,6 +29,10 @@ class SugarJar
|
|
|
27
29
|
SugarJar::Log.debug("Loading config #{f}")
|
|
28
30
|
data = YAML.safe_load_file(f)
|
|
29
31
|
warn_on_deprecated_configs(data, f)
|
|
32
|
+
if data['github_host']
|
|
33
|
+
data['forge_host'] = data['github_host'] if data['forge_host'].nil?
|
|
34
|
+
data.delete('github_host')
|
|
35
|
+
end
|
|
30
36
|
# an empty file is a `nil` which you can't merge
|
|
31
37
|
c.merge!(YAML.safe_load_file(f)) if data
|
|
32
38
|
SugarJar::Log.debug("Modified config: #{c}")
|
|
@@ -41,14 +47,37 @@ class SugarJar
|
|
|
41
47
|
|
|
42
48
|
if ignore_deprecated_options.include?(opt)
|
|
43
49
|
SugarJar::Log.debug(
|
|
44
|
-
"Not warning about deprecated option
|
|
45
|
-
'
|
|
50
|
+
"#{fname}: Not warning about deprecated option `#{opt}` due to " +
|
|
51
|
+
'`ignore_deprecated_options` in that file.',
|
|
46
52
|
)
|
|
47
53
|
next
|
|
48
54
|
end
|
|
49
55
|
SugarJar::Log.warn(
|
|
50
|
-
"
|
|
51
|
-
'suppress this warning with ignore_deprecated_options
|
|
56
|
+
"#{fname}: contains deprecated option `#{opt}`. You can " +
|
|
57
|
+
'suppress this warning with `ignore_deprecated_options`.',
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# github_host has special handling
|
|
62
|
+
return unless data['github_host']
|
|
63
|
+
|
|
64
|
+
if ignore_deprecated_options.include?('github_host')
|
|
65
|
+
SugarJar::Log.debug(
|
|
66
|
+
"#{fname}: Deprecated option `github_host` found, but not " +
|
|
67
|
+
'warning due to `ignore_deprecated_options` in that file.',
|
|
68
|
+
)
|
|
69
|
+
elsif data.key?('forge_host')
|
|
70
|
+
SugarJar::Log.warn(
|
|
71
|
+
"#{fname}: Deprecated option `github_host` found. " +
|
|
72
|
+
'Ignoring in favor of newer `force_host` option. You can ' +
|
|
73
|
+
'suppress this warning with `ignore_deprecated_options`.',
|
|
74
|
+
)
|
|
75
|
+
else
|
|
76
|
+
SugarJar::Log.warn(
|
|
77
|
+
"#{fname}: Deprecated option `github_host` found. " +
|
|
78
|
+
'Treating it as if it was `forge_host` for now. Please update ' +
|
|
79
|
+
'your config file to use this new option. You can suppress ' +
|
|
80
|
+
'this warning with `ignore_deprecated_options`.',
|
|
52
81
|
)
|
|
53
82
|
end
|
|
54
83
|
end
|
data/lib/sugarjar/log.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'mixlib/log'
|
|
2
2
|
|
|
3
|
+
# rubocop:disable Style/OneClassPerFile
|
|
3
4
|
module Mixlib
|
|
4
5
|
module Log
|
|
5
6
|
# A simple formatter so that 'info' is just like 'puts'
|
|
@@ -22,3 +23,4 @@ class SugarJar
|
|
|
22
23
|
extend Mixlib::Log
|
|
23
24
|
end
|
|
24
25
|
end
|
|
26
|
+
# rubocop:enable Style/OneClassPerFile
|