mistilteinn 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ *~
2
+ .gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/
6
+ vendor/
@@ -0,0 +1,9 @@
1
+ ticket:
2
+ source: redmine
3
+
4
+ redmine:
5
+ url: https://codefirst.org/redmine/
6
+ project: mistilteinn-shell
7
+
8
+ github:
9
+ url: https://github.com/mistilteinn/mistilteinn-shell
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --profile
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,84 @@
1
+ Mistilteinn for shell
2
+ ==============================
3
+ [![Build Status](https://secure.travis-ci.org/mistilteinn/mistilteinn-shell.png)](http://travis-ci.org/mistilteinn/mistilteinn-shell)
4
+
5
+ OVERVIEW
6
+ ------------------------------
7
+
8
+ Mistilteinn for shell is a comamnd to support a development style for
9
+ using git and redmine.
10
+
11
+ Prerequires
12
+ ------------------------------
13
+
14
+ * Ruby 1.8.7
15
+ * RubyGems 1.4.2 or later
16
+ * git-hooks http://github.com/mistilteinn/git-hooks
17
+ * git subcommands https://github.com/mistilteinn/git-tools
18
+
19
+ Install
20
+ ------------------------------
21
+
22
+ ### Prerequires
23
+
24
+ $ bundle install --path vendor/bundle
25
+
26
+ ### Run
27
+
28
+ $ bundle exec mistilteinn
29
+
30
+ ### Run test
31
+
32
+ $ bundle exec rake spec
33
+
34
+ ### Package
35
+
36
+ $ bundle exec rake build
37
+
38
+ ### Install to system
39
+
40
+ $ bundle exec rake build
41
+ $ cd pkg
42
+ $ gem install mistilteinn-*.gem
43
+
44
+ Usage
45
+ ------------------------------
46
+
47
+ ### self cehck
48
+
49
+ Check if miltilteinn works:
50
+
51
+ $ mistilteinn self-check
52
+
53
+ ### init
54
+
55
+ Initialize working directory for mistilteinn:
56
+
57
+ $ mistilteinn init
58
+ $ vim .mistilteinn/config.yaml
59
+
60
+ ### list ticket
61
+
62
+ $ mistilteinn list
63
+
64
+ ### create ticket
65
+
66
+ $ mistilteinn create hoge
67
+
68
+ AUTHOR
69
+ ------------------------------
70
+
71
+ * @mzp
72
+ * @suer
73
+
74
+ License
75
+ -----------------------
76
+
77
+ The MIT License (MIT) Copyright (c) 2012 codefirst.org
78
+
79
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
80
+
81
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
82
+
83
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
84
+
@@ -0,0 +1,20 @@
1
+ # -*- mode:ruby -*-
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/clean'
5
+ require 'rspec/core/rake_task'
6
+ require "bundler/gem_tasks"
7
+
8
+ CLEAN.include(
9
+ "**/*.db"
10
+ )
11
+
12
+ CLOBBER.include(
13
+ "pkg"
14
+ )
15
+
16
+ RSpec::Core::RakeTask.new do |t|
17
+ t.pattern = 'spec/**/*_spec.rb'
18
+ end
19
+
20
+ task :default => [:spec, :clean]
File without changes
@@ -0,0 +1,42 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+ require 'pp'
3
+ require 'subcommand'
4
+ require 'mistilteinn/config'
5
+ require 'mistilteinn/git'
6
+ require 'mistilteinn/ticket'
7
+ require 'mistilteinn/cli'
8
+
9
+ include Subcommands
10
+
11
+ options = {}
12
+ global_options do|opts|
13
+ options[:config] = File.expand_path '.mistilteinn/config.yaml', Mistilteinn::Git.root
14
+ opts.on('-c CONFIG', '--config=CONIF') do|config|
15
+ options[:config] = config
16
+ end
17
+ end
18
+
19
+ def curry(*args)
20
+ lambda{|obj| obj.send(*args)}
21
+ end
22
+
23
+ commands = Mistilteinn::Cli::Command.commands.map(&curry(:new, self))
24
+
25
+ name = opt_parse
26
+
27
+ begin
28
+ config = Mistilteinn::Config.load options[:config]
29
+ rescue => e
30
+ puts "#{options[:config]}: #{e.message}"
31
+ exit 1
32
+ end
33
+
34
+ obj = commands.find{|c| c.name == (name || '-').to_sym }
35
+ if obj then
36
+ obj.run config, ARGV
37
+ else
38
+ puts <<END
39
+ Please see '#{$0} help'
40
+ END
41
+ exit 1
42
+ end
@@ -0,0 +1,6 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+ require 'mistilteinn/cli/command'
3
+
4
+ Dir[File.dirname(__FILE__) + '/cli/*.rb'].each do|name|
5
+ require "mistilteinn/cli/#{File.basename name, '.rb'}"
6
+ end
@@ -0,0 +1,47 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+
3
+ module Mistilteinn
4
+ module Cli
5
+ class Command
6
+ attr_reader :its, :config, :args
7
+
8
+ def initialize(obj)
9
+ obj.command name do|opts|
10
+ opts.description = 'show current ticket list'
11
+ end
12
+ end
13
+
14
+ def its
15
+ klass = Mistilteinn::Ticket[config.ticket.source]
16
+ klass.new config
17
+ end
18
+
19
+ def run(config, args)
20
+ @config = config
21
+ @args = args
22
+ action
23
+ end
24
+
25
+ @@klass = []
26
+ class << self
27
+ def inherited(k)
28
+ @@klass << k
29
+ end
30
+
31
+ def commands
32
+ @@klass
33
+ end
34
+
35
+ def name(x)
36
+ define_method(:name){ x.to_sym }
37
+ end
38
+
39
+ def desc(x)
40
+ define_method(:desc){ x }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+
@@ -0,0 +1,10 @@
1
+ module Mistilteinn::Cli
2
+ class Create < ::Mistilteinn::Cli::Command
3
+ name :create
4
+ desc 'create ticket'
5
+
6
+ def action
7
+ its.create args.join(' ')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ #! /bin/sh
2
+
3
+ if [ -n "${GIT_DIR}" ]; then
4
+ hooksdir="./${GIT_DIR}/hooks/"
5
+ else
6
+ hooksdir="./"
7
+ fi
8
+
9
+ . "${hooksdir}common.sh"
10
+
11
+ ticket="$(extractTicketId)"
12
+ if [ -n "${ticket}" ]; then
13
+ appendMsgTo1stLine "$1" "${ticket}"
14
+ fi
@@ -0,0 +1,60 @@
1
+ #! /bin/sh
2
+
3
+ getGitBranchName()
4
+ {
5
+ branch="$(git symbolic-ref HEAD 2>/dev/null)" ||
6
+ "$(git describe --contains --all HEAD)"
7
+ echo ${branch##refs/heads/}
8
+ }
9
+
10
+ isOnMasterBranch()
11
+ {
12
+ if [ "$(getGitBranchName)" = "master" ]; then
13
+ return 0
14
+ fi
15
+ return 1
16
+ }
17
+
18
+ appendMsgTo1stLine()
19
+ {
20
+ mv $1 $1.$$
21
+ if [ -s "$1.$$" ]; then
22
+ if head -1 "$1.$$" | grep "$2" > /dev/null; then
23
+ cp "$1.$$" "$1"
24
+ else
25
+ sed '1s/$/ '"$2"'/' "$1.$$" > $1
26
+ fi
27
+ else
28
+ echo "$2" > "$1"
29
+ fi
30
+ rm -f $1.$$
31
+ }
32
+
33
+ extractTicketId()
34
+ {
35
+ echo "$(getGitBranchName)" \
36
+ | awk 'BEGIN{ FS="[/]"}
37
+ $1 == "id" { printf "refs #%s", $2 }
38
+ $2 == "id" { printf "refs #%s", $3 }'
39
+ }
40
+
41
+ hasTicketId()
42
+ {
43
+ first="$(git cat-file -p $1 \
44
+ | sed '1,/^$/d' | head -1 \
45
+ | sed '/.*refs #[0-9][0-9]*.*/!d')"
46
+
47
+ if [ -n "${first}" ]; then
48
+ echo "true"
49
+ else
50
+ echo "false"
51
+ fi
52
+ }
53
+
54
+ extractParents()
55
+ {
56
+ parents="$(git cat-file -p $1 \
57
+ | grep '^parent [0-9a-f]\{40\}$')"
58
+ echo "${parents##parent }"
59
+ }
60
+
@@ -0,0 +1,22 @@
1
+ #! /bin/sh
2
+
3
+ if [ -z "$(git branch)" ]; then
4
+ exit 0
5
+ fi
6
+
7
+ if [ -n "${GIT_DIR}" ]; then
8
+ hooksdir="./${GIT_DIR}/hooks/"
9
+ else
10
+ hooksdir="./"
11
+ fi
12
+
13
+ . "${hooksdir}common.sh"
14
+
15
+ isOnMasterBranch
16
+ if [ $? -eq 0 ]; then
17
+ echo "can't commit on master branch."
18
+ echo "please commit on topic branch."
19
+ exit 1
20
+ fi
21
+
22
+ exit 0
@@ -0,0 +1,46 @@
1
+ # -*- coding: undecided -*-
2
+ require 'pathname'
3
+ require 'fileutils'
4
+ require 'mistilteinn/git'
5
+
6
+ module Mistilteinn::Cli
7
+ class Init < ::Mistilteinn::Cli::Command
8
+ name :init
9
+ desc 'initialize this repository for mistilteinn'
10
+
11
+ def action
12
+ copy( children('hooks'), git_root('.git/hooks') )
13
+ copy( children('templates'), git_root('.mistilteinn') )
14
+ end
15
+
16
+ private
17
+ def children(name)
18
+ path = Pathname(File.dirname(__FILE__)) + name
19
+ path.children
20
+ end
21
+
22
+ def git_root(name)
23
+ path = Pathname(::Mistilteinn::Git.root) + name
24
+ path.tap {
25
+ unless path.exist?
26
+ puts "mkdir -p #{config}"
27
+ config.mkpath
28
+ end
29
+ }
30
+ end
31
+
32
+ def copy(files, dir)
33
+ puts "copy to #{dir}"
34
+ files.each do|src|
35
+ print "generate #{src.basename}..."
36
+ dest = dir + src.basename
37
+ if dest.exist? then
38
+ puts "skip"
39
+ else
40
+ FileUtils.copy src, dest
41
+ puts "ok"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+ require 'mistilteinn/git'
3
+
4
+ module Mistilteinn::Cli
5
+ class IsInside < ::Mistilteinn::Cli::Command
6
+ name 'is-inside'
7
+ desc 'check if current working direcotry is mistilteinn'
8
+
9
+ def action
10
+ if ::Mistilteinn::Git::work_tree? and config.exist? then
11
+ exit 0
12
+ else
13
+ exit 1
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ module Mistilteinn::Cli
2
+ class List < ::Mistilteinn::Cli::Command
3
+ name :list
4
+ desc 'show current ticket list'
5
+
6
+ def action
7
+ its.tickets.each do|entry|
8
+ puts entry.format
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,59 @@
1
+ module Mistilteinn::Cli
2
+ class SelfCheck < ::Mistilteinn::Cli::Command
3
+ name 'self-check'
4
+ desc 'check whether mistilteinn works'
5
+
6
+ def action
7
+ section "ticket source"
8
+ check("source type") {
9
+ its.class rescue error("'#{config.ticket.source}' is not valid.")
10
+ }
11
+ check(its.class){ its.check }
12
+
13
+ section "git"
14
+ check_if("inside work tree?") { Mistilteinn::Git.work_tree? }
15
+ check_if("git-now subcommand") { Mistilteinn::Git.command? 'now' }
16
+ check_if("git-master subcommand") { Mistilteinn::Git.command? 'master' }
17
+ check_if("git-hooks subcommand") { Mistilteinn::Git.command? 'hooks' }
18
+
19
+ puts '','Works! Have a good programming!!'
20
+ rescue => e
21
+ puts <<END
22
+ #{e.message}
23
+
24
+ Oh, Mistilteinn does not work.
25
+ Please check your system or configure file.
26
+ END
27
+ exit 1
28
+ end
29
+
30
+ def error(msg)
31
+ raise StandardError.new(msg)
32
+ end
33
+
34
+ def section(title)
35
+ puts <<END
36
+
37
+ ------------------------------
38
+ #{title}
39
+ ------------------------------
40
+ END
41
+ end
42
+
43
+ def check(title, &f)
44
+ print title, " => "
45
+ STDOUT.flush
46
+ puts f.call
47
+ end
48
+
49
+ def check_if(title, &p)
50
+ check(title) {
51
+ if p[] then
52
+ "ok"
53
+ else
54
+ error("error")
55
+ end
56
+ }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,12 @@
1
+ ticket:
2
+ # redmine, github or gitconfig
3
+ source: redmine
4
+
5
+ redmine:
6
+ url: https://example.com/redmine/
7
+ project: some-project-name
8
+ apikey: your_key
9
+ # or 'git config redmine.apikey your_key'
10
+
11
+ github:
12
+ url: https://github.com/mistilteinn/mistilteinn-shell
@@ -0,0 +1,54 @@
1
+ #! /opt/local/bin/ruby -w
2
+ # -*- mode:ruby; coding:utf-8 -*-
3
+
4
+ require 'yaml'
5
+ require 'ostruct'
6
+ require 'mistilteinn/git'
7
+
8
+ module Mistilteinn
9
+ class ConfigError < StandardError
10
+ end
11
+
12
+ class Config
13
+ def self.load(path)
14
+ if File.exist? path then
15
+ self.new(YAML.load_file(path), path)
16
+ else
17
+ self.new({} , path)
18
+ end
19
+ end
20
+
21
+ def initialize(hash, path = nil)
22
+ @hash = hash
23
+ @path = path
24
+ end
25
+
26
+ def exist?
27
+ File.exist?(@path) if @path
28
+ end
29
+
30
+ def method_missing(name, *args)
31
+ if args.empty? then
32
+ key = name.to_s
33
+ WrapObj.new(key, @hash[key] || {} )
34
+ else
35
+ super(name, *args)
36
+ end
37
+ end
38
+
39
+ class WrapObj
40
+ def initialize(name, hash)
41
+ @name = name
42
+ @hash = hash
43
+ end
44
+
45
+ def method_missing(name, *args)
46
+ key = name.to_s
47
+ super(name, *args) unless args.empty?
48
+ @hash[key] or
49
+ ::Mistilteinn::Git.config("#{@name}.#{key}") or
50
+ raise ConfigError.new("no config(#{@name}.#{key})")
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,30 @@
1
+ #! /opt/local/bin/ruby -w
2
+ # -*- mode:ruby; coding:utf-8 -*-
3
+
4
+ module Mistilteinn
5
+ module Git
6
+ class << self
7
+ def config(name)
8
+ cmd "git config #{name}"
9
+ end
10
+
11
+ def root
12
+ cmd "git rev-parse --show-toplevel"
13
+ end
14
+
15
+ def work_tree?()
16
+ cmd("git rev-parse --is-inside-work-tree") == "true"
17
+ end
18
+
19
+ def command?(cmd)
20
+ cmd("which git-#{cmd}") != nil
21
+ end
22
+
23
+ private
24
+ def cmd(str)
25
+ str = %x(#{str} 2>/dev/null || echo "").strip
26
+ str.empty? ? nil : str
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,42 @@
1
+ #! /opt/local/bin/ruby -w
2
+ # -*- mode:ruby; coding:utf-8 -*-
3
+
4
+ require 'open-uri'
5
+ require 'json'
6
+ require 'net/http'
7
+ require 'net/https'
8
+
9
+ module Mistilteinn
10
+ module HttpUtil
11
+ class HttpError < StandardError; end
12
+
13
+ class << self
14
+ def get_json(url, params={})
15
+ url = url.to_s + '?' + params.map{|key,value| "#{key}=#{value}" }.join("&")
16
+ begin
17
+ open(url) do |io|
18
+ JSON.parse(io.read)
19
+ end
20
+ rescue => e
21
+ raise HttpError.new("#{e.message} (#{url})")
22
+ end
23
+ end
24
+
25
+ def post_json(url, headers, data)
26
+ http = Net::HTTP.new(url.host, url.port)
27
+ http.use_ssl = url.scheme == 'https'
28
+
29
+ http.start do
30
+ ret = http.post(url.path,
31
+ data.to_json,
32
+ headers.merge("Content-Type" => "application/json"))
33
+ case ret
34
+ when Net::HTTPSuccess
35
+ else
36
+ raise HttpError.new("#{ret} (#{url})")
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,19 @@
1
+ require 'mistilteinn/ticket/redmine'
2
+ require 'mistilteinn/ticket/github'
3
+ require 'mistilteinn/ticket/git_config'
4
+
5
+ module Mistilteinn
6
+ module Ticket
7
+ def [](name)
8
+ case name.to_sym
9
+ when :redmine
10
+ Mistilteinn::Ticket::Redmine
11
+ when :github
12
+ Mistilteinn::Ticket::Github
13
+ when :gitconfig
14
+ Mistilteinn::Ticket::GitConfig
15
+ end
16
+ end
17
+ module_function :[]
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+
2
+
3
+ module Mistilteinn
4
+ module Ticket
5
+ Entry = Struct.new 'Entry', :id, :name, :status
6
+
7
+ class Entry
8
+ def format
9
+ "#{id} #{name} [#{status}]"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,157 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+ require 'tempfile'
3
+
4
+ module Mistilteinn
5
+ module Ticket
6
+ class Config
7
+ def initialize(config_hash, path)
8
+ @config = config_hash
9
+ @path = path
10
+ end
11
+ attr_reader :config
12
+
13
+ def has_key?(key)
14
+ @config.has_key?(key) || @config.has_key?(key.to_s)
15
+ end
16
+
17
+ def []=(*args)
18
+ assignment(args[0], args[1])
19
+ end
20
+
21
+ def [](key)
22
+ key = key.to_s if key.class == Symbol
23
+ method_missing(key)
24
+ end
25
+
26
+ def method_missing(name, *args)
27
+ name = name.to_s
28
+ is_assignment = create_if_nil = false
29
+ if name[-1..-1] == '=' then
30
+ is_assignment = true
31
+ name.slice! -1
32
+ end
33
+ if name[-1..-1] == '_' then
34
+ create_if_nil = true
35
+ name.slice! -1
36
+ end
37
+
38
+ return assignment(name, args[0]) if is_assignment
39
+
40
+ config_object = get_config_object(@path+[name.to_s])
41
+ return nil if config_object.config.empty? and not create_if_nil
42
+
43
+ if config_object.config.class == Hash then
44
+ config_object
45
+ else
46
+ config_object.config
47
+ end
48
+ end
49
+
50
+ private
51
+ def get_config_object(path)
52
+ return @@config_objects[path] if @@config_objects.has_key? path
53
+
54
+ if @config.has_key? path[-1] then
55
+ @@config_objects[path] = Config::new(@config[path[-1]], path)
56
+ else
57
+ @config[path[-1]] = {}
58
+ @@config_objects[path] = Config::new({}, path)
59
+ end
60
+ end
61
+
62
+ def Config::init
63
+ @@config_objects = {[] => Config::parse_config}
64
+ @@config_objects[[]]
65
+ end
66
+
67
+ def Config::parse_config
68
+ config_hash = {}
69
+ get_by_regexp('".*"').each do |path,value|
70
+ subconfig = config_hash
71
+ elems = path.split '.'
72
+ elems[0..-2].each do |path|
73
+ subconfig[path] = {} if subconfig[path].nil?
74
+ subconfig = subconfig[path]
75
+ end
76
+ subconfig[elems[-1]] = value
77
+ end
78
+ Config::new(config_hash, [])
79
+ end
80
+
81
+ def Config::get_by_regexp(regex)
82
+ %x(git config --get-regexp #{regex}).split(/\n/).map do |line|
83
+ line.match(/(.+?) (.*)/)[1..2]
84
+ end
85
+ end
86
+
87
+ def Config::set(name, value)
88
+ %x(git config #{name} "#{value}")
89
+ end
90
+
91
+ def assignment(key, value)
92
+ Config::set("#{@path.join('.')}.#{key}", value)
93
+ end
94
+ end
95
+
96
+ class GitConfig
97
+ class ConfigError < StandardError; end
98
+
99
+ def initialize(config)
100
+ @config = Config::init
101
+ end
102
+
103
+ def tickets
104
+ lastTicketNo = @config.ticket.ticketno.to_i
105
+ (1...lastTicketNo).map do |id|
106
+ data = @config.ticket["id/#{id}"]
107
+ ::Mistilteinn::Ticket::Entry.new(id, data.subject, data.status)
108
+ end
109
+ end
110
+
111
+ def create(title = "")
112
+ ticketFormat = <<END
113
+ Subject: #{title}
114
+ Author: #{@config.user.name}
115
+ Date: #{Time.now}
116
+ Status: new
117
+ Description: |-
118
+
119
+ END
120
+
121
+ editTempFile(ticketFormat) do |f, modified|
122
+ return if not modified and title.empty?
123
+
124
+ ticket = @config.ticket
125
+ ticketNo = (ticket.ticketno || "1").to_i
126
+
127
+ YAML.load_documents(f) do |yaml|
128
+ yaml.each do |key, value|
129
+ ticket["id/#{ticketNo}_"][key] = value
130
+ end
131
+ end
132
+ ticket.ticketno = (ticketNo+1).to_s
133
+ end
134
+ end
135
+
136
+ def edit(id)
137
+ end
138
+
139
+ private
140
+ def editTempFile(initialString, &proc)
141
+ tmp = Tempfile.new("tmp")
142
+ tmp.write initialString
143
+ tmp.close
144
+
145
+ editor = @config.core_.editor || ENV["EDITOR"]
146
+ system "#{editor} #{tmp.path}"
147
+ File.open(tmp.path) do |f|
148
+ modified = f.read != initialString
149
+ f.rewind
150
+ proc.call(f, modified)
151
+ end
152
+ tmp.unlink
153
+ end
154
+ end
155
+ end
156
+ end
157
+
@@ -0,0 +1,37 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+ require 'mistilteinn/http_util'
3
+ require 'mistilteinn/ticket/entry'
4
+
5
+ module Mistilteinn
6
+ module Ticket
7
+ class Github
8
+ class ConfigError < StandardError; end
9
+
10
+ API_URL_ROOT = "https://api.github.com/"
11
+
12
+ def initialize(config)
13
+ @url = config.github.url
14
+ unless @url
15
+ raise ConfigError.new
16
+ end
17
+ end
18
+
19
+ def tickets
20
+ ::Mistilteinn::HttpUtil::get_json(api("issues")).map do |issue|
21
+ ::Mistilteinn::Ticket::Entry.new(issue['number'],
22
+ issue['title'],
23
+ issue['state'])
24
+ end
25
+ end
26
+
27
+ def create(title)
28
+ # FIXME or DIE
29
+ end
30
+
31
+ private
32
+ def api(name)
33
+ URI(API_URL_ROOT) + "./repos/#{URI(@url).path}/#{name}"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,49 @@
1
+ #! /opt/local/bin/ruby -w
2
+ # -*- mode:ruby; coding:utf-8 -*-
3
+ require 'uri'
4
+ require 'mistilteinn/http_util'
5
+ require 'mistilteinn/ticket/entry'
6
+
7
+ module Mistilteinn
8
+ module Ticket
9
+ class Redmine
10
+ def initialize(config)
11
+ @config = config.redmine
12
+ end
13
+
14
+ def tickets
15
+ HttpUtil.get_json(api('issues'),
16
+ { :project_id => @config.project,
17
+ :key => @config.apikey})['issues'].map{|entry|
18
+ ::Mistilteinn::Ticket::Entry.new(entry['id'],
19
+ entry['subject'],
20
+ entry['status']['name'])
21
+ }
22
+ end
23
+
24
+ def create(title)
25
+ HttpUtil.post_json(api('issues'),
26
+ { "X-Redmine-API-Key" => @config.apikey },
27
+ { :issue => {
28
+ :project_id => @config.project,
29
+ :subject => title,
30
+ }})
31
+ end
32
+
33
+ def check
34
+ begin
35
+ HttpUtil.get_json(api('users/current'),
36
+ { :key => @config.apikey})
37
+ 'ok'
38
+ rescue HttpUtil::HttpError => e
39
+ "Error: #{e.message}"
40
+ end
41
+ end
42
+
43
+ private
44
+ def api(name)
45
+ URI(@config.url + '/') + "#{name}.json"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,6 @@
1
+ #! /opt/local/bin/ruby -w
2
+ # -*- mode:ruby; coding:utf-8 -*-
3
+
4
+ module Mistilteinn
5
+ VERSION = '0.1.0'
6
+ end
@@ -0,0 +1,22 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+ require File.expand_path('../lib/mistilteinn/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["MIZUNO Hiroki"]
6
+ gem.email = ["mzp.ppp@gmail.com"]
7
+ gem.description = %q{Mistilteinn is a command to support a development with git and redmine.}
8
+ gem.summary = %q{Mistilteinn is a command to support a development with git and redmine.}
9
+ gem.homepage = "https://github.com/mistilteinn/mistilteinn-shell"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "mistilteinn"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Mistilteinn::VERSION
17
+
18
+ gem.add_dependency 'json', ['>= 0'] unless defined? JSON
19
+ gem.add_dependency 'subcommand', ['>= 0']
20
+ gem.add_development_dependency 'rspec', ['>= 0']
21
+ gem.add_development_dependency 'rake', ['>= 0']
22
+ end
File without changes
@@ -0,0 +1,46 @@
1
+ #! /opt/local/bin/ruby -w
2
+ # -*- mode:ruby; coding:utf-8 -*-
3
+
4
+ require 'spec_helper'
5
+
6
+ spec 'config' do
7
+ describe 'load from file' do
8
+ before do
9
+ File.should_receive(:exist?) { true }
10
+ YAML.should_receive(:load_file) {
11
+ {'ticket' => {
12
+ 'source' => 'local',
13
+ 'path' => '/path/to/ticket.txt'
14
+ }}}
15
+ end
16
+
17
+ context 'ticket' do
18
+ subject { Mistilteinn::Config.load('config.yml').ticket }
19
+ its(:source) { should == 'local' }
20
+ its(:path) { should == '/path/to/ticket.txt' }
21
+ end
22
+ end
23
+
24
+ describe 'get config from git-config instead of ymal' do
25
+ before do
26
+ File.should_receive(:exist?) { true }
27
+ YAML.should_receive(:load_file) {
28
+ {'ticket' => {
29
+ 'source' => 'local',
30
+ 'path' => '/path/to/ticket.txt'
31
+ }}}
32
+ Mistilteinn::Git.should_receive(:config).with('ticket.apikey') { 'xxxx' }
33
+ @config = Mistilteinn::Config.load('config.yml')
34
+ end
35
+
36
+ subject { @config.ticket }
37
+ its(:apikey) { should == 'xxxx' }
38
+ end
39
+
40
+ describe 'load error' do
41
+ before { @config = Mistilteinn::Config.new({}) }
42
+ it {
43
+ expect { @config.ticket.x }.to raise_error(Mistilteinn::ConfigError)
44
+ }
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ # -*- mode:ruby; coding:utf-8 -*-
2
+
3
+ def spec(name, &f)
4
+ require "mistilteinn/#{name}"
5
+ xs = name.split('/').map{|x| x.capitalize }.join('::')
6
+ describe "Mistilteinn::#{xs}", &f
7
+ end
@@ -0,0 +1,86 @@
1
+ #! /opt/local/bin/ruby -w
2
+ # -*- mode:ruby; coding:utf-8 -*-
3
+
4
+ require 'spec_helper'
5
+ require 'uri'
6
+ require 'mistilteinn/http_util'
7
+
8
+ spec 'ticket/redmine' do
9
+ before do
10
+ @config = Mistilteinn::Config.new({ 'redmine' => {
11
+ 'url' => 'http://example.com/redmine',
12
+ 'project' => 'some-project',
13
+ 'apikey' => 'key' }})
14
+ @redmine = Mistilteinn::Ticket::Redmine.new @config
15
+ end
16
+
17
+ describe 'ticket list' do
18
+ before do
19
+ Mistilteinn::HttpUtil.should_receive(:get_json).
20
+ with(URI('http://example.com/redmine/issues.json'),
21
+ { :project_id => 'some-project', :key => 'key' }) do
22
+ { "issues" =>
23
+ [
24
+ { "id" => "1", "subject" => "Ticket A", "status" => { "name" => "open" }},
25
+ { "id" => "2", "subject" => "Ticket B", "status" => { "name" => "close" }}
26
+ ]}
27
+ end
28
+ end
29
+
30
+ subject { @redmine.tickets }
31
+ its(:length) { should == 2 }
32
+
33
+ describe 'Ticket A' do
34
+ subject { @redmine.tickets[0] }
35
+ its(:id) { should == "1" }
36
+ its(:name) { should == "Ticket A" }
37
+ its(:status) { should == "open" }
38
+ end
39
+
40
+ describe 'Ticket B' do
41
+ subject { @redmine.tickets[1] }
42
+ its(:id) { should == "2" }
43
+ its(:name) { should == "Ticket B" }
44
+ its(:status) { should == "close" }
45
+ end
46
+ end
47
+
48
+ describe 'create ticket' do
49
+ it do
50
+ Mistilteinn::HttpUtil.should_receive(:post_json).
51
+ with(URI('http://example.com/redmine/issues.json'),
52
+ { 'X-Redmine-API-Key' => 'key' },
53
+ { :issue => {
54
+ :project_id => 'some-project',
55
+ :subject => 'hogehoge'
56
+ }})
57
+ @redmine.create 'hogehoge'
58
+ end
59
+ end
60
+
61
+ describe 'self-check' do
62
+ context 'success' do
63
+ before do
64
+ Mistilteinn::HttpUtil.should_receive(:get_json).
65
+ with(URI('http://example.com/redmine/users/current.json'),
66
+ { :key => 'key' }) do {} end
67
+ end
68
+
69
+ subject { @redmine }
70
+ its(:check) { should == 'ok' }
71
+ end
72
+
73
+ context 'fail' do
74
+ before do
75
+ Mistilteinn::HttpUtil.should_receive(:get_json).
76
+ with(URI('http://example.com/redmine/users/current.json'),
77
+ { :key => 'key' }) do
78
+ raise Mistilteinn::HttpUtil::HttpError.new('foo bar')
79
+ end
80
+ end
81
+
82
+ subject { @redmine }
83
+ its(:check) { should == 'Error: foo bar' }
84
+ end
85
+ end
86
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mistilteinn
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - MIZUNO Hiroki
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: &70337693909060 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70337693909060
25
+ - !ruby/object:Gem::Dependency
26
+ name: subcommand
27
+ requirement: &70337693908460 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70337693908460
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70337693907860 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70337693907860
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: &70337693895220 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70337693895220
58
+ description: Mistilteinn is a command to support a development with git and redmine.
59
+ email:
60
+ - mzp.ppp@gmail.com
61
+ executables:
62
+ - mistilteinn
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - .gitignore
67
+ - .mistilteinn/config.yaml
68
+ - .rspec
69
+ - Gemfile
70
+ - README.markdown
71
+ - Rakefile
72
+ - bin/.gitkeep
73
+ - bin/mistilteinn
74
+ - lib/mistilteinn/cli.rb
75
+ - lib/mistilteinn/cli/command.rb
76
+ - lib/mistilteinn/cli/create.rb
77
+ - lib/mistilteinn/cli/hooks/commit-msg
78
+ - lib/mistilteinn/cli/hooks/common.sh
79
+ - lib/mistilteinn/cli/hooks/pre-commit
80
+ - lib/mistilteinn/cli/init.rb
81
+ - lib/mistilteinn/cli/is_inside.rb
82
+ - lib/mistilteinn/cli/list.rb
83
+ - lib/mistilteinn/cli/self_check.rb
84
+ - lib/mistilteinn/cli/templates/config.yaml
85
+ - lib/mistilteinn/config.rb
86
+ - lib/mistilteinn/git.rb
87
+ - lib/mistilteinn/http_util.rb
88
+ - lib/mistilteinn/ticket.rb
89
+ - lib/mistilteinn/ticket/entry.rb
90
+ - lib/mistilteinn/ticket/git_config.rb
91
+ - lib/mistilteinn/ticket/github.rb
92
+ - lib/mistilteinn/ticket/redmine.rb
93
+ - lib/mistilteinn/version.rb
94
+ - mistilteinn.gemspec
95
+ - spec/.gitkeep
96
+ - spec/config_spec.rb
97
+ - spec/spec_helper.rb
98
+ - spec/ticket/redmine_spec.rb
99
+ homepage: https://github.com/mistilteinn/mistilteinn-shell
100
+ licenses: []
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 1.8.16
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: Mistilteinn is a command to support a development with git and redmine.
123
+ test_files:
124
+ - spec/config_spec.rb
125
+ - spec/spec_helper.rb
126
+ - spec/ticket/redmine_spec.rb