sugarjar 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2c4dd59aaf4843033f5c38df43b3fdfa556298708bc7f437f2923e00f9133c8
4
- data.tar.gz: 5edeeb730db94059fd10b115b192ed239782b797473eb3b1fcf5aa749ca23e95
3
+ metadata.gz: c9a62438fa0d483eb64cd28cb5de3e603d6907a353194fac8df0bc8cd51a55f1
4
+ data.tar.gz: ff816417124253671a07ffe4ee2c6cb066a3b8f3f6dc0bac439a667297b595bf
5
5
  SHA512:
6
- metadata.gz: 3869512549691df320f1dc344424b65944cd8cb501e25cd1a982f9b8d4d92cf608531147a8c5eb7a7437eee7644683ef9cf57e6035c44b61e4d247eec3331e03
7
- data.tar.gz: 159e663e59a6c2aa939a5e9aecb90ce811bb9a168476d842ced28eab7a9968b760daec22661455a7bdaf3ac75ecc11a1c706e2ea07a6368ab653bcc3a222a597
6
+ metadata.gz: a97436c810c10af47d507eeb8c29070da38927884aef6f6ffaa39a9476777ba88e4c176fdb69ab67a979c832c3d32339f1c848c97ef1f6ecd5dcf17025f2b9e0
7
+ data.tar.gz: 478d20bcc6c8ed561f2ab6294d38a0e3267a96f0e239a565e498b483505dff950ad1712931a777012141e955438bb5f082db75698eb478a36981666bba38af19
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # SugjarJar
1
+ # SugarJar
2
2
 
3
3
  ![CI](https://github.com/jaymzh/sugarjar/workflows/CI/badge.svg)
4
4
 
@@ -12,84 +12,219 @@ the Phabricator workflow this aims to bring to the GitHub workflow.
12
12
  In particular there are a lot of helpers for using a squash-merge workflow that
13
13
  is poorly handled by the standard toolsets.
14
14
 
15
- ## Commands
15
+ If you miss Mondrian or Phabrictor - this is the tool for you!
16
16
 
17
- ### amend
17
+ If you don't, there's a ton of useful stuff for everyone!
18
18
 
19
- Amend the current commit. Alias for `git commit --amend`. Accepts other
20
- arguments such as `-a` or files.
19
+ ## Auto cleanup squash-merged branches
21
20
 
22
- ### amendq, qamend
21
+ It is common for a PR to go back and forth with a variety of nits, lint fixes,
22
+ typos, etc. that can muddy history. So many projects will "squash and merge"
23
+ when they accept a pull request. Howevet, that means `git branch -d <branch>`
24
+ doesn't work. Git will tell you the branch isn't fully merged. You can, of
25
+ course `git branch -D <branch>`, but that does no safety checks at all, it
26
+ forces the deletion.
23
27
 
24
- Same as `amend` but without changing the message. Alias for `git commit --amend
25
- --no-edit`.
28
+ Enter `sj bclean` - it determines of the contents of your branch has been merge
29
+ and safely deletes if so.
26
30
 
27
- ### bclean
31
+ ``` shell
32
+ sj bclean
33
+ ```
34
+
35
+ Will delete a branch, if it has been merged, **even if it was squash-merged**.
28
36
 
29
- If safe, delete the current branch. Unlike `git branch -d`, bclean can handle
30
- squash-merged branches. Think of it as a smarter `git branch -d`.
37
+ You can pass it a branch if you'd like (it defaults to the branch you're on):
38
+ `sj bclean <branch>`.
31
39
 
32
- ### bcleanall
40
+ But it gets better! You can use `sj bcleanall` to remove all branches that have
41
+ been merged:
42
+
43
+ ```shell
44
+ $ git branch
45
+ * argparse
46
+ master
47
+ feature
48
+ hubhost
49
+ $ git bcleanall
50
+ Skipping branch argparse - there are unmerged commits
51
+ Reaped branch feature
52
+ Reaped branch hubhost
53
+ ```
33
54
 
34
- Walk all branches, and try to delete them if it's safe. See `bclean` for
35
- details.
55
+ ## Smarter clones and remotes
56
+
57
+ There's a pattern to every new repo we want to contribute to. First we fork,
58
+ then we clone the fork, then we add a remote of the upstream repo. It's
59
+ monotonous. SugarJar does this for you:
60
+
61
+ ```shell
62
+ sj smartclone jaymzh/sugarjar
63
+ ```
36
64
 
