git-issue 0.7.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.
- data/.document +5 -0
- data/LICENSE +20 -0
- data/README.markdown +115 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/bin/git-issue +8 -0
- data/git-issue.gemspec +62 -0
- data/images/git-issue_screenshot-1.png +0 -0
- data/images/git-issue_screenshot-2.png +0 -0
- data/lib/git_issue.rb +96 -0
- data/lib/git_issue/base.rb +263 -0
- data/lib/git_issue/github.rb +362 -0
- data/lib/git_issue/redmine.rb +450 -0
- data/spec/git_issue/base_spec.rb +78 -0
- data/spec/git_issue/github_spec.rb +186 -0
- data/spec/git_issue/redmine_spec.rb +70 -0
- data/spec/git_issue_spec.rb +39 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +9 -0
- metadata +113 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Tomohito Ozaki
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
git-issue
|
2
|
+
====================================================
|
3
|
+
|
4
|
+
git subcommand of browse/modify issue traker's tickets.
|
5
|
+
|
6
|
+
now supporse Redmine,Github-issues
|
7
|
+
|
8
|
+
## ScreenShots
|
9
|
+
|
10
|
+
<img src='https://github.com/yuroyoro/git-issue/raw/master/images/git-issue_screenshot-1.png' width='600'/>
|
11
|
+
<img src='https://github.com/yuroyoro/git-issue/raw/master/images/git-issue_screenshot-2.png' width='600'/>
|
12
|
+
|
13
|
+
## Instration
|
14
|
+
|
15
|
+
$ git clone https://github.com/yuroyoro/git-issue.git
|
16
|
+
$ cd git-issue
|
17
|
+
$ rake install jeweler
|
18
|
+
$ rake build
|
19
|
+
$ gem install pkg/git-issue-<version>.gem
|
20
|
+
|
21
|
+
## Configuration
|
22
|
+
|
23
|
+
set type of issue traking system(redmine or github)
|
24
|
+
|
25
|
+
$ git config issue.type redmine
|
26
|
+
|
27
|
+
set url of issue traking system's api endopoint.
|
28
|
+
|
29
|
+
$ git config issue.url http://redmine.example.com
|
30
|
+
|
31
|
+
set api-key for accessing issue traking system.
|
32
|
+
|
33
|
+
$ git config issue.apikey FWeaj3I9laei03A....
|
34
|
+
|
35
|
+
set repository name if using github.
|
36
|
+
|
37
|
+
$ git config issue.repo gitterb
|
38
|
+
|
39
|
+
set your account name if using github.
|
40
|
+
|
41
|
+
$ git config issue.user yuroyoro
|
42
|
+
|
43
|
+
## Usage(Redmine)
|
44
|
+
|
45
|
+
git issue <command> [ticket_id] [<args>]
|
46
|
+
|
47
|
+
Commnads:
|
48
|
+
show s show given issue summary. if given no id, geuss id from current branch name.
|
49
|
+
list l listing issues.
|
50
|
+
mine m display issues that assigned to you.
|
51
|
+
commit c commit with filling issue subject to messsage.if given no id, geuss id from current branch name.
|
52
|
+
update u update issue properties. if given no id, geuss id from current branch name.
|
53
|
+
branch b checout to branch using specified issue id. if branch dose'nt exisits, create it. (ex ticket/id/<issue_id>)
|
54
|
+
publish pub push branch to remote repository and set upstream
|
55
|
+
rebase rb rebase branch onto specific newbase
|
56
|
+
help h show usage.
|
57
|
+
local loc listing local branches tickets
|
58
|
+
project prj listing ticket belongs to sspecified project
|
59
|
+
|
60
|
+
Options:
|
61
|
+
-a, --all update all paths in the index file
|
62
|
+
-f, --force force create branch
|
63
|
+
-v, --verbose show issue details
|
64
|
+
-n, --max-count=VALUE maximum number of issues
|
65
|
+
--oneline display short info
|
66
|
+
--raw-id output ticket number only
|
67
|
+
--remote=VALUE on publish, remote repository to push branch
|
68
|
+
--onto=VALUE on rebase, start new branch with HEAD equal to "newbase"
|
69
|
+
--debug debug print
|
70
|
+
-j, --supperss_journals show issue journals
|
71
|
+
-r, --supperss_relations show issue relations tickets
|
72
|
+
-c, --supperss_changesets show issue changesets
|
73
|
+
-q, --query=VALUE filter query of listing tickets
|
74
|
+
--subject=VALUE use the given value to update subject
|
75
|
+
--ratio=VALUE use the given value to update done-ratio(%)
|
76
|
+
--status=VALUE use the given value to update issue statues id
|
77
|
+
--priority=VALUE use the given value to update issue priority id
|
78
|
+
--tracker=VALUE use the given value to update tracker id
|
79
|
+
--assigned_to_id=VALUE use the given value to update assigned_to id
|
80
|
+
--category=VALUE use the given value to update category id
|
81
|
+
--fixed_version=VALUE use the given value to update fixed_version id
|
82
|
+
--custom_fields=VALUE value should be specifies '<custom_fields_id1>:<value2>,<custom_fields_id2>:<value2>, ...'
|
83
|
+
--notes=VALUE add notes to issue
|
84
|
+
|
85
|
+
## Usage(Redmine)
|
86
|
+
|
87
|
+
git issue <command> [ticket_id] [<args>]
|
88
|
+
|
89
|
+
Commnads:
|
90
|
+
show s show given issue summary. if given no id, geuss id from current branch name.
|
91
|
+
list l listing issues.
|
92
|
+
mine m display issues that assigned to you.
|
93
|
+
commit c commit with filling issue subject to messsage.if given no id, geuss id from current branch name.
|
94
|
+
update u update issue properties. if given no id, geuss id from current branch name.
|
95
|
+
branch b checout to branch using specified issue id. if branch dose'nt exisits, create it. (ex ticket/id/<issue_id>)
|
96
|
+
publish pub push branch to remote repository and set upstream
|
97
|
+
rebase rb rebase branch onto specific newbase
|
98
|
+
help h show usage.
|
99
|
+
|
100
|
+
Options:
|
101
|
+
-a, --all update all paths in the index file
|
102
|
+
-f, --force force create branch
|
103
|
+
-v, --verbose show issue details
|
104
|
+
-n, --max-count=VALUE maximum number of issues
|
105
|
+
--oneline display short info
|
106
|
+
--raw-id output ticket number only
|
107
|
+
--remote=VALUE on publish, remote repository to push branch
|
108
|
+
--onto=VALUE on rebase, start new branch with HEAD equal to "newbase"
|
109
|
+
--debug debug print
|
110
|
+
-s, --supperss_commentsc show issue journals
|
111
|
+
--state=VALUE Where 'state' is either 'open' or 'closed'
|
112
|
+
|
113
|
+
## Copyright
|
114
|
+
|
115
|
+
Copyright (c) 2011 Tomohito Ozaki. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "git-issue"
|
8
|
+
gem.summary = %Q{git extention command for issue tracker system.}
|
9
|
+
gem.description = %Q{git extention command for issue tracker system.}
|
10
|
+
gem.email = "ozaki@yuroyoro.com"
|
11
|
+
gem.homepage = "http://github.com/yuroyoro/git-issue"
|
12
|
+
gem.authors = ["Tomohito Ozaki"]
|
13
|
+
gem.add_development_dependency "rspec"
|
14
|
+
gem.add_development_dependency "activesupport"
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rspec/core/rake_task'
|
22
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
23
|
+
# spec.libs << 'lib' << 'spec'
|
24
|
+
# spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
26
|
+
end
|
27
|
+
|
28
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
29
|
+
# spec.libs << 'lib' << 'spec'
|
30
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
31
|
+
spec.rcov = true
|
32
|
+
end
|
33
|
+
|
34
|
+
task :spec => :check_dependencies
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
require 'rdoc/task'
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
if File.exist?('VERSION')
|
41
|
+
version = File.read('VERSION')
|
42
|
+
else
|
43
|
+
version = ""
|
44
|
+
end
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "git-issue #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.7.0
|
data/bin/git-issue
ADDED
data/git-issue.gemspec
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{git-issue}
|
8
|
+
s.version = "0.7.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Tomohito Ozaki"]
|
12
|
+
s.date = %q{2012-02-23}
|
13
|
+
s.default_executable = %q{git-issue}
|
14
|
+
s.description = %q{git extention command for issue tracker system.}
|
15
|
+
s.email = %q{ozaki@yuroyoro.com}
|
16
|
+
s.executables = ["git-issue"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE",
|
19
|
+
"README.markdown"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".document",
|
23
|
+
"LICENSE",
|
24
|
+
"README.markdown",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"bin/git-issue",
|
28
|
+
"git-issue.gemspec",
|
29
|
+
"images/git-issue_screenshot-1.png",
|
30
|
+
"images/git-issue_screenshot-2.png",
|
31
|
+
"lib/git_issue.rb",
|
32
|
+
"lib/git_issue/base.rb",
|
33
|
+
"lib/git_issue/github.rb",
|
34
|
+
"lib/git_issue/redmine.rb",
|
35
|
+
"spec/git_issue/base_spec.rb",
|
36
|
+
"spec/git_issue/github_spec.rb",
|
37
|
+
"spec/git_issue/redmine_spec.rb",
|
38
|
+
"spec/git_issue_spec.rb",
|
39
|
+
"spec/spec.opts",
|
40
|
+
"spec/spec_helper.rb"
|
41
|
+
]
|
42
|
+
s.homepage = %q{http://github.com/yuroyoro/git-issue}
|
43
|
+
s.require_paths = ["lib"]
|
44
|
+
s.rubygems_version = %q{1.5.2}
|
45
|
+
s.summary = %q{git extention command for issue tracker system.}
|
46
|
+
|
47
|
+
if s.respond_to? :specification_version then
|
48
|
+
s.specification_version = 3
|
49
|
+
|
50
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
51
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
52
|
+
s.add_development_dependency(%q<activesupport>, [">= 0"])
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
55
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
56
|
+
end
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
59
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
Binary file
|
Binary file
|
data/lib/git_issue.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
$KCODE="UTF8" if RUBY_VERSION < '1.9.0'
|
5
|
+
|
6
|
+
require 'pp'
|
7
|
+
require 'rubygems'
|
8
|
+
require 'uri'
|
9
|
+
require 'open-uri'
|
10
|
+
require "net/http"
|
11
|
+
require "net/https"
|
12
|
+
require "uri"
|
13
|
+
require 'fileutils'
|
14
|
+
require 'json'
|
15
|
+
require 'optparse'
|
16
|
+
require 'tempfile'
|
17
|
+
require 'active_support/all'
|
18
|
+
|
19
|
+
module GitIssue
|
20
|
+
class Command
|
21
|
+
attr_reader :name, :short_name, :description
|
22
|
+
def initialize(name, short_name, description)
|
23
|
+
@name, @short_name, @description = name, short_name, description
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Helper
|
28
|
+
|
29
|
+
CONFIGURE_MESSAGE = <<-END
|
30
|
+
please set issue tracker %s.
|
31
|
+
|
32
|
+
%s
|
33
|
+
END
|
34
|
+
|
35
|
+
def configure_error(attr_name, example)
|
36
|
+
raise CONFIGURE_MESSAGE % [attr_name, example]
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def configured_value(name)
|
41
|
+
res = `git config issue.#{name}`
|
42
|
+
res.strip
|
43
|
+
end
|
44
|
+
|
45
|
+
def global_configured_value(name)
|
46
|
+
res = `git config --global #{name}`
|
47
|
+
res.strip
|
48
|
+
end
|
49
|
+
|
50
|
+
def its_klass_of(its_type)
|
51
|
+
case its_type
|
52
|
+
when /redmine/i then GitIssue::Redmine
|
53
|
+
when /github/i then GitIssue::Github
|
54
|
+
else
|
55
|
+
raise "unknown issue tracker type : #{its_type}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
module_function :configured_value, :global_configured_value, :configure_error, :its_klass_of
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.main(argv)
|
63
|
+
status = true
|
64
|
+
|
65
|
+
begin
|
66
|
+
its_type = Helper.configured_value('type')
|
67
|
+
apikey = Helper.configured_value('apikey')
|
68
|
+
|
69
|
+
# Use global config for hub
|
70
|
+
if its_type.blank?
|
71
|
+
github_user = Helper.global_configured_value('github.user')
|
72
|
+
unless github_user.blank?
|
73
|
+
its_type = 'github'
|
74
|
+
apikey = Helper.global_configured_value('github.token')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
Helper.configure_error('type (redmine | github)', "git config issue.type redmine") if its_type.blank?
|
79
|
+
Helper.configure_error('apikey', "git config issue.apikey some_api_key") if apikey.blank?
|
80
|
+
|
81
|
+
its_klass = Helper.its_klass_of(its_type)
|
82
|
+
status = its_klass.new(ARGV).execute || true
|
83
|
+
rescue => e
|
84
|
+
puts e
|
85
|
+
puts e.backtrace.join("\n")
|
86
|
+
status = false
|
87
|
+
end
|
88
|
+
|
89
|
+
exit(status)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
require File.dirname(__FILE__) + '/git_issue/base'
|
95
|
+
require File.dirname(__FILE__) + '/git_issue/redmine'
|
96
|
+
require File.dirname(__FILE__) + '/git_issue/github'
|
@@ -0,0 +1,263 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
class GitIssue::Base
|
4
|
+
include GitIssue::Helper
|
5
|
+
|
6
|
+
attr_reader :apikey, :command, :tickets, :options
|
7
|
+
attr_accessor :sysout, :syserr
|
8
|
+
|
9
|
+
def initialize(args, options = {})
|
10
|
+
|
11
|
+
@opt_parse_obj = opt_parser
|
12
|
+
args = parse_options(args)
|
13
|
+
|
14
|
+
@sysout = options[:sysout] || $stdout
|
15
|
+
@syserr = options[:syserr] || $stderr
|
16
|
+
|
17
|
+
split_ticket = lambda{|s| s.nil? || s.empty? ? nil : s.split(/,/).map{|v| v.strip.to_i} }
|
18
|
+
|
19
|
+
@tickets = []
|
20
|
+
cmd = args.shift || default_cmd
|
21
|
+
|
22
|
+
if cmd =~ /(\d+,?\s?)+/
|
23
|
+
@tickets = split_ticket.call(cmd)
|
24
|
+
cmd = :show
|
25
|
+
end
|
26
|
+
cmd = cmd.to_sym
|
27
|
+
|
28
|
+
@command = find_command(cmd)
|
29
|
+
|
30
|
+
exit_with_message("invalid command <#{cmd}>") unless @command
|
31
|
+
|
32
|
+
@tickets += args.map{|s| split_ticket.call(s)}.flatten.uniq
|
33
|
+
@tickets = [guess_ticket] if @tickets.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_cmd
|
37
|
+
:list
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute
|
41
|
+
if @tickets.nil? || @tickets.empty?
|
42
|
+
self.send(@command.name, @options)
|
43
|
+
else
|
44
|
+
@tickets.each do |ticket|
|
45
|
+
self.send(@command.name, @options.merge(:ticket_id => ticket))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
def help(options = {})
|
52
|
+
puts @opt_parse_obj.banner
|
53
|
+
puts " Commnads:"
|
54
|
+
puts usage
|
55
|
+
puts ""
|
56
|
+
puts " Options:"
|
57
|
+
puts @opt_parse_obj.summarize
|
58
|
+
end
|
59
|
+
|
60
|
+
def publish(options = {})
|
61
|
+
ticket, branch_name = ticket_and_branch(options)
|
62
|
+
remote = options[:remote] || "origin"
|
63
|
+
system "git push -u #{remote} #{branch_name}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def rebase(options = {})
|
67
|
+
raise '--onto is required.' unless options[:onto]
|
68
|
+
ticket, branch_name = ticket_and_branch(options)
|
69
|
+
onto = options[:onto]
|
70
|
+
|
71
|
+
cb = current_branch
|
72
|
+
|
73
|
+
system "git rebase --onto #{onto} #{onto} #{branch_name}"
|
74
|
+
system "git checkout #{cb}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def commands
|
78
|
+
[
|
79
|
+
GitIssue::Command.new(:show, :s, 'show given issue summary. if given no id, geuss id from current branch name.'),
|
80
|
+
GitIssue::Command.new(:list, :l, 'listing issues.'),
|
81
|
+
GitIssue::Command.new(:mine, :m, 'display issues that assigned to you.'),
|
82
|
+
GitIssue::Command.new(:commit, :c, 'commit with filling issue subject to messsage.if given no id, geuss id from current branch name.'),
|
83
|
+
GitIssue::Command.new(:add, :a, 'create issue.'),
|
84
|
+
GitIssue::Command.new(:update, :u, 'update issue properties. if given no id, geuss id from current branch name.'),
|
85
|
+
GitIssue::Command.new(:branch, :b, "checout to branch using specified issue id. if branch dose'nt exisits, create it. (ex ticket/id/<issue_id>)"),
|
86
|
+
|
87
|
+
GitIssue::Command.new(:publish,:pub, "push branch to remote repository and set upstream "),
|
88
|
+
GitIssue::Command.new(:rebase, :rb, "rebase branch onto specific newbase"),
|
89
|
+
|
90
|
+
GitIssue::Command.new(:help, :h, "show usage.")
|
91
|
+
]
|
92
|
+
end
|
93
|
+
|
94
|
+
def find_command(cmd)
|
95
|
+
cmd = cmd.to_sym
|
96
|
+
commands.find{|c| c.name == cmd || c.short_name == cmd }
|
97
|
+
end
|
98
|
+
|
99
|
+
def usage
|
100
|
+
commands.map{|c| "%-8s %s %s" % [c.name, c.short_name, c.description ] }.join("\n")
|
101
|
+
end
|
102
|
+
|
103
|
+
def time_ago_in_words(time)
|
104
|
+
t = Time.parse(time)
|
105
|
+
a = (Time.now - t).to_i
|
106
|
+
|
107
|
+
case a
|
108
|
+
when 0 then return 'just now'
|
109
|
+
when 1..59 then return a.to_s + '秒前'
|
110
|
+
when 60..119 then return '1分前'
|
111
|
+
when 120..3540 then return (a/60).to_i.to_s + '分前'
|
112
|
+
when 3541..7100 then return '1時間前'
|
113
|
+
when 7101..82800 then return ((a+99)/3600).to_i.to_s + '時間前'
|
114
|
+
when 82801..172000 then return '1日前'
|
115
|
+
when 172001..432000 then return ((a+800)/(60*60*24)).to_i.to_s + '日前'
|
116
|
+
else return ((a+800)/(60*60*24)).to_i.to_s + '日前'
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def exit_with_message(msg, status=1)
|
121
|
+
err msg
|
122
|
+
exit(status)
|
123
|
+
end
|
124
|
+
|
125
|
+
BRANCH_NAME_FORMAT = "ticket/id/%s"
|
126
|
+
|
127
|
+
def ticket_branch(ticket_id)
|
128
|
+
BRANCH_NAME_FORMAT % ticket_id
|
129
|
+
end
|
130
|
+
|
131
|
+
def current_branch
|
132
|
+
%x(git branch -l | grep "*" | cut -d " " -f 2).strip
|
133
|
+
end
|
134
|
+
|
135
|
+
def guess_ticket
|
136
|
+
branch = current_branch
|
137
|
+
if branch =~ %r!id/(\d+)!
|
138
|
+
ticket = $1
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def ticket_and_branch(options)
|
143
|
+
if options[:ticket_id]
|
144
|
+
ticket = options[:ticket_id]
|
145
|
+
branch_name = ticket_branch(ticket)
|
146
|
+
else
|
147
|
+
branch_name = current_branch
|
148
|
+
ticket = guess_ticket
|
149
|
+
end
|
150
|
+
[ticket, branch_name]
|
151
|
+
end
|
152
|
+
|
153
|
+
def response_success?(response)
|
154
|
+
code = response.code.to_i
|
155
|
+
code >= 200 && code < 300
|
156
|
+
end
|
157
|
+
|
158
|
+
# this is unnecessary hacks for multibytes charactors handling...
|
159
|
+
def mlength(s)
|
160
|
+
width = 0
|
161
|
+
cnt = 0
|
162
|
+
s.split(//u).each{|c| cnt += 1 ;width += 1 if c.length > 1 }
|
163
|
+
cnt + width
|
164
|
+
end
|
165
|
+
|
166
|
+
# this is unnecessary hacks for multibytes charactors handling...
|
167
|
+
def mljust(s, n)
|
168
|
+
return "" unless s
|
169
|
+
cnt = 0
|
170
|
+
chars = []
|
171
|
+
|
172
|
+
s.split(//u).each do |c|
|
173
|
+
next if cnt > n
|
174
|
+
chars << c
|
175
|
+
cnt += 1
|
176
|
+
cnt += 1 if c.length > 1
|
177
|
+
end
|
178
|
+
if cnt > n
|
179
|
+
chars.pop
|
180
|
+
cnt -= 1
|
181
|
+
cnt -= 1 if chars.last.length > 1
|
182
|
+
end
|
183
|
+
chars << " " * (n - cnt) if n > cnt
|
184
|
+
chars.join
|
185
|
+
end
|
186
|
+
|
187
|
+
# for 1.8.6...
|
188
|
+
def mktmpdir(prefix_suffix=nil, tmpdir=nil)
|
189
|
+
case prefix_suffix
|
190
|
+
when nil
|
191
|
+
prefix = "d"
|
192
|
+
suffix = ""
|
193
|
+
when String
|
194
|
+
prefix = prefix_suffix
|
195
|
+
suffix = ""
|
196
|
+
when Array
|
197
|
+
prefix = prefix_suffix[0]
|
198
|
+
suffix = prefix_suffix[1]
|
199
|
+
else
|
200
|
+
raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}"
|
201
|
+
end
|
202
|
+
tmpdir ||= Dir.tmpdir
|
203
|
+
t = Time.now.strftime("%Y%m%d")
|
204
|
+
n = nil
|
205
|
+
begin
|
206
|
+
path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
|
207
|
+
path << "-#{n}" if n
|
208
|
+
path << suffix
|
209
|
+
Dir.mkdir(path, 0700)
|
210
|
+
rescue Errno::EEXIST
|
211
|
+
n ||= 0
|
212
|
+
n += 1
|
213
|
+
retry
|
214
|
+
end
|
215
|
+
|
216
|
+
if block_given?
|
217
|
+
begin
|
218
|
+
yield path
|
219
|
+
ensure
|
220
|
+
FileUtils.remove_entry_secure path
|
221
|
+
end
|
222
|
+
else
|
223
|
+
path
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def to_date(d)
|
228
|
+
Date.parse(d).strftime('%Y/%m/%d') rescue d
|
229
|
+
end
|
230
|
+
|
231
|
+
def parse_options(args)
|
232
|
+
@options = {}
|
233
|
+
@opt_parse_obj.parse!(args)
|
234
|
+
args
|
235
|
+
end
|
236
|
+
|
237
|
+
def opt_parser
|
238
|
+
OptionParser.new{|opts|
|
239
|
+
opts.banner = 'git issue <command> [ticket_id] [<args>]'
|
240
|
+
opts.on("--all", "-a", "update all paths in the index file "){ @options[:all] = true }
|
241
|
+
opts.on("--force", "-f", "force create branch"){ @options[:force] = true }
|
242
|
+
opts.on("--verbose", "-v", "show issue details"){|v| @options[:verbose] = true}
|
243
|
+
opts.on("--max-count=VALUE", "-n=VALUE", "maximum number of issues "){|v| @options[:max_count] = v.to_i}
|
244
|
+
opts.on("--oneline", "display short info"){|v| @options[:oneline] = true}
|
245
|
+
opts.on("--raw-id", "output ticket number only"){|v| @options[:raw_id] = true}
|
246
|
+
opts.on("--remote=VALUE", 'on publish, remote repository to push branch ') {|v| @options[:remote] = v}
|
247
|
+
opts.on("--onto=VALUE", 'on rebase, start new branch with HEAD equal to "newbase" ') {|v| @options[:onto] = v}
|
248
|
+
|
249
|
+
opts.on("--debug", "debug print"){@debug= true }
|
250
|
+
}
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
def puts(msg)
|
255
|
+
@sysout.puts msg
|
256
|
+
end
|
257
|
+
|
258
|
+
def err(msg)
|
259
|
+
@syserr.puts msg
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
|