git-whistles 1.0.2 → 1.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cdbbcadb6c855b3aa67a6daf8c8b05c1872ca75b
4
- data.tar.gz: fb2487cc9827db9edcf36fc6a5fccc739a8ef3ac
3
+ metadata.gz: 4304a8f417f4f756f4c2522288980894837415ce
4
+ data.tar.gz: d295f0cbd94e9d4dc09a3ab957928324809c122d
5
5
  SHA512:
6
- metadata.gz: 78c7d6c34c2f4f8996152002eaa7bb0933d0ec5a0629e22cbc46f898c2c302dbb21039717aeed1740836cf2cd82b6b78444ef7f0f7587a6e5f5634ea53cbb953
7
- data.tar.gz: 92bb64c2bdedb443a0378a597b6e35f988c7d77dee073e30bfb60e7d880cfad244dd9164578ba94b5e0bcc73ad169f7d380246755911e216194c891666fcff14
6
+ metadata.gz: 51ad1985a2f3fe9cf36a5eb55672f2a434d522407b0eed62e0fff7daeb1ccaed6ea0636700705b101f32cabddfac24309ef8ffd8059c4659503abc2e69f15e13
7
+ data.tar.gz: 754aa0292b9ad21327a127b9e1815854fd767f95e1f51b4b021f49ca4a944308a13880222b2791eceb12d4abe7d12833d07a119d070197a37e41df2db69d9513
data/.gitignore CHANGED
@@ -7,3 +7,4 @@ pkg
7
7
  rdoc
8
8
  tmp
9
9
  nbproject
10
+ .idea/
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- git-whistles (1.0.2)
4
+ git-whistles (1.1.0)
5
5
  jira-ruby
6
6
  pivotal-tracker (~> 0.5.6)
7
7
  term-ansicolor
@@ -9,7 +9,7 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- activesupport (4.2.5)
12
+ activesupport (4.2.5.1)
13
13
  i18n (~> 0.7)
14
14
  json (~> 1.7, >= 1.7.7)
15
15
  minitest (~> 5.1)
@@ -20,7 +20,7 @@ GEM
20
20
  crack (0.4.3)
21
21
  safe_yaml (~> 1.0.0)
22
22
  diff-lcs (1.2.5)
23
- domain_name (0.5.25)
23
+ domain_name (0.5.20160128)
24
24
  unf (>= 0.0.5, < 1.0.0)
25
25
  http-cookie (1.0.2)
26
26
  domain_name (~> 0.5)
@@ -79,7 +79,7 @@ GEM
79
79
  thread_safe (~> 0.1)
80
80
  unf (0.1.4)
81
81
  unf_ext
82
- unf_ext (0.0.7.1)
82
+ unf_ext (0.0.7.2)
83
83
 
84
84
  PLATFORMS
85
85
  ruby
data/README.md CHANGED
@@ -17,6 +17,8 @@ Install with:
17
17
 
18
18
  `git jira-branch <issue-id>` - Creates a branch name suggestion from the specified JIRA issue ID. It also writes the branch name as a comment on the issue and allows to transition the issue.
19
19
 
20
+ `git jira-pr [--from your-branch] [--to target-branch]` - Open your browser at a Github pull-request page for the specified branch (defaults to the current `head`). If you're using JIRA and your branch has a issue id in its name, populates your pull request with that issue details, else it just creates an empty Pull Request from the current HEAD.
21
+
20
22
  `git latest-pushes [-n NR_RESULTS] [-p PATTERN]` - Show latest pushed branches to origin. Defaults to 20 results. Pattern is appended to refs/remotes/origin/ so include the team or project name to filter results.
21
23
 
22
24
  `git list-branches [-l] [-r] [-i integration-branch]` - Colourful listing of all local or origin branches, and their distance to an integration branch (`master` by default).
data/bin/git-chop ADDED
@@ -0,0 +1 @@
1
+ ../libexec/runner.rb
data/bin/git-jira-branch CHANGED
@@ -14,11 +14,15 @@ require 'jira'
14
14
  require 'readline'
15
15
  require 'term/ansicolor'
16
16
  require 'git-whistles/app'
17
+ require 'git-whistles/jira'
17
18
 
18
19
  class App < Git::Whistles::App
19
20
 
20
21
  def initialize
21
22
  super
23
+
24
+ @jira = Git::Whistles::Jira.new
25
+ @client = @jira.get_client
22
26
  end
23
27
 
24
28
  def main(args)
@@ -34,7 +38,7 @@ class App < Git::Whistles::App
34
38
  # get JIRA Issue info
35
39
  issue = get_jira_info(issue_id)
36
40
 