37
- ### binfo
65
+ (also `sj sclone`)
38
66
 
39
- Verbose information about the current branch.
67
+ This will:
40
68
 
41
- ### br
69
+ * Make a fork of the repo, if you don't already have one
70
+ * Clone your fork
71
+ * Add the original as an 'upstream' remote
42
72
 
43
- Verbose branch list. An alias for `git branch -v`.
73
+ Note that it takes `hub`s short-names for repos. No need to specify a full URL,
74
+ just a $org/$repo.
44
75
 
45
- ### feature
76
+ Like `git clone`, `sj sclone` will accept an additional arguement as the
77
+ destination directory to clone to. It will also pass any other unknown options
78
+ to `git clone` under the hood.
46
79
 
47
- Create a "feature branch." It's morally equivalent to `git checkout -b` except
48
- it defaults to creating it based on some form of 'master' instead of your
49
- current branch. In order of preference it will be `upstream/master`,
50
- `origin/master`, or `master`, depending upon what remotes are available.
80
+ ## Work with stacked branches more easily
51
81
 
52
- ### forcepush, fpush
82
+ It's important to break changes into reviewable chunks, but working with
83
+ stacked branches can be confusing. Enter `binfo` - it gives you a view of your
84
+ current branch all the way up to master. In this example imagine we have a
85
+ branch structure like:
53
86
 
54
- The same as `smartpush`, but uses `--force-with-lease`. This is a "safer" way
55
- of doing force-pushes and is the recommended way to push after rebasing or
56
- amending. Never do this to shared branches. Very convenient for keeping the
57
- branch behind a pull-request clean.
87
+ ```text
88
+ +- test2.1
89
+ /
90
+ master --- test --- test2 --- test3
91
+ ```
58
92
 
59
- ### lint
93
+ This is what `binfo` on test3 looks like:
60
94
 
61
- Run any linters configured in `.sugarjar.yaml`.
95
+ ```shell
96
+ $ sj binfo
97
+ * e451865 (HEAD -> test3) test3
98
+ * e545b41 (test2) test2
99
+ * c808eae (test1) test1
100
+ o 44cf9e2 (origin/master, origin/HEAD, master) Lint/gemspec cleanups
101
+ ```
62
102
 
63
- ### smartclone, sclone
103
+ while `binfo` on test2.1 looks like:
64
104
 
65
- A smart wrapper to `git clone` that handles forking and managing remotes for
66
- you. It will clone a git repository using hub-style short name (`$org/$repo`).
67
- If the org of the repository is not the same as your github-user then it will
68
- fork the repo for you to your account (if not already done) and then setup your
69
- remotes so that `origin` is your fork and `upstream` is the upstream.
105
+ ```shell
106
+ $ sj binfo
107
+ * 36d0136 (HEAD -> test2.1) test2.1
108
+ * e545b41 (test2) test2
109
+ * c808eae (test1) test1
110
+ o 44cf9e2 (origin/master, origin/HEAD, master) Lint/gemspec cleanups
111
+ ```
70
112
 
71
- ### smartpush, spush
113
+ ## Have a better lint/unittest experience!
72
114
 
73
- A smart wrapper to `git push` that runs whatever is defined in `on_push` in
74
- `.sugarjar.yml`, and only pushes if they succeed.
115
+ Ever made a PR, only to find out later that it failed tests because of some
116
+ small lint issue? Not anymore! SJ can be configured to run things before
117
+ pushing. For example,in the SugarJar repo, we have it run Rubocop (ruby lint)
118
+ and Markdownlint "on_push". If those fail, it lets you know and doesn't push.
75
119
 
76
- It will also allow you to not specify a remote or branch, and will default to
77
- `origin` and whatever your current local branch name is.
120
+ You can configure SugarJar to tell how how to run both lints and unittests for
121
+ a given repo and if one or both should be run prior to pushing.
78
122
 
79
- ### unit
123
+ The details on the config file format is below, but we provide three commands:
80
124
 
81
- Run any unitests configured in `.sugarjar.yaml`.
125
+ ```shell
126
+ git lint
127
+ ```
82
128
 
83
- ### up
129
+ Run all linters.
84
130
 
85
- Rebase the current branch on the branch it's tracking, or if it's tracking one
86
- then, otherise `upstream/master` if it exists, or `origin/master`.
131
+ ```shell
132
+ git unit
133
+ ```
87
134
 
