twig 1.3 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.md CHANGED
@@ -1,6 +1,22 @@
1
1
  Twig
2
2
  ====
3
3
 
4
+ 1.4 (2013-08-07)
5
+ ----------------
6
+ * ENHANCEMENT: Speed up listing branches by 3–4x.
7
+ * ENHANCEMENT: Add `twig diff`, which diffs the current branch against its
8
+ `diff-branch` property, and `twig diff <branch>`, which diffs the given branch
9
+ against its `diff-branch` property.
10
+ * ENHANCEMENT: Add `twig rebase`, which rebases the current branch onto the
11
+ branch in its `diff-branch` property, and `twig rebase <branch>`, which
12
+ rebases the given branch onto its `diff-branch`.
13
+ * ENHANCEMENT: Add `twig init-completion --force` for overwriting existing
14
+ completion scripts. Useful for upgrading to the latest Twig completion
15
+ scripts.
16
+ * ENHANCEMENT: Improve `twig gh-update` error reporting by listing the affected
17
+ API endpoints upon failure.
18
+ * FIX: Deprecate `~/.twigrc` in favor of `~/.twigconfig`.
19
+
4
20
  1.3 (2013-05-22)
5
21
  ----------------
6
22
  * ENHANCEMENT: Add `--branch-width` and `--<property>-width` options for setting
@@ -43,7 +59,7 @@ Twig
43
59
  * FIX: Handle line breaks gracefully in `~/.twigrc` config file.
44
60
  * FIX: Exit with a non-zero status when trying to get or unset a branch property
45
61
  that isn't set, or trying to set a branch property to an invalid value.
46
- * FIX : Don't allow getting/setting/unsetting a branch property whose name is an
62
+ * FIX: Don't allow getting/setting/unsetting a branch property whose name is an
47
63
  empty string.
48
64
 
49
65
  1.0.1 (2013-02-13)
data/README.md CHANGED
@@ -44,6 +44,7 @@ chronologically with their properties.
44
44
  * `twig <property> <value> -b <branch>`: Set property for any branch
45
45
  * `twig --unset <property> -b <branch>`: Unset property for any branch
46
46
  * `twig init-completion`: Set up tab completion for `-b` and `--branch`
47
+ * `twig init-completion --force`: Update to the latest tab completion script
47
48
  * `twig --help`: More info
48
49
 
49
50
 
@@ -131,15 +132,15 @@ Remember the order in which you were rebasing your stack of branches:
131
132
  $ git checkout master
132
133
  Switched to branch 'master'.
133
134
 
134
- $ twig rebase-onto branch2 -b branch3
135
- Saved property "rebase-onto" as "branch2" for branch "branch3".
135
+ $ twig diff-branch branch2 -b branch3
136
+ Saved property "diff-branch" as "branch2" for branch "branch3".
136
137
 
137
- $ twig rebase-onto branch1 -b branch2
138
- Saved property "rebase-onto" as "branch1" for branch "branch2".
138
+ $ twig diff-branch branch1 -b branch2
139
+ Saved property "diff-branch" as "branch1" for branch "branch2".
139
140
 
140
141
  $ twig
141
142
 
142
- rebase-onto branch
143
+ diff-branch branch
143
144
  ----------- ------
144
145
  2013-01-26 18:00:25 (7m ago) branch2 branch3
145
146
  2013-01-26 16:49:47 (2h ago) branch1 branch2
@@ -152,17 +153,93 @@ You can set just about any custom property you need to remember for each branch.
152
153
  Subcommands
153
154
  ===========
154
155
 
