git-whistles 1.0.2 → 1.1.0

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