88
- ### upall
135
+ Run all unittests.
89
136
 
90
- Same as `up`, but for all branches.
137
+ ```shell
138
+ git smartpush # or spush
139
+ ```
91
140
 
92
- ## User Configuration
141
+ Run configured push-time actions (nothing, lint, unit, both), and do not
142
+ push if any of them fail.
143
+
144
+ ## Better push defaults
145
+
146
+ In addition to running pre-push tests for you `smartpush` also picks smart
147
+ defaults for push. So if you `sj spush` with no arguements, it uses the
148
+ `origin` remote and the same branch name you're on as the remote branch.
149
+
150
+ ## Cleaning up your own history
151
+
152
+ Perhaps you contribute to a project that prefers to use merge commits, so you
153
+ like to clean up your own history. This is often difficult to get right - a
154
+ combination of rebases, amends and force pushes. We provide two commands here
155
+ to help.
156
+
157
+ The first is pretty straight forward and is basically just an alias: `sj
158
+ amend`. It will ammend whatever you want to the most recent commit (just an
159
+ alias for `git commit --amend`). It has a partner `qamend` (or `amendq` if you
160
+ prefer) that will do so without prompting to update your commit message.
161
+
162
+ So now you've rebased or amended, pushing becomes challening. You can `git push
163
+ --force`, but everyone knows that's incredibly dangerous. Is there a better
164
+ way? There is! Git provides `git push --force-with-lease` - it checks to make
165
+ sure you're up-to-date with the remote before forcing the push. But man that
166
+ command is a mouthful! Enter `sj fpush`. It has all the smarts of `sj
167
+ smartpush` (runs configured pre-push actions), but adds `--force-with-lease` to
168
+ the command!
169
+
170
+ ## Better feature branches
171
+
172
+ When you want to start a new feature, you want to start developing against
173
+ latest. That's why `sj feature` defaults to creating a branch against what we
174
+ call "most master". That is, `upstream/master` if it exists, otherwise
175
+ `origin/master` if that exists, otherwise `master`. You can pass in an
176
+ additional arguement to base it off of something else.
177
+
178
+ ```shell
179
+ $ git branch
180
+ master
181
+ test1
182
+ test2
183
+ * test2.1
184
+ test3
185
+ $ sj feature test-branch
186
+ Created feature branch test-branch based on origin/master
187
+ $ sj feature dependent-feature test-branch
188
+ Created feature branch dependent-feature based on test-branch
189
+ ```
190
+
191
+ ## And more!
192
+
193
+ See `sj help` for more commands!
194
+
195
+ ## Using SugarJar as a git wrapper
196
+
197
+ SugarJar, by default, will pass any command it doesn't know straight to `hub`
198
+ (which passes commands **it** doesn't know to `git`). As such you can alias it
199
+ to `git` and just have a super-git.
200
+
201
+ ```shell
202
+ $ alias git=sj
203
+ $ git config -l | grep color
204
+ color.diff=auto
205
+ color.status=auto
206
+ color.branch=auto
207
+ color.branch.current=yellow reverse
208
+ color.branch.local=yellow
209
+ color.branch.remote=green
210
+ $ git br
211
+ * dependent-feature 44cf9e2 Lint/gemspec cleanups
212
+ master 44cf9e2 Lint/gemspec cleanups
213
+ test-branch 44cf9e2 Lint/gemspec cleanups
214
+ test1 c808eae [ahead 1] test1
215
+ test2 e545b41 test2
216
+ test2.1 c1831b3 test2.1
217
+ test3 e451865 test3
218
+ ```
219
+
220
+ It's for this reason that SugarJar doesn't have conflicting command names. You
221
+ can turn off fallthru by setting `fallthru: false` in your config.
222
+
223
+ The only command we "override" is `version`, in which case we not only print
224
+ our version, but also call `hub version` which prints its version and calls
225
+ `git version` too!
226
+
227
+ ## Configuration
93
228
 
94
229
  Sugarjar will read in both a system-level config file
95
230
  (`/etc/sugarjar/config.yaml`) and a user-level config file
@@ -133,17 +268,41 @@ on_push:
133
268
  - lint
134
269
  ```
135
270
 