155
- Twig comes with a few subcommands that are handy for use with GitHub
156
- repositories: `gh-open`, `gh-open-issue`, and `gh-update`.
156
+ A Twig subcommand is a little script that makes use of a branch's Twig
157
+ properties. You can [write your own](#writing-a-subcommand), but here are some
158
+ subcommands that Twig comes with.
157
159
 
158
- While inside a Git repo, run `twig gh-open` to see the repo's GitHub URL, and open
159
- a browser window if possible:
160
+
161
+ twig diff
162
+ ---------
163
+
164
+ If you have a stack of branches with different parent branches, it gets tricky
165
+ to remember which branch to diff against. `twig diff` makes it easy:
166
+
167
+ $ git checkout branch2
168
+
169
+ # Remember your branch's diff branch:
170
+ $ twig diff-branch branch1
171
+ Saved property "diff-branch" as "branch1" for branch "branch2".
172
+
173
+ # Generate a diff between branch1 (the current branch) and branch2:
174
+ $ twig diff
175
+
176
+ More usage:
177
+
178
+ # Generate a diff between any given branch and its `diff-branch`:
179
+ $ twig diff my-other-branch
180
+
181
+ # Pass options through to `git diff`:
182
+ $ twig diff --stat
183
+
184
+ # Pipe results to a diff viewer:
185
+ $ twig diff | gitx
186
+
187
+
188
+ twig rebase
189
+ -----------
190
+
191
+ If you have a stack of branches that you need to rebase in the same order,
192
+ `twig rebase` simplifies the process:
193
+
194
+ $ git checkout branch2
195
+
196
+ # Remember your branches' diff (parent) branches:
197
+ $ twig diff-branch branch1
198
+ Saved property "diff-branch" as "branch1" for branch "branch2".
199
+
200
+ # Rebase branch2 (the current branch) onto branch1:
201
+ $ twig rebase
202
+ Rebase "branch2" onto "development"? (y/n)
203
+
204
+ More usage:
205
+
206
+ # Rebase any given branch onto its `diff-branch`:
207
+ $ twig rebase my-other-branch
208
+
209
+ # Pass options through to `git rebase`:
210
+ $ twig rebase -i
211
+
212
+
213
+ twig gh-open
214
+ ------------
215
+
216
+ While inside a GitHub repo, run `twig gh-open` to see the repo's GitHub URL, and
217
+ open a browser window if possible:
160
218
 
161
219
  $ cd myproject
162
220
 
163
221
  $ twig gh-open
164
222
  GitHub URL: https://github.com/myname/myproject
165
223
 
224
+
225
+ twig gh-open-issue
226
+ ------------------
227
+
228
+ For any branch that has an `issue` property, you can use the `gh-open-issue`
229
+ subcommand to view that issue on GitHub:
230
+
231
+ # Current branch:
232
+ $ twig gh-open-issue
233
+ GitHub issue URL: https://github.com/myname/myproject/issues/111
234
+
235
+ # Any branch:
236
+ $ twig gh-open-issue -b <branch name>
237
+ GitHub issue URL: https://github.com/myname/myproject/issues/222
238
+
239
+
240
+ twig gh-update
241
+ --------------
242
+
166
243
  If you're working on an issue for a GitHub repository, the `gh-update`
167
244
  subcommand syncs issue statuses with GitHub:
168
245
 
@@ -181,6 +258,7 @@ subcommand syncs issue statuses with GitHub:
181
258
  2013-01-22 17:12:23 (4d ago) - - master
182
259
 
183
260
  $ twig gh-update
261
+ Getting latest states for GitHub issues...
184
262
  # Automatically looks up the GitHub issue status for each
185
263
  # of your local branches, and saves it locally.
186
264
 
@@ -194,16 +272,9 @@ subcommand syncs issue statuses with GitHub:
194
272
 
195
273
  Run `twig gh-update` periodically to keep up with GitHub issues locally.
196
274
 
197
- For any branch that has an `issue` property, you can use the `gh-open-issue`
198
- subcommand to view that issue on GitHub:
199
275
 
200
- # Current branch:
201
- $ twig gh-open-issue
202
- GitHub issue URL: https://github.com/myname/myproject/issues/111
203
-
204
- # Any branch:
205
- $ twig gh-open-issue -b <branch name>
206
- GitHub issue URL: https://github.com/myname/myproject/issues/222
276
+ Writing a subcommand
277
+ --------------------
207
278
 
208
279
  You can write any Twig subcommand that fits your own Git workflow. To write a
209
280
  Twig subcommand:
@@ -231,8 +302,8 @@ Some ideas for subcommands:
231
302
  emailing your team about what you're up to.
232
303
  * Create a gem that contains your team's favorite custom Twig subcommands.
233
304
 
234
- If you write a subcommand that others can appreciate, send a pull request or add
235
- it to the [Twig wiki][wiki]!
305
+ If you write a subcommand that others might appreciate, send a pull request or
306
+ add it to the [Twig wiki][wiki]!
236
307
 
237
308
 
238
309
  More info
data/bin/twig CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # Entry point for Twig: <http://rondevera.github.io/twig/>
4
+
3
5
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'twig'))
4
6
 