37
- branch_name_suggested = "#{issue_id.upcase}-#{issue.fields['summary'].downcase}"
41
+ branch_name_suggested = "#{issue_id.upcase}/#{issue.fields['summary'].downcase}"
38
42
  branch_name_suggested.gsub!(/[^\w\d\/]/, '-').gsub!(/-+/, '-')
39
43
 
40
44
  puts 'The suggested branch name is: ' << Term::ANSIColor.yellow(branch_name_suggested)
@@ -105,50 +109,9 @@ class App < Git::Whistles::App
105
109
  end
106
110
 
107
111
  def get_jira_info(issue_id)
108
- if username.empty?
109
- puts Term::ANSIColor.yellow %Q{
110
- Your branch appears to have a issue ID,
111
- but I don't know your JIRA username!
112
- Please set it with:
113
- $ git config [--global] jira.username <username>
114
- }
115
- die "Aborting."
116
- end
117
-
118
- password = `git config jira.password`.strip
119
- if password.empty?
120
- puts Term::ANSIColor.yellow %Q{
121
- Your branch appears to have a issue ID,
122
- but I don't know your JIRA password!
123
- Please set it with:
124
- $ git config [--global] jira.password <password>
125
- }
126
- die "Aborting."
127
- end
128
-
129
- site = `git config jira.site`.strip
130
- if site.empty?
131
- puts Term::ANSIColor.yellow %Q{
132
- Your branch appears to have a issue ID,
133
- but I don't know your JIRA site!
134
- Please set it with:
135
- $ git config [--global] jira.site <https://mydomain.atlassian.net>
136
- }
137
- die "Aborting."
138
- end
139
112
  log.info "Finding your JIRA Issue¬"
140
113
 
141
- options = {
142
- username: username,
143
- password: password,
144
- site: site,
145
- context_path: '',
146
- auth_type: :basic,
147
- read_timeout: 120
148
- }
149
-
150
- client = JIRA::Client.new(options)
151
- issue = client.Issue.find(issue_id)
114
+ issue = @client.Issue.find(issue_id)
152
115
 
153
116
  log.info '.'
154
117
  log.info "Found issue #{issue_id} in '#{issue.fields['project']['name']}'"