271
+ ## Enterprise GitHub
272
+
273
+ Like `hub`, SugarJar supports GitHub Enterprise. In fact, we provide extra
274
+ features just for it.
275
+
276
+ We recommend the global or user config specify the `github_host`. However, most
277
+ users will also have a few repos from upstream so always specifying a
278
+ `github_host` is sub-optimal.
279
+
280
+ So, when you overwrite the `github_host` on the command line, we go ahead and
281
+ set the `hub.host` git config in that single repo so that it'll "just work"
282
+ from there on out.
283
+
284
+ In other words, assuming your global SJ config has `github_host:
285
+ github.sample.com`, and the you clone sugarjar with:
286
+
287
+ ```shell
288
+ sj clone jaymzh/sugarjar --github-host githuh.com
289
+ ```
290
+
291
+ We will add the `hub.host` to the `sugarjar` clone so that future `hub` or `sj`
292
+ commands work without needing to specify..
293
+
136
294
  ## FAQ
137
295
 
138
296
  Why the name SugarJar?
139
297
 
140
- It's mostly a backranym. Like jellyfish, I wanted two letters that were on
141
- home row on different sides of the keyboard to make it easy to type. I looked
142
- at the possible options that where there and not taken and tried to find one
143
- I could make an appropriate name out of. Since this utility adds lots of sugar
144
- to git and github, it seemed appropriate.
298
+ It's mostly a backranym. Like jellyfish, I wanted two letters that were on home
299
+ row on different sides of the keyboard to make it easy to type. I looked at the
300
+ possible options that where there and not taken and tried to find one I could
301
+ make an appropriate name out of. Since this utility adds lots of sugar to git
302
+ and github, it seemed appropriate.
145
303
 
146
304
  Why did you use `hub` instead of the newer `gh` CLI?
147
305
 
148
- `gh` is less feature-rich (currently). I'm also considering making this optionally
149
- act as a wrapper to `hub` the way `hub` can be a wrapper to `git`.
306
+ `gh` is still new and not yet as feature rich as `hub`. Also I wanted SugarJar
307
+ to be able to be a git wrapper, and so wrapping `hub` allows us to do that but
308
+ wrapping `gh` does not.
@@ -22,6 +22,8 @@ class SugarJar
22
22
  SugarJar::Log.debug("Feature: #{name}, #{base}")
23
23
  die("#{name} already exists!") if all_branches.include?(name)
24
24
  base ||= most_master
25
+ base_pieces = base.split('/')
26
+ hub('fetch', base_pieces[0]) if base_pieces.length > 1
25
27
  hub('checkout', '-b', name, base)
26
28
  SugarJar::Log.info("Created feature branch #{name} based on #{base}")
27
29
  end
@@ -44,16 +46,16 @@ class SugarJar
44
46
  # rubocop:disable Style/Next
45
47
  unless clean_branch(branch)
46
48
  SugarJar::Log.info(
47
- "Skipping branch #{branch} - there are unmerged commits"
49
+ "Skipping branch #{branch} - there are unmerged commits",
48
50
  )
49
51
  end
50
52
  # rubocop:enable Style/Next
51
53
  end
52
54
  end
53
55
 
54
- def co(name)
56
+ def co(*args)
55
57
  assert_in_repo
56
- hub('checkout', name)
58
+ hub('checkout', *args)
57
59
  end
58
60
 
59
61
  def br
@@ -82,7 +84,7 @@ class SugarJar
82
84
  def amend(*args)
83
85
  assert_in_repo
84
86
  # This cannot use shellout since we need a full terminal for the editor
85
- exit(system('/usr/bin/git', 'commit', '--amend', *args))
87
+ exit(system(which('git'), 'commit', '--amend', *args))
86
88
  end
87
89
 
88
90
  def qamend(*args)
@@ -104,7 +106,7 @@ class SugarJar
104
106
  else
105
107
  SugarJar::Log.error(
106
108
  "Failed to rebase #{branch}, aborting that and moving to next " +
107
- 'branch'
109
+ 'branch',
108
110
  )
109
111
  hub('rebase', '--abort')
110
112
  end
@@ -202,10 +204,15 @@ class SugarJar
202
204
  if current == @ghost
203
205
  SugarJar::Log.debug('Repo hub.host already set correctly')
204
206
  else