5
7
  repo_required = ARGV != ['--help'] && ARGV != ['help'] && ARGV != ['--version']
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Summary:
4
+ #
5
+ # `twig diff [<branch>] [<options>]`
6
+ #
7
+ # Usage:
8
+ #
9
+ # - `twig diff`:
10
+ # Shows the diff between the current branch and its `diff-branch` property.
11
+ #
12
+ # - `twig diff <options>`:
13
+ # Shows the diff between the current branch and its `diff-branch`, and passes
14
+ # options through to `git-diff`, e.g., `twig diff --stat`.
15
+ #
16
+ # - `twig diff <branch>`:
17
+ # Shows the diff between the given branch and its `diff-branch` property.
18
+ #
19
+ # - `twig diff <branch> <options>`:
20
+ # Shows the diff between the given branch and its `diff-branch`, and passes
21
+ # options through to `git-diff`, e.g., `twig diff my_branch --stat`.
22
+ #
23
+ # Subcommand for Twig: <http://rondevera.github.io/twig/>
24
+ # Author: Ron DeVera <http://rondevera.com>
25
+
26
+ args = ARGV.dup
27
+
28
+ branch_given = args.any? && args.first[0, 1] != '-'
29
+ topic_branch = args.shift.strip if branch_given # Use given branch
30
+ topic_branch ||= `git rev-parse --abbrev-ref HEAD`.strip # Use current branch
31
+
32
+ diff_branch = `twig diff-branch -b "#{topic_branch}"`.strip
33
+ diff_options = args.join(' ') # Pass remaining options to `git-diff`
34
+
35
+ abort if diff_branch.empty?
36
+
37
+ puts %{Getting diff of "#{topic_branch}" against "#{diff_branch}"...}
38
+ exec %{git diff "#{diff_branch}" "#{topic_branch}" #{diff_options}}
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Opens a browser window for the current GitHub repo.
4
4
  #
5
+ # Subcommand for Twig: <http://rondevera.github.io/twig/>
5
6
  # Author: Ron DeVera <http://rondevera.com>
6
7
 
7
8
  require 'rubygems'
@@ -9,7 +10,13 @@ require 'twig'
9
10
  require 'launchy'
10
11
 
11
12
  Twig::GithubRepo.new do |gh_repo|
12
- url = "https://github.com/#{gh_repo.username}/#{gh_repo.repository}"
13
+ twig = Twig.new
14
+ twig.read_config_file!
15
+ twig.read_cli_options!(ARGV)
16
+
17
+ gh_uri_prefix = twig.options[:github_uri_prefix] || 'https://github.com'
18
+ url = "#{gh_uri_prefix}/#{gh_repo.username}/#{gh_repo.repository}"
19
+
13
20
  puts "GitHub URL: #{url}"
14
21
  Launchy.open(url) rescue nil
15
22
  end
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  # Usage:
4
+ #
4
5
  # - `twig gh-open-issue`:
5
6
  # Opens a browser window for the GitHub issue, if any, for the current branch.
7
+ #
6
8
  # - `twig gh-open-issue -b <branch>`:
7
9
  # Opens the GitHub issue, if any, for the specified branch.
8
10
  #
11
+ # Subcommand for Twig: <http://rondevera.github.io/twig/>
9
12
  # Author: Ron DeVera <http://rondevera.com>
10
13
 
11
14
  require 'rubygems'
@@ -14,7 +17,9 @@ require 'launchy'
14
17
 
15
18
  Twig::GithubRepo.new do |gh_repo|
16
19
  twig = Twig.new
20
+ twig.read_config_file!
17
21
  twig.read_cli_options!(ARGV)
22
+
18
23
  branch_name = twig.options[:branch] || twig.current_branch_name
19
24
  issue_id = twig.get_branch_property(branch_name, 'issue')
20
25
 
@@ -22,7 +27,8 @@ Twig::GithubRepo.new do |gh_repo|
22
27
  abort %{The branch "#{branch_name}" doesn't have an "issue" property.}
23
28
  end
24
29
 
25
- url = "https://github.com/#{gh_repo.username}/#{gh_repo.repository}"
30
+ gh_uri_prefix = twig.options[:github_uri_prefix] || 'https://github.com'
31
+ url = "#{gh_uri_prefix}/#{gh_repo.username}/#{gh_repo.repository}"
26
32
  url << "/issues/#{issue_id}"
27
33
 
28
34
  puts "GitHub issue URL: #{url}"
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Updates each branch with the latest issue status on GitHub.
4
4
  #
5
+ # Subcommand for Twig: <http://rondevera.github.io/twig/>
5
6
  # Author: Ron DeVera <http://rondevera.com>
6
7
 
7
8
  require File.join(File.dirname(__FILE__), '..', 'lib', 'twig')
@@ -19,14 +20,18 @@ Twig::GithubRepo.new do |gh_repo|
19
20
  print 'Getting latest states for GitHub issues...'
20
21
 
21
22
  issues = {}
23
+ issues_uri_prefix = twig.options[:github_api_uri_prefix] || 'https://api.github.com'
22
24
  issues_uri_base =
23
- "https://api.github.com/repos/#{gh_repo.username}/#{gh_repo.repository}/issues"
25
+ "#{issues_uri_prefix}/repos/#{gh_repo.username}/#{gh_repo.repository}/issues"
24
26
  issues_uris = [
25
27
  URI.parse("#{issues_uri_base}?state=open"),
26
28
  URI.parse("#{issues_uri_base}?state=closed")
27
29
  ]
28
30
  user_agent = "Twig/#{Twig::VERSION} (for Git; <#{Twig::HOMEPAGE}>)"
29
31
 
32
+ error = "\n\nERROR: Couldn't get open issues from GitHub." <<
33
+ "\n- API endpoints: " << issues_uris.map { |uri| "<#{uri}>" }.join(', ')
34
+
30
35
  begin
31
36
  issues_uris.each do |issues_uri|
32
37
  http = Net::HTTP.new(issues_uri.host, issues_uri.port)
@@ -44,10 +49,11 @@ Twig::GithubRepo.new do |gh_repo|
44
49
  issues[issue_data['number']] = issue_data
45
50
  end
46
51
  else
47
- abort "\nERROR: Couldn't get open issues from GitHub. " <<
48
- "(Response: #{response.code})"
52
+ abort error + "\n- Response: #{response.code}"
49
53
  end
50
54
  end
55
+ rescue OpenSSL::SSL::SSLError => exception
56
+ abort error
51
57
  end
52
58
 
53
59
  twig.branches.each do |branch|
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Your friendly neighborhood `twig --help` alias.
4
4
  #
5
+ # Subcommand for Twig: <http://rondevera.github.io/twig/>
5
6
  # Author: Ron DeVera <http://rondevera.com>
6
7
 
7
8
  puts `twig --help`
@@ -3,9 +3,11 @@
3
3
  # Initializes tab completion for Twig. To use this, run
4
4
  # `twig init-completion` and follow the instructions.
5
5
  #
6
+ # Subcommand for Twig: <http://rondevera.github.io/twig/>
6
7
  # Author: Ron DeVera <http://rondevera.com>
7
8
 
8
- debug = ARGV.include?('--debug')
9
+ args = ARGV.dup
10
+ debug = args.delete('--debug')
9
11
  bash_version = `bash -c 'echo $BASH_VERSION'`.strip
10
12
 
11
13
  if debug
@@ -13,5 +15,5 @@ if debug
13
15
  puts "- bash_version: #{bash_version.inspect}"
14
16
  end
15
17
 
16
- exec('twig-init-completion-bash') if bash_version != ''
18
+ exec('twig-init-completion-bash ' + args.join(' ')) if bash_version != ''
17
19
  abort 'Could not initialize Twig tab completion for this shell.'
@@ -3,6 +3,7 @@
3
3
  # Initializes bash tab completion for Twig. To use this, run
4
4
  # `twig init-completion` and follow the instructions.
5
5
  #
6
+ # Subcommand for Twig: <http://rondevera.github.io/twig/>
6
7
  # Author: Ron DeVera <http://rondevera.com>
7
8
 
8
9
  require 'fileutils'
@@ -12,17 +13,19 @@ script = <<-SCRIPT
12
13
 
13
14
  #!/usr/bin/env bash
14
15
 
15
- # AUTO-GENERATED with Twig v#{version}. Regenerate with `twig init-completion`.
16
+ # AUTO-GENERATED with Twig v#{version}. Regenerate with
17
+ # `twig init-completion --force`.
16
18
  #
17
19
  # Initializes bash tab completion for Twig. To use this, run
18
20
  # `twig init-completion` and follow the instructions.
19
21
  #
22
+ # Twig: <http://rondevera.github.io/twig/>
20
23
  # Author: Ron DeVera <http://rondevera.com>
21
24
 
22
25
  __twig_branches() {
23
26
  local current words
24
27
  current="${COMP_WORDS[COMP_CWORD]}"
25
- words="$(git for-each-ref refs/heads/ --format="%(refname:short)" | tr '\n' ' ')"
28
+ words="$(git for-each-ref refs/heads/ --format="%(refname:short)" | tr '\\n' ' ')"
26
29
  COMPREPLY=($(compgen -W "$words" -- "$current"))
27
30
  return 0
28
31
  }
@@ -36,6 +39,9 @@ __twig() {
36
39
 
37
40
  case "${previous}" in
38
41
  -b|--branch) __twig_branches ;;
42
+ diff) __twig_branches ;;
43
+ diff-branch) __twig_branches ;;
44
+ rebase) __twig_branches ;;
39
45
  esac
