twig 1.3 → 1.4

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.
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