205
- SugarJar::Log.info(
206
- "Overwriting repo hub.host from #{current} to #{@ghhost}"
207
+ # Even though we have an explicit config, in most cases, it
208
+ # comes from a global or user config, but the config in the
209
+ # local repo we likely set. So we'd just constantly revert that.
210
+ SugarJar::Log.debug(
211
+ "Not overwriting repo hub.host. Already set to #{current}. " +
212
+ "To change it, run `git config --local --add hub.host #{@ghhost}`",
207
213
  )
208
214
  end
215
+ return
209
216
  end
210
217
  hub('config', '--local', '--add', 'hub.host', @ghhost)
211
218
  end
@@ -287,7 +294,7 @@ class SugarJar
287
294
  end
288
295
  if out.length.zero?
289
296
  SugarJar::Log.debug(
290
- "cherry-pick shows branch #{branch} obviously safe to delete"
297
+ "cherry-pick shows branch #{branch} obviously safe to delete",
291
298
  )
292
299
  return true
293
300
  end
@@ -303,10 +310,10 @@ class SugarJar
303
310
  s = hub_nofail('merge', '--squash', branch)
304
311
  if s.error?
305
312
  cleanup_tmp_branch(tmpbranch, branch)
306
- error(
313
+ SugarJar::Log.error(
307
314
  'Failed to merge changes into current master. This means we could ' +
308
315
  'not figure out if this is merged or not. Check manually and use ' +
309
- "'git branch -D #{branch}' if it is safe to do so."
316
+ "'git branch -D #{branch}' if it is safe to do so.",
310
317
  )
311
318
  return false
312
319
  end
@@ -317,12 +324,12 @@ class SugarJar
317
324
  cleanup_tmp_branch(tmpbranch, branch)
318
325
  if out.empty?
319
326
  SugarJar::Log.debug(
320
- 'After squash-merging, this branch appears safe to delete'
327
+ 'After squash-merging, this branch appears safe to delete',
321
328
  )
322
329
  true
323
330
  else
324
331
  SugarJar::Log.debug(
325
- 'After squash-merging, this branch is NOT fully merged to master'
332
+ 'After squash-merging, this branch is NOT fully merged to master',
326
333
  )
327
334
  false
328
335
  end
@@ -22,7 +22,9 @@ class SugarJar
22
22
  c = DEFAULTS.dup
23
23
  _find_ordered_files.each do |f|
24
24
  SugarJar::Log.debug("Loading config #{f}")
25
- c.merge!(YAML.safe_load(File.read(f)))
25
+ data = YAML.safe_load(File.read(f))
26
+ # an empty file is a `nil` which you can't merge
27
+ c.merge!(YAML.safe_load(File.read(f))) if data
26
28
  SugarJar::Log.debug("Modified config: #{c}")
27
29
  end
28
30
  c
@@ -3,9 +3,32 @@ require_relative 'log'
3
3
  class SugarJar
4
4
  # Some common methods needed by other classes
5
5
  module Util
6
+ # Finds the first entry in the path for a binary and checks
7
+ # to make sure it's not us (i.e. we may be linked to as 'git'
8
+ # or 'hub', but when we are calling that, we don't want ourselves.
9
+ def which_nofail(cmd)
10
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
11
+ p = File.join(dir, cmd)
12
+ # if it exists, and it is executable and is not us...
13
+ if File.exist?(p) && File.executable?(p) &&
14
+ File.basename(File.realpath(p)) != 'sj'
15
+ return p
16
+ end
17
+ end
18
+ false
19
+ end
20
+
21
+ def which(cmd)
22
+ path = which_nofail(cmd)
23
+ return path if path
24
+
25
+ SugarJar::Log.fatal("Could not find #{cmd} in your path")
26
+ exit(1)
27
+ end
28
+
6
29
  def hub_nofail(*args)
7
30
  SugarJar::Log.trace("Running: hub #{args.join(' ')}")
8
- Mixlib::ShellOut.new(['/usr/bin/hub'] + args).run_command
31
+ Mixlib::ShellOut.new([which('hub')] + args).run_command
9
32
  end
10
33
 
11
34
  def hub(*args)
@@ -1,3 +1,3 @@
1
1
  class SugarJar
2
- VERSION = '0.0.1'.freeze
2
+ VERSION = '0.0.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sugarjar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Dibowitz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-05 00:00:00.000000000 Z
11
+ date: 2020-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-log
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: yaml
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: bundler
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -130,7 +116,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
116
  - !ruby/object:Gem::Version
131
117
  version: '0'
132
118
  requirements: []
133
- rubygems_version: 3.0.3
119
+ rubyforge_project:
120
+ rubygems_version: 2.7.6.2
134
121
  signing_key:
135
122
  specification_version: 4
136
123
  summary: A git/github helper script