minglemingle 0.0.1
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/CHANGES +4 -0
- data/LICENSE.TXT +203 -0
- data/README +79 -0
- data/Rakefile +349 -0
- data/TODO +14 -0
- data/bin/mm +17 -0
- data/doc/jamis.rb +591 -0
- data/install.rb +88 -0
- data/lib/mm.rb +81 -0
- data/lib/mm/cmds/abstract_command.rb +78 -0
- data/lib/mm/cmds/card.rb +57 -0
- data/lib/mm/cmds/cards.rb +58 -0
- data/lib/mm/cmds/favorites.rb +29 -0
- data/lib/mm/cmds/help.rb +70 -0
- data/lib/mm/cmds/init.rb +43 -0
- data/lib/mm/cmds/run.rb +54 -0
- data/lib/mm/cmds/svncommit.rb +68 -0
- data/lib/mm/cmds/tabs.rb +28 -0
- data/lib/mm/cmds/user.rb +40 -0
- data/lib/mm/cmds/view.rb +37 -0
- data/lib/mm/repository.rb +40 -0
- data/lib/mm/rest_api.rb +63 -0
- data/lib/mm/transition_execution.tab.rb +279 -0
- data/lib/mm/utils.rb +41 -0
- data/test/abstract_command_test.rb +31 -0
- data/test/test_helper.rb +26 -0
- metadata +86 -0
data/install.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'find'
|
3
|
+
require 'ftools'
|
4
|
+
|
5
|
+
include Config
|
6
|
+
|
7
|
+
$ruby = CONFIG['ruby_install_name']
|
8
|
+
|
9
|
+
##
|
10
|
+
# Install a binary file. We patch in on the way through to
|
11
|
+
# insert a #! line. If this is a Unix install, we name
|
12
|
+
# the command (for example) 'mm' and let the shebang line
|
13
|
+
# handle running it. Under windows, we add a '.rb' extension
|
14
|
+
# and let file associations to their stuff
|
15
|
+
#
|
16
|
+
|
17
|
+
def installBIN(from, opfile)
|
18
|
+
|
19
|
+
tmp_dir = nil
|
20
|
+
for t in [".", "/tmp", "c:/temp", $bindir]
|
21
|
+
stat = File.stat(t) rescue next
|
22
|
+
if stat.directory? and stat.writable?
|
23
|
+
tmp_dir = t
|
24
|
+
break
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
fail "Cannot find a temporary directory" unless tmp_dir
|
29
|
+
tmp_file = File.join(tmp_dir, "_tmp")
|
30
|
+
|
31
|
+
File.open(from) do |ip|
|
32
|
+
File.open(tmp_file, "w") do |op|
|
33
|
+
ruby = File.join($realbindir, $ruby)
|
34
|
+
op.puts "#!#{ruby}"
|
35
|
+
op.write ip.read
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
opfile += ".rb" if CONFIG["target_os"] =~ /mswin/i
|
40
|
+
File::install(tmp_file, File.join($bindir, opfile), 0755, true)
|
41
|
+
File::unlink(tmp_file)
|
42
|
+
end
|
43
|
+
|
44
|
+
$sitedir = CONFIG["sitelibdir"]
|
45
|
+
unless $sitedir
|
46
|
+
version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
|
47
|
+
$libdir = File.join(CONFIG["libdir"], "ruby", version)
|
48
|
+
$sitedir = $:.find {|x| x =~ /site_ruby/}
|
49
|
+
if !$sitedir
|
50
|
+
$sitedir = File.join($libdir, "site_ruby")
|
51
|
+
elsif $sitedir !~ Regexp.quote(version)
|
52
|
+
$sitedir = File.join($sitedir, version)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
$bindir = CONFIG["bindir"]
|
57
|
+
|
58
|
+
$realbindir = $bindir
|
59
|
+
|
60
|
+
bindir = CONFIG["bindir"]
|
61
|
+
if (destdir = ENV['DESTDIR'])
|
62
|
+
$bindir = destdir + $bindir
|
63
|
+
$sitedir = destdir + $sitedir
|
64
|
+
|
65
|
+
File::makedirs($bindir)
|
66
|
+
File::makedirs($sitedir)
|
67
|
+
end
|
68
|
+
|
69
|
+
mm_dest = File.join($sitedir, "mm")
|
70
|
+
File::makedirs(mm_dest, true)
|
71
|
+
File::chmod(0755, mm_dest)
|
72
|
+
|
73
|
+
# The library files
|
74
|
+
|
75
|
+
files = Dir.chdir('lib') { Dir['**/*.rb', '**/*.rake'] }
|
76
|
+
|
77
|
+
for fn in files
|
78
|
+
fn_dir = File.dirname(fn)
|
79
|
+
target_dir = File.join($sitedir, fn_dir)
|
80
|
+
if ! File.exist?(target_dir)
|
81
|
+
File.makedirs(target_dir)
|
82
|
+
end
|
83
|
+
File::install(File.join('lib', fn), File.join($sitedir, fn), 0644, true)
|
84
|
+
end
|
85
|
+
|
86
|
+
# and the executable
|
87
|
+
|
88
|
+
installBIN("bin/mm", "mm")
|
data/lib/mm.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# Copyright (c) 2008 Li Xiao
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'mm/utils'
|
16
|
+
require 'mm/rest_api'
|
17
|
+
|
18
|
+
require 'mm/cmds/abstract_command'
|
19
|
+
require 'mm/cmds/init'
|
20
|
+
require 'mm/cmds/run'
|
21
|
+
require 'mm/cmds/svncommit'
|
22
|
+
require 'mm/cmds/user'
|
23
|
+
require 'mm/cmds/card'
|
24
|
+
require 'mm/cmds/cards'
|
25
|
+
require 'mm/cmds/favorites'
|
26
|
+
require 'mm/cmds/tabs'
|
27
|
+
require 'mm/cmds/view'
|
28
|
+
require 'mm/cmds/help'
|
29
|
+
|
30
|
+
module MM
|
31
|
+
VERSION="0.0.1"
|
32
|
+
|
33
|
+
module API
|
34
|
+
def team_members
|
35
|
+
return @team_members if defined?(@team_members)
|
36
|
+
init(Resource::User)
|
37
|
+
@team_members = Resource::User.find(:all)
|
38
|
+
end
|
39
|
+
|
40
|
+
def property_definitions
|
41
|
+
return @property_definitions if defined?(@property_definitions)
|
42
|
+
init(Resource::PropertyDefinition)
|
43
|
+
@property_definitions = Resource::PropertyDefinition.find(:all)
|
44
|
+
end
|
45
|
+
|
46
|
+
def favorites
|
47
|
+
init(Resource::Favorite)
|
48
|
+
Resource::Favorite.find(:all)
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_transition_execution(attrs)
|
52
|
+
init(Resource::TransitionExecution)
|
53
|
+
Resource::TransitionExecution.create(attrs)
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_card(options)
|
57
|
+
init(Resource::Card)
|
58
|
+
Resource::Card.find(:first, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def find_card_by_number(number)
|
62
|
+
init(Resource::Card)
|
63
|
+
Resource::Card.find(number)
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_cards(options)
|
67
|
+
init(Resource::Card)
|
68
|
+
Resource::Card.find(:all, :params => options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def init(klass)
|
72
|
+
Command::Init.new.do_once(klass)
|
73
|
+
end
|
74
|
+
|
75
|
+
def execute_cmd(cmd)
|
76
|
+
%x[#{cmd}]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
MM::Command::AbstractCommand.send(:include, MM::API)
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Copyright (c) 2008 Li Xiao
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'mm/repository'
|
15
|
+
|
16
|
+
module MM
|
17
|
+
module Command
|
18
|
+
class AbstractCommand
|
19
|
+
def run(argv)
|
20
|
+
if respond_to?(:option_parser)
|
21
|
+
option_parser.parse!(argv)
|
22
|
+
end
|
23
|
+
parse(argv) unless argv.empty?
|
24
|
+
cache_options
|
25
|
+
view do_once
|
26
|
+
end
|
27
|
+
|
28
|
+
def view(result)
|
29
|
+
output result
|
30
|
+
end
|
31
|
+
|
32
|
+
def options
|
33
|
+
@options ||= Repository.new[self.class.name] || {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse(argv)
|
37
|
+
end
|
38
|
+
|
39
|
+
def doc
|
40
|
+
puts(respond_to?(:option_parser) ? option_parser : "No document.")
|
41
|
+
end
|
42
|
+
|
43
|
+
def cache_options
|
44
|
+
Repository.new[self.class.name] = options
|
45
|
+
end
|
46
|
+
|
47
|
+
def output(message=nil)
|
48
|
+
if block_given?
|
49
|
+
output yield
|
50
|
+
return
|
51
|
+
elsif message.is_a?(String)
|
52
|
+
puts message
|
53
|
+
elsif options[:attr]
|
54
|
+
value = if pd = property_definitions.find{|pd| pd.name.downcase == options[:attr].downcase}
|
55
|
+
property_value(pd, message)
|
56
|
+
else
|
57
|
+
message.send(options[:attr])
|
58
|
+
end
|
59
|
+
output(" * #{options[:attr]}: #{value}")
|
60
|
+
else
|
61
|
+
output(message.to_yaml)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def property_value(pd, card)
|
66
|
+
obj_value = card.send(pd.column_name)
|
67
|
+
case
|
68
|
+
when pd.card_property?(obj_value)
|
69
|
+
find_card(:id => obj_value).short_summarization
|
70
|
+
when pd.user_property?(obj_value)
|
71
|
+
team_members.find{|u|u.id==obj_value}.name
|
72
|
+
else
|
73
|
+
obj_value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/mm/cmds/card.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright (c) 2008 Li Xiao
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'mm/cmds/abstract_command'
|
15
|
+
|
16
|
+
module MM
|
17
|
+
module Command
|
18
|
+
class Card < AbstractCommand
|
19
|
+
def view(card)
|
20
|
+
if options[:attr] || options[:show_all]
|
21
|
+
super(card)
|
22
|
+
else
|
23
|
+
super(card.summarization)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def do_once
|
28
|
+
output "card number => #{options[:number]}"
|
29
|
+
find_card_by_number(options[:number])
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse(argv)
|
33
|
+
options[:number] = argv[0].gsub(/[^\d]/, '').strip
|
34
|
+
end
|
35
|
+
|
36
|
+
def option_parser
|
37
|
+
OptionParser.new do |opts|
|
38
|
+
opts.banner = "usage: mm card <card_number>"
|
39
|
+
opts.separator ""
|
40
|
+
opts.separator "Synopsis:"
|
41
|
+
opts.separator "mm card 1 => find card by card number 1 and show all attributes"
|
42
|
+
opts.separator "mm card 1 -a description => find card by card number 1 and show its description"
|
43
|
+
opts.separator ""
|
44
|
+
opts.separator "Options:"
|
45
|
+
|
46
|
+
opts.on_tail("-a", "--attribute ATTR_NAME", "show specified attribute value") do |attr_name|
|
47
|
+
options[:attr] = attr_name
|
48
|
+
end
|
49
|
+
|
50
|
+
opts.on_tail("-s", "--show_all", "show all card attributes") do
|
51
|
+
options[:show_all] = true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Copyright (c) 2008 Li Xiao
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'mm/cmds/abstract_command'
|
15
|
+
|
16
|
+
module MM
|
17
|
+
module Command
|
18
|
+
class Cards < AbstractCommand
|
19
|
+
def view(cards)
|
20
|
+
cards.each do |card|
|
21
|
+
output '----------'
|
22
|
+
output card.short_summarization
|
23
|
+
if options[:attrs]
|
24
|
+
options[:attrs].each do |attr_name|
|
25
|
+
options[:attr] = attr_name
|
26
|
+
output card
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def do_once
|
33
|
+
output "card list params => #{options.inspect}"
|
34
|
+
find_cards(options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse(argv)
|
38
|
+
view_options = argv.join(' ').strip
|
39
|
+
options.merge!(eval(view_options =~ /^\{.*\}$/ ? view_options : "{#{view_options}}"))
|
40
|
+
end
|
41
|
+
|
42
|
+
def option_parser
|
43
|
+
OptionParser.new do |opts|
|
44
|
+
opts.banner = "usage: mm cards [options]"
|
45
|
+
opts.separator ""
|
46
|
+
opts.separator "Synopsis:"
|
47
|
+
opts.separator "mm cards \"{:view => 'favorite/tab name'}\" => find cards by favorite's/tab's name"
|
48
|
+
opts.separator "mm cards \"{:view => 'favorite/tab name', :page => 2}\" => find cards in the page 2 by favorite's/tab's name"
|
49
|
+
opts.separator ""
|
50
|
+
opts.separator "Options:"
|
51
|
+
opts.on("-a att_name1,attr_name2", Array, "show specified attribute value.") do |names|
|
52
|
+
options[:attrs] = names
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright (c) 2008 Li Xiao
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'mm/cmds/abstract_command'
|
15
|
+
|
16
|
+
#not finished yet
|
17
|
+
module MM
|
18
|
+
module Command
|
19
|
+
class Favorites < AbstractCommand
|
20
|
+
def view(favorites)
|
21
|
+
output "All favorites: \n#{favorites.collect{|f| " * #{f.name}"}.join("\n")}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def do_once
|
25
|
+
favorites
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/mm/cmds/help.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Copyright (c) 2008 Li Xiao
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'mm/cmds/abstract_command'
|
15
|
+
|
16
|
+
module MM
|
17
|
+
module Command
|
18
|
+
class Help < AbstractCommand
|
19
|
+
def do_once
|
20
|
+
return doc if options[:cmd].blank?
|
21
|
+
"#{MM.cmd_instance(options[:cmd]).doc}\n"
|
22
|
+
rescue Exception => e
|
23
|
+
"Unknow subcommand: #{options[:cmd]}\n#{doc}\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse(argv)
|
27
|
+
options[:cmd] = argv.first
|
28
|
+
end
|
29
|
+
|
30
|
+
#don't want to cache options of this command
|
31
|
+
def cache_options
|
32
|
+
end
|
33
|
+
|
34
|
+
def doc
|
35
|
+
%{
|
36
|
+
mingle mingle, version #{MM::VERSION}
|
37
|
+
Type 'mm help <subcommand>' for help on a specific subcommand.
|
38
|
+
|
39
|
+
Queck start:
|
40
|
+
* Suppose I am working on a project pet_store checked out at '~/pet_store'.
|
41
|
+
* cd ~/pet_store
|
42
|
+
* mm init http://my_login:password@mingle_server/projects/pet_store
|
43
|
+
* mm cards => list first page cards on All tab
|
44
|
+
* mm view My Work -a owner,priority => list cards on card list view named 'My Work' including property owner and priority
|
45
|
+
* mm card 102 => show name and description of the card
|
46
|
+
* mm run 'Start fix #102' => run transition 'Start fix' on card 102
|
47
|
+
* mm svnci -m "[complete development #1 with 'fixed revision' => \#{revision}, resolution => fixed (some comment)] blabla..." => commit code and run transition script inside of []
|
48
|
+
* mm view => show view cached which is 'My Work' with property 'owner' and 'priority' by last time using view command
|
49
|
+
* mm card => show card cached number of which is 102 by last time using card command
|
50
|
+
|
51
|
+
Available subcommands:
|
52
|
+
help [subcommand] show help doc of subcommand
|
53
|
+
init [url] init MingleMingle working directory with Mingle REST api project base url
|
54
|
+
card [number] show card content by card number
|
55
|
+
cards [params] show cards by params, it will do nothing without params.
|
56
|
+
user [id/login] show user info by id/login
|
57
|
+
view name show cards find by view/tab name
|
58
|
+
run script run transition
|
59
|
+
svncommit(svnci) run transition execution script inside the commit message after committed code(subversion)
|
60
|
+
|
61
|
+
MingleMingle is a tool for integrating Mingle(http://studios.thoughtworks.com/) with command-line
|
62
|
+
For additional information, see http://minglemingle.rubyforge.org
|
63
|
+
Notes:
|
64
|
+
* In the command line, should use \\! instead of !.
|
65
|
+
* There would be a '.mm_pstore' file created for cache in the MingleMingle working directory.
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|