40
46
 
41
47
  return 0
@@ -48,16 +54,29 @@ script = script.strip + "\n"
48
54
 
49
55
 
50
56
 
57
+ args = ARGV.dup
58
+ force = args.delete('--force')
59
+
51
60
  twig_dir = '~/.twig'
52
61
  FileUtils.mkdir_p(File.expand_path(twig_dir))
53
62
 
54
- script_path = File.join(twig_dir, '/twig-completion.bash')
63
+ script_path = File.join(twig_dir, '/twig-completion.bash')
55
64
  full_script_path = File.expand_path(script_path)
56
- unless File.exists?(full_script_path)
65
+ script_exists = File.exists?(full_script_path)
66
+
67
+ if script_exists && !force
68
+ puts "The file `#{script_path}` already exists."
69
+ puts "To overwrite it, run `twig init-completion --force`."
70
+ else
57
71
  File.open(full_script_path, 'w') do |file|
58
72
  file.write script
59
73
  end
60
- puts "Created #{script_path}."
74
+
75
+ if script_exists
76
+ puts "Overwrote #{script_path}."
77
+ else
78
+ puts "Created #{script_path}."
79
+ end
61
80
  end
62
81
 
63
82
  puts
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Summary:
4
+ #
5
+ # `twig rebase [<branch>] [<options>]`
6
+ #
7
+ # Usage:
8
+ #
9
+ # - `twig rebase`:
10
+ # Rebases the current branch onto the branch in its `diff-branch` property.
11
+ #
12
+ # - `twig rebase <options>`:
13
+ # Rebases the current branch onto its `diff-branch`, and passes options
14
+ # through to `git-rebase`, e.g., `twig rebase -i`.
15
+ #
16
+ # - `twig rebase <branch>`:
17
+ # Rebases the given branch onto its `diff-branch`.
18
+ #
19
+ # - `twig rebase <branch> <options>`:
20
+ # Rebases the given branch and its `diff-branch`, and passes options
21
+ # through to `git-rebase`, e.g., `twig rebase my_branch -i`.
22
+ #
23
+ # Subcommand for Twig: <http://rondevera.github.io/twig/>
24
+ # Author: Ron DeVera <http://rondevera.com>
25
+
26
+ args = ARGV.dup
27
+
28
+ branch_given = args.any? && args.first[0, 1] != '-'
29
+ topic_branch = args.shift.strip if branch_given # Use given branch
30
+ topic_branch ||= `git rev-parse --abbrev-ref HEAD`.strip # Use current branch
31
+
32
+ base_branch = `twig diff-branch -b "#{topic_branch}"`.strip
33
+ rebase_options = args.join(' ') # Pass remaining options to `git-rebase`
34
+
35
+ abort if base_branch.empty?
36
+
37
+ print %{Rebase "#{topic_branch}" onto "#{base_branch}"? (y/n) }
38
+ input = STDIN.gets.strip.downcase
39
+ if input == 'y' || input == 'yes'
40
+ exec %{git rebase #{rebase_options} "#{base_branch}" "#{topic_branch}"}
41
+ else
42
+ puts 'Cancelled.'
43
+ end