data/bin/git-jira-pr ADDED
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ #
4
+ # git-jira-pr --
5
+ #
6
+ # Open a pull request for the current branch in your default browser
7
+ #
8
+ # Assumes the branches are named
9
+ # <team>/<branch-title>-<story-id>
10
+ #
11
+ require 'rubygems'
12
+ require 'jira'
13
+ require 'optparse'
14
+ require 'cgi'
15
+ require 'term/ansicolor'
16
+ require 'git-whistles/app'
17
+ require 'git-whistles/jira'
18
+
19
+ class App < Git::Whistles::App
20
+
21
+ BROWSERS = %w(xdg-open open firefox iceweasel)
22
+ SAFE_QUERY_STRING_SIZE = 8000
23
+
24
+ def initialize
25
+ super
26
+
27
+ @client = Git::Whistles::Jira.new.get_client
28
+ end
29
+
30
+ def main(args)
31
+ super
32
+ parse_args!(args)
33
+
34
+ if args.count > 0
35
+ die "Too many arguments", :usage => true
36
+ end
37
+
38
+ if options.from == options.to
39
+ die "You cannot issue a pull request to the same branch (#{options.from})."
40
+ end
41
+
42
+ query = { }
43
+
44
+ # guess team name
45
+ if options.from =~ %r{^(\w+-\w+)/.*}
46
+ team, issue_id = $1.capitalize.split('-')
47
+ else
48
+ issue_id = team = nil
49
+ end
50
+
51
+ # guess title.
52
+ title = options.from.split('/').last.split(/[_-]/).delete_if { |word| word =~ /^\d+$/ }.join(' ').capitalize
53
+ query[:"pull_request[title]"] = team ? "#{team}: #{title}" : title
54
+
55
+ # add Jira infos
56
+ add_jira_info(query, "#{team}-#{issue_id}".upcase) if issue_id =~ /(\d+)$/
57
+
58
+ query_string = query.map { |key,value|
59
+ "#{CGI.escape key.to_s}=#{CGI.escape value}"
60
+ }.join('&')
61
+ url = "https://github.com/#{repo}/compare/#{options.to}...#{options.from}?#{query_string}"
62
+
63
+ puts "Preparing a pull request for branch #{options.from}"
64
+
65
+ unless launch_browser(url)
66
+ log.warn "Sorry, I don't know how to launch a web browser on your system. You can open it yourself and paste this URL:\n#{url}"
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def defaults
73
+ {
74
+ :from => run!('git symbolic-ref HEAD').strip.gsub(%r(^refs/heads/), ""),
75
+ :to => 'master',
76
+ :remote => 'origin'
77
+ }
78
+ end
79
+
80
+ def option_parser
81
+ @option_parser ||= OptionParser.new do |op|
82
+ op.banner = "Usage: git jira-pr [options]"
83
+
84
+ op.on("-f", "--from YOUR_BRANCH", "Branch to issue pull request for [head]") do |v|
85
+ options.from = v
86
+ end
87
+
88
+ op.on("-to", "--to UPSTREAM_BRANCH", "Branch into which you want your code merged [master]") do |v|
89
+ options.to = v
90
+ end
91
+
92
+ op.on("-r", "--remote NAME", "The remote you're sending this to [origin]") do |v|
93
+ options.to = v
94
+ end
95
+ end
96
+ end
97
+
98
+ def origin_url
99
+ @origin_url ||= begin
100
+ run!("git config --get remote.#{options.remote}.url").strip.tap do |url|
101
+ url =~ /github\.com/ or die "origin does not have a Github URL !"
102
+ end
103
+ end
104
+ end
105
+
106
+ def repo
107
+ @repo ||= origin_url.sub(/.*github\.com[\/:]/,'').sub(/\.git$/,'')
108
+ end
109
+
110
+ def add_jira_info(query, issue_id)
111
+ log.info "Finding your Jira Issue¬"
112
+
113
+ issue = @client.Issue.find(issue_id)
114
+ log.info '.'
115
+
116
+ if issue.nil?
117
+ log.warn "Apologies... I could not find issue #{issue_id}."
118
+ return
119
+ end
120
+
121
+ log.info "Found story #{issue_id} in '#{issue.fields['project']['name']}'"
122
+
123
+ title = "#{issue_id}: #{issue.summary}"
124
+ headline = "Jira story [##{issue_id}](#{@client.options[:site]}/browse/#{issue_id}) in project *#{issue.project.name}*:"
125
+ description = issue.description.split("\n").map do |line|
126
+ (1..6).each { |i| line.gsub!(/(h#{i}.)/, '#' * i) }
127
+ line.gsub!(/({{)|(}})/, '`')
128
+ "> #{line}"
129
+ end.join("\n")
130
+
131
+ query.merge! subject: issue.summary, :"pull_request[title]" => title
132
+
133
+ if (headline.length + description.length) > SAFE_QUERY_STRING_SIZE
134
+ log.warn "Oops looks like your story body exceeds maximum allowed caracters to send a github request"
135
+ log.warn "Please copy the info below to your pull request body:"
136
+ puts
137
+ puts headline
138
+ puts
139
+ puts
140
+ puts description
141
+ puts
142
+ puts
143
+ puts "Press any key to continue..."
144
+ gets
145
+ query.merge! :"pull_request[body]" => "Please check your command line for the story body"
146
+ else
147
+ body = "TODO: describe your changes\n\n===\n\n#{headline}\n\n#{description}"
148
+ query.merge! :"pull_request[body]" => body
149
+ end
150
+ end
151
+
152
+ def launch_browser(url)
153
+ BROWSERS.each do |command|
154
+ next if run("which #{command}").strip.empty?
155
+ system(command, url) and return true
156
+ end
157
+ false
158
+ end
159
+
160
+ end
161
+
162
+ ############################################################################
163
+
164
+ App.run!
@@ -0,0 +1 @@
1
+ ../libexec/runner.rb
data/bin/git-merge-po ADDED
@@ -0,0 +1 @@
1
+ ../libexec/runner.rb
@@ -0,0 +1 @@
1
+ ../libexec/runner.rb
@@ -0,0 +1,62 @@
1
+ module Git
2
+ module Whistles
3
+ class Jira
4
+ attr_reader :username, :password, :site
5
+
6
+ def initialize
7
+ get_config
8
+ end
9
+
10
+ def get_client(opts = {})
11
+ options = {
12
+ username: @username,
13
+ password: @password,
14
+ site: @site,
15
+ context_path: '',
16
+ auth_type: :basic,
17
+ read_timeout: 120
18
+ }
19
+
20
+ options.merge!(opts)
21
+
22
+ JIRA::Client.new(options)
23
+ end
24
+
25
+ def get_config
26
+ @username = `git config jira.username`.strip
27
+ if username.empty?
28
+ puts Term::ANSIColor.yellow %Q{
29
+ Your branch appears to have a issue ID,
30
+ but I don't know your JIRA username!
31
+ Please set it with:
32
+ $ git config [--global] jira.username <username>
33
+ }
34
+ die "Aborting."
35
+ end
36
+
37
+ @password = `git config jira.password`.strip
38
+ if password.empty?
39
+ puts Term::ANSIColor.yellow %Q{
40
+ Your branch appears to have a issue ID,
41
+ but I don't know your JIRA password!
42
+ Please set it with:
43
+ $ git config [--global] jira.password <password>
44
+ }
45
+ die "Aborting."
46
+ end
47
+
48
+ @site = `git config jira.site`.strip
49
+ if site.empty?
50
+ puts Term::ANSIColor.yellow %Q{
51
+ Your branch appears to have a issue ID,
52
+ but I don't know your JIRA site!
53
+ Please set it with:
54
+ $ git config [--global] jira.site <https://mydomain.atlassian.net>
55
+ }
56
+ die "Aborting."
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+ end
@@ -4,7 +4,7 @@ require 'pathname'
4
4
 
5
5
  module Git
6
6
  module Whistles
7
- VERSION = "1.0.2"
7
+ VERSION = "1.1.0"
8
8
  GEMDIR = Pathname.new(__FILE__).parent.parent.parent
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-whistles
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julien Letessier
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-01-23 00:00:00.000000000 Z
12
+ date: 2016-02-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -131,6 +131,7 @@ executables:
131
131
  - git-explore
132
132
  - git-ff-all-branches
133
133
  - git-jira-branch
134
+ - git-jira-pr
134
135
  - git-latest-pushes
135
136
  - git-list-branches
136
137
  - git-merge-po
@@ -155,6 +156,7 @@ files:
155
156
  - bin/git-explore
156
157
  - bin/git-ff-all-branches
157
158
  - bin/git-jira-branch
159
+ - bin/git-jira-pr
158
160
  - bin/git-latest-pushes
159
161
  - bin/git-list-branches
160
162
  - bin/git-merge-po
@@ -168,6 +170,7 @@ files:
168
170
  - lib/git-whistles.rb
169
171
  - lib/git-whistles/app.rb
170
172
  - lib/git-whistles/helpers.rb
173
+ - lib/git-whistles/jira.rb
171
174
  - lib/git-whistles/logger.rb
172
175
  - lib/git-whistles/version.rb
173
176
  - libexec/git-chop.sh
@@ -200,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
203
  version: 1.3.6
201
204
  requirements: []
202
205
  rubyforge_project:
203
- rubygems_version: 2.4.5.1
206
+ rubygems_version: 2.5.1
204
207
  signing_key:
205
208
  specification_version: 4
206
209
  summary: 'A few helpers for classic Git workflows: makes branching and merging, PO
data/bin/git-chop DELETED
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
- #
4
- # runner.rb --
5
- #
6
- # Run shell scripts from a gem.
7
- # Symlink to this script to run a script with the same name living in
8
- # libexec/.
9
- #
10
- require 'pathname'
11
- require 'rubygems'
12
- require 'git-whistles'
13
-
14
- target_script = Pathname.new($0).basename
15
- script_path = Git::Whistles::GEMDIR.join('libexec', "#{target_script}.sh").cleanpath.to_s
16
-
17
- Kernel.exec script_path, *ARGV
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
- #
4
- # runner.rb --
5
- #
6
- # Run shell scripts from a gem.
7
- # Symlink to this script to run a script with the same name living in
8
- # libexec/.
9
- #
10
- require 'pathname'
11
- require 'rubygems'
12
- require 'git-whistles'
13
-
14
- target_script = Pathname.new($0).basename
15
- script_path = Git::Whistles::GEMDIR.join('libexec', "#{target_script}.sh").cleanpath.to_s
16
-
17
- Kernel.exec script_path, *ARGV
data/bin/git-merge-po DELETED
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
- #
4
- # runner.rb --
5
- #
6
- # Run shell scripts from a gem.
7
- # Symlink to this script to run a script with the same name living in
8
- # libexec/.
9
- #
10
- require 'pathname'
11
- require 'rubygems'
12
- require 'git-whistles'
13
-
14
- target_script = Pathname.new($0).basename
15
- script_path = Git::Whistles::GEMDIR.join('libexec', "#{target_script}.sh").cleanpath.to_s
16
-
17
- Kernel.exec script_path, *ARGV
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
- #
4
- # runner.rb --
5
- #
6
- # Run shell scripts from a gem.
7
- # Symlink to this script to run a script with the same name living in
8
- # libexec/.
9
- #
10
- require 'pathname'
11
- require 'rubygems'
12
- require 'git-whistles'
13
-
14
- target_script = Pathname.new($0).basename
15
- script_path = Git::Whistles::GEMDIR.join('libexec', "#{target_script}.sh").cleanpath.to_s
16
-
17
- Kernel.exec script_path, *